From c8229df673acaa099a5257ba2a7221cd18792a22 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Wed, 17 Jun 2020 18:52:48 +0100 Subject: [PATCH 1/2] Create AsyncMB prior to storing params to skip double zero init --- .../AsyncRewriter.AsyncIteratorRewriter.cs | 21 ++++++++++++++----- .../Lowering/AsyncRewriter/AsyncRewriter.cs | 5 ++++- .../IteratorRewriter/IteratorRewriter.cs | 14 +++++++++++-- .../StateMachineRewriter.cs | 18 +++++++++++----- 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs index 7d4cac57cc923..fd8d8c1e02edb 100644 --- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.AsyncIteratorRewriter.cs @@ -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; @@ -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.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(); @@ -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())); @@ -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 proxies) { + var bodyBuilder = ArrayBuilder.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()); } /// diff --git a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs index 934fe0289428b..12e0fd9a73d98 100644 --- a/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/AsyncRewriter/AsyncRewriter.cs @@ -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; @@ -193,7 +194,7 @@ protected override void InitializeStateMachine(ArrayBuilder body } } - protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType) + protected override BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary proxies) { // If the async method's result type is a type parameter of the method, then the AsyncTaskMethodBuilder // needs to use the method's type parameters inside the rewritten method body. All other methods generated @@ -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( diff --git a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs index 46fc1c22aee65..843020502866e 100644 --- a/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/IteratorRewriter/IteratorRewriter.cs @@ -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; @@ -289,9 +290,18 @@ protected override void InitializeStateMachine(ArrayBuilder 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 proxies) { - return F.Return(F.Local(stateMachineVariable)); + var bodyBuilder = ArrayBuilder.GetInstance(); + + bodyBuilder.Add(GenerateParameterStorage(stateMachineVariable, proxies)); + + // return local; + bodyBuilder.Add( + F.Return( + F.Local(stateMachineVariable))); + + return F.Block(bodyBuilder.ToImmutableAndFree()); } private void GenerateMoveNextAndDispose( diff --git a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs index 9acb7f050d68b..26bc1a598aba6 100644 --- a/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/StateMachineRewriter/StateMachineRewriter.cs @@ -75,7 +75,7 @@ protected StateMachineRewriter( /// /// Generate implementation-specific state machine initialization for the kickoff method body. /// - protected abstract BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType); + protected abstract BoundStatement GenerateStateMachineCreation(LocalSymbol stateMachineVariable, NamedTypeSymbol frameType, IReadOnlyDictionary proxies); /// /// Generate implementation-specific state machine member method implementations. @@ -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 proxies) + { + var bodyBuilder = ArrayBuilder.GetInstance(); + // starting with the "this" proxy if (!method.IsStatic) { @@ -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( From 2dcaf88f5f23b4258e9dfe312ca49e06b488babf Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Wed, 17 Jun 2020 20:19:05 +0100 Subject: [PATCH 2/2] Fix tests --- .../Emit/CodeGen/CodeGenAsyncIteratorTests.cs | 28 +++++++++---------- .../Test/Emit/CodeGen/CodeGenAsyncTests.cs | 10 +++---- .../CodeGenDisplayClassOptimisationTests.cs | 10 +++---- .../Test/Emit/CodeGen/CodeGenScriptTests.cs | 20 ++++++------- .../EditAndContinue/LocalSlotMappingTests.cs | 20 ++++++------- .../BindingAsyncTasklikeMoreTests.cs | 10 +++---- 6 files changed, 49 insertions(+), 49 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs index 67a383cc41675..9441da7d470f6 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncIteratorTests.cs @@ -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.d__0.<>1__state"" - IL_000e: ldarg.0 - IL_000f: call ""int System.Environment.CurrentManagedThreadId.get"" - IL_0014: stfld ""int C.d__0.<>l__initialThreadId"" + IL_0008: call ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create()"" + IL_000d: stfld ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder"" + IL_0012: ldarg.0 + IL_0013: ldarg.1 + IL_0014: stfld ""int C.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.d__0.<>t__builder"" + IL_001a: call ""int System.Environment.CurrentManagedThreadId.get"" + IL_001f: stfld ""int C.d__0.<>l__initialThreadId"" IL_0024: ret }", sequencePoints: "C+d__0..ctor", source: source); } @@ -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.d__0.<>1__state"" - IL_000d: ldarg.0 - IL_000e: call ""int System.Environment.CurrentManagedThreadId.get"" - IL_0013: stfld ""int C.d__0.<>l__initialThreadId"" + IL_0007: call ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder System.Runtime.CompilerServices.AsyncIteratorMethodBuilder.Create()"" + IL_000c: stfld ""System.Runtime.CompilerServices.AsyncIteratorMethodBuilder C.d__0.<>t__builder"" + IL_0011: ldarg.0 + IL_0012: ldarg.1 + IL_0013: stfld ""int C.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.d__0.<>t__builder"" + IL_0019: call ""int System.Environment.CurrentManagedThreadId.get"" + IL_001e: stfld ""int C.d__0.<>l__initialThreadId"" IL_0023: ret }", sequencePoints: "C+d__0..ctor", source: source); } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs index 2f95f663db0c6..efca6b5224321 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAsyncTests.cs @@ -2575,11 +2575,11 @@ public static void Main() .maxstack 2 .locals init (Test.d__1 V_0) IL_0000: ldloca.s V_0 - IL_0002: ldarg.0 - IL_0003: stfld ""System.Threading.AutoResetEvent Test.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.d__1.<>t__builder"" + IL_0002: call ""System.Runtime.CompilerServices.AsyncVoidMethodBuilder System.Runtime.CompilerServices.AsyncVoidMethodBuilder.Create()"" + IL_0007: stfld ""System.Runtime.CompilerServices.AsyncVoidMethodBuilder Test.d__1.<>t__builder"" + IL_000c: ldloca.s V_0 + IL_000e: ldarg.0 + IL_000f: stfld ""System.Threading.AutoResetEvent Test.d__1.handle"" IL_0014: ldloca.s V_0 IL_0016: ldc.i4.m1 IL_0017: stfld ""int Test.d__1.<>1__state"" diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDisplayClassOptimisationTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDisplayClassOptimisationTests.cs index 3090941e501c3..3f35ada855609 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDisplayClassOptimisationTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenDisplayClassOptimisationTests.cs @@ -1678,11 +1678,11 @@ .locals init ( [0] valuetype Program/'d__0' ) IL_0000: ldloca.s 0 - IL_0002: ldarg.0 - IL_0003: stfld class C Program/'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/'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/'d__0'::'<>t__builder' + IL_000c: ldloca.s 0 + IL_000e: ldarg.0 + IL_000f: stfld class C Program/'d__0'::enumerable IL_0014: ldloca.s 0 IL_0016: ldc.i4.m1 IL_0017: stfld int32 Program/'d__0'::'<>1__state' diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenScriptTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenScriptTests.cs index 53a8f80df5295..2f5da6df95b3d 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenScriptTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenScriptTests.cs @@ -503,11 +503,11 @@ .locals init (<>d__0 V_0) IL_0000: newobj ""<>d__0..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - IL_0007: ldarg.0 - IL_0008: stfld ""Script <>d__0.<>4__this"" - IL_000d: ldloc.0 - IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" - IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder <>d__0.<>t__builder"" + IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" + IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder <>d__0.<>t__builder"" + IL_0011: ldloc.0 + IL_0012: ldarg.0 + IL_0013: stfld ""Script <>d__0.<>4__this"" IL_0018: ldloc.0 IL_0019: ldc.i4.m1 IL_001a: stfld ""int <>d__0.<>1__state"" @@ -563,11 +563,11 @@ .locals init (<>d__0 V_0) IL_0000: newobj ""<>d__0..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - IL_0007: ldarg.0 - IL_0008: stfld ""Script <>d__0.<>4__this"" - IL_000d: ldloc.0 - IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" - IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder <>d__0.<>t__builder"" + IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" + IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder <>d__0.<>t__builder"" + IL_0011: ldloc.0 + IL_0012: ldarg.0 + IL_0013: stfld ""Script <>d__0.<>4__this"" IL_0018: ldloc.0 IL_0019: ldc.i4.m1 IL_001a: stfld ""int <>d__0.<>1__state"" diff --git a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs index 0c57a9b32ee39..2ffede5d60a5c 100644 --- a/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs +++ b/src/Compilers/CSharp/Test/Emit/Emit/EditAndContinue/LocalSlotMappingTests.cs @@ -4232,11 +4232,11 @@ .locals init (C.d__0 V_0) ~IL_0000: newobj ""C.d__0..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - ~IL_0007: ldarg.0 - IL_0008: stfld ""object C.d__0.o"" - IL_000d: ldloc.0 - IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" - IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" + ~IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" + IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" + IL_0011: ldloc.0 + IL_0012: ldarg.0 + IL_0013: stfld ""object C.d__0.o"" IL_0018: ldloc.0 -IL_0019: ldc.i4.m1 -IL_001a: stfld ""int C.d__0.<>1__state"" @@ -4292,11 +4292,11 @@ .locals init (C.d__0 V_0) ~IL_0000: newobj ""C.d__0..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - ~IL_0007: ldarg.0 - IL_0008: stfld ""System.Threading.Tasks.Task C.d__0.o"" - IL_000d: ldloc.0 - -IL_000e: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" - IL_0013: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" + ~IL_0007: call ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create()"" + IL_000c: stfld ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.d__0.<>t__builder"" + IL_0011: ldloc.0 + IL_0012: ldarg.0 + IL_0013: stfld ""System.Threading.Tasks.Task C.d__0.o"" IL_0018: ldloc.0 IL_0019: ldc.i4.m1 IL_001a: stfld ""int C.d__0.<>1__state"" diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs index b6159e8476e37..1e89c27bfeba2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/BindingAsyncTasklikeMoreTests.cs @@ -141,11 +141,11 @@ .locals init (C.d__1 V_0) IL_0000: newobj ""C.d__1..ctor()"" IL_0005: stloc.0 IL_0006: ldloc.0 - IL_0007: ldarg.0 - IL_0008: stfld ""T C.d__1.t"" - IL_000d: ldloc.0 - IL_000e: call ""MyTaskMethodBuilder MyTaskMethodBuilder.Create()"" - IL_0013: stfld ""MyTaskMethodBuilder C.d__1.<>t__builder"" + IL_0007: call ""MyTaskMethodBuilder MyTaskMethodBuilder.Create()"" + IL_000c: stfld ""MyTaskMethodBuilder C.d__1.<>t__builder"" + IL_0011: ldloc.0 + IL_0012: ldarg.0 + IL_0013: stfld ""T C.d__1.t"" IL_0018: ldloc.0 IL_0019: ldc.i4.m1 IL_001a: stfld ""int C.d__1.<>1__state""