提交 d8a4bfb8 编写于 作者: K Kevin_H

Add a reference in CompilationTestData to hold on to the Compilation that was...

Add a reference in CompilationTestData to hold on to the Compilation that was used to initialize it.  The IL visualizer requires Symbols of the Compilation to still be alive when visualizing tokens.

Most of the time, we hold a reference to the compilation in the test method, so the lifetime of the Symbols would be long enough for all test verification to occur.  However, in some tests, the Compilation is created in a helper and then thrown away as soon as the PE image is emitted.  Verification steps later in the test method could result in AVs if a GC occurs at the wrong time. (changeset 1347747)
上级 54c837ae
......@@ -2348,6 +2348,7 @@ internal override FunctionId EmitFunctionId
// testData is only passed when running tests.
if (testData != null)
{
testData.Compilation = this;
moduleBeingBuilt.SetMethodTestData(testData.Methods);
testData.Module = moduleBeingBuilt;
}
......
......@@ -54,6 +54,7 @@ internal static class EmitHelpers
if (testData != null)
{
testData.Compilation = compilation;
moduleBeingBuilt.SetMethodTestData(testData.Methods);
testData.Module = moduleBeingBuilt;
}
......
......@@ -19,6 +19,10 @@ public MethodData(ILBuilder ilBuilder, IMethodSymbol method)
}
}
// ILBuilder requires that Symbols still be alive when visualizing tokens from the IL stream.
// We'll hold on to a reference here.
public Compilation Compilation;
// The map is used for storing a list of methods and their associated IL.
// The key is a formatted qualified method name, e.g. Namespace.Class<T>.m<S>
public readonly ConcurrentDictionary<string, MethodData> Methods = new ConcurrentDictionary<string, MethodData>();
......@@ -27,5 +31,13 @@ public MethodData(ILBuilder ilBuilder, IMethodSymbol method)
public Cci.IModule Module;
public Func<object> SymWriterFactory;
public void Reset()
{
this.Compilation = null;
this.Methods.Clear();
this.Module = null;
this.SymWriterFactory = null;
}
}
}
......@@ -2174,6 +2174,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
If testData IsNot Nothing Then
testData.Compilation = Me
moduleBeingBuilt.SetMethodTestData(testData.Methods)
testData.Module = moduleBeingBuilt
End If
......
......@@ -46,6 +46,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
edits:=edits)
If testData IsNot Nothing Then
testData.Compilation = compilation
moduleBeingBuilt.SetMethodTestData(testData.Methods)
testData.Module = moduleBeingBuilt
End If
......
......@@ -220,7 +220,7 @@ public void Emit(Compilation mainCompilation, IEnumerable<ResourceDescription> m
var diagnostics = DiagnosticBag.GetInstance();
var dependencies = new List<ModuleData>();
testData.Methods.Clear();
testData.Reset();
ImmutableArray<byte> mainImage, mainPdb;
bool succeeded = EmitCompilation(mainCompilation, manifestResources, dependencies, diagnostics, testData, out mainImage, out mainPdb);
......@@ -409,6 +409,7 @@ void IDisposable.Dispose()
internal CompilationTestData GetCompilationTestData()
{
Debug.Assert(testData.Compilation != null, "If CompilationTestData does not have a pointer to the compilation that initialized it, then AVs may result when attempting to access Symbols during IL visualization.");
if (testData.Module == null)
{
throw new InvalidOperationException("You must call Emit before calling GetCompilationTestData.");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册