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);
        }
Esempio n. 3
0
        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);
        }