This repository has been archived by the owner on Jan 23, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Reduce Execution Context Save+Restore (dotnet/coreclr#15629)
* Reduce Save+Restore for ExecutionContext * Use flag rather than comparison to static * Skip null check for pre-checked EC.Run * Feedback * Add static helper lookup for default context for TP * Add note for enregistering * Return to Default context when no values * Default + FlowSuppressed Context * Move AsyncMethodBuilder.Start to static non-generic * Feedback Signed-off-by: dotnet-bot-corefx-mirror <[email protected]>
- Loading branch information
1 parent
54d3e65
commit 072b288
Showing
5 changed files
with
268 additions
and
102 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 68 additions & 0 deletions
68
src/Common/src/CoreLib/System/Runtime/CompilerServices/AsyncMethodBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// 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; | ||
using System.Diagnostics; | ||
using System.Threading; | ||
|
||
namespace System.Runtime.CompilerServices | ||
{ | ||
internal static partial class AsyncMethodBuilder | ||
{ | ||
/// <summary>Initiates the builder's execution with the associated state machine.</summary> | ||
/// <typeparam name="TStateMachine">Specifies the type of the state machine.</typeparam> | ||
/// <param name="stateMachine">The state machine instance, passed by reference.</param> | ||
[DebuggerStepThrough] | ||
public static void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine | ||
{ | ||
if (stateMachine == null) // TStateMachines are generally non-nullable value types, so this check will be elided | ||
{ | ||
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.stateMachine); | ||
} | ||
|
||
// enregistrer variables with 0 post-fix so they can be used in registers without EH forcing them to stack | ||
// Capture references to Thread Contexts | ||
Thread currentThread0 = Thread.CurrentThread; | ||
Thread currentThread = currentThread0; | ||
ExecutionContext previousExecutionCtx0 = currentThread0.ExecutionContext; | ||
|
||
// Store current ExecutionContext and SynchronizationContext as "previousXxx". | ||
// This allows us to restore them and undo any Context changes made in stateMachine.MoveNext | ||
// so that they won't "leak" out of the first await. | ||
ExecutionContext previousExecutionCtx = previousExecutionCtx0; | ||
SynchronizationContext previousSyncCtx = currentThread0.SynchronizationContext; | ||
|
||
try | ||
{ | ||
stateMachine.MoveNext(); | ||
} | ||
finally | ||
{ | ||
// Re-enregistrer variables post EH with 1 post-fix so they can be used in registers rather than from stack | ||
SynchronizationContext previousSyncCtx1 = previousSyncCtx; | ||
Thread currentThread1 = currentThread; | ||
// The common case is that these have not changed, so avoid the cost of a write barrier if not needed. | ||
if (previousSyncCtx1 != currentThread1.SynchronizationContext) | ||
{ | ||
// Restore changed SynchronizationContext back to previous | ||
currentThread1.SynchronizationContext = previousSyncCtx1; | ||
} | ||
|
||
ExecutionContext previousExecutionCtx1 = previousExecutionCtx; | ||
ExecutionContext currentExecutionCtx1 = currentThread1.ExecutionContext; | ||
if (previousExecutionCtx1 != currentExecutionCtx1) | ||
{ | ||
// Restore changed ExecutionContext back to previous | ||
currentThread1.ExecutionContext = previousExecutionCtx1; | ||
if ((currentExecutionCtx1 != null && currentExecutionCtx1.HasChangeNotifications) || | ||
(previousExecutionCtx1 != null && previousExecutionCtx1.HasChangeNotifications)) | ||
{ | ||
// There are change notifications; trigger any affected | ||
ExecutionContext.OnValuesChanged(currentExecutionCtx1, previousExecutionCtx1); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.