Emit Async Methods in crossgen2#124203
Merged
jtschuster merged 101 commits intodotnet:mainfrom Mar 10, 2026
Merged
Conversation
- Add UseRuntimeAsync property for source projects - Add TestRuntimeAsync property for test projects - Enable RuntimeAsync with crossgen2 - Add pipeline leg for runtimeasync tests with crossgen2
Member
Author
|
/azp run runtime-coreclr crossgen2 |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR adds initial support for emitting and consuming runtime-async-related methods in crossgen2 ReadyToRun (R2R) images, including new signature flags and runtime-side lookup/GC-walk plumbing for async variants and resumption stubs.
Changes:
- Enables
runtime-async=onfeature flagging for selected source and test projects, and adds a dedicated CI leg to run R2R + runtime-async library tests. - Extends R2R method signature encoding/decoding to represent async variants and resumption stubs, and updates crossgen2 tooling/readers to surface these modifiers.
- Adds runtime support for locating and registering resumption stub entrypoints so stack walking/GC can associate R2R resumption stubs with a
MethodDesc.
Reviewed changes
Copilot reviewed 35 out of 36 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/Directory.Build.targets | Enables preview features + runtime-async=on for source projects when UseRuntimeAsync=true. |
| eng/testing/tests.targets | Adjusts runtime-async enablement for tests and adds TestRuntimeAsync override knob. |
| eng/pipelines/coreclr/crossgen2.yml | Adds a new CI test matrix leg for R2R + runtime-async libraries testing. |
| src/coreclr/inc/corcompile.h | Adds ENCODE_METHOD_SIG_ResumptionStub flag for method signature encoding. |
| src/coreclr/tools/Common/Internal/Runtime/ReadyToRunConstants.cs | Adds managed enum flag READYTORUN_METHOD_SIG_ResumptionStub. |
| src/coreclr/vm/zapsig.cpp | Reads new ResumptionStub flag during method sig decode (currently unused in logic). |
| src/coreclr/vm/stackwalk.cpp | Relaxes a debug assert for unwind table registration to accommodate async R2R scenarios. |
| src/coreclr/vm/readytoruninfo.h | Declares runtime API to look up resumption stub entrypoints for async variants. |
| src/coreclr/vm/readytoruninfo.cpp | Implements resumption stub lookup and registers R2R-backed stub MethodDesc for GC stack walks. |
| src/coreclr/vm/method.hpp | Extends async lookup enum and dynamic IL stub types to represent R2R resumption stubs. |
| src/coreclr/vm/methodtable.cpp | Adds an AsyncResumptionStub lookup path (currently duplicative of the existing slow path). |
| src/coreclr/vm/ilstubcache.h | Declares helper to create a DynamicMethodDesc wrapper around precompiled (R2R) stub code. |
| src/coreclr/vm/ilstubcache.cpp | Implements creation of an R2R-backed IL-stub MethodDesc with native entrypoint set directly. |
| src/coreclr/vm/jitinterface.cpp | Tweaks READYTORUN_HELPER handling (includes an unexpected printf). |
| src/coreclr/inc/readytorunhelpers.h | Adds mapping for READYTORUN_HELPER_ThrowExact. |
| src/coreclr/inc/readytorun.h | Clarifies formatting/commenting for async continuation helpers. |
| src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.cs | Shows [RESUME] in method display and improves BadImageFormatException message. |
| src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs | Tracks async/resume modifiers when parsing instance method + PGO sections. |
| src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunMethod.cs | Stores/display method modifiers (async/resume) in signature string. |
| src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/PgoInfoKey.cs | Includes modifiers in PGO key signature string generation. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj | Adds AsyncMethodVariant.Mangling.cs to the build. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/IL/ReadyToRunILProvider.cs | Broadens IL provisioning to handle async variants and resumption stubs. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunTableManager.cs | Categorizes async variants/resumption stubs with instantiated methods for table emission. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs | Avoids inlining async call/thunk methods and force-adds required async metadata references once. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs | Minor whitespace/style fix. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/SignatureBuilder.cs | Emits ResumptionStub flag and hashes resumption stubs with their async variant method signature. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ModuleTokenResolver.cs | Adjusts method token resolution and adds field token resolution helper. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs | Ensures async variants/resumption stubs aren’t incorrectly optimized as ordinary defs. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs | Handles async variants/resumption stubs in instantiated entrypoint table emission. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs | Skips emitting inlining info for async thunks and avoids work for methods with no inlinees. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ExceptionInfoLookupTableNode.cs | Skips EH-info table processing for resumption stubs. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs | Adjusts GC map encoding size computation (currently incorrect for non-64-bit pointer sizes). |
| src/coreclr/tools/Common/TypeSystem/IL/Stubs/AsyncResumptionStub.cs | Updates diagnostic naming and hashing; marks token generation on emit. |
| src/coreclr/tools/Common/TypeSystem/IL/InstantiatedMethodIL.cs | Relaxes a Debug.Assert to accommodate non-standard owning method relationships. |
| src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs | Enables READYTORUN path to provide an async resumption stub and relaxes a debug assert for async variants. |
| src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs | Tracks continuation types as valid types. |
| src/coreclr/tools/Common/Compiler/AsyncMethodVariant.cs | Treats resumption stubs as async thunks for compilation decisions. |
Comments suppressed due to low confidence (1)
src/coreclr/vm/jitinterface.cpp:14153
- Avoid calling
printffrom the VM here. This will write to stdout in production and can interfere with host output; it also bypasses existing logging/diagnostics patterns already present in this block (STRESS_LOG+_ASSERTE). Please remove theprintfand rely on the existing logging/assertion mechanisms (or route through the runtime logging infrastructure if an additional message is needed).
result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper_Obj);
break;
case READYTORUN_HELPER_DelayLoad_Helper_ObjObj:
...tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <[email protected]>
|
No pipelines are associated with this pull request. |
|
Azure Pipelines successfully started running 1 pipeline(s). |
jakobbotsch
reviewed
Mar 6, 2026
1. ARM Thumb bit (emit.cpp): Add codeDelta to emitRecordRelocationWithAddlDelta for CORINFO_AsyncResumeInfo.Resume and DiagnosticIP. On ARM32, CorInfoReloc::DIRECT maps to IMAGE_REL_BASED_HIGHLOW which doesn't add the Thumb bit, causing SIGILL when DispatchContinuations calls the resume stub. 2. Tiered compilation init (ilstubcache.cpp): Call DetermineAndSetIsEligibleForTieredCompilation() on the MethodDescChunk in CreateR2RBackedILStub. Without this, GC stack walks through R2R-backed IL stubs assert on IsEligibleForTieredCompilation(). Co-authored-by: Copilot <[email protected]>
Member
Author
|
Looks like all failures are unrelated |
davidwrighton
requested changes
Mar 9, 2026
Member
davidwrighton
left a comment
There was a problem hiding this comment.
I see a need for minor changes only.
.../tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs
Show resolved
Hide resolved
Add comment why we don't emit async methods in composite or ARM32 Use runtime check to avoid setting entrypoint for async helpers in non-r2r scenarios
davidwrighton
approved these changes
Mar 10, 2026
kotlarmilos
added a commit
to kotlarmilos/runtime
that referenced
this pull request
Mar 11, 2026
…tion in async methods Add a TypeDesc case to GetModuleTokenForType to handle InstantiatedType and other non-EcmaType TypeDesc variants by delegating to the existing ModuleTokenResolver.GetModuleTokenForType. Fixes a regression from dotnet#124203 where async resumption stubs referencing generic type instantiations (e.g., CallStruct1M0<T>) crash with NotImplementedException on Apple simulator CoreCLR RuntimeTests. Co-authored-by: Copilot <[email protected]>
kotlarmilos
added a commit
that referenced
this pull request
Mar 12, 2026
…tion in async methods (#125444) Fixes a regression introduced in #124203 where crossgen2 crashes with `NotImplementedException: Unsupported token resolution for Internal.TypeSystem.InstantiatedType` when compiling async methods that reference generic type instantiations (e.g., `CallStruct1M0<T>`) on Apple mobile platforms. ## Problem The `GetModuleTokenForType` local function in `HandleToModuleToken` handles `SignatureMethodVariable`, `ParameterizedType`, and `EcmaType`, but does not handle `InstantiatedType`. When async resumption stubs resolve tokens for instantiated generic types, the code falls through to the `default` case and throws. Affected jobs in `runtime-extra-platforms` pipeline: - `iossimulator-arm64 Release AllSubsets_CoreCLR_RuntimeTests` - `iossimulator-x64 Release AllSubsets_CoreCLR_RuntimeTests` - `tvossimulator-arm64 Release AllSubsets_CoreCLR_RuntimeTests` **Failed build:** https://dev.azure.com/dnceng-public/public/_build/results?buildId=1329675&view=results Co-authored-by: Copilot <[email protected]>
Copilot AI
pushed a commit
that referenced
this pull request
Mar 13, 2026
Emit async methods and resumption stubs in crossgen2 ReadyToRun images Add support for compiling and emitting runtime-async methods, their async thunks, and resumption stubs into ReadyToRun (R2R) images produced by crossgen2. Async method signatures are emitted in the InstanceMethod table with a new ENCODE_METHOD_SIG_AsyncVariant (0x100) flag. Resumption stubs are encoded as precode fixups using a new READYTORUN_FIXUP_ResumptionStubEntryPoint (0x38) fixup kind, where the "signature" is the RVA of the stub code. At fixup resolution time, a DynamicMethodDesc/ILStub is created to represent the resumption and provide GC and unwind info. Async methods that do not await skip resumption stub emission. Key changes: - Add ResumptionStubEntryPointSignature node and fixup support - Implement getAsyncResumptionStub and getFunctionEntryPoint in crossgen2's CorInfoImpl to enable the JIT to emit async calls - Set R2R entrypoints on JIT-synthesized async helper calls (context capture/restore) via SetCallEntrypointForR2R - Extend ReadyToRunILProvider to handle AsyncMethodVariant and AsyncResumptionStub IL bodies, including cross-module token rewriting through ManifestModuleWrappedMethodIL - Route async variants and resumption stubs through the instance entrypoint table and inlining info emission - Fix PEObjectWriter ARM64 page-relative relocations to support non-zero addends (needed for resumption stub code deltas) - Fix GC pointer map encoding for types whose size is not pointer-aligned (off-by-one in encodedGCRefMap allocation) - Mark CEE_JMP as unsupported in R2R (incorrect indirection cell setup) - Disable hot/cold splitting for async methods (runtime limitation) - Disable async method emission in composite mode and ARM32 (known issues tracked in #125337 and #125338) - Extend crossgen2 CI pipeline to arm64 (linux, osx, windows) - Update r2rdump/ReadyToRunReader to discover resumption stubs - Update ReadyToRun format documentation with new fixup kinds and method signature flag Co-authored-by: Jan Kotas <[email protected]> Co-authored-by: Copilot <[email protected]>
Copilot AI
pushed a commit
that referenced
this pull request
Mar 13, 2026
…tion in async methods (#125444) Fixes a regression introduced in #124203 where crossgen2 crashes with `NotImplementedException: Unsupported token resolution for Internal.TypeSystem.InstantiatedType` when compiling async methods that reference generic type instantiations (e.g., `CallStruct1M0<T>`) on Apple mobile platforms. ## Problem The `GetModuleTokenForType` local function in `HandleToModuleToken` handles `SignatureMethodVariable`, `ParameterizedType`, and `EcmaType`, but does not handle `InstantiatedType`. When async resumption stubs resolve tokens for instantiated generic types, the code falls through to the `default` case and throws. Affected jobs in `runtime-extra-platforms` pipeline: - `iossimulator-arm64 Release AllSubsets_CoreCLR_RuntimeTests` - `iossimulator-x64 Release AllSubsets_CoreCLR_RuntimeTests` - `tvossimulator-arm64 Release AllSubsets_CoreCLR_RuntimeTests` **Failed build:** https://dev.azure.com/dnceng-public/public/_build/results?buildId=1329675&view=results Co-authored-by: Copilot <[email protected]>
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emit async methods, and their resumption stubs into ReadyToRun images. Also compiles and emits async thunks for task-returning methods.
Signatures for async methods are emitted in the InstanceMethod table, with an additional ENCODE_METHOD_SIG_AsyncVariant (0x100) flag.
Resumption stubs are encoded as precode fixups for the async method with the "signature" being the RVA of the start point of the code. When the fixups are resolved, a DynamicMethodDesc / ILStub is created to represent the resumption and enable GC and unwind info to be resolved. Async methods which do not await and do not need resumption stubs won't have a resumption stub fixup.
The resumption stub MethodDescs are created following the existing pattern for ILStubs, but set the code to the R2R code rather than a precode thunk.