/// <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; } }
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; } } }
/// <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); }
/// <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; } }
/// <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; } }
/// <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; } }
/// <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; }