diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs
index 81d9f982c4e7ea..0eeea7e127dfd0 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs
@@ -15,6 +15,42 @@
namespace System.Runtime.CompilerServices
{
+ internal struct ExecutionAndSyncBlockStore
+ {
+ // 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.
+ public ExecutionContext? _previousExecutionCtx;
+ public SynchronizationContext? _previousSyncCtx;
+ public Thread _thread;
+
+ public void Push()
+ {
+ _thread = Thread.CurrentThread;
+ // Here we get the execution context for synchronous restoring,
+ // not for flowing across suspension to potentially another thread.
+ // Therefore we do not need to worry about IsFlowSuppressed
+ _previousExecutionCtx = _thread._executionContext;
+ _previousSyncCtx = _thread._synchronizationContext;
+ }
+
+ public void Pop()
+ {
+ // The common case is that these have not changed, so avoid the cost of a write barrier if not needed.
+ if (_previousSyncCtx != _thread._synchronizationContext)
+ {
+ // Restore changed SynchronizationContext back to previous
+ _thread._synchronizationContext = _previousSyncCtx;
+ }
+
+ ExecutionContext? currentExecutionCtx = _thread._executionContext;
+ if (_previousExecutionCtx != currentExecutionCtx)
+ {
+ ExecutionContext.RestoreChangedContextToThread(_thread, _previousExecutionCtx, currentExecutionCtx);
+ }
+ }
+ }
+
[Flags]
// Keep in sync with CORINFO_CONTINUATION_FLAGS
internal enum ContinuationFlags
@@ -170,13 +206,12 @@ public static partial class AsyncHelpers
[Intrinsic]
private static void TailAwait() => throw new UnreachableException();
- // This is state used by suspension/resumption machinery and stored in
- // the two places that initiate runtime async chains: either a
- // task-returning thunk, or DispatchContinuations. A pointer to this
- // state is kept in the runtime async TLS. This storage method avoids
- // costly write barriers on the hot path of suspension/resumption.
- private ref struct RuntimeAsyncStackState
+ // Used during suspensions to hold the continuation chain and on what we are waiting.
+ // Methods like FinalizeTaskReturningThunk will unlink the state and wrap into a Task.
+ private struct RuntimeAsyncAwaitState
{
+ public Continuation? SentinelContinuation;
+
// The following are the possible introducers of asynchrony into a chain of awaits.
// In other words - when we build a chain of continuations it would be logicaly attached
// to one of these notifiers.
@@ -185,82 +220,17 @@ private ref struct RuntimeAsyncStackState
public ValueTaskSourceNotifier? ValueTaskSourceNotifier;
public Task? TaskNotifier;
- // When we suspend in the leaf, the contexts are captured into these fields.
- public ExecutionContext? LeafExecutionContext;
- public SynchronizationContext? LeafSynchronizationContext;
-
- // When we enter the root of the async chain (either an async thunk
- // or DispatchContinuations), the contexts are captured into these
- // fields.
- public ExecutionContext? RootExecutionContext;
- public SynchronizationContext? RootSynchronizationContext;
-
- public unsafe RuntimeAsyncStackState* Next;
-
- public void Push(Thread thread)
- {
- RootExecutionContext = thread._executionContext;
- RootSynchronizationContext = thread._synchronizationContext;
- }
-
- public void Pop(Thread thread)
- {
- // The common case is that these have not changed, so avoid the cost of a write barrier if not needed.
- if (RootSynchronizationContext != thread._synchronizationContext)
- {
- // Restore changed SynchronizationContext back to previous
- thread._synchronizationContext = RootSynchronizationContext;
- }
-
- ExecutionContext? currentExecutionCtx = thread._executionContext;
- if (RootExecutionContext != currentExecutionCtx)
- {
- ExecutionContext.RestoreChangedContextToThread(thread, RootExecutionContext, currentExecutionCtx);
- }
- }
- }
-
- // Used during suspensions to hold the continuation chain and on what we are waiting.
- // Methods like FinalizeTaskReturningThunk will unlink the state and wrap into a Task.
- private unsafe struct RuntimeAsyncAwaitState
- {
- public Continuation? SentinelContinuation;
-
- // We cache the thread here to avoid unnecessary repeated TLS lookups.
- public Thread CurrentThread;
-
- public RuntimeAsyncStackState* StackState;
+ public ExecutionContext? ExecutionContext;
+ public SynchronizationContext? SynchronizationContext;
public void CaptureContexts()
{
- // CaptureContext is called from leaf await helpers. We either just started a runtime async chain
- // (from a thunk), or we came from DispatchContinuations (on resumption).
- // Both cases have already initialized CurrentThread.
- Thread curThread = CurrentThread;
- Debug.Assert(curThread != null);
- Debug.Assert(StackState != null);
+ Thread curThread = Thread.CurrentThreadAssumedInitialized;
// Here we get the execution context for presenting to the notifier,
// not for flowing across suspension to potentially another thread.
// Therefore we do not need to worry about IsFlowSuppressed
- StackState->LeafExecutionContext = curThread._executionContext;
- StackState->LeafSynchronizationContext = curThread._synchronizationContext;
- }
-
- // At the start of an async chain (task-returning thunk or DispatchContinuations) this function
- // is called
- public void Push(RuntimeAsyncStackState* stackState)
- {
- stackState->Next = StackState;
- StackState = stackState;
- stackState->Push(CurrentThread ??= Thread.CurrentThread);
- }
-
- // This function is called at the end of an async chain
- public void Pop()
- {
- Debug.Assert(CurrentThread != null);
- StackState->Pop(CurrentThread);
- StackState = StackState->Next;
+ ExecutionContext = curThread._executionContext;
+ SynchronizationContext = curThread._synchronizationContext;
}
}
@@ -327,18 +297,20 @@ private static unsafe Continuation AllocContinuationClass(Continuation prevConti
/// Task or a ValueTaskNotifier whose completion we are awaiting.
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
- private static unsafe void TransparentAwait(object o)
+ private static void TransparentAwait(object o)
{
ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
- Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation();
+ Continuation? sentinelContinuation = state.SentinelContinuation;
+ if (sentinelContinuation == null)
+ state.SentinelContinuation = sentinelContinuation = new Continuation();
if (o is Task t)
{
- state.StackState->TaskNotifier = t;
+ state.TaskNotifier = t;
}
else
{
- state.StackState->ValueTaskSourceNotifier = (ValueTaskSourceNotifier)o;
+ state.ValueTaskSourceNotifier = (ValueTaskSourceNotifier)o;
}
state.CaptureContexts();
@@ -371,19 +343,13 @@ void ITaskCompletionAction.Invoke(Task completingTask)
bool ITaskCompletionAction.InvokeMayRunArbitraryCode => true;
- private Action GetContinuationAction()
- {
- object? action = m_action;
- Debug.Assert(action is Action);
- return Unsafe.As(action);
- }
+ private Action GetContinuationAction() => (Action)m_action!;
private Continuation MoveContinuationState()
{
- object? stateObject = m_stateObject;
- Debug.Assert(stateObject is Continuation);
+ Continuation continuation = (Continuation)m_stateObject!;
m_stateObject = null;
- return Unsafe.As(stateObject);
+ return continuation;
}
private void SetContinuationState(Continuation value)
@@ -392,23 +358,23 @@ private void SetContinuationState(Continuation value)
m_stateObject = value;
}
- internal unsafe bool HandleSuspended(ref RuntimeAsyncAwaitState state)
+ internal bool HandleSuspended()
{
- Thread currentThread = state.CurrentThread;
- Debug.Assert(currentThread != null);
+ ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
- RuntimeAsyncStackState* stackState = state.StackState;
- ExecutionContext? suspendingExecutionContext = stackState->LeafExecutionContext;
- SynchronizationContext? suspendingSyncContext = stackState->LeafSynchronizationContext;
- if (suspendingExecutionContext != currentThread._executionContext)
- {
- currentThread._executionContext = suspendingExecutionContext;
- }
+ RestoreContextsOnSuspension(false, state.ExecutionContext, state.SynchronizationContext);
- if (suspendingSyncContext != currentThread._synchronizationContext)
- {
- currentThread._synchronizationContext = suspendingSyncContext;
- }
+ ICriticalNotifyCompletion? critNotifier = state.CriticalNotifier;
+ INotifyCompletion? notifier = state.Notifier;
+ ValueTaskSourceNotifier? vtsNotifier = state.ValueTaskSourceNotifier;
+ Task? taskNotifier = state.TaskNotifier;
+
+ state.CriticalNotifier = null;
+ state.Notifier = null;
+ state.ValueTaskSourceNotifier = null;
+ state.TaskNotifier = null;
+ state.ExecutionContext = null;
+ state.SynchronizationContext = null;
Continuation sentinelContinuation = state.SentinelContinuation!;
Continuation headContinuation = sentinelContinuation.Next!;
@@ -427,11 +393,11 @@ internal unsafe bool HandleSuspended(ref RuntimeAsyncAwaitState state)
try
{
- if (stackState->CriticalNotifier is { } critNotifier)
+ if (critNotifier != null)
{
critNotifier.UnsafeOnCompleted(GetContinuationAction());
}
- else if (stackState->TaskNotifier is { } taskNotifier)
+ else if (taskNotifier != null)
{
// Runtime async callable wrapper for task returning
// method. This implements the context transparent
@@ -441,7 +407,7 @@ internal unsafe bool HandleSuspended(ref RuntimeAsyncAwaitState state)
ThreadPool.UnsafeQueueUserWorkItemInternal(this, preferLocal: true);
}
}
- else if (stackState->ValueTaskSourceNotifier is { } valueTaskSourceNotifier)
+ else if (vtsNotifier != null)
{
// The awaiter must inform the ValueTaskSource on whether the continuation
// wants to run on a context, although the source may decide to ignore the suggestion.
@@ -476,12 +442,12 @@ internal unsafe bool HandleSuspended(ref RuntimeAsyncAwaitState state)
// Clear continuation flags, so that continuation runs transparently
nextUserContinuation.Flags &= ~continueFlags;
- valueTaskSourceNotifier.OnCompleted(s_runContinuationAction, this, configFlags);
+ vtsNotifier.OnCompleted(s_runContinuationAction, this, configFlags);
}
else
{
- Debug.Assert(stackState->Notifier != null);
- stackState->Notifier!.OnCompleted(GetContinuationAction());
+ Debug.Assert(notifier != null);
+ notifier.OnCompleted(GetContinuationAction());
}
return true;
@@ -494,7 +460,7 @@ internal unsafe bool HandleSuspended(ref RuntimeAsyncAwaitState state)
return false;
}
- internal void InstrumentedHandleSuspended(AsyncInstrumentation.Flags flags, ref RuntimeAsyncAwaitState state, Continuation? newContinuation = null)
+ internal void InstrumentedHandleSuspended(AsyncInstrumentation.Flags flags, Continuation? newContinuation = null)
{
if (AsyncInstrumentation.IsEnabled.AsyncDebugger(flags))
{
@@ -502,7 +468,7 @@ internal void InstrumentedHandleSuspended(AsyncInstrumentation.Flags flags, ref
AsyncDebugger.HandleSuspended(nextContinuation, newContinuation);
- if (!HandleSuspended(ref state))
+ if (!HandleSuspended())
{
AsyncDebugger.HandleSuspendedFailed(this, nextContinuation);
}
@@ -510,7 +476,7 @@ internal void InstrumentedHandleSuspended(AsyncInstrumentation.Flags flags, ref
return;
}
- HandleSuspended(ref state);
+ HandleSuspended();
}
#pragma warning disable CA1822 // Mark members as static
@@ -534,17 +500,13 @@ private unsafe void DispatchContinuations()
}
}
- RuntimeAsyncStackState stackState = default;
-
- ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
- awaitState.Push(&stackState);
-
- ref AsyncDispatcherInfo* refDispatcherInfo = ref AsyncDispatcherInfo.t_current;
+ ExecutionAndSyncBlockStore contexts = default;
+ contexts.Push();
AsyncDispatcherInfo asyncDispatcherInfo;
- asyncDispatcherInfo.Next = refDispatcherInfo;
+ asyncDispatcherInfo.Next = AsyncDispatcherInfo.t_current;
asyncDispatcherInfo.NextContinuation = MoveContinuationState();
- refDispatcherInfo = &asyncDispatcherInfo;
+ AsyncDispatcherInfo.t_current = &asyncDispatcherInfo;
while (true)
{
@@ -562,10 +524,10 @@ private unsafe void DispatchContinuations()
if (newContinuation != null)
{
newContinuation.Next = nextContinuation;
- HandleSuspended(ref awaitState);
+ HandleSuspended();
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
return;
}
}
@@ -580,8 +542,9 @@ private unsafe void DispatchContinuations()
TrySetCanceled(oce.CancellationToken, oce) :
TrySetException(ex);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
if (!successfullySet)
{
@@ -599,8 +562,9 @@ private unsafe void DispatchContinuations()
{
bool successfullySet = TrySetResult(m_result);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
if (!successfullySet)
{
@@ -612,8 +576,8 @@ private unsafe void DispatchContinuations()
if (QueueContinuationFollowUpActionIfNecessary(asyncDispatcherInfo.NextContinuation))
{
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
return;
}
@@ -621,8 +585,8 @@ private unsafe void DispatchContinuations()
{
SetContinuationState(asyncDispatcherInfo.NextContinuation);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
InstrumentedDispatchContinuations(AsyncInstrumentation.ActiveFlags);
return;
@@ -633,17 +597,13 @@ private unsafe void DispatchContinuations()
[StackTraceHidden]
private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags flags)
{
- RuntimeAsyncStackState stackState = default;
-
- ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState;
- awaitState.Push(&stackState);
-
- ref AsyncDispatcherInfo* refDispatcherInfo = ref AsyncDispatcherInfo.t_current;
+ ExecutionAndSyncBlockStore contexts = default;
+ contexts.Push();
AsyncDispatcherInfo asyncDispatcherInfo;
- asyncDispatcherInfo.Next = refDispatcherInfo;
+ asyncDispatcherInfo.Next = AsyncDispatcherInfo.t_current;
asyncDispatcherInfo.NextContinuation = MoveContinuationState();
- refDispatcherInfo = &asyncDispatcherInfo;
+ AsyncDispatcherInfo.t_current = &asyncDispatcherInfo;
RuntimeAsyncInstrumentationHelpers.ResumeRuntimeAsyncContext(this, ref asyncDispatcherInfo, flags);
@@ -665,10 +625,10 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags
{
newContinuation.Next = nextContinuation;
RuntimeAsyncInstrumentationHelpers.SuspendRuntimeAsyncContext(flags, curContinuation, newContinuation);
- InstrumentedHandleSuspended(flags, ref awaitState, newContinuation);
+ InstrumentedHandleSuspended(flags, newContinuation);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
return;
}
@@ -687,8 +647,9 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags
TrySetCanceled(oce.CancellationToken, oce) :
TrySetException(ex);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
if (!successfullySet)
{
@@ -710,8 +671,9 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags
bool successfullySet = TrySetResult(m_result);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
if (!successfullySet)
{
@@ -725,8 +687,8 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags
{
RuntimeAsyncInstrumentationHelpers.SuspendRuntimeAsyncContext(ref asyncDispatcherInfo, flags, curContinuation);
- awaitState.Pop();
- refDispatcherInfo = asyncDispatcherInfo.Next;
+ contexts.Pop();
+ AsyncDispatcherInfo.t_current = asyncDispatcherInfo.Next;
return;
}
@@ -833,7 +795,7 @@ private bool QueueContinuationFollowUpActionIfNecessary(Continuation continuatio
};
}
- private static void InstrumentedFinalizeRuntimeAsyncTask(RuntimeAsyncTask task, ref RuntimeAsyncAwaitState state, AsyncInstrumentation.Flags flags)
+ private static void InstrumentedFinalizeRuntimeAsyncTask(RuntimeAsyncTask task, AsyncInstrumentation.Flags flags)
{
if (AsyncInstrumentation.IsEnabled.CreateAsyncContext(flags))
{
@@ -844,54 +806,54 @@ private static void InstrumentedFinalizeRuntimeAsyncTask(RuntimeAsyncTask
}
}
- task.InstrumentedHandleSuspended(flags, ref state);
+ task.InstrumentedHandleSuspended(flags);
return;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static void FinalizeRuntimeAsyncTask(ref RuntimeAsyncAwaitState state, RuntimeAsyncTask task)
+ private static void FinalizeRuntimeAsyncTask(RuntimeAsyncTask task)
{
if (RuntimeAsyncInstrumentationHelpers.InstrumentCheckPoint)
{
AsyncInstrumentation.Flags flags = AsyncInstrumentation.SyncActiveFlags();
if (flags != AsyncInstrumentation.Flags.Disabled)
{
- InstrumentedFinalizeRuntimeAsyncTask(task, ref state, flags);
+ InstrumentedFinalizeRuntimeAsyncTask(task, flags);
return;
}
}
- task.HandleSuspended(ref state);
+ task.HandleSuspended();
}
// Change return type to RuntimeAsyncTask -- no benefit since this is used for Task returning thunks only
#pragma warning disable CA1859
// When a Task-returning thunk gets a continuation result
// it calls here to make a Task that awaits on the current async state.
- private static Task FinalizeTaskReturningThunk(ref RuntimeAsyncAwaitState state)
+ private static Task FinalizeTaskReturningThunk()
{
RuntimeAsyncTask result = new();
- FinalizeRuntimeAsyncTask(ref state, result!);
+ FinalizeRuntimeAsyncTask(result!);
return result;
}
- private static Task FinalizeTaskReturningThunk(ref RuntimeAsyncAwaitState state)
+ private static Task FinalizeTaskReturningThunk()
{
RuntimeAsyncTask result = new();
- FinalizeRuntimeAsyncTask(ref state, result!);
+ FinalizeRuntimeAsyncTask(result!);
return result;
}
- private static ValueTask FinalizeValueTaskReturningThunk(ref RuntimeAsyncAwaitState state)
+ private static ValueTask FinalizeValueTaskReturningThunk()
{
// We only come to these methods in the expensive case (already
// suspended), so ValueTask optimization here is not relevant.
- return new ValueTask(FinalizeTaskReturningThunk(ref state));
+ return new ValueTask(FinalizeTaskReturningThunk());
}
- private static ValueTask FinalizeValueTaskReturningThunk(ref RuntimeAsyncAwaitState state)
+ private static ValueTask FinalizeValueTaskReturningThunk()
{
- return new ValueTask(FinalizeTaskReturningThunk(ref state));
+ return new ValueTask(FinalizeTaskReturningThunk());
}
private static Task TaskFromException(Exception ex)
diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs
index d5f367c6498b0b..2d9891ef57b874 100644
--- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs
+++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs
@@ -38,22 +38,15 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
ILLocalVariable returnTaskLocal = emitter.NewLocal(returnType);
- MetadataType asyncHelpersType = context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8);
- TypeDesc stackStateType = asyncHelpersType.GetKnownNestedType("RuntimeAsyncStackState"u8);
- ILLocalVariable stackStateLocal = emitter.NewLocal(stackStateType);
- TypeDesc awaitStateType = asyncHelpersType.GetKnownNestedType("RuntimeAsyncAwaitState"u8);
- ILLocalVariable refAwaitStateLocal = emitter.NewLocal(awaitStateType.MakeByRefType());
+ TypeDesc executionAndSyncBlockStoreType = context.SystemModule.GetKnownType("System.Runtime.CompilerServices"u8, "ExecutionAndSyncBlockStore"u8);
+ ILLocalVariable executionAndSyncBlockStoreLocal = emitter.NewLocal(executionAndSyncBlockStoreType);
ILCodeLabel returnTaskLabel = emitter.NewCodeLabel();
ILCodeLabel suspendedLabel = emitter.NewCodeLabel();
ILCodeLabel finishedLabel = emitter.NewCodeLabel();
- codestream.Emit(ILOpcode.ldsflda, emitter.NewToken(asyncHelpersType.GetKnownField("t_runtimeAsyncAwaitState"u8)));
- codestream.EmitStLoc(refAwaitStateLocal);
-
- codestream.EmitLdLoc(refAwaitStateLocal);
- codestream.EmitLdLoca(stackStateLocal);
- codestream.Emit(ILOpcode.call, emitter.NewToken(awaitStateType.GetKnownMethod("Push"u8, null)));
+ codestream.EmitLdLoca(executionAndSyncBlockStoreLocal);
+ codestream.Emit(ILOpcode.call, emitter.NewToken(executionAndSyncBlockStoreType.GetKnownMethod("Push"u8, null)));
ILExceptionRegionBuilder tryFinallyRegion = emitter.NewFinallyRegion();
{
@@ -97,7 +90,9 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
codestream.EmitStLoc(logicalResultLocal);
}
- MethodDesc asyncCallContinuationMd = asyncHelpersType.GetKnownMethod("AsyncCallContinuation"u8, null);
+ MethodDesc asyncCallContinuationMd = context.SystemModule
+ .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8)
+ .GetKnownMethod("AsyncCallContinuation"u8, null);
codestream.Emit(ILOpcode.call, emitter.NewToken(asyncCallContinuationMd));
@@ -166,7 +161,8 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
parameters: new[] { exceptionType }
);
- fromExceptionMd = asyncHelpersType
+ fromExceptionMd = context.SystemModule
+ .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8)
.GetKnownMethod(isValueTask ? "ValueTaskFromException"u8 : "TaskFromException"u8, fromExceptionSignature)
.MakeInstantiatedMethod(new Instantiation(logicalReturnType));
}
@@ -179,7 +175,8 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
parameters: new[] { exceptionType }
);
- fromExceptionMd = asyncHelpersType
+ fromExceptionMd = context.SystemModule
+ .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8)
.GetKnownMethod(isValueTask ? "ValueTaskFromException"u8 : "TaskFromException"u8, fromExceptionSignature);
}
@@ -198,10 +195,11 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
MethodSignatureFlags.Static,
genericParameterCount: 1,
returnType: ((MetadataType)returnType.GetTypeDefinition()).MakeInstantiatedType(context.GetSignatureVariable(0, true)),
- parameters: [awaitStateType.MakeByRefType()]
+ parameters: Array.Empty()
);
- finalizeTaskReturningThunkMd = asyncHelpersType
+ finalizeTaskReturningThunkMd = context.SystemModule
+ .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8)
.GetKnownMethod(isValueTask ? "FinalizeValueTaskReturningThunk"u8 : "FinalizeTaskReturningThunk"u8, finalizeReturningThunkSignature)
.MakeInstantiatedMethod(new Instantiation(logicalReturnType));
}
@@ -211,14 +209,14 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
MethodSignatureFlags.Static,
genericParameterCount: 0,
returnType: returnType,
- parameters: [awaitStateType.MakeByRefType()]
+ parameters: Array.Empty()
);
- finalizeTaskReturningThunkMd = asyncHelpersType
+ finalizeTaskReturningThunkMd = context.SystemModule
+ .GetKnownType("System.Runtime.CompilerServices"u8, "AsyncHelpers"u8)
.GetKnownMethod(isValueTask ? "FinalizeValueTaskReturningThunk"u8 : "FinalizeTaskReturningThunk"u8, finalizeReturningThunkSignature);
}
- codestream.EmitLdLoc(refAwaitStateLocal);
codestream.Emit(ILOpcode.call, emitter.NewToken(finalizeTaskReturningThunkMd));
codestream.EmitStLoc(returnTaskLocal);
codestream.Emit(ILOpcode.leave, returnTaskLabel);
@@ -229,8 +227,8 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me
{
codestream.BeginHandler(tryFinallyRegion);
- codestream.EmitLdLoc(refAwaitStateLocal);
- codestream.Emit(ILOpcode.call, emitter.NewToken(awaitStateType.GetKnownMethod("Pop"u8, null)));
+ codestream.EmitLdLoca(executionAndSyncBlockStoreLocal);
+ codestream.Emit(ILOpcode.call, emitter.NewToken(executionAndSyncBlockStoreType.GetKnownMethod("Pop"u8, null)));
codestream.Emit(ILOpcode.endfinally);
codestream.EndHandler(tryFinallyRegion);
}
diff --git a/src/coreclr/vm/asyncthunks.cpp b/src/coreclr/vm/asyncthunks.cpp
index ef45a4a41c715d..3fa631527cf29c 100644
--- a/src/coreclr/vm/asyncthunks.cpp
+++ b/src/coreclr/vm/asyncthunks.cpp
@@ -93,10 +93,8 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig&
// Emits roughly the following code:
//
- // RuntimeAsyncStackState stackState;
- // ref RuntimeAsyncAwaitState awaitState = ref AsyncHelpers.t_runtimeAsyncAwaitState;
- // awaitState.Push(&stackState);
- //
+ // ExecutionAndSyncBlockStore store = default;
+ // store.Push();
// try
// {
// try
@@ -106,7 +104,7 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig&
// if (AsyncHelpers.AsyncCallContinuation() == null)
// return Task.FromResult(result);
//
- // return FinalizeTaskReturningThunk(ref awaitState);
+ // return FinalizeTaskReturningThunk();
// }
// catch (Exception ex)
// {
@@ -115,7 +113,7 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig&
// }
// finally
// {
- // awaitState.Pop();
+ // store.Pop();
// }
ILCodeStream* pCode = pSL->NewCodeStream(ILStubLinker::kDispatch);
@@ -134,24 +132,15 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig&
LocalDesc returnLocalDesc(thTaskRet);
DWORD returnTaskLocal = pCode->NewLocal(returnLocalDesc);
-
- LocalDesc stackStateLocalDesc(TypeHandle(CoreLibBinder::GetClass(CLASS__RUNTIME_ASYNC_STACK_STATE)));
- DWORD stackStateLocal = pCode->NewLocal(stackStateLocalDesc);
-
- LocalDesc refAwaitStateLocalDesc(TypeHandle(CoreLibBinder::GetClass(CLASS__RUNTIME_ASYNC_AWAIT_STATE)));
- refAwaitStateLocalDesc.MakeByRef();
- DWORD refAwaitStateLocal = pCode->NewLocal(refAwaitStateLocalDesc);
+ LocalDesc executionAndSyncBlockStoreLocalDesc(CoreLibBinder::GetClass(CLASS__EXECUTIONANDSYNCBLOCKSTORE));
+ DWORD executionAndSyncBlockStoreLocal = pCode->NewLocal(executionAndSyncBlockStoreLocalDesc);
ILCodeLabel* returnTaskLabel = pCode->NewCodeLabel();
ILCodeLabel* suspendedLabel = pCode->NewCodeLabel();
ILCodeLabel* finishedLabel = pCode->NewCodeLabel();
- pCode->EmitLDSFLDA(pCode->GetToken(CoreLibBinder::GetField(FIELD__ASYNC_HELPERS__TLS_RUNTIME_ASYNC_AWAIT_STATE)));
- pCode->EmitSTLOC(refAwaitStateLocal);
-
- pCode->EmitLDLOC(refAwaitStateLocal);
- pCode->EmitLDLOCA(stackStateLocal);
- pCode->EmitCALL(METHOD__RUNTIME_ASYNC_AWAIT_STATE__PUSH, 2, 0);
+ pCode->EmitLDLOCA(executionAndSyncBlockStoreLocal);
+ pCode->EmitCALL(pCode->GetToken(CoreLibBinder::GetMethod(METHOD__EXECUTIONANDSYNCBLOCKSTORE__PUSH)), 1, 0);
{
pCode->BeginTryBlock();
@@ -263,8 +252,7 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig&
md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK);
finalizeTaskReturningThunkToken = pCode->GetToken(md);
}
- pCode->EmitLDLOC(refAwaitStateLocal);
- pCode->EmitCALL(finalizeTaskReturningThunkToken, 1, 1);
+ pCode->EmitCALL(finalizeTaskReturningThunkToken, 0, 1);
pCode->EmitSTLOC(returnTaskLocal);
pCode->EmitLEAVE(returnTaskLabel);
@@ -273,8 +261,8 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig&
//
{
pCode->BeginFinallyBlock();
- pCode->EmitLDLOC(refAwaitStateLocal);
- pCode->EmitCALL(METHOD__RUNTIME_ASYNC_AWAIT_STATE__POP, 1, 0);
+ pCode->EmitLDLOCA(executionAndSyncBlockStoreLocal);
+ pCode->EmitCALL(pCode->GetToken(CoreLibBinder::GetMethod(METHOD__EXECUTIONANDSYNCBLOCKSTORE__POP)), 1, 0);
pCode->EmitENDFINALLY();
pCode->EndFinallyBlock();
}
diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h
index 674942ce365a61..f75fdcce0c832d 100644
--- a/src/coreclr/vm/corelib.h
+++ b/src/coreclr/vm/corelib.h
@@ -683,6 +683,10 @@ DEFINE_CLASS(RESOURCE_MANAGER, Resources, ResourceManager)
DEFINE_CLASS(RTFIELD, Reflection, RtFieldInfo)
DEFINE_METHOD(RTFIELD, GET_FIELDESC, GetFieldDesc, IM_RetIntPtr)
+DEFINE_CLASS(EXECUTIONANDSYNCBLOCKSTORE, CompilerServices, ExecutionAndSyncBlockStore)
+DEFINE_METHOD(EXECUTIONANDSYNCBLOCKSTORE, PUSH, Push, NoSig)
+DEFINE_METHOD(EXECUTIONANDSYNCBLOCKSTORE, POP, Pop, NoSig)
+
DEFINE_CLASS(RUNTIME_HELPERS, CompilerServices, RuntimeHelpers)
DEFINE_METHOD(RUNTIME_HELPERS, IS_BITWISE_EQUATABLE, IsBitwiseEquatable, NoSig)
DEFINE_METHOD(RUNTIME_HELPERS, GET_RAW_DATA, GetRawData, NoSig)
@@ -707,10 +711,10 @@ DEFINE_METHOD(ASYNC_HELPERS, ALLOC_CONTINUATION, AllocContinuation,
DEFINE_METHOD(ASYNC_HELPERS, ALLOC_CONTINUATION_METHOD, AllocContinuationMethod, NoSig)
DEFINE_METHOD(ASYNC_HELPERS, ALLOC_CONTINUATION_CLASS, AllocContinuationClass, NoSig)
-DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_TASK_RETURNING_THUNK, FinalizeTaskReturningThunk, SM_RefRuntimeAsyncAwaitState_RetTask)
-DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_TASK_RETURNING_THUNK_1, FinalizeTaskReturningThunk, GM_RefRuntimeAsyncAwaitState_RetTaskOfT)
-DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_VALUETASK_RETURNING_THUNK, FinalizeValueTaskReturningThunk, SM_RefRuntimeAsyncAwaitState_RetValueTask)
-DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_VALUETASK_RETURNING_THUNK_1, FinalizeValueTaskReturningThunk, GM_RefRuntimeAsyncAwaitState_RetValueTaskOfT)
+DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_TASK_RETURNING_THUNK, FinalizeTaskReturningThunk, SM_RetTask)
+DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_TASK_RETURNING_THUNK_1, FinalizeTaskReturningThunk, GM_RetTaskOfT)
+DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_VALUETASK_RETURNING_THUNK, FinalizeValueTaskReturningThunk, SM_RetValueTask)
+DEFINE_METHOD(ASYNC_HELPERS, FINALIZE_VALUETASK_RETURNING_THUNK_1, FinalizeValueTaskReturningThunk, GM_RetValueTaskOfT)
DEFINE_METHOD(ASYNC_HELPERS, TASK_FROM_EXCEPTION, TaskFromException, SM_Exception_RetTask)
DEFINE_METHOD(ASYNC_HELPERS, TASK_FROM_EXCEPTION_1, TaskFromException, GM_Exception_RetTaskOfT)
@@ -728,18 +732,11 @@ DEFINE_METHOD(ASYNC_HELPERS, RESTORE_CONTEXTS, RestoreContexts, No
DEFINE_METHOD(ASYNC_HELPERS, RESTORE_CONTEXTS_ON_SUSPENSION, RestoreContextsOnSuspension, NoSig)
DEFINE_METHOD(ASYNC_HELPERS, ASYNC_CALL_CONTINUATION, AsyncCallContinuation, NoSig)
DEFINE_METHOD(ASYNC_HELPERS, TAIL_AWAIT, TailAwait, NoSig)
-DEFINE_FIELD(ASYNC_HELPERS, TLS_RUNTIME_ASYNC_AWAIT_STATE, t_runtimeAsyncAwaitState)
#ifdef FEATURE_INTERPRETER
DEFINE_METHOD(ASYNC_HELPERS, RESUME_INTERPRETER_CONTINUATION, ResumeInterpreterContinuation, NoSig)
#endif
-DEFINE_CLASS(RUNTIME_ASYNC_AWAIT_STATE, CompilerServices, AsyncHelpers+RuntimeAsyncAwaitState)
-DEFINE_METHOD(RUNTIME_ASYNC_AWAIT_STATE, PUSH, Push, NoSig)
-DEFINE_METHOD(RUNTIME_ASYNC_AWAIT_STATE, POP, Pop, NoSig)
-
-DEFINE_CLASS(RUNTIME_ASYNC_STACK_STATE, CompilerServices, AsyncHelpers+RuntimeAsyncStackState)
-
DEFINE_CLASS_U(CompilerServices, Continuation, ContinuationObject)
DEFINE_FIELD_U(Next, ContinuationObject, Next)
DEFINE_FIELD_U(ResumeInfo, ContinuationObject, ResumeInfo)
@@ -981,11 +978,11 @@ DEFINE_FIELD(EXECUTIONCONTEXT, DEFAULT_FLOW_SUPPRESSED, DefaultFlowSu
DEFINE_CLASS(DIRECTONTHREADLOCALDATA, Threading, Thread+DirectOnThreadLocalData)
DEFINE_CLASS(THREAD, Threading, Thread)
-DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, SM_PtrThread_RetVoid)
+DEFINE_METHOD(THREAD, START_CALLBACK, StartCallback, SM_PtrThread_RetVoid)
DEFINE_METHOD(THREAD, POLLGC, PollGC, NoSig)
DEFINE_METHOD(THREAD, ON_THREAD_EXITING, OnThreadExited, SM_PtrThread_PtrException_RetVoid)
#ifdef FOR_ILLINK
-DEFINE_METHOD(THREAD, CTOR, .ctor, IM_RetVoid)
+DEFINE_METHOD(THREAD, CTOR, .ctor, IM_RetVoid)
#endif // FOR_ILLINK
#ifdef FEATURE_OBJCMARSHAL
diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h
index d304d63ff9d908..0d631bf34b4db0 100644
--- a/src/coreclr/vm/metasig.h
+++ b/src/coreclr/vm/metasig.h
@@ -547,10 +547,8 @@ DEFINE_METASIG(SM(PtrByte_RetStr, P(b), s))
DEFINE_METASIG(SM(Str_RetPtrByte, s, P(b)))
DEFINE_METASIG(SM(PtrByte_RetVoid, P(b), v))
-DEFINE_METASIG_T(SM(RefRuntimeAsyncAwaitState_RetTask, r(g(RUNTIME_ASYNC_AWAIT_STATE)), C(TASK)))
-DEFINE_METASIG_T(SM(RefRuntimeAsyncAwaitState_RetValueTask, r(g(RUNTIME_ASYNC_AWAIT_STATE)), g(VALUETASK)))
-DEFINE_METASIG_T(GM(RefRuntimeAsyncAwaitState_RetTaskOfT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, r(g(RUNTIME_ASYNC_AWAIT_STATE)), GI(C(TASK_1), 1, M(0))))
-DEFINE_METASIG_T(GM(RefRuntimeAsyncAwaitState_RetValueTaskOfT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, r(g(RUNTIME_ASYNC_AWAIT_STATE)), GI(g(VALUETASK_1), 1, M(0))))
+DEFINE_METASIG_T(GM(RetTaskOfT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, , GI(C(TASK_1), 1, M(0))))
+DEFINE_METASIG_T(GM(RetValueTaskOfT, IMAGE_CEE_CS_CALLCONV_DEFAULT, 1, , GI(g(VALUETASK_1), 1, M(0))))
// Undefine macros in case we include the file again in the compilation unit
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.cs
index 510b863d4dda8e..0d5ff2b7ca8143 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.cs
@@ -25,11 +25,14 @@ public static partial class AsyncHelpers
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
[StackTraceHidden]
- public static unsafe void AwaitAwaiter(TAwaiter awaiter) where TAwaiter : INotifyCompletion
+ public static void AwaitAwaiter(TAwaiter awaiter) where TAwaiter : INotifyCompletion
{
ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
- Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation();
- state.StackState->Notifier = awaiter;
+ Continuation? sentinelContinuation = state.SentinelContinuation;
+ if (sentinelContinuation == null)
+ state.SentinelContinuation = sentinelContinuation = new Continuation();
+
+ state.Notifier = awaiter;
state.CaptureContexts();
AsyncSuspend(sentinelContinuation);
}
@@ -45,11 +48,14 @@ public static unsafe void AwaitAwaiter(TAwaiter awaiter) where TAwaite
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
[StackTraceHidden]
- public static unsafe void UnsafeAwaitAwaiter(TAwaiter awaiter) where TAwaiter : ICriticalNotifyCompletion
+ public static void UnsafeAwaitAwaiter(TAwaiter awaiter) where TAwaiter : ICriticalNotifyCompletion
{
ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
- Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation();
- state.StackState->CriticalNotifier = awaiter;
+ Continuation? sentinelContinuation = state.SentinelContinuation;
+ if (sentinelContinuation == null)
+ state.SentinelContinuation = sentinelContinuation = new Continuation();
+
+ state.CriticalNotifier = awaiter;
state.CaptureContexts();
AsyncSuspend(sentinelContinuation);
}
diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataModule.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataModule.cs
index 6172fe6fdf295c..5bfcc075bb5d13 100644
--- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataModule.cs
+++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ClrDataModule.cs
@@ -89,7 +89,7 @@ CustomQueryInterfaceResult ICustomQueryInterface.GetInterface(ref Guid iid, out
try
{
Guid iidMetaDataImport = typeof(IMetaDataImport).GUID;
- if (_legacyModulePointer != 0 && Marshal.QueryInterface(_legacyModulePointer, iidMetaDataImport, out nint ppMdi) >= 0)
+ if (_legacyModulePointer != 0 && _legacyModulePointer != 1 && Marshal.QueryInterface(_legacyModulePointer, iidMetaDataImport, out nint ppMdi) >= 0)
{
legacyImport = ComInterfaceMarshaller.ConvertToManaged((void*)ppMdi);
Marshal.Release(ppMdi);