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