Async instantiating and unboxing thunks#122126
Conversation
|
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas |
See some discussion on this matter in #121971 An instantiating/unboxing thunk for an async method must be an async method because the thunk needs to direct-call (aka await) another async method. Technically the resume stub is not pointless as the thunk may suspend, produce continuation, and later something needs to resume the thunk. Logically you are correct though. The thunk has no purpose after making the inner call. We could have a kind of tail-call-like optimization for the thunks where in case of suspension the thunk just passes the callee continuation up to the caller (and thus removes itself from continuation chain and from resume sequence altogether). |
Maybe you can hack it up by emitting something like: // < do the inner call>
// fetch the callee`s continuation, if any
Continuation c = AsyncCallContinuation();
if (c != null)
{
// return calee's continuation to the caller.
AsyncSuspend(c);
// UNREACHABLE
}
return result;This has not been tried, so it is a big YMMV. |
|
Draft Pull Request was automatically closed for 30 days of inactivity. Please let us know if you'd like to reopen it. |
Can be used to instruct the JIT that an upcoming await should not create an explicit suspension point. This can be used to optimize instantiating/unboxing stubs and will simplify the NAOT side of the implementation of those.
30f892a to
fd8c9b9
Compare
There was a problem hiding this comment.
Pull request overview
This PR enables NativeAOT compilation/testing for async instantiating and unboxing thunks by introducing a “tail await” mechanism in the JIT and using it from generated thunks, then unblocking the corresponding async tests.
Changes:
- Unblocked
inst-unbox-thunksasync tests on NativeAOT by removingActiveIssueannotations. - Added
AsyncHelpers.TailAwaitintrinsic and JIT support to mark the next await as a “tail await” (no new suspension point; return callee continuation). - Updated NativeAOT thunk IL emission + JIT flags plumbing so instantiating/unboxing thunks can call async targets.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tests/async/inst-unbox-thunks/inst-unbox-thunks.cs | Removes NativeAOT ActiveIssue gates so the scenarios run in CI. |
| src/coreclr/vm/asyncthunks.cpp | Comment update to reference AsyncHelpers.AsyncCallContinuation(). |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.InterfaceThunks.cs | Emits TailAwait before calling async DIM targets; adds helpers to identify DIM instantiation thunks. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerTypeSystemContext.BoxedTypes.cs | Emits TailAwait before calling async “special” unboxing thunk targets (generic unboxing thunk path). |
| src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | Sets CORJIT_FLAG_ASYNC when compiling certain thunk methods whose targets are async calls (NativeAOT path). |
| src/coreclr/jit/namedintrinsiclist.h | Registers the new AsyncHelpers.TailAwait named intrinsic. |
| src/coreclr/jit/importercalls.cpp | Recognizes/imports TailAwait intrinsic and tags the next async call as a tail await. |
| src/coreclr/jit/gentree.h | Adds AsyncCallInfo.IsTailAwait. |
| src/coreclr/jit/compiler.h | Adds m_nextAwaitIsTail state for the importer. |
| src/coreclr/jit/async.h | Adds tail-await transformation helpers and refactors some async-transform helpers to be lazily initialized. |
| src/coreclr/jit/async.cpp | Implements tail-await transformation and refactors shared return/local creation. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs | Adds AsyncHelpers.TailAwait intrinsic declaration. |
| docs/design/coreclr/botr/runtime-async-codegen.md | Updates doc text to refer to AsyncHelpers.AsyncCallContinuation() instead of StubHelpers. |
jakobbotsch
left a comment
There was a problem hiding this comment.
LGTM, but @EgorBo can you PTAL on the JIT parts too?
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/ba-g ICU seems to be missing on an ARM32 machine? |
We need to:
CORJIT_FLAG_ASYNCwhen the target is AsyncCallAlso includes a JIT change from #124175.
Fixes #121781.
Cc @dotnet/ilc-contrib @jakobbotsch