Skip to content

Commit

Permalink
Merge pull request dotnet#45262 from benaadams/async-zero-init
Browse files Browse the repository at this point in the history
Call AsyncXMethodBuilder.Create prior to storing fields to elide double zeroing
  • Loading branch information
jaredpar authored Jun 29, 2020
2 parents 859ec6f + 2dcaf88 commit db87fbd
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
Expand Down Expand Up @@ -149,15 +150,19 @@ protected override void GenerateConstructor()
// Produces:
// .ctor(int state)
// {
// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
// this.state = state;
// this.initialThreadId = {managedThreadId};
// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
// }
Debug.Assert(stateMachineType.Constructor is IteratorConstructor);

F.CurrentFunction = stateMachineType.Constructor;
var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance();
bodyBuilder.Add(F.BaseInitialization());

// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
bodyBuilder.Add(GenerateCreateAndAssignBuilder());

bodyBuilder.Add(F.Assignment(F.InstanceField(stateField), F.Parameter(F.CurrentFunction.Parameters[0]))); // this.state = state;

var managedThreadId = MakeCurrentThreadId();
Expand All @@ -167,8 +172,6 @@ protected override void GenerateConstructor()
bodyBuilder.Add(F.Assignment(F.InstanceField(initialThreadIdField), managedThreadId));
}

// this.builder = System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create();
bodyBuilder.Add(GenerateCreateAndAssignBuilder());

bodyBuilder.Add(F.Return());
F.CloseMethod(F.Block(bodyBuilder.ToImmutableAndFree()));
Expand Down Expand Up @@ -248,10 +251,18 @@ protected override BoundStatement InitializeParameterField(MethodSymbol getEnume
return result;
}

protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType)
protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies)
{
var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance();

bodyBuilder.Add(GenerateParameterStorage(stateMachineVariable, proxies));

// return local;
return F.Block(F.Return(F.Local(stateMachineVariable)));
bodyBuilder.Add(
F.Return(
F.Local(stateMachineVariable)));

return F.Block(bodyBuilder.ToImmutableAndFree());
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Symbols;
Expand Down Expand Up @@ -193,7 +194,7 @@ protected override void InitializeStateMachine(ArrayBuilder<BoundStatement> body
}
}

protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType)
protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies)
{
// If the async method's result type is a type parameter of the method, then the AsyncTaskMethodBuilder<T>
// needs to use the method's type parameters inside the rewritten method body. All other methods generated
Expand All @@ -215,6 +216,8 @@ protected override BoundStatement GenerateStateMachineCreation(LocalSymbol state
null,
methodScopeAsyncMethodBuilderMemberCollection.CreateBuilder)));

bodyBuilder.Add(GenerateParameterStorage(stateMachineVariable, proxies));

// local.$stateField = NotStartedStateMachine
bodyBuilder.Add(
F.Assignment(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CodeGen;
Expand Down Expand Up @@ -289,9 +290,18 @@ protected override void InitializeStateMachine(ArrayBuilder<BoundStatement> body
F.New(stateMachineType.Constructor.AsMember(frameType), F.Literal(initialState))));
}

protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType)
protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies)
{
return F.Return(F.Local(stateMachineVariable));
var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance();

bodyBuilder.Add(GenerateParameterStorage(stateMachineVariable, proxies));

// return local;
bodyBuilder.Add(
F.Return(
F.Local(stateMachineVariable)));

return F.Block(bodyBuilder.ToImmutableAndFree());
}

private void GenerateMoveNextAndDispose(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ protected StateMachineRewriter(
/// <summary>
/// Generate implementation-specific state machine initialization for the kickoff method body.
/// </summary>
protected abstract BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType);
protected abstract BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies);

/// <summary>
/// Generate implementation-specific state machine member method implementations.
Expand Down Expand Up @@ -283,6 +283,17 @@ private BoundStatement GenerateKickoffMethodBody()
// plus code to initialize all of the parameter proxies result.proxy
var proxies = PreserveInitialParameterValuesAndThreadId ? initialParameters : nonReusableLocalProxies;

bodyBuilder.Add(GenerateStateMachineCreation(stateMachineVariable, frameType, proxies));

return F.Block(
ImmutableArray.Create(stateMachineVariable),
bodyBuilder.ToImmutableAndFree());
}

protected BoundStatement GenerateParameterStorage(LocalSymbol stateMachineVariable, IReadOnlyDictionary<Symbol, CapturedSymbolReplacement> proxies)
{
var bodyBuilder = ArrayBuilder<BoundStatement>.GetInstance();

// starting with the "this" proxy
if (!method.IsStatic)
{
Expand All @@ -305,10 +316,7 @@ private BoundStatement GenerateKickoffMethodBody()
}
}

bodyBuilder.Add(GenerateStateMachineCreation(stateMachineVariable, frameType));
return F.Block(
ImmutableArray.Create(stateMachineVariable),
bodyBuilder.ToImmutableAndFree());
return F.Block(bodyBuilder.ToImmutableAndFree());
}

protected SynthesizedImplementationMethod OpenMethodImplementation(
Expand Down
28 changes: 14 additions & 14 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2371,14 +2371,14 @@ .maxstack 2
IL_0001: call ""object..ctor()""
IL_0006: nop
IL_0007: ldarg.0
IL_0008: ldarg.1
IL_0009: stfld ""int C.<M>d__0.<>1__state""
IL_000e: ldarg.0
IL_000f: call ""int System.Environment.CurrentManagedThreadId.get""
IL_0014: stfld ""int C.<M>d__0.<>l__initialThreadId""
IL_0008: call ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create()""
IL_000d: stfld ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_0012: ldarg.0
IL_0013: ldarg.1
IL_0014: stfld ""int C.<M>d__0.<>1__state""
IL_0019: ldarg.0
IL_001a: call ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create()""
IL_001f: stfld ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_001a: call ""int System.Environment.CurrentManagedThreadId.get""
IL_001f: stfld ""int C.<M>d__0.<>l__initialThreadId""
IL_0024: ret
}", sequencePoints: "C+<M>d__0..ctor", source: source);
}
Expand All @@ -2391,14 +2391,14 @@ .maxstack 2
IL_0000: ldarg.0
IL_0001: call ""object..ctor()""
IL_0006: ldarg.0
IL_0007: ldarg.1
IL_0008: stfld ""int C.<M>d__0.<>1__state""
IL_000d: ldarg.0
IL_000e: call ""int System.Environment.CurrentManagedThreadId.get""
IL_0013: stfld ""int C.<M>d__0.<>l__initialThreadId""
IL_0007: call ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create()""
IL_000c: stfld ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_0011: ldarg.0
IL_0012: ldarg.1
IL_0013: stfld ""int C.<M>d__0.<>1__state""
IL_0018: ldarg.0
IL_0019: call ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create()""
IL_001e: stfld ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.<M>d__0.<>t__builder""
IL_0019: call ""int System.Environment.CurrentManagedThreadId.get""
IL_001e: stfld ""int C.<M>d__0.<>l__initialThreadId""
IL_0023: ret
}", sequencePoints: "C+<M>d__0..ctor", source: source);
}
Expand Down
10 changes: 5 additions & 5 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2575,11 +2575,11 @@ public static void Main()
.maxstack 2
.locals init (Test.<F>d__1 V_0)
IL_0000: ldloca.s V_0
IL_0002: ldarg.0
IL_0003: stfld ""System.Threading.AutoResetEvent Test.<F>d__1.handle""
IL_0008: ldloca.s V_0
IL_000a: call ""System.Runtime.CompilerServices.AsyncVoidMethodBuilder System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create()""
IL_000f: stfld ""System.Runtime.CompilerServices.AsyncVoidMethodBuilder Test.<F>d__1.<>t__builder""
IL_0002: call ""System.Runtime.CompilerServices.AsyncVoidMethodBuilder System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create()""
IL_0007: stfld ""System.Runtime.CompilerServices.AsyncVoidMethodBuilder Test.<F>d__1.<>t__builder""
IL_000c: ldloca.s V_0
IL_000e: ldarg.0
IL_000f: stfld ""System.Threading.AutoResetEvent Test.<F>d__1.handle""
IL_0014: ldloca.s V_0
IL_0016: ldc.i4.m1
IL_0017: stfld ""int Test.<F>d__1.<>1__state""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1678,11 +1678,11 @@ .locals init (
[0] valuetype Program/'<M>d__0'
)
IL_0000: ldloca.s 0
IL_0002: ldarg.0
IL_0003: stfld class C Program/'<M>d__0'::enumerable
IL_0008: ldloca.s 0
IL_000a: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::Create()
IL_000f: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder Program/'<M>d__0'::'<>t__builder'
IL_0002: call valuetype [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder::Create()
IL_0007: stfld valuetype [mscorlib]System.Runtime.CompilerServices.AsyncVoidMethodBuilder Program/'<M>d__0'::'<>t__builder'
IL_000c: ldloca.s 0
IL_000e: ldarg.0
IL_000f: stfld class C Program/'<M>d__0'::enumerable
IL_0014: ldloca.s 0
IL_0016: ldc.i4.m1
IL_0017: stfld int32 Program/'<M>d__0'::'<>1__state'
Expand Down
20 changes: 10 additions & 10 deletions src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenScriptTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -503,11 +503,11 @@ .locals init (<<Initialize>>d__0 V_0)
IL_0000: newobj ""<<Initialize>>d__0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldarg.0
IL_0008: stfld ""Script <<Initialize>>d__0.<>4__this""
IL_000d: ldloc.0
IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> <<Initialize>>d__0.<>t__builder""
IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> <<Initialize>>d__0.<>t__builder""
IL_0011: ldloc.0
IL_0012: ldarg.0
IL_0013: stfld ""Script <<Initialize>>d__0.<>4__this""
IL_0018: ldloc.0
IL_0019: ldc.i4.m1
IL_001a: stfld ""int <<Initialize>>d__0.<>1__state""
Expand Down Expand Up @@ -563,11 +563,11 @@ .locals init (<<Initialize>>d__0 V_0)
IL_0000: newobj ""<<Initialize>>d__0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldarg.0
IL_0008: stfld ""Script <<Initialize>>d__0.<>4__this""
IL_000d: ldloc.0
IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> <<Initialize>>d__0.<>t__builder""
IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> <<Initialize>>d__0.<>t__builder""
IL_0011: ldloc.0
IL_0012: ldarg.0
IL_0013: stfld ""Script <<Initialize>>d__0.<>4__this""
IL_0018: ldloc.0
IL_0019: ldc.i4.m1
IL_001a: stfld ""int <<Initialize>>d__0.<>1__state""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4232,11 +4232,11 @@ .locals init (C.<G>d__0 V_0)
~IL_0000: newobj ""C.<G>d__0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
~IL_0007: ldarg.0
IL_0008: stfld ""object C.<G>d__0.o""
IL_000d: ldloc.0
IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> C.<G>d__0.<>t__builder""
~IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> C.<G>d__0.<>t__builder""
IL_0011: ldloc.0
IL_0012: ldarg.0
IL_0013: stfld ""object C.<G>d__0.o""
IL_0018: ldloc.0
-IL_0019: ldc.i4.m1
-IL_001a: stfld ""int C.<G>d__0.<>1__state""
Expand Down Expand Up @@ -4292,11 +4292,11 @@ .locals init (C.<G>d__0 V_0)
~IL_0000: newobj ""C.<G>d__0..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
~IL_0007: ldarg.0
IL_0008: stfld ""System.Threading.Tasks.Task<object> C.<G>d__0.o""
IL_000d: ldloc.0
-IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> C.<G>d__0.<>t__builder""
~IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object>.Create()""
IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<object> C.<G>d__0.<>t__builder""
IL_0011: ldloc.0
IL_0012: ldarg.0
IL_0013: stfld ""System.Threading.Tasks.Task<object> C.<G>d__0.o""
IL_0018: ldloc.0
IL_0019: ldc.i4.m1
IL_001a: stfld ""int C.<G>d__0.<>1__state""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ .locals init (C.<G>d__1<T> V_0)
IL_0000: newobj ""C.<G>d__1<T>..ctor()""
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldarg.0
IL_0008: stfld ""T C.<G>d__1<T>.t""
IL_000d: ldloc.0
IL_000e: call ""MyTaskMethodBuilder<T> MyTaskMethodBuilder<T>.Create()""
IL_0013: stfld ""MyTaskMethodBuilder<T> C.<G>d__1<T>.<>t__builder""
IL_0007: call ""MyTaskMethodBuilder<T> MyTaskMethodBuilder<T>.Create()""
IL_000c: stfld ""MyTaskMethodBuilder<T> C.<G>d__1<T>.<>t__builder""
IL_0011: ldloc.0
IL_0012: ldarg.0
IL_0013: stfld ""T C.<G>d__1<T>.t""
IL_0018: ldloc.0
IL_0019: ldc.i4.m1
IL_001a: stfld ""int C.<G>d__1<T>.<>1__state""
Expand Down

0 comments on commit db87fbd

Please sign in to comment.