From 88342e51daeb2b284964ec9e2e2a8a3910fa5c66 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Tue, 8 Jan 2019 11:10:09 +0000 Subject: [PATCH 1/2] Fast-path GetStateMachineBox --- .../Runtime/CompilerServices/AsyncMethodBuilder.cs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index a4c0f7907449..ce5b20b5c391 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -445,6 +445,18 @@ private IAsyncStateMachineBox GetStateMachineBox( return stronglyTypedBox; } + // We haven't created the IAsyncStateMachineBox yet, create it + return CreateStateMachineBox(ref stateMachine, currentContext); + } + + /// Creates the "boxed" state machine object. + /// Specifies the type of the async state machine. + /// The state machine. + /// The current to initialize the state machine with. + /// The "boxed" state machine. + private IAsyncStateMachineBox CreateStateMachineBox(ref TStateMachine stateMachine, + ExecutionContext currentContext) where TStateMachine : IAsyncStateMachine + { // The least common case: we have a weakly-typed boxed. This results if the debugger // or some other use of reflection accesses a property like ObjectIdForDebugger or a // method like SetNotificationForWaitCompletion prior to the first await happening. In @@ -479,7 +491,7 @@ private IAsyncStateMachineBox GetStateMachineBox( // At this point, m_task should really be null, in which case we want to create the box. // However, in a variety of debugger-related (erroneous) situations, it might be non-null, - // e.g. if the Task property is examined in a Watch window, forcing it to be lazily-intialized + // e.g. if the Task property is examined in a Watch window, forcing it to be lazily-initialized // as a Task rather than as an AsyncStateMachineBox. The worst that happens in such // cases is we lose the ability to properly step in the debugger, as the debugger uses that // object's identity to track this specific builder/state machine. As such, we proceed to From 4d6677120a4edc3e7e42af94a3d077bb1de228c2 Mon Sep 17 00:00:00 2001 From: Ben Adams Date: Tue, 8 Jan 2019 12:14:42 +0000 Subject: [PATCH 2/2] Be explicit about what is happening --- .../src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index ce5b20b5c391..c7f45798999c 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -425,6 +425,7 @@ public void AwaitUnsafeOnCompleted( /// Specifies the type of the async state machine. /// The state machine. /// The "boxed" state machine. + [MethodImpl(MethodImplOptions.AggressiveInlining)] private IAsyncStateMachineBox GetStateMachineBox( ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine @@ -454,6 +455,7 @@ private IAsyncStateMachineBox GetStateMachineBox( /// The state machine. /// The current to initialize the state machine with. /// The "boxed" state machine. + [MethodImpl(MethodImplOptions.NoInlining)] private IAsyncStateMachineBox CreateStateMachineBox(ref TStateMachine stateMachine, ExecutionContext currentContext) where TStateMachine : IAsyncStateMachine {