Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ private static unsafe Continuation AllocContinuationClass(Continuation prevConti
/// <param name="valueTask">ValueTask whose completion we are awaiting.</param>
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
private static unsafe void TransparentAwaitValueTask(ValueTask valueTask)
private static unsafe void TransparentSuspendForValueTask(ValueTask valueTask)
{
ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation();
Expand Down Expand Up @@ -411,7 +411,7 @@ private static unsafe void AwaitValueTaskSource(object source, short token)

[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
private static unsafe void TransparentAwaitValueTaskOfT<T>(ValueTask<T> valueTask)
private static unsafe void TransparentSuspendForValueTaskOfT<T>(ValueTask<T> valueTask)
{
ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation();
Expand Down Expand Up @@ -473,7 +473,7 @@ private static unsafe void AwaitValueTaskSourceOfT<T>(object source, short token
/// <param name="t">Task whose completion we are awaiting.</param>
[BypassReadyToRun]
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.Async)]
private static unsafe void TransparentAwait(Task t)
private static unsafe void TransparentSuspendForTask(Task t)
{
ref RuntimeAsyncAwaitState state = ref t_runtimeAsyncAwaitState;
Continuation? sentinelContinuation = state.SentinelContinuation ??= new Continuation();
Expand All @@ -484,6 +484,57 @@ private static unsafe void TransparentAwait(Task t)
AsyncSuspend(sentinelContinuation);
}

[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
private static void TransparentAwait(Task task)
{
if (!task.IsCompleted)
{
TransparentSuspendForTask(task);
}

TaskAwaiter.ValidateEnd(task);
}

[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
private static T TransparentAwait<T>(Task<T> task)
{
if (!task.IsCompleted)
{
TransparentSuspendForTask(task);
}

TaskAwaiter.ValidateEnd(task);
return task.ResultOnSuccess;
}

[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
private static void TransparentAwait(ValueTask task)
{
if (!task.IsCompleted)
{
TailAwait();
TransparentSuspendForValueTask(task);
}

task.ThrowIfCompletedUnsuccessfully();
}

[BypassReadyToRun]
[MethodImpl(MethodImplOptions.Async)]
private static T TransparentAwait<T>(ValueTask<T> task)
{
if (!task.IsCompleted)
{
TailAwait();
TransparentSuspendForValueTaskOfT(task);
}

return task.Result;
}

// Represents execution of a chain of suspended and resuming runtime
// async functions.
private sealed class RuntimeAsyncTask<T> : Task<T>, ITaskCompletionAction
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,7 @@ enum CorInfoOptions
CORINFO_GENERICS_CTXT_FROM_METHODTABLE),
CORINFO_GENERICS_CTXT_KEEP_ALIVE = 0x00000100, // Keep the generics context alive throughout the method even if there is no explicit use, and report its location to the CLR
CORINFO_ASYNC_SAVE_CONTEXTS = 0x00000200, // Runtime async method must save and restore contexts
CORINFO_ASYNC_VERSION = 0x00000400, // This is an async version whose IL belongs to a non-async method
};

//
Expand Down Expand Up @@ -3143,6 +3144,10 @@ class ICorStaticInfo
CORINFO_ASYNC_INFO* pAsyncInfoOut
) = 0;

// Get information about which await call to use to await the return type
// of the non-async version of an async call.
virtual CORINFO_METHOD_HANDLE getAwaitReturnCall(CORINFO_METHOD_HANDLE callerHandle, CORINFO_LOOKUP* instArg) = 0;

/*********************************************************************************/
//
// Diagnostic methods
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,10 @@ void getEEInfo(
void getAsyncInfo(
CORINFO_ASYNC_INFO* pAsyncInfoOut) override;

CORINFO_METHOD_HANDLE getAwaitReturnCall(
CORINFO_METHOD_HANDLE callerHandle,
CORINFO_LOOKUP* instArg) override;

mdMethodDef getMethodDefFromMethod(
CORINFO_METHOD_HANDLE hMethod) override;

Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* 5635ae9d-ffa5-4336-b027-a383971e3918 */
0x5635ae9d,
0xffa5,
0x4336,
{0xb0, 0x27, 0xa3, 0x83, 0x97, 0x1e, 0x39, 0x18}
constexpr GUID JITEEVersionIdentifier = { /* 632e62c5-83d1-4817-9c69-94f84640505d */
0x632e62c5,
0x83d1,
0x4817,
{0x9c, 0x69, 0x94, 0xf8, 0x46, 0x40, 0x50, 0x5d}
};

#endif // JIT_EE_VERSIONING_GUID_H
1 change: 1 addition & 0 deletions src/coreclr/jit/ICorJitInfo_names_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ DEF_CLR_API(runWithErrorTrap)
DEF_CLR_API(runWithSPMIErrorTrap)
DEF_CLR_API(getEEInfo)
DEF_CLR_API(getAsyncInfo)
DEF_CLR_API(getAwaitReturnCall)
DEF_CLR_API(getMethodDefFromMethod)
DEF_CLR_API(printMethodName)
DEF_CLR_API(getMethodNameFromMetadata)
Expand Down
10 changes: 10 additions & 0 deletions src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,16 @@ void WrapICorJitInfo::getAsyncInfo(
API_LEAVE(getAsyncInfo);
}

CORINFO_METHOD_HANDLE WrapICorJitInfo::getAwaitReturnCall(
CORINFO_METHOD_HANDLE callerHandle,
CORINFO_LOOKUP* instArg)
{
API_ENTER(getAwaitReturnCall);
CORINFO_METHOD_HANDLE temp = wrapHnd->getAwaitReturnCall(callerHandle, instArg);
API_LEAVE(getAwaitReturnCall);
return temp;
}

mdMethodDef WrapICorJitInfo::getMethodDefFromMethod(
CORINFO_METHOD_HANDLE hMethod)
{
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3138,6 +3138,11 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
{
printf("OPTIONS: compilation is an async state machine\n");
}

if (compIsAsyncVersion())
{
printf("OPTIONS: compilation IL belongs to synchronous version\n");
}
}
#endif

Expand Down
12 changes: 11 additions & 1 deletion src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4925,6 +4925,7 @@ class Compiler
// This call is a task await
PREFIX_IS_TASK_AWAIT = 0x00000080,
PREFIX_TASK_AWAIT_CONTINUE_ON_CAPTURED_CONTEXT = 0x00000100,
PREFIX_IS_ASYNC_VERSION_TAIL_AWAIT = 0x00000200,
};

static void impValidateMemoryAccessOpcode(const BYTE* codeAddr, const BYTE* codeEndp, bool volatilePrefix);
Expand Down Expand Up @@ -5103,7 +5104,8 @@ class Compiler

void impSetupAsyncCall(GenTreeCall* call, OPCODE opcode, unsigned prefixFlags, const DebugInfo& callDI);

void impInsertAsyncContinuationForLdvirtftnCall(GenTreeCall* call);
void impInsertAsyncArgsForLdvirtftnCall(GenTreeCall* call);
void impAddAsyncArgsToInlinedCall(GenTreeCall* call);

CORINFO_CLASS_HANDLE impGetSpecialIntrinsicExactReturnType(GenTreeCall* call);

Expand Down Expand Up @@ -5583,6 +5585,7 @@ class Compiler
void impLoadArg(unsigned ilArgNum, IL_OFFSET offset);
void impLoadLoc(unsigned ilLclNum, IL_OFFSET offset);
bool impReturnInstruction(int prefixFlags, OPCODE& opcode);
void impWrapTopOfStackInAwait();
void impPoisonImplicitByrefsBeforeReturn();

// A free list of linked list nodes used to represent to-do stacks of basic blocks.
Expand Down Expand Up @@ -11765,11 +11768,18 @@ class Compiler
#endif // TARGET_AMD64
}

// Does this function have async calling convention and can have suspension points?
bool compIsAsync() const
{
return opts.jitFlags->IsSet(JitFlags::JIT_FLAG_ASYNC);
}

// Is this the async version of a non-async method? IL belongs to non-async method.
bool compIsAsyncVersion() const
{
return (info.compMethodInfo->options & CORINFO_ASYNC_VERSION) != 0;
}

//------------------------------------------------------------------------
// compMethodReturnsMultiRegRetType: Does this method return a multi-reg value?
//
Expand Down
Loading
Loading