Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiler crash in LambdaRewriter #21506

Closed
tmat opened this issue Aug 15, 2017 · 1 comment · Fixed by #21510
Closed

Compiler crash in LambdaRewriter #21506

tmat opened this issue Aug 15, 2017 · 1 comment · Fixed by #21510

Comments

@tmat
Copy link
Member

tmat commented Aug 15, 2017

VS insertion to vsuml failed due to a bug in the compiler. The insertion is blocked until this issue is fixed.

Stack trace:

 	Microsoft.CodeAnalysis.dll!Microsoft.CodeAnalysis.FatalError.Report(System.Exception exception, System.Action<System.Exception> handler) Line 173	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedTypeAsTask.AnonymousMethod__0() Line 385	C#	Symbols loaded.
 	[Native to Managed Transition]		Annotated Frame
 	mscorlib.dll!System.ThrowHelper.ThrowArgumentException(System.ExceptionResource resource) Line 72	C#	Symbols loaded.
 	mscorlib.dll!System.Collections.Generic.Dictionary<Microsoft.CodeAnalysis.CSharp.Symbol, Microsoft.CodeAnalysis.CSharp.CapturedSymbolReplacement>.Insert(Microsoft.CodeAnalysis.CSharp.Symbol key, Microsoft.CodeAnalysis.CSharp.CapturedSymbolReplacement value, bool add) Line 336	C#	Symbols loaded.
>	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.LambdaRewriter.SynthesizeClosureEnvironments.AnonymousMethod__0(Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope scope) Line 378	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.VisitScopeTree(Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope treeRoot, System.Action<Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope> action) Line 226	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.VisitScopeTree(Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope treeRoot, System.Action<Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope> action) Line 226	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.VisitScopeTree(Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope treeRoot, System.Action<Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Analysis.Scope> action) Line 226	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.LambdaRewriter.SynthesizeClosureEnvironments(Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<Microsoft.CodeAnalysis.CodeGen.ClosureDebugInfo> closureDebugInfo) Line 409	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.LambdaRewriter.Rewrite(Microsoft.CodeAnalysis.CSharp.BoundStatement loweredBody, Microsoft.CodeAnalysis.CSharp.Symbols.NamedTypeSymbol thisType, Microsoft.CodeAnalysis.CSharp.Symbols.ParameterSymbol thisParameter, Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol method, int methodOrdinal, Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol substitutedSourceMethod, Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<Microsoft.CodeAnalysis.CodeGen.LambdaDebugInfo> lambdaDebugInfoBuilder, Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<Microsoft.CodeAnalysis.CodeGen.ClosureDebugInfo> closureDebugInfoBuilder, Microsoft.CodeAnalysis.CodeGen.VariableSlotAllocator slotAllocatorOpt, Microsoft.CodeAnalysis.CSharp.TypeCompilationState compilationState, Microsoft.CodeAnalysis.DiagnosticBag diagnostics, System.Collections.Generic.HashSet<Microsoft.CodeAnalysis.CSharp.Symbols.LocalSymbol> assignLocals) Line 275	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.MethodCompiler.LowerBodyOrInitializer(Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol method, int methodOrdinal, Microsoft.CodeAnalysis.CSharp.BoundStatement body, Microsoft.CodeAnalysis.CSharp.SynthesizedSubmissionFields previousSubmissionFields, Microsoft.CodeAnalysis.CSharp.TypeCompilationState compilationState, bool instrumentForDynamicAnalysis, Microsoft.CodeAnalysis.CodeGen.DebugDocumentProvider debugDocumentProvider, ref System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.CodeGen.SourceSpan> dynamicAnalysisSpans, Microsoft.CodeAnalysis.DiagnosticBag diagnostics, ref Microsoft.CodeAnalysis.CodeGen.VariableSlotAllocator lazyVariableSlotAllocator, Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<Microsoft.CodeAnalysis.CodeGen.LambdaDebugInfo> lambdaDebugInfoBuilder, Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder<Microsoft.CodeAnalysis.CodeGen.ClosureDebugInfo> closureDebugInfoBuilder, out Microsoft.CodeAnalysis.CSharp.StateMachineTypeSymbol stateMachineTypeOpt) Line 1284	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethod(Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol methodSymbol, int methodOrdinal, ref Microsoft.CodeAnalysis.CSharp.Binder.ProcessedFieldInitializers processedInitializers, Microsoft.CodeAnalysis.CSharp.SynthesizedSubmissionFields previousSubmissionFields, Microsoft.CodeAnalysis.CSharp.TypeCompilationState compilationState) Line 1062	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedType(Microsoft.CodeAnalysis.CSharp.Symbols.NamedTypeSymbol containingType) Line 497	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.CSharp.dll!Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedTypeAsTask.AnonymousMethod__0() Line 384	C#	Symbols loaded.
 	Microsoft.CodeAnalysis.dll!Roslyn.Utilities.UICultureUtilities.WithCurrentUICulture.AnonymousMethod__0() Line 138	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke() Line 2884	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.Tasks.Task.Execute() Line 2498	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj) Line 2861	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 954	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Line 902	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot) Line 2827	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Line 2767	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Line 2704	C#	Symbols loaded.
 	mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch() Line 820	C#	Symbols loaded.
 	mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Line 1161	C#	Symbols loaded.

Crash dump: %internal_share%\public\tomat\Bugs\LambdaCrash

@tmat
Copy link
Member Author

tmat commented Aug 15, 2017

FYI @dotnet/roslyn-infrastructure

@tmat tmat added this to the 15.5 milestone Aug 15, 2017
agocke added a commit that referenced this issue Aug 15, 2017
In the introduction of the new 'this' optimization routine,
one of the things which was changed was to treat 'this' more
like a formal parameter of the method, as opposed to a variable
living in an implicit, higher scope. This has some advantages
in simplicity for analysis, but created a problem when it came
to proxies. The current analysis builds the proxy list by walking
the tree and finding all captured variables and adding them
to the proxy dictionary keyed by the original variable symbol.
For instance, if a local variable is captured to a field, during
rewriting it will be added to the proxy list as (original symbol,
hoisted field). Since most symbols are only ever captured to a
single replacement field, this usually works fine -- all proxies
can exist side-by-side in the proxy list since there is no intersection.

However, this is not true for captured environment pointers. When
a new environment is introduced, a local will be created to point
to that environment. That local may itself be captured by nested
variables, creating a linked list from nested scopes to parent scope.
Most notably, *multiple* nested environments may capture the *same*
environment pointer in *different* hoisted fields. This means that
the proxies dictionary cannot hold all mappings at once, since the
mapping for a given captured environment pointer will depend on the
current scope.

The current code actually accounts for this already by adding a
captured environment pointer to the proxy list on a nested scope's
introduction, and removing it upon leaving that scope.

By changing 'this' to be treated like a formal parameter, I
circumvented this logic, introducing a bug. When two scopes tried
to capture the 'this' pointer, the compiler crashed due to trying
to add two mappings to the same key.

This change fixes this problem by treating the 'this' parameter
like an environment pointer for the purposes of capturing and
hoisting. It's possible that we want to treat it like a formal
parameter, but if so it's probably better to treat all captured
environment pointers the same way and introduce a scope-aware
notion of proxies, rather than having a global dictionary.

Fixes #21506
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants