예제 #1
0
        /// <summary>
        /// Ensures that code generation has been run for the provided assembly.
        /// </summary>
        /// <param name="input">
        /// The assembly to generate code for.
        /// </param>
        public GeneratedAssembly GenerateAndLoadForAssembly(Assembly input)
        {
            try
            {
                RegisterGeneratedCodeTargets(input);
                if (!ShouldGenerateCodeForAssembly(input))
                {
                    return(TryLoadGeneratedAssemblyFromCache(input));
                }

                var timer     = Stopwatch.StartNew();
                var generated = GenerateForAssemblies(new List <Assembly> {
                    input
                }, true);

                CachedAssembly generatedAssembly;
                if (generated.Syntax != null)
                {
                    var emitDebugSymbols = RuntimeVersion.IsAssemblyDebugBuild(input);
                    generatedAssembly = CompileAndLoad(generated, emitDebugSymbols);
                }
                else
                {
                    generatedAssembly = new CachedAssembly {
                        Loaded = true
                    };
                }

                foreach (var assembly in generated.SourceAssemblies)
                {
                    CompiledAssemblies.AddOrUpdate(
                        assembly.GetName().FullName,
                        generatedAssembly,
                        (_, __) => generatedAssembly);
                }

                if (Logger.IsVerbose2)
                {
                    Logger.Verbose2(
                        ErrorCode.CodeGenCompilationSucceeded,
                        "Generated code for 1 assembly in {0}ms",
                        timer.ElapsedMilliseconds);
                }

                return(generatedAssembly);
            }
            catch (Exception exception)
            {
                var message =
                    $"Exception generating code for input assembly {input.GetName().FullName}\nException: {LogFormatter.PrintException(exception)}";
                Logger.Warn(ErrorCode.CodeGenCompilationFailed, message, exception);
                throw;
            }
        }
예제 #2
0
 private static void SetDatadogAssembly(string path, Assembly cachedAssembly)
 {
     for (var i = 0; i < _assemblies.Length; i++)
     {
         if (_assemblies[i].Path == path)
         {
             _assemblies[i] = new CachedAssembly(path, cachedAssembly);
             break;
         }
     }
 }
예제 #3
0
        /// <exception cref="IOException"/>
        private static AssemblyMetadata GetOrCreateAssemblyFromFile(string fullPath)
        {
            AssemblyMetadata assembly = null;

            // may throw:
            FileKey key = FileKey.Create(fullPath);

            CachedAssembly cachedAssembly;
            bool           existingKey = assembliesFromFiles.TryGetValue(key, out cachedAssembly);

            if (existingKey && cachedAssembly.Metadata.TryGetTarget(out assembly))
            {
                return(assembly);
            }

            // memory-map all modules of the assembly:
            assembly = AssemblyMetadata.CreateFromFile(fullPath);

            // refresh the timestamp (the file may have changed just before we memory-mapped it):
            bool fault = true;

            try
            {
                key   = FileKey.Create(fullPath);
                fault = false;
            }
            finally
            {
                if (fault)
                {
                    assembly.Dispose();
                }
            }

            cachedAssembly           = new CachedAssembly(assembly);
            assembliesFromFiles[key] = cachedAssembly;

            if (!existingKey)
            {
                assemblyKeys.Add(key);
                EnableCompactTimer();
            }

            return(assembly);
        }
예제 #4
0
        /// <summary>
        /// Generates and loads code for the specified inputs.
        /// </summary>
        /// <param name="inputs">The assemblies to generate code for.</param>
        public IReadOnlyList <GeneratedAssembly> GenerateAndLoadForAssemblies(params Assembly[] inputs)
        {
            if (inputs == null)
            {
                throw new ArgumentNullException(nameof(inputs));
            }

            var results = new List <GeneratedAssembly>();

            var timer            = Stopwatch.StartNew();
            var emitDebugSymbols = false;

            foreach (var input in inputs)
            {
                if (!emitDebugSymbols)
                {
                    emitDebugSymbols |= RuntimeVersion.IsAssemblyDebugBuild(input);
                }

                RegisterGeneratedCodeTargets(input);
                var cached = TryLoadGeneratedAssemblyFromCache(input);
                if (cached != null)
                {
                    results.Add(cached);
                }
            }

            var grainAssemblies = inputs.Where(ShouldGenerateCodeForAssembly).ToList();

            if (grainAssemblies.Count == 0)
            {
                // Already up to date.
                return(results);
            }

            try
            {
                // Generate code for newly loaded assemblies.
                var generatedSyntax = GenerateForAssemblies(grainAssemblies, true);

                CachedAssembly generatedAssembly;
                if (generatedSyntax.Syntax != null)
                {
                    generatedAssembly = CompileAndLoad(generatedSyntax, emitDebugSymbols);
                    if (generatedAssembly != null)
                    {
                        results.Add(generatedAssembly);
                    }
                }
                else
                {
                    generatedAssembly = new CachedAssembly {
                        Loaded = true
                    };
                }

                foreach (var assembly in generatedSyntax.SourceAssemblies)
                {
                    CompiledAssemblies.AddOrUpdate(
                        assembly.GetName().FullName,
                        generatedAssembly,
                        (_, __) => generatedAssembly);
                }

                if (Logger.IsVerbose2)
                {
                    Logger.Verbose2(
                        ErrorCode.CodeGenCompilationSucceeded,
                        "Generated code for {0} assemblies in {1}ms",
                        generatedSyntax.SourceAssemblies.Count,
                        timer.ElapsedMilliseconds);
                }

                return(results);
            }
            catch (Exception exception)
            {
                var assemblyNames = string.Join("\n", grainAssemblies.Select(_ => _.GetName().FullName));
                var message       =
                    $"Exception generating code for input assemblies:\n{assemblyNames}\nException: {LogFormatter.PrintException(exception)}";
                Logger.Warn(ErrorCode.CodeGenCompilationFailed, message, exception);
                throw;
            }
        }
예제 #5
0
        /// <summary>
        /// Generates and loads code for the specified inputs.
        /// </summary>
        /// <param name="inputs">The assemblies to generate code for.</param>
        public void GenerateAndLoadForAssemblies(params Assembly[] inputs)
        {
            if (inputs == null)
            {
                throw new ArgumentNullException(nameof(inputs));
            }

            var timer = Stopwatch.StartNew();
            var emitDebugSymbols = false;
            foreach (var input in inputs)
            {
                if (!emitDebugSymbols)
                {
                    emitDebugSymbols |= RuntimeVersion.IsAssemblyDebugBuild(input);
                }

                RegisterGeneratedCodeTargets(input);
                TryLoadGeneratedAssemblyFromCache(input);
            }

            var grainAssemblies = inputs.Where(ShouldGenerateCodeForAssembly).ToList();
            if (grainAssemblies.Count == 0)
            {
                // Already up to date.
                return;
            }

            try
            {
                // Generate code for newly loaded assemblies.
                var generatedSyntax = GenerateForAssemblies(grainAssemblies, true);

                CachedAssembly generatedAssembly;
                if (generatedSyntax.Syntax != null)
                {
                    generatedAssembly = CompileAndLoad(generatedSyntax, emitDebugSymbols);
                }
                else
                {
                    generatedAssembly = new CachedAssembly { Loaded = true };
                }

                foreach (var assembly in generatedSyntax.SourceAssemblies)
                {
                    CompiledAssemblies.AddOrUpdate(
                        assembly.GetName().FullName,
                        generatedAssembly,
                        (_, __) => generatedAssembly);
                }

                if (Logger.IsVerbose2)
                {
                    Logger.Verbose2(
                        ErrorCode.CodeGenCompilationSucceeded,
                        "Generated code for {0} assemblies in {1}ms",
                        generatedSyntax.SourceAssemblies.Count,
                        timer.ElapsedMilliseconds);
                }
            }
            catch (Exception exception)
            {
                var assemblyNames = string.Join("\n", grainAssemblies.Select(_ => _.GetName().FullName));
                var message =
                    $"Exception generating code for input assemblies:\n{assemblyNames}\nException: {LogFormatter.PrintException(exception)}";
                Logger.Warn(ErrorCode.CodeGenCompilationFailed, message, exception);
                throw;
            }
        }
예제 #6
0
        /// <summary>
        /// Ensures that code generation has been run for the provided assembly.
        /// </summary>
        /// <param name="input">
        /// The assembly to generate code for.
        /// </param>
        public void GenerateAndLoadForAssembly(Assembly input)
        {
            try
            {
                RegisterGeneratedCodeTargets(input);
                if (!ShouldGenerateCodeForAssembly(input))
                {
                    TryLoadGeneratedAssemblyFromCache(input);

                    return;
                }

                var timer = Stopwatch.StartNew();
                var generated = GenerateForAssemblies(new List<Assembly> { input }, true);

                CachedAssembly generatedAssembly;
                if (generated.Syntax != null)
                {
                    var emitDebugSymbols = RuntimeVersion.IsAssemblyDebugBuild(input);
                    generatedAssembly = CompileAndLoad(generated, emitDebugSymbols);
                }
                else
                {
                    generatedAssembly = new CachedAssembly { Loaded = true };
                }

                foreach (var assembly in generated.SourceAssemblies)
                {
                    CompiledAssemblies.AddOrUpdate(
                        assembly.GetName().FullName,
                        generatedAssembly,
                        (_, __) => generatedAssembly);
                }

                if (Logger.IsVerbose2)
                {
                    Logger.Verbose2(
                        ErrorCode.CodeGenCompilationSucceeded,
                        "Generated code for 1 assembly in {0}ms",
                        timer.ElapsedMilliseconds);
                }
            }
            catch (Exception exception)
            {
                var message =
                    $"Exception generating code for input assembly {input.GetName().FullName}\nException: {LogFormatter.PrintException(exception)}";
                Logger.Warn(ErrorCode.CodeGenCompilationFailed, message, exception);
                throw;
            }
        }
예제 #7
0
        /// <exception cref="IOException"/>
        private static AssemblyMetadata GetOrCreateAssemblyFromFile(string fullPath)
        {
            AssemblyMetadata assembly = null;

            // may throw:
            FileKey key = FileKey.Create(fullPath);

            CachedAssembly cachedAssembly;
            bool existingKey = s_assembliesFromFiles.TryGetValue(key, out cachedAssembly);
            if (existingKey && cachedAssembly.Metadata.TryGetTarget(out assembly))
            {
                return assembly;
            }

            // memory-map all modules of the assembly:
            assembly = AssemblyMetadata.CreateFromFile(fullPath);

            // refresh the timestamp (the file may have changed just before we memory-mapped it):
            bool fault = true;
            try
            {
                key = FileKey.Create(fullPath);
                fault = false;
            }
            finally
            {
                if (fault)
                {
                    assembly.Dispose();
                }
            }

            cachedAssembly = new CachedAssembly(assembly);
            s_assembliesFromFiles[key] = cachedAssembly;

            if (!existingKey)
            {
                s_assemblyKeys.Add(key);
                EnableCompactTimer();
            }

            return assembly;
        }