internal static CompileResult CompileExpressionWithRetry(
            ImmutableArray <MetadataBlock> metadataBlocks,
            string expr,
            ImmutableArray <Alias> aliases,
            ExpressionCompiler.CreateContextDelegate createContext,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage,
            out CompilationTestData testData)
        {
            var r = ExpressionCompiler.CompileWithRetry(
                metadataBlocks,
                DebuggerDiagnosticFormatter.Instance,
                createContext,
                (context, diagnostics) =>
            {
                var td = new CompilationTestData();
                ResultProperties resultProperties;
                var compileResult = context.CompileExpression(
                    expr,
                    DkmEvaluationFlags.TreatAsExpression,
                    aliases,
                    diagnostics,
                    out resultProperties,
                    td);
                return(new CompileExpressionResult(compileResult, td));
            },
                getMetaDataBytesPtr,
                out errorMessage);

            testData = r.TestData;
            return(r.CompileResult);
        }
예제 #2
0
        private static void ShouldTryAgain_False(DkmUtilities.GetMetadataBytesPtrFunction gmdbpf)
        {
            var references = ImmutableArray <MetadataBlock> .Empty;
            var missingAssemblyIdentities = ImmutableArray.Create(new AssemblyIdentity("A"));

            Assert.False(ExpressionCompiler.ShouldTryAgainWithMoreMetadataBlocks(gmdbpf, missingAssemblyIdentities, ref references));
            Assert.Empty(references);
        }
예제 #3
0
        public void ShouldTryAgain_OtherException()
        {
            DkmUtilities.GetMetadataBytesPtrFunction gmdbpf = (AssemblyIdentity assemblyIdentity, out uint uSize) =>
            {
                throw new Exception();
            };

            var references = ImmutableArray <MetadataBlock> .Empty;
            var missingAssemblyIdentities = ImmutableArray.Create(new AssemblyIdentity("A"));

            Assert.Throws <Exception>(() => ExpressionCompiler.ShouldTryAgainWithMoreMetadataBlocks(gmdbpf, missingAssemblyIdentities, ref references));
        }
예제 #4
0
        /// <remarks>
        /// Internal for testing.
        /// </remarks>
        internal static bool ShouldTryAgainWithMoreMetadataBlocks(DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtrFunction, ImmutableArray <AssemblyIdentity> missingAssemblyIdentities, ref ImmutableArray <MetadataBlock> references)
        {
            var newReferences = DkmUtilities.GetMetadataBlocks(getMetaDataBytesPtrFunction, missingAssemblyIdentities);

            if (newReferences.Length > 0)
            {
                references = references.AddRange(newReferences);
                return(true);
            }

            return(false);
        }
예제 #5
0
        internal static TResult CompileWithRetry <TResult>(
            ImmutableArray <MetadataBlock> metadataBlocks,
            DiagnosticFormatter formatter,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage)
        {
            errorMessage = null;
            TResult compileResult;

            bool tryAgain;

            do
            {
                var context     = createContext(metadataBlocks, useReferencedModulesOnly: false);
                var diagnostics = DiagnosticBag.GetInstance();
                compileResult = compile(context, diagnostics);
                tryAgain      = false;
                if (diagnostics.HasAnyErrors())
                {
                    bool useReferencedModulesOnly;
                    ImmutableArray <AssemblyIdentity> missingAssemblyIdentities;
                    errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities(
                        diagnostics,
                        formatter,
                        preferredUICulture: null,
                        useReferencedModulesOnly: out useReferencedModulesOnly,
                        missingAssemblyIdentities: out missingAssemblyIdentities);
                    if (useReferencedModulesOnly)
                    {
                        Debug.Assert(missingAssemblyIdentities.IsEmpty);
                        var otherContext     = createContext(metadataBlocks, useReferencedModulesOnly: true);
                        var otherDiagnostics = DiagnosticBag.GetInstance();
                        var otherResult      = compile(otherContext, otherDiagnostics);
                        if (!otherDiagnostics.HasAnyErrors())
                        {
                            errorMessage  = null;
                            compileResult = otherResult;
                        }
                        otherDiagnostics.Free();
                    }
                    else
                    {
                        tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks);
                    }
                }
                diagnostics.Free();
            } while (tryAgain);

            return(compileResult);
        }
예제 #6
0
        public void ShouldTryAgain_RPC_E_DISCONNECTED()
        {
            DkmUtilities.GetMetadataBytesPtrFunction gmdbpf =
                (AssemblyIdentity assemblyIdentity, out uint uSize) =>
            {
                Marshal.ThrowExceptionForHR(unchecked ((int)0x80010108));
                throw ExceptionUtilities.Unreachable;
            };

            var references = ImmutableArray <MetadataBlock> .Empty;
            var missingAssemblyIdentities = ImmutableArray.Create(new AssemblyIdentity("A"));

            Assert.Throws <COMException>(() => ExpressionCompiler.ShouldTryAgainWithMoreMetadataBlocks(gmdbpf, missingAssemblyIdentities, ref references));
        }
예제 #7
0
        public void ShouldTryAgain_COR_E_BADIMAGEFORMAT()
        {
            DkmUtilities.GetMetadataBytesPtrFunction gmdbpf = (AssemblyIdentity assemblyIdentity, out uint uSize) =>
            {
                Marshal.ThrowExceptionForHR(unchecked ((int)MetadataUtilities.COR_E_BADIMAGEFORMAT));
                throw ExceptionUtilities.Unreachable;
            };

            var references = ImmutableArray <MetadataBlock> .Empty;
            var missingAssemblyIdentities = ImmutableArray.Create(new AssemblyIdentity("A"));

            Assert.False(ExpressionCompiler.ShouldTryAgainWithMoreMetadataBlocks(gmdbpf, missingAssemblyIdentities, ref references));
            Assert.Empty(references);
        }
 internal static CompileResult CompileExpressionWithRetry(
     ImmutableArray <MetadataBlock> metadataBlocks,
     EvaluationContextBase context,
     ExpressionCompiler.CompileDelegate <CompileResult> compile,
     DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
     out string errorMessage)
 {
     return(ExpressionCompiler.CompileWithRetry(
                metadataBlocks,
                DebuggerDiagnosticFormatter.Instance,
                (blocks, useReferencedModulesOnly) => context,
                compile,
                getMetaDataBytesPtr,
                out errorMessage));
 }
예제 #9
0
        public unsafe void ShouldTryAgain_Mixed()
        {
            var comp1 = CreateStandardCompilation("public class C { }", assemblyName: GetUniqueName());
            var comp2 = CreateStandardCompilation("public class D { }", assemblyName: GetUniqueName());

            using (PinnedMetadata pinned1 = new PinnedMetadata(GetMetadataBytes(comp1)),
                   pinned2 = new PinnedMetadata(GetMetadataBytes(comp2)))
            {
                var assemblyIdentity1 = comp1.Assembly.Identity;
                var assemblyIdentity2 = comp2.Assembly.Identity;
                Assert.NotEqual(assemblyIdentity1, assemblyIdentity2);

                DkmUtilities.GetMetadataBytesPtrFunction gmdbpf = (AssemblyIdentity assemblyIdentity, out uint uSize) =>
                {
                    if (assemblyIdentity == assemblyIdentity1)
                    {
                        uSize = (uint)pinned1.Size;
                        return(pinned1.Pointer);
                    }
                    else if (assemblyIdentity == assemblyIdentity2)
                    {
                        uSize = (uint)pinned2.Size;
                        return(pinned2.Pointer);
                    }
                    else
                    {
                        Marshal.ThrowExceptionForHR(unchecked ((int)MetadataUtilities.CORDBG_E_MISSING_METADATA));
                        throw ExceptionUtilities.Unreachable;
                    }
                };

                var references = ImmutableArray.Create(default(MetadataBlock));
                var unknownAssemblyIdentity   = new AssemblyIdentity(GetUniqueName());
                var missingAssemblyIdentities = ImmutableArray.Create(assemblyIdentity1, unknownAssemblyIdentity, assemblyIdentity2);
                Assert.True(ExpressionCompiler.ShouldTryAgainWithMoreMetadataBlocks(gmdbpf, missingAssemblyIdentities, ref references));
                Assert.Equal(3, references.Length);

                Assert.Equal(default(MetadataBlock), references[0]);

                Assert.Equal(pinned1.Pointer, references[1].Pointer);
                Assert.Equal(pinned1.Size, references[1].Size);

                Assert.Equal(pinned2.Pointer, references[2].Pointer);
                Assert.Equal(pinned2.Size, references[2].Size);
            }
        }
예제 #10
0
        public unsafe void ShouldTryAgain_Success()
        {
            var comp = CreateStandardCompilation("public class C { }");

            using (var pinned = new PinnedMetadata(GetMetadataBytes(comp)))
            {
                DkmUtilities.GetMetadataBytesPtrFunction gmdbpf = (AssemblyIdentity assemblyIdentity, out uint uSize) =>
                {
                    uSize = (uint)pinned.Size;
                    return(pinned.Pointer);
                };

                var references = ImmutableArray <MetadataBlock> .Empty;
                var missingAssemblyIdentity   = new AssemblyIdentity("A");
                var missingAssemblyIdentities = ImmutableArray.Create(missingAssemblyIdentity);
                Assert.True(ExpressionCompiler.ShouldTryAgainWithMoreMetadataBlocks(gmdbpf, missingAssemblyIdentities, ref references));

                var newReference = references.Single();
                Assert.Equal(pinned.Pointer, newReference.Pointer);
                Assert.Equal(pinned.Size, newReference.Size);
            }
        }
예제 #11
0
        internal static TResult CompileWithRetry <TResult>(
            ImmutableArray <MetadataBlock> metadataBlocks,
            DiagnosticFormatter formatter,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage)
        {
            TResult compileResult;

            PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null;
            bool tryAgain;

            do
            {
                errorMessage = null;

                var context     = createContext(metadataBlocks, useReferencedModulesOnly: false);
                var diagnostics = DiagnosticBag.GetInstance();
                compileResult = compile(context, diagnostics);
                tryAgain      = false;
                if (diagnostics.HasAnyErrors())
                {
                    bool useReferencedModulesOnly;
                    ImmutableArray <AssemblyIdentity> missingAssemblyIdentities;
                    errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities(
                        diagnostics,
                        formatter,
                        preferredUICulture: null,
                        useReferencedModulesOnly: out useReferencedModulesOnly,
                        missingAssemblyIdentities: out missingAssemblyIdentities);
                    if (useReferencedModulesOnly)
                    {
                        Debug.Assert(missingAssemblyIdentities.IsEmpty);
                        var otherContext     = createContext(metadataBlocks, useReferencedModulesOnly: true);
                        var otherDiagnostics = DiagnosticBag.GetInstance();
                        var otherResult      = compile(otherContext, otherDiagnostics);
                        if (!otherDiagnostics.HasAnyErrors())
                        {
                            errorMessage  = null;
                            compileResult = otherResult;
                        }
                        otherDiagnostics.Free();
                    }
                    else
                    {
                        if (!missingAssemblyIdentities.IsEmpty)
                        {
                            if (assembliesLoadedInRetryLoop == null)
                            {
                                assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance();
                            }
                            // If any identities failed to add (they were already in the list), then don't retry.
                            if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities))
                            {
                                tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks);
                            }
                        }
                    }
                }
                diagnostics.Free();
            } while (tryAgain);
            assembliesLoadedInRetryLoop?.Free();

            return(compileResult);
        }
예제 #12
0
        internal static TResult CompileWithRetry <TResult>(
            ImmutableArray <MetadataBlock> metadataBlocks,
            DiagnosticFormatter formatter,
            CreateContextDelegate createContext,
            CompileDelegate <TResult> compile,
            DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr,
            out string errorMessage)
        {
            TResult compileResult;

            PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null;
            bool tryAgain;
            var  linqLibrary = EvaluationContextBase.SystemLinqIdentity;

            do
            {
                errorMessage = null;

                var context     = createContext(metadataBlocks, useReferencedModulesOnly: false);
                var diagnostics = DiagnosticBag.GetInstance();
                compileResult = compile(context, diagnostics);
                tryAgain      = false;
                if (diagnostics.HasAnyErrors())
                {
                    bool useReferencedModulesOnly;
                    ImmutableArray <AssemblyIdentity> missingAssemblyIdentities;
                    errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities(
                        diagnostics,
                        formatter,
                        preferredUICulture: null,
                        linqLibrary: linqLibrary,
                        useReferencedModulesOnly: out useReferencedModulesOnly,
                        missingAssemblyIdentities: out missingAssemblyIdentities);
                    // If there were LINQ-related errors, we'll initially add System.Linq (set above).
                    // If that doesn't work, we'll fall back to System.Core for subsequent retries.
                    linqLibrary = EvaluationContextBase.SystemCoreIdentity;

                    // Can we remove the `useReferencedModulesOnly` attempt if we're only using
                    // modules reachable from the current module? In short, can we avoid retrying?
                    if (useReferencedModulesOnly)
                    {
                        Debug.Assert(missingAssemblyIdentities.IsEmpty);
                        var otherContext     = createContext(metadataBlocks, useReferencedModulesOnly: true);
                        var otherDiagnostics = DiagnosticBag.GetInstance();
                        var otherResult      = compile(otherContext, otherDiagnostics);
                        if (!otherDiagnostics.HasAnyErrors())
                        {
                            errorMessage  = null;
                            compileResult = otherResult;
                        }
                        otherDiagnostics.Free();
                    }
                    else
                    {
                        if (!missingAssemblyIdentities.IsEmpty)
                        {
                            if (assembliesLoadedInRetryLoop == null)
                            {
                                assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance();
                            }
                            // If any identities failed to add (they were already in the list), then don't retry.
                            if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities))
                            {
                                tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks);
                            }
                        }
                    }
                }
                diagnostics.Free();
            } while (tryAgain);
            assembliesLoadedInRetryLoop?.Free();

            return(compileResult);
        }