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 3501630d114f6e..637670f2f86bbc 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 @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using System.Threading.Tasks.Sources; @@ -207,6 +208,7 @@ public static partial class AsyncHelpers // 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. + [NonVersionable] private ref struct RuntimeAsyncStackState { // The following are the possible introducers of asynchrony into a chain of awaits. @@ -221,39 +223,12 @@ private ref struct RuntimeAsyncStackState 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. + // Methods like CreateRuntimeAsyncTask will unlink the state and wrap into a Task. + [NonVersionable] private unsafe struct RuntimeAsyncAwaitState { public Continuation? SentinelContinuation; @@ -282,22 +257,51 @@ public void CaptureContexts() // At the start of an async chain (task-returning thunk or DispatchContinuations) this function // is called + [NonVersionable] public void Push(RuntimeAsyncStackState* stackState) { stackState->Next = StackState; StackState = stackState; - stackState->Push(CurrentThread ??= Thread.CurrentThread); + CurrentThread ??= Thread.CurrentThread; } // This function is called at the end of an async chain + [NonVersionable] public void Pop() { Debug.Assert(CurrentThread != null); - StackState->Pop(CurrentThread); StackState = StackState->Next; } } + private struct AsyncContexts + { + private SynchronizationContext? _synchronizationContext; + private ExecutionContext? _executionContext; + + public void Push(Thread thread) + { + _synchronizationContext = thread._synchronizationContext; + _executionContext = thread._executionContext; + } + + 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 (_synchronizationContext != thread._synchronizationContext) + { + // Restore changed SynchronizationContext back to previous + thread._synchronizationContext = _synchronizationContext; + } + + ExecutionContext? currentExecutionCtx = thread._executionContext; + if (_executionContext != currentExecutionCtx) + { + ExecutionContext.RestoreChangedContextToThread(thread, _executionContext, currentExecutionCtx); + } + } + } + [ThreadStatic] private static RuntimeAsyncAwaitState t_runtimeAsyncAwaitState; @@ -351,7 +355,7 @@ private static unsafe Continuation AllocContinuationClass(Continuation prevConti [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe void AwaitTask(Task task, ConfigureAwaitOptions options) + private static unsafe void Suspend(Task task, ConfigureAwaitOptions options) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -386,7 +390,7 @@ private static unsafe void AwaitTask(Task task, ConfigureAwaitOptions options) [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe T AwaitTask(Task task, ConfigureAwaitOptions options) + private static unsafe T Suspend(Task task, ConfigureAwaitOptions options) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -432,7 +436,7 @@ private static unsafe T AwaitTask(Task task, ConfigureAwaitOptions options /// ValueTask whose completion we are awaiting. [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe void TransparentAwaitValueTask(ValueTask valueTask) + private static unsafe void TransparentSuspend(ValueTask valueTask) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -481,7 +485,7 @@ private static unsafe void TransparentAwaitValueTask(ValueTask valueTask) [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe void AwaitValueTaskSource(IValueTaskSource source, short token, bool continueOnCapturedContext) + private static unsafe void Suspend(IValueTaskSource source, short token, bool continueOnCapturedContext) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -518,7 +522,7 @@ private static unsafe void AwaitValueTaskSource(IValueTaskSource source, short t [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe T TransparentAwaitValueTaskOfT(ValueTask valueTask) + private static unsafe T TransparentSuspend(ValueTask valueTask) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -567,7 +571,7 @@ private static unsafe T TransparentAwaitValueTaskOfT(ValueTask valueTask) [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe T AwaitValueTaskSource(IValueTaskSource source, short token, bool continueOnCapturedContext) + private static unsafe T Suspend(IValueTaskSource source, short token, bool continueOnCapturedContext) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -609,7 +613,7 @@ private static unsafe T AwaitValueTaskSource(IValueTaskSource source, shor /// Task whose completion we are awaiting. [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe void TransparentAwait(Task task) + private static unsafe void TransparentSuspend(Task task) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -639,7 +643,7 @@ private static unsafe void TransparentAwait(Task task) /// Task whose completion we are awaiting. [BypassReadyToRun] [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)] - private static unsafe T TransparentAwaitOfT(Task task) + private static unsafe T TransparentSuspend(Task task) { ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState; Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation(); @@ -664,14 +668,17 @@ private static unsafe T TransparentAwaitOfT(Task task) return default!; } + // The next four overloads 'TransparentAwait' are called by the JIT in + // async versions of task-returning methods to await the task that + // would normally be returned. [BypassReadyToRun] [MethodImpl(MethodImplOptions.Async)] - private static void TransparentAwaitWithResult(Task task) + private static void TransparentAwait(Task task) { if (!task.IsCompleted) { TailAwait(); - TransparentAwait(task); + TransparentSuspend(task); return; } @@ -680,12 +687,12 @@ private static void TransparentAwaitWithResult(Task task) [BypassReadyToRun] [MethodImpl(MethodImplOptions.Async)] - private static void TransparentAwaitWithResult(ValueTask task) + private static void TransparentAwait(ValueTask task) { if (!task.IsCompleted) { TailAwait(); - TransparentAwaitValueTask(task); + TransparentSuspend(task); return; } @@ -694,12 +701,12 @@ private static void TransparentAwaitWithResult(ValueTask task) [BypassReadyToRun] [MethodImpl(MethodImplOptions.Async)] - private static T TransparentAwaitWithResult(Task task) + private static T TransparentAwait(Task task) { if (!task.IsCompleted) { TailAwait(); - return TransparentAwaitOfT(task); + return TransparentSuspend(task); } TaskAwaiter.ValidateEnd(task); @@ -708,12 +715,12 @@ private static T TransparentAwaitWithResult(Task task) [BypassReadyToRun] [MethodImpl(MethodImplOptions.Async)] - private static T TransparentAwaitWithResult(ValueTask task) + private static T TransparentAwait(ValueTask task) { if (!task.IsCompleted) { TailAwait(); - return TransparentAwaitValueTaskOfT(task); + return TransparentSuspend(task); } return task.Result; @@ -917,6 +924,9 @@ private unsafe void DispatchContinuations() ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState; awaitState.Push(&stackState); + AsyncContexts contexts = default; + contexts.Push(awaitState.CurrentThread!); + ref AsyncDispatcherInfo* refDispatcherInfo = ref AsyncDispatcherInfo.t_current; AsyncDispatcherInfo asyncDispatcherInfo; @@ -948,6 +958,7 @@ private unsafe void DispatchContinuations() newContinuation.Next = nextContinuation; HandleSuspended(ref awaitState); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; return; @@ -964,6 +975,7 @@ private unsafe void DispatchContinuations() TrySetCanceled(oce.CancellationToken, oce) : TrySetException(ex); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; @@ -983,6 +995,7 @@ private unsafe void DispatchContinuations() { bool successfullySet = TrySetResult(m_result); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; @@ -996,6 +1009,7 @@ private unsafe void DispatchContinuations() if (QueueContinuationFollowUpActionIfNecessary(asyncDispatcherInfo.NextContinuation)) { + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; return; @@ -1005,6 +1019,7 @@ private unsafe void DispatchContinuations() { SetContinuationState(asyncDispatcherInfo.NextContinuation); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; @@ -1025,6 +1040,9 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags ref RuntimeAsyncAwaitState awaitState = ref t_runtimeAsyncAwaitState; awaitState.Push(&stackState); + AsyncContexts contexts = default; + contexts.Push(awaitState.CurrentThread!); + ref AsyncDispatcherInfo* refDispatcherInfo = ref AsyncDispatcherInfo.t_current; AsyncDispatcherInfo asyncDispatcherInfo; @@ -1063,6 +1081,7 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags RuntimeAsyncInstrumentationHelpers.AwaitSuspendedRuntimeAsyncContext(ref asyncDispatcherInfo, flags, curContinuation, newContinuation, awaitState.SentinelContinuation!.Next); InstrumentedHandleSuspended(flags, ref awaitState); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; return; @@ -1083,6 +1102,7 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags TrySetCanceled(oce.CancellationToken, oce) : TrySetException(ex); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; @@ -1106,6 +1126,7 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags bool successfullySet = TrySetResult(m_result); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; @@ -1121,6 +1142,7 @@ private unsafe void InstrumentedDispatchContinuations(AsyncInstrumentation.Flags { RuntimeAsyncInstrumentationHelpers.QueueSuspendedRuntimeAsyncContext(ref asyncDispatcherInfo, flags, asyncDispatcherInfo.NextContinuation); + contexts.Pop(awaitState.CurrentThread!); awaitState.Pop(); refDispatcherInfo = asyncDispatcherInfo.Next; return; @@ -1265,30 +1287,30 @@ private static void FinalizeRuntimeAsyncTask(ref RuntimeAsyncAwaitState state #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 CreateRuntimeAsyncTask(ref RuntimeAsyncAwaitState state) { RuntimeAsyncTask result = new(); FinalizeRuntimeAsyncTask(ref state, result!); return result; } - private static Task FinalizeTaskReturningThunk(ref RuntimeAsyncAwaitState state) + private static Task CreateRuntimeAsyncTask(ref RuntimeAsyncAwaitState state) { RuntimeAsyncTask result = new(); FinalizeRuntimeAsyncTask(ref state, result!); return result; } - private static ValueTask FinalizeValueTaskReturningThunk(ref RuntimeAsyncAwaitState state) + private static ValueTask CreateRuntimeAsyncValueTask(ref RuntimeAsyncAwaitState state) { // 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(CreateRuntimeAsyncTask(ref state)); } - private static ValueTask FinalizeValueTaskReturningThunk(ref RuntimeAsyncAwaitState state) + private static ValueTask CreateRuntimeAsyncValueTask(ref RuntimeAsyncAwaitState state) { - return new ValueTask(FinalizeTaskReturningThunk(ref state)); + return new ValueTask(CreateRuntimeAsyncTask(ref state)); } private static Task TaskFromException(Exception ex) @@ -1544,19 +1566,6 @@ private static void FinishSuspensionWithContinuationContext(ref object continuat } } - [StackTraceHidden] - internal static T CompletedTaskResult(Task task) - { - TaskAwaiter.ValidateEnd(task); - return task.ResultOnSuccess; - } - - [StackTraceHidden] - internal static void CompletedTask(Task task) - { - TaskAwaiter.ValidateEnd(task); - } - // Instrumentation helpers called from InstrumentedDispatchContinuations. // These methods should not throw - exceptions would break the dispatch loop. internal static class RuntimeAsyncInstrumentationHelpers diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index 36167779d00519..94445e6555ae74 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -19,10 +19,10 @@ // src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h // If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION` // and handle pending work. -#define READYTORUN_MAJOR_VERSION 24 +#define READYTORUN_MAJOR_VERSION 25 #define READYTORUN_MINOR_VERSION 0x0000 -#define MINIMUM_READYTORUN_MAJOR_VERSION 24 +#define MINIMUM_READYTORUN_MAJOR_VERSION 25 // R2R Version 2.1 adds the InliningInfo section // R2R Version 2.2 adds the ProfileDataInfo section @@ -64,6 +64,7 @@ // R2R Version 22 changes NativeVarInfo encoding to include CALL_RETURN_VALUE // R2R Version 23 changes delegate layout to have target before methodPtr // R2R Version 24 changes ARM32 virtual stub dispatch hidden parameter register to R12 +// R2R Version 25 renames runtime async infrastructure members and makes thunk-used members NonVersionable struct READYTORUN_CORE_HEADER { diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 1b811f91084775..8dfeb7b0e2cdf0 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -11689,7 +11689,7 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) //------------------------------------------------------------------------ // impWrapTopOfStackInAwait: // Wrap the value on the top of the stack in -// AsyncHelpers.TransparentAwaitWithResult. +// AsyncHelpers.TransparentAwait. // // Returns: // True if successful. False if the EE could not create the call (only during @@ -11701,7 +11701,7 @@ bool Compiler::impReturnInstruction(int prefixFlags, OPCODE& opcode) // mistyped; the original IL returns a Task or ValueTask, but the runtime // async version expects to return the unwrapped result. This function // accomplishes the unwrapping by inserting an async call to -// AsyncHelpers.TransparentAwaitWithResult around the value on the top of the +// AsyncHelpers.TransparentAwait around the value on the top of the // stack. // bool Compiler::impWrapTopOfStackInAwait() @@ -11814,7 +11814,7 @@ bool Compiler::impWrapTopOfStackInAwait() //------------------------------------------------------------------------ // impFoldAwaitedTopOfStack: // Fold a few patterns where introducing a call to -// AsyncHelpers.TransparentAwaitWithResult is unnecessary. +// AsyncHelpers.TransparentAwait is unnecessary. // // Returns: // True if the top of stack was folded and the importer stack was updated diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index e1cc51c1f9f698..9e8e5b1f3d2afe 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -11,7 +11,7 @@ struct ReadyToRunHeaderConstants { static const uint32_t Signature = 0x00525452; // 'RTR' - static const uint32_t CurrentMajorVersion = 24; + static const uint32_t CurrentMajorVersion = 25; static const uint32_t CurrentMinorVersion = 0; }; diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index bba736ba320985..64ed09698e99f3 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -15,7 +15,7 @@ internal struct ReadyToRunHeaderConstants { public const uint Signature = 0x00525452; // 'RTR' - public const ushort CurrentMajorVersion = 24; + public const ushort CurrentMajorVersion = 25; public const ushort CurrentMinorVersion = 0; } #if READYTORUN diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 442be2390dc0ba..50e8e460895ed1 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -3521,7 +3521,7 @@ private void getAsyncInfo(ref CORINFO_ASYNC_INFO pAsyncInfoOut) ? context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8) : context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8); MethodSignature signature = new MethodSignature(MethodSignatureFlags.Static, 0, context.GetWellKnownType(WellKnownType.Void), [parameterType]); - runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwaitWithResult"u8, signature); + runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwait"u8, signature); } else { @@ -3530,7 +3530,7 @@ private void getAsyncInfo(ref CORINFO_ASYNC_INFO pAsyncInfoOut) ? context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask`1"u8).MakeInstantiatedType(signatureVariable) : context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task`1"u8).MakeInstantiatedType(signatureVariable); MethodSignature signature = new MethodSignature(MethodSignatureFlags.Static, 1, signatureVariable, [parameterType]); - runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwaitWithResult"u8, signature).MakeInstantiatedMethod(returnType); + runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwait"u8, signature).MakeInstantiatedMethod(returnType); } MethodDesc result = runtimeDeterminedResult.GetCanonMethodTarget(CanonicalFormKind.Specific); diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs index dc6cc330b645c1..7a9add8bbb76d1 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncThunks.cs @@ -11,7 +11,7 @@ public static class AsyncThunkILEmitter // Emits a thunk that wraps an async method to return a Task or ValueTask. // The thunk calls the async method, and if it completes synchronously, // it returns a completed Task/ValueTask. If the async method suspends, - // it calls FinalizeTaskReturningThunk/FinalizeValueTaskReturningThunk method to get the Task/ValueTask. + // it calls CreateRuntimeAsyncTask/CreateRuntimeAsyncValueTask method to get the Task/ValueTask. // The emitted code matches method EmitTaskReturningThunk in CoreCLR VM. public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, MethodDesc asyncMethod) @@ -191,35 +191,35 @@ public static MethodIL EmitTaskReturningThunk(MethodDesc taskReturningMethod, Me codestream.EmitLabel(suspendedLabel); - MethodDesc finalizeTaskReturningThunkMd; + MethodDesc createRuntimeAsyncTaskMd; if (logicalReturnType != null) { - MethodSignature finalizeReturningThunkSignature = new MethodSignature( + MethodSignature createRuntimeAsyncTaskSignature = new MethodSignature( MethodSignatureFlags.Static, genericParameterCount: 1, returnType: ((MetadataType)returnType.GetTypeDefinition()).MakeInstantiatedType(context.GetSignatureVariable(0, true)), parameters: [awaitStateType.MakeByRefType()] ); - finalizeTaskReturningThunkMd = asyncHelpersType - .GetKnownMethod(isValueTask ? "FinalizeValueTaskReturningThunk"u8 : "FinalizeTaskReturningThunk"u8, finalizeReturningThunkSignature) + createRuntimeAsyncTaskMd = asyncHelpersType + .GetKnownMethod(isValueTask ? "CreateRuntimeAsyncValueTask"u8 : "CreateRuntimeAsyncTask"u8, createRuntimeAsyncTaskSignature) .MakeInstantiatedMethod(new Instantiation(logicalReturnType)); } else { - MethodSignature finalizeReturningThunkSignature = new MethodSignature( + MethodSignature createRuntimeAsyncTaskSignature = new MethodSignature( MethodSignatureFlags.Static, genericParameterCount: 0, returnType: returnType, parameters: [awaitStateType.MakeByRefType()] ); - finalizeTaskReturningThunkMd = asyncHelpersType - .GetKnownMethod(isValueTask ? "FinalizeValueTaskReturningThunk"u8 : "FinalizeTaskReturningThunk"u8, finalizeReturningThunkSignature); + createRuntimeAsyncTaskMd = asyncHelpersType + .GetKnownMethod(isValueTask ? "CreateRuntimeAsyncValueTask"u8 : "CreateRuntimeAsyncTask"u8, createRuntimeAsyncTaskSignature); } codestream.EmitLdLoc(refAwaitStateLocal); - codestream.Emit(ILOpcode.call, emitter.NewToken(finalizeTaskReturningThunkMd)); + codestream.Emit(ILOpcode.call, emitter.NewToken(createRuntimeAsyncTaskMd)); codestream.EmitStLoc(returnTaskLocal); codestream.Emit(ILOpcode.leave, returnTaskLabel); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index ab198087de1b90..b0b170c4ff0282 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -1810,7 +1810,7 @@ private void ImportReturn() ? context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask"u8) : context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task"u8); MethodSignature signature = new MethodSignature(MethodSignatureFlags.Static, 0, context.GetWellKnownType(WellKnownType.Void), [parameterType]); - runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwaitWithResult"u8, signature); + runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwait"u8, signature); } else { @@ -1819,7 +1819,7 @@ private void ImportReturn() ? context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "ValueTask`1"u8).MakeInstantiatedType(signatureVariable) : context.SystemModule.GetKnownType("System.Threading.Tasks"u8, "Task`1"u8).MakeInstantiatedType(signatureVariable); MethodSignature signature = new MethodSignature(MethodSignatureFlags.Static, 1, signatureVariable, [parameterType]); - runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwaitWithResult"u8, signature).MakeInstantiatedMethod(returnType); + runtimeDeterminedResult = asyncHelpers.GetKnownMethod("TransparentAwait"u8, signature).MakeInstantiatedMethod(returnType); } MethodDesc targetMethod = runtimeDeterminedResult.GetCanonMethodTarget(CanonicalFormKind.Specific); diff --git a/src/coreclr/vm/asyncthunks.cpp b/src/coreclr/vm/asyncthunks.cpp index 4f976e561d873a..233bc7a3832c67 100644 --- a/src/coreclr/vm/asyncthunks.cpp +++ b/src/coreclr/vm/asyncthunks.cpp @@ -93,7 +93,7 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig& // if (AsyncHelpers.AsyncCallContinuation() == null) // return Task.FromResult(result); // - // return FinalizeTaskReturningThunk(ref awaitState); + // return CreateRuntimeAsyncTask(ref awaitState); // } // catch (Exception ex) // { @@ -229,29 +229,29 @@ void MethodDesc::EmitTaskReturningThunk(MethodDesc* pAsyncCallVariant, MetaSig& pCode->EmitLabel(suspendedLabel); - int finalizeTaskReturningThunkToken; + int createRuntimeAsyncTaskToken; if (logicalResultLocal != UINT_MAX) { MethodDesc* md; if (isValueTask) - md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_VALUETASK_RETURNING_THUNK_1); + md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__CREATE_RUNTIME_ASYNC_VALUE_TASK_1); else - md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK_1); + md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__CREATE_RUNTIME_ASYNC_TASK_1); md = FindOrCreateAssociatedMethodDesc(md, md->GetMethodTable(), FALSE, Instantiation(&thLogicalRetType, 1), FALSE); - finalizeTaskReturningThunkToken = GetTokenForGenericMethodCallWithAsyncReturnType(pCode, md); + createRuntimeAsyncTaskToken = GetTokenForGenericMethodCallWithAsyncReturnType(pCode, md); } else { MethodDesc* md; if (isValueTask) - md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_VALUETASK_RETURNING_THUNK); + md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__CREATE_RUNTIME_ASYNC_VALUE_TASK); else - md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__FINALIZE_TASK_RETURNING_THUNK); - finalizeTaskReturningThunkToken = pCode->GetToken(md); + md = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__CREATE_RUNTIME_ASYNC_TASK); + createRuntimeAsyncTaskToken = pCode->GetToken(md); } pCode->EmitLDLOC(refAwaitStateLocal); - pCode->EmitCALL(finalizeTaskReturningThunkToken, 1, 1); + pCode->EmitCALL(createRuntimeAsyncTaskToken, 1, 1); pCode->EmitSTLOC(returnTaskLocal); pCode->EmitLEAVE(returnTaskLabel); diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 2db9241ecbe031..89f73e1d3a0ee6 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -707,26 +707,20 @@ 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, CREATE_RUNTIME_ASYNC_TASK, CreateRuntimeAsyncTask, SM_RefRuntimeAsyncAwaitState_RetTask) +DEFINE_METHOD(ASYNC_HELPERS, CREATE_RUNTIME_ASYNC_TASK_1, CreateRuntimeAsyncTask, GM_RefRuntimeAsyncAwaitState_RetTaskOfT) +DEFINE_METHOD(ASYNC_HELPERS, CREATE_RUNTIME_ASYNC_VALUE_TASK, CreateRuntimeAsyncValueTask, SM_RefRuntimeAsyncAwaitState_RetValueTask) +DEFINE_METHOD(ASYNC_HELPERS, CREATE_RUNTIME_ASYNC_VALUE_TASK_1, CreateRuntimeAsyncValueTask, GM_RefRuntimeAsyncAwaitState_RetValueTaskOfT) DEFINE_METHOD(ASYNC_HELPERS, TASK_FROM_EXCEPTION, TaskFromException, SM_Exception_RetTask) DEFINE_METHOD(ASYNC_HELPERS, TASK_FROM_EXCEPTION_1, TaskFromException, GM_Exception_RetTaskOfT) DEFINE_METHOD(ASYNC_HELPERS, VALUETASK_FROM_EXCEPTION, ValueTaskFromException, SM_Exception_RetValueTask) DEFINE_METHOD(ASYNC_HELPERS, VALUETASK_FROM_EXCEPTION_1, ValueTaskFromException, GM_Exception_RetValueTaskOfT) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT, TransparentAwait, NoSig) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_OF_T, TransparentAwaitOfT, NoSig) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_VALUE_TASK, TransparentAwaitValueTask, NoSig) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_VALUE_TASK_OF_T, TransparentAwaitValueTaskOfT, NoSig) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_TASK_WITH_RESULT, TransparentAwaitWithResult, SM_Task_RetVoid) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_VALUETASK_WITH_RESULT, TransparentAwaitWithResult, SM_ValueTask_RetVoid) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_TASK_OF_T_WITH_RESULT, TransparentAwaitWithResult, GM_TaskOfT_RetT) -DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_VALUETASK_OF_T_WITH_RESULT, TransparentAwaitWithResult, GM_ValueTaskOfT_RetT) -DEFINE_METHOD(ASYNC_HELPERS, COMPLETED_TASK_RESULT, CompletedTaskResult, NoSig) -DEFINE_METHOD(ASYNC_HELPERS, COMPLETED_TASK, CompletedTask, NoSig) +DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_TASK, TransparentAwait, SM_Task_RetVoid) +DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_VALUETASK, TransparentAwait, SM_ValueTask_RetVoid) +DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_TASK_OF_T, TransparentAwait, GM_TaskOfT_RetT) +DEFINE_METHOD(ASYNC_HELPERS, TRANSPARENT_AWAIT_VALUETASK_OF_T, TransparentAwait, GM_ValueTaskOfT_RetT) DEFINE_METHOD(ASYNC_HELPERS, CAPTURE_EXECUTION_CONTEXT, CaptureExecutionContext, NoSig) DEFINE_METHOD(ASYNC_HELPERS, CAPTURE_CONTINUATION_CONTEXT, CaptureContinuationContext, NoSig) DEFINE_METHOD(ASYNC_HELPERS, CAPTURE_CONTEXTS, CaptureContexts, NoSig) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index c75a158e4df49e..15e690a883749e 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -10345,11 +10345,11 @@ CORINFO_METHOD_HANDLE CEEInfo::getAwaitReturnCall(CORINFO_METHOD_HANDLE callerHa { if (sig.IsReturnTypeVoid()) { - pTypicalAwaitMD = pMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_VALUETASK_WITH_RESULT); + pTypicalAwaitMD = pMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_VALUETASK); } else { - pTypicalAwaitMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_VALUETASK_OF_T_WITH_RESULT); + pTypicalAwaitMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_VALUETASK_OF_T); pMD = MethodDesc::FindOrCreateAssociatedMethodDesc(pTypicalAwaitMD, pTypicalAwaitMD->GetMethodTable(), FALSE, Instantiation(&retType, 1), TRUE); } } @@ -10357,11 +10357,11 @@ CORINFO_METHOD_HANDLE CEEInfo::getAwaitReturnCall(CORINFO_METHOD_HANDLE callerHa { if (sig.IsReturnTypeVoid()) { - pTypicalAwaitMD = pMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_TASK_WITH_RESULT); + pTypicalAwaitMD = pMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_TASK); } else { - pTypicalAwaitMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_TASK_OF_T_WITH_RESULT); + pTypicalAwaitMD = CoreLibBinder::GetMethod(METHOD__ASYNC_HELPERS__TRANSPARENT_AWAIT_TASK_OF_T); pMD = MethodDesc::FindOrCreateAssociatedMethodDesc(pTypicalAwaitMD, pTypicalAwaitMD->GetMethodTable(), FALSE, Instantiation(&retType, 1), TRUE); } } 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 daa89fb6a7a225..02e0130920e3ea 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 @@ -69,7 +69,7 @@ public static T Await(Task task) if (!task.IsCompleted) { TailAwait(); - return AwaitTask(task, ConfigureAwaitOptions.ContinueOnCapturedContext); + return Suspend(task, ConfigureAwaitOptions.ContinueOnCapturedContext); } TaskAwaiter.ValidateEnd(task); @@ -89,7 +89,7 @@ public static void Await(Task task) if (!task.IsCompleted) { TailAwait(); - AwaitTask(task, ConfigureAwaitOptions.ContinueOnCapturedContext); + Suspend(task, ConfigureAwaitOptions.ContinueOnCapturedContext); return; } @@ -122,7 +122,7 @@ public static T Await(ValueTask task) } TailAwait(); - return AwaitTask(t, ConfigureAwaitOptions.ContinueOnCapturedContext); + return Suspend(t, ConfigureAwaitOptions.ContinueOnCapturedContext); } Debug.Assert(obj is IValueTaskSource); @@ -130,7 +130,7 @@ public static T Await(ValueTask task) if (vts.GetStatus(task._token) == ValueTaskSourceStatus.Pending) { TailAwait(); - return AwaitValueTaskSource(vts, task._token, true); + return Suspend(vts, task._token, true); } return vts.GetResult(task._token); @@ -161,7 +161,7 @@ public static void Await(ValueTask task) } TailAwait(); - AwaitTask(t, ConfigureAwaitOptions.ContinueOnCapturedContext); + Suspend(t, ConfigureAwaitOptions.ContinueOnCapturedContext); return; } @@ -170,7 +170,7 @@ public static void Await(ValueTask task) if (vts.GetStatus(task._token) == ValueTaskSourceStatus.Pending) { TailAwait(); - AwaitValueTaskSource(vts, task._token, true); + Suspend(vts, task._token, true); return; } @@ -198,7 +198,7 @@ public static void Await(ConfiguredTaskAwaitable configuredAwaitable) if (!awaiter.IsCompleted) { TailAwait(); - AwaitTask(awaiter.m_task, awaiter.m_options); + Suspend(awaiter.m_task, awaiter.m_options); return; } @@ -245,7 +245,7 @@ public static void Await(ConfiguredValueTaskAwaitable configuredAwaitable) } TailAwait(); - AwaitTask(t, task._continueOnCapturedContext ? ConfigureAwaitOptions.ContinueOnCapturedContext : ConfigureAwaitOptions.None); + Suspend(t, task._continueOnCapturedContext ? ConfigureAwaitOptions.ContinueOnCapturedContext : ConfigureAwaitOptions.None); return; } @@ -254,7 +254,7 @@ public static void Await(ConfiguredValueTaskAwaitable configuredAwaitable) if (vts.GetStatus(task._token) == ValueTaskSourceStatus.Pending) { TailAwait(); - AwaitValueTaskSource(vts, task._token, task._continueOnCapturedContext); + Suspend(vts, task._token, task._continueOnCapturedContext); return; } @@ -280,7 +280,7 @@ public static T Await(ConfiguredTaskAwaitable configuredAwaitable) if (!awaiter.IsCompleted) { TailAwait(); - return AwaitTask(awaiter.m_task, awaiter.m_options); + return Suspend(awaiter.m_task, awaiter.m_options); } return awaiter.GetResult(); @@ -313,7 +313,7 @@ public static T Await(ConfiguredValueTaskAwaitable configuredAwaitable) } TailAwait(); - return AwaitTask(t, task._continueOnCapturedContext ? ConfigureAwaitOptions.ContinueOnCapturedContext : ConfigureAwaitOptions.None); + return Suspend(t, task._continueOnCapturedContext ? ConfigureAwaitOptions.ContinueOnCapturedContext : ConfigureAwaitOptions.None); } Debug.Assert(obj is IValueTaskSource); @@ -321,7 +321,7 @@ public static T Await(ConfiguredValueTaskAwaitable configuredAwaitable) if (vts.GetStatus(task._token) == ValueTaskSourceStatus.Pending) { TailAwait(); - return AwaitValueTaskSource(vts, task._token, task._continueOnCapturedContext); + return Suspend(vts, task._token, task._continueOnCapturedContext); } return vts.GetResult(task._token);