Skip to content

Commit

Permalink
Emit state machine suspension points info
Browse files Browse the repository at this point in the history
  • Loading branch information
tmat committed May 21, 2022
1 parent 59a05a5 commit 86bcdcb
Show file tree
Hide file tree
Showing 68 changed files with 3,949 additions and 835 deletions.
32 changes: 24 additions & 8 deletions src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
VariableSlotAllocator lazyVariableSlotAllocator = null;
var lambdaDebugInfoBuilder = ArrayBuilder<LambdaDebugInfo>.GetInstance();
var closureDebugInfoBuilder = ArrayBuilder<ClosureDebugInfo>.GetInstance();
var stateMachineStateDebugInfoBuilder = ArrayBuilder<StateMachineStateDebugInfo>.GetInstance();
StateMachineTypeSymbol stateMachineTypeOpt = null;
const int methodOrdinal = -1;

Expand All @@ -280,16 +281,19 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder,
closureDebugInfoBuilder,
stateMachineStateDebugInfoBuilder,
out stateMachineTypeOpt);

Debug.Assert((object)lazyVariableSlotAllocator == null);
Debug.Assert((object)stateMachineTypeOpt == null);
Debug.Assert(dynamicAnalysisSpans.IsEmpty);
Debug.Assert(lambdaDebugInfoBuilder.IsEmpty());
Debug.Assert(closureDebugInfoBuilder.IsEmpty());
Debug.Assert(stateMachineStateDebugInfoBuilder.IsEmpty());

lambdaDebugInfoBuilder.Free();
closureDebugInfoBuilder.Free();
stateMachineStateDebugInfoBuilder.Free();

if (emitMethodBodies)
{
Expand All @@ -300,6 +304,7 @@ private static MethodSymbol GetEntryPoint(CSharpCompilation compilation, PEModul
loweredBody,
ImmutableArray<LambdaDebugInfo>.Empty,
ImmutableArray<ClosureDebugInfo>.Empty,
ImmutableArray<StateMachineStateDebugInfo>.Empty,
stateMachineTypeOpt: null,
variableSlotAllocatorOpt: null,
diagnostics: diagnostics,
Expand Down Expand Up @@ -698,6 +703,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
return;
}

var stateMachineStateDebugInfoBuilder = ArrayBuilder<StateMachineStateDebugInfo>.GetInstance();
var oldImportChain = compilationState.CurrentImportChain;
try
{
Expand Down Expand Up @@ -727,13 +733,13 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
{
// Local functions can be iterators as well as be async (lambdas can only be async), so we need to lower both iterators and async
IteratorStateMachine iteratorStateMachine;
BoundStatement loweredBody = IteratorRewriter.Rewrite(methodWithBody.Body, method, methodOrdinal, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out iteratorStateMachine);
BoundStatement loweredBody = IteratorRewriter.Rewrite(methodWithBody.Body, method, methodOrdinal, stateMachineStateDebugInfoBuilder, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out iteratorStateMachine);
StateMachineTypeSymbol stateMachine = iteratorStateMachine;

if (!loweredBody.HasErrors)
{
AsyncStateMachine asyncStateMachine;
loweredBody = AsyncRewriter.Rewrite(loweredBody, method, methodOrdinal, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out asyncStateMachine);
loweredBody = AsyncRewriter.Rewrite(loweredBody, method, methodOrdinal, stateMachineStateDebugInfoBuilder, variableSlotAllocatorOpt, compilationState, diagnosticsThisMethod, out asyncStateMachine);

Debug.Assert((object)iteratorStateMachine == null || (object)asyncStateMachine == null);
stateMachine = stateMachine ?? asyncStateMachine;
Expand All @@ -756,6 +762,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
loweredBody,
ImmutableArray<LambdaDebugInfo>.Empty,
ImmutableArray<ClosureDebugInfo>.Empty,
stateMachineStateDebugInfoBuilder.ToImmutable(),
stateMachine,
variableSlotAllocatorOpt,
diagnosticsThisMethod,
Expand Down Expand Up @@ -789,11 +796,14 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
{
Debug.Assert(emittedBody is null);
}

stateMachineStateDebugInfoBuilder.Clear();
}
}
finally
{
compilationState.CurrentImportChain = oldImportChain;
stateMachineStateDebugInfoBuilder.Free();
}
}

Expand Down Expand Up @@ -873,6 +883,7 @@ private void CompileFieldLikeEventAccessor(SourceEventSymbol eventSymbol, bool i
boundBody,
ImmutableArray<LambdaDebugInfo>.Empty,
ImmutableArray<ClosureDebugInfo>.Empty,
ImmutableArray<StateMachineStateDebugInfo>.Empty,
stateMachineTypeOpt: null,
variableSlotAllocatorOpt: null,
diagnostics: diagnosticsThisMethod,
Expand Down Expand Up @@ -1190,6 +1201,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
StateMachineTypeSymbol stateMachineTypeOpt = null;
var lambdaDebugInfoBuilder = ArrayBuilder<LambdaDebugInfo>.GetInstance();
var closureDebugInfoBuilder = ArrayBuilder<ClosureDebugInfo>.GetInstance();
var stateMachineStateDebugInfoBuilder = ArrayBuilder<StateMachineStateDebugInfo>.GetInstance();
BoundStatement loweredBodyOpt = null;

try
Expand All @@ -1209,6 +1221,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder,
closureDebugInfoBuilder,
stateMachineStateDebugInfoBuilder,
out stateMachineTypeOpt);

Debug.Assert(loweredBodyOpt != null);
Expand Down Expand Up @@ -1261,6 +1274,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
ref lazyVariableSlotAllocator,
lambdaDebugInfoBuilder,
closureDebugInfoBuilder,
stateMachineStateDebugInfoBuilder,
out initializerStateMachineTypeOpt);

processedInitializers.LoweredInitializers = lowered;
Expand Down Expand Up @@ -1323,6 +1337,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
boundBody,
lambdaDebugInfoBuilder.ToImmutable(),
closureDebugInfoBuilder.ToImmutable(),
stateMachineStateDebugInfoBuilder.ToImmutable(),
stateMachineTypeOpt,
lazyVariableSlotAllocator,
diagsForCurrentMethod,
Expand All @@ -1343,6 +1358,7 @@ forSemanticModel.Syntax is { } semanticModelSyntax &&
{
lambdaDebugInfoBuilder.Free();
closureDebugInfoBuilder.Free();
stateMachineStateDebugInfoBuilder.Free();
}
}
finally
Expand All @@ -1366,6 +1382,7 @@ internal static BoundStatement LowerBodyOrInitializer(
ref VariableSlotAllocator lazyVariableSlotAllocator,
ArrayBuilder<LambdaDebugInfo> lambdaDebugInfoBuilder,
ArrayBuilder<ClosureDebugInfo> closureDebugInfoBuilder,
ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder,
out StateMachineTypeSymbol stateMachineTypeOpt)
{
Debug.Assert(compilationState.ModuleBuilderOpt != null);
Expand Down Expand Up @@ -1420,10 +1437,7 @@ internal static BoundStatement LowerBodyOrInitializer(
return loweredBody;
}

if (lazyVariableSlotAllocator == null)
{
lazyVariableSlotAllocator = compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method, diagnostics.DiagnosticBag);
}
lazyVariableSlotAllocator ??= compilationState.ModuleBuilderOpt.TryCreateVariableSlotAllocator(method, method, diagnostics.DiagnosticBag);

BoundStatement bodyWithoutLambdas = loweredBody;
if (sawLambdas || sawLocalFunctions)
Expand All @@ -1448,15 +1462,15 @@ internal static BoundStatement LowerBodyOrInitializer(
return bodyWithoutLambdas;
}

BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, methodOrdinal, lazyVariableSlotAllocator, compilationState, diagnostics,
BoundStatement bodyWithoutIterators = IteratorRewriter.Rewrite(bodyWithoutLambdas, method, methodOrdinal, stateMachineStateDebugInfoBuilder, lazyVariableSlotAllocator, compilationState, diagnostics,
out IteratorStateMachine iteratorStateMachine);

if (bodyWithoutIterators.HasErrors)
{
return bodyWithoutIterators;
}

BoundStatement bodyWithoutAsync = AsyncRewriter.Rewrite(bodyWithoutIterators, method, methodOrdinal, lazyVariableSlotAllocator, compilationState, diagnostics,
BoundStatement bodyWithoutAsync = AsyncRewriter.Rewrite(bodyWithoutIterators, method, methodOrdinal, stateMachineStateDebugInfoBuilder, lazyVariableSlotAllocator, compilationState, diagnostics,
out AsyncStateMachine asyncStateMachine);

Debug.Assert((object)iteratorStateMachine == null || (object)asyncStateMachine == null);
Expand All @@ -1481,6 +1495,7 @@ private static MethodBody GenerateMethodBody(
BoundStatement block,
ImmutableArray<LambdaDebugInfo> lambdaDebugInfo,
ImmutableArray<ClosureDebugInfo> closureDebugInfo,
ImmutableArray<StateMachineStateDebugInfo> stateMachineStateDebugInfos,
StateMachineTypeSymbol stateMachineTypeOpt,
VariableSlotAllocator variableSlotAllocatorOpt,
BindingDiagnosticBag diagnostics,
Expand Down Expand Up @@ -1630,6 +1645,7 @@ private static MethodBody GenerateMethodBody(
stateMachineHoistedLocalScopes,
stateMachineHoistedLocalSlots,
stateMachineAwaiterSlots,
StateMachineStatesDebugInfo.Create(variableSlotAllocatorOpt, stateMachineStateDebugInfos),
moveNextBodyDebugInfoOpt,
dynamicAnalysisDataOpt);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,13 @@ internal AsyncIteratorMethodToStateMachineRewriter(MethodSymbol method,
IReadOnlySet<Symbol> hoistedVariables,
IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies,
SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
int nextFreeHoistedLocalSlot,
BindingDiagnosticBag diagnostics)
: base(method, methodOrdinal, asyncMethodBuilderMemberCollection, F,
state, builder, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals,
slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
{
Debug.Assert(asyncIteratorInfo != null);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ internal AsyncMethodToStateMachineRewriter(
IReadOnlySet<Symbol> hoistedVariables,
IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> nonReusableLocalProxies,
SynthesizedLocalOrdinalsDispenser synthesizedLocalOrdinals,
ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
int nextFreeHoistedLocalSlot,
BindingDiagnosticBag diagnostics)
: base(F, method, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
: base(F, method, state, hoistedVariables, nonReusableLocalProxies, synthesizedLocalOrdinals, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, nextFreeHoistedLocalSlot, diagnostics)
{
_method = method;
_asyncMethodBuilderMemberCollection = asyncMethodBuilderMemberCollection;
Expand Down Expand Up @@ -120,6 +121,12 @@ private FieldSymbol GetAwaiterField(TypeSymbol awaiterType)
return result;
}

protected override string EncMissingStateMessage
=> CodeAnalysisResources.EncCannotResumeSuspendedAsyncMethod;

protected override int FirstUnusedResumableState
=> StateMachineStates.FirstUnusedState;

/// <summary>
/// Generate the body for <c>MoveNext()</c>.
/// </summary>
Expand All @@ -143,7 +150,7 @@ internal void GenerateMoveNext(BoundStatement body, MethodSymbol moveNextMethod)
F.Block(ImmutableArray<LocalSymbol>.Empty,
// switch (state) ...
F.HiddenSequencePoint(),
Dispatch(),
Dispatch(isOutermost: true),
// [body]
rewrittenBody
),
Expand Down Expand Up @@ -436,7 +443,7 @@ private BoundExpression GenerateGetIsCompleted(LocalSymbol awaiterTemp, MethodSy

private BoundBlock GenerateAwaitForIncompleteTask(LocalSymbol awaiterTemp)
{
AddState(out int stateNumber, out GeneratedLabelSymbol resumeLabel);
AddResumableState(awaiterTemp.GetDeclaratorSyntax(), out int stateNumber, out GeneratedLabelSymbol resumeLabel);

TypeSymbol awaiterFieldType = awaiterTemp.Type.IsVerifierReference()
? F.SpecialType(SpecialType.System_Object)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,11 @@ internal AsyncIteratorRewriter(
MethodSymbol method,
int methodOrdinal,
AsyncStateMachine stateMachineType,
ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics)
: base(body, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
: base(body, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
{
Debug.Assert(!TypeSymbol.Equals(method.IteratorElementTypeWithAnnotations.Type, null, TypeCompareKind.ConsiderEverything2));

Expand Down Expand Up @@ -697,6 +698,7 @@ protected override void GenerateMoveNext(SynthesizedImplementationMethod moveNex
hoistedVariables: hoistedVariables,
nonReusableLocalProxies: nonReusableLocalProxies,
synthesizedLocalOrdinals: synthesizedLocalOrdinals,
stateMachineStateDebugInfoBuilder,
slotAllocatorOpt: slotAllocatorOpt,
nextFreeHoistedLocalSlot: nextFreeHoistedLocalSlot,
diagnostics: diagnostics);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ private AsyncRewriter(
MethodSymbol method,
int methodOrdinal,
AsyncStateMachine stateMachineType,
ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics)
: base(body, method, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
: base(body, method, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
{
_constructedSuccessfully = AsyncMethodBuilderMemberCollection.TryCreate(F, method, this.stateMachineType.TypeMap, out _asyncMethodBuilderMemberCollection);
_methodOrdinal = methodOrdinal;
Expand All @@ -41,6 +42,7 @@ internal static BoundStatement Rewrite(
BoundStatement bodyWithAwaitLifted,
MethodSymbol method,
int methodOrdinal,
ArrayBuilder<StateMachineStateDebugInfo> stateMachineStateDebugInfoBuilder,
VariableSlotAllocator slotAllocatorOpt,
TypeCompilationState compilationState,
BindingDiagnosticBag diagnostics,
Expand Down Expand Up @@ -73,8 +75,8 @@ internal static BoundStatement Rewrite(
compilationState.ModuleBuilderOpt.CompilationState.SetStateMachineType(method, stateMachineType);

AsyncRewriter rewriter = isAsyncEnumerableOrEnumerator
? new AsyncIteratorRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics)
: new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, slotAllocatorOpt, compilationState, diagnostics);
? new AsyncIteratorRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics)
: new AsyncRewriter(bodyWithAwaitLifted, method, methodOrdinal, stateMachineType, stateMachineStateDebugInfoBuilder, slotAllocatorOpt, compilationState, diagnostics);

if (!rewriter.VerifyPresenceOfRequiredAPIs())
{
Expand Down Expand Up @@ -265,6 +267,7 @@ protected virtual void GenerateMoveNext(SynthesizedImplementationMethod moveNext
hoistedVariables: hoistedVariables,
nonReusableLocalProxies: nonReusableLocalProxies,
synthesizedLocalOrdinals: synthesizedLocalOrdinals,
stateMachineStateDebugInfoBuilder,
slotAllocatorOpt: slotAllocatorOpt,
nextFreeHoistedLocalSlot: nextFreeHoistedLocalSlot,
diagnostics: diagnostics);
Expand Down
Loading

0 comments on commit 86bcdcb

Please sign in to comment.