internal override CSharpCompilation GetCompilation(DkmClrModuleInstance moduleInstance) { var appDomain = moduleInstance.AppDomain; var moduleVersionId = moduleInstance.Mvid; var previous = appDomain.GetMetadataContext <CSharpMetadataContext>(); var metadataBlocks = moduleInstance.RuntimeInstance.GetMetadataBlocks(appDomain, previous.MetadataBlocks); var kind = GetMakeAssemblyReferencesKind(); var contextId = MetadataContextId.GetContextId(moduleVersionId, kind); var assemblyContexts = previous.Matches(metadataBlocks) ? previous.AssemblyContexts : ImmutableDictionary <MetadataContextId, CSharpMetadataContext> .Empty; CSharpMetadataContext previousContext; assemblyContexts.TryGetValue(contextId, out previousContext); var compilation = previousContext.Compilation; if (compilation == null) { compilation = metadataBlocks.ToCompilation(moduleVersionId, kind); appDomain.SetMetadataContext( new MetadataContext <CSharpMetadataContext>( metadataBlocks, assemblyContexts.SetItem(contextId, new CSharpMetadataContext(compilation))), report: kind == MakeAssemblyReferencesKind.AllReferences); } return(compilation); }
internal static EvaluationContext CreateTypeContext <TAppDomain>( TAppDomain appDomain, GetMetadataContextDelegate <TAppDomain> getMetadataContext, ImmutableArray <MetadataBlock> metadataBlocks, Guid moduleVersionId, int typeToken, MakeAssemblyReferencesKind kind) { CSharpCompilation?compilation; if (kind == MakeAssemblyReferencesKind.DirectReferencesOnly) { // Avoid using the cache for referenced assemblies only // since this should be the exceptional case. compilation = metadataBlocks.ToCompilationReferencedModulesOnly(moduleVersionId); return(EvaluationContext.CreateTypeContext( compilation, moduleVersionId, typeToken)); } var contextId = MetadataContextId.GetContextId(moduleVersionId, kind); var previous = getMetadataContext(appDomain); CSharpMetadataContext previousMetadataContext = default; if (previous.Matches(metadataBlocks)) { previous.AssemblyContexts.TryGetValue(contextId, out previousMetadataContext); } // Re-use the previous compilation if possible. compilation = previousMetadataContext.Compilation; if (compilation == null) { compilation = metadataBlocks.ToCompilation(moduleVersionId, kind); } var context = EvaluationContext.CreateTypeContext( compilation, moduleVersionId, typeToken); // New type context is not attached to the AppDomain since it is less // re-usable than the previous attached method context. (We could hold // on to it if we don't have a previous method context but it's unlikely // that we evaluated a type-level expression before a method-level.) Debug.Assert(context != previousMetadataContext.EvaluationContext); return(context); }
internal static EvaluationContext CreateMethodContext <TAppDomain>( TAppDomain appDomain, GetMetadataContextDelegate <TAppDomain> getMetadataContext, SetMetadataContextDelegate <TAppDomain> setMetadataContext, ImmutableArray <MetadataBlock> metadataBlocks, object?symReader, Guid moduleVersionId, int methodToken, int methodVersion, uint ilOffset, int localSignatureToken, MakeAssemblyReferencesKind kind) { CSharpCompilation compilation; int offset = EvaluationContextBase.NormalizeILOffset(ilOffset); if (kind == MakeAssemblyReferencesKind.DirectReferencesOnly) { // Avoid using the cache for referenced assemblies only // since this should be the exceptional case. compilation = metadataBlocks.ToCompilationReferencedModulesOnly(moduleVersionId); return(EvaluationContext.CreateMethodContext( compilation, symReader, moduleVersionId, methodToken, methodVersion, offset, localSignatureToken)); } var contextId = MetadataContextId.GetContextId(moduleVersionId, kind); var previous = getMetadataContext(appDomain); var assemblyContexts = previous.Matches(metadataBlocks) ? previous.AssemblyContexts : ImmutableDictionary <MetadataContextId, CSharpMetadataContext> .Empty; CSharpMetadataContext previousMetadataContext; assemblyContexts.TryGetValue(contextId, out previousMetadataContext); // Re-use the previous compilation if possible. compilation = previousMetadataContext.Compilation; if (compilation != null) { // Re-use entire context if method scope has not changed. var previousContext = previousMetadataContext.EvaluationContext; if (previousContext != null && previousContext.MethodContextReuseConstraints.HasValue && previousContext.MethodContextReuseConstraints.GetValueOrDefault().AreSatisfied(moduleVersionId, methodToken, methodVersion, offset)) { return(previousContext); } } else { compilation = metadataBlocks.ToCompilation(moduleVersionId, kind); } var context = EvaluationContext.CreateMethodContext( compilation, symReader, moduleVersionId, methodToken, methodVersion, offset, localSignatureToken); if (context != previousMetadataContext.EvaluationContext) { setMetadataContext( appDomain, new MetadataContext <CSharpMetadataContext>( metadataBlocks, assemblyContexts.SetItem(contextId, new CSharpMetadataContext(context.Compilation, context))), report: kind == MakeAssemblyReferencesKind.AllReferences); } return(context); }