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
|
/azp run runtime-coreclr crossgen2 |
|
Azure Pipelines successfully started running 1 pipeline(s). |
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 <175728472+Copilot@users.noreply.github.com>
|
/azp run runtime-coreclr crossgen2 |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Replace the getFunctionEntryPoint + setEntryPoint calls for async context helpers (CaptureContexts, RestoreContexts, CaptureExecution- Context, RestoreExecutionContext, RestoreContextsOnSuspension, CaptureContinuationContext) with proper CORINFO_HELP_* JIT helpers. The previous getFunctionEntryPoint calls created MethodEntrypoint nodes in crossgen2's dependency graph, which had the side effect of making previously-uncompilable methods compilable. This exposed a pre-existing bug where IL 'jmp' instructions generate R2R 'jmp qword ptr [cell]' that the delay-load thunk cannot resolve, causing infinite loops. Using JIT helpers avoids this side effect entirely — helpers go through the ReadyToRun helper fixup table and don't add method entry points to the dependency graph. The helpers also work correctly on ARM64 since they use the standard R2R helper calling convention. Also make getFunctionEntryPoint throw RequiresRuntimeJitException in crossgen2 to prevent future callers from re-introducing this problem. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…in PEObjectWriter" This reverts commit 603ac20.
|
/azp run runtime-coreclr crossgen2 |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Add the new async context helpers (CaptureContexts, RestoreContexts, CaptureExecutionContext, RestoreExecutionContext, RestoreContextsOn- Suspension, CaptureContinuationContext) to: - JitHelper.cs: resolve helper ID to managed method for NativeAOT - ILImporter.Scanner.cs: register helpers via GetHelperEntrypoint - ReadyToRunSignature.cs: display names for R2RDump Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move the async context helper entries (0x118-0x11D) after InitClass/ InitInstClass (0x116-0x117) so the enum values are in sequential order. No value changes, just reordering in the source files. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add linux_arm64, osx_arm64, and windows_arm64 to the TestReadyToRun_RuntimeAsync_Libraries test matrix in the crossgen2 pipeline. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
src/coreclr/inc/readytorun.h
Outdated
| READYTORUN_HELPER_AllocContinuationMethod = 0x122, | ||
| READYTORUN_HELPER_AsyncCaptureContexts = 0x123, | ||
| READYTORUN_HELPER_AsyncRestoreContexts = 0x124, | ||
| READYTORUN_HELPER_AsyncCaptureExecCtx = 0x125, |
There was a problem hiding this comment.
Can we use full names everywhere - avoid abbreviations? It looks odd that some methods have "Context" and others just "Ctx".
Rename CORINFO_HELP_ALLOC_CONTINUATION* to CORINFO_HELP_ASYNC_HELPERS_ALLOC_CONTINUATION* and CORINFO_HELP_ASYNC_* to CORINFO_HELP_ASYNC_HELPERS_* across all files. Same pattern for READYTORUN_HELPER_ and ReadyToRunHelper enum values. Also update R2RDump display strings to use full unabbreviated names. Also remove incremental-build-issues.md that was accidentally committed. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
| READYTORUN_HELPER_InitClass = 0x116, | ||
| READYTORUN_HELPER_InitInstClass = 0x117, | ||
|
|
||
| READYTORUN_HELPER_AsyncHelpersAllocContinuation = 0x120, |
There was a problem hiding this comment.
Last naming nit: HELPER_AsyncHelpers - there is one too many helpers. I would omit "AsyncHelpers" completely from these names.
There was a problem hiding this comment.
Yeah, I was debating whether it's too verbose or helps to differentiate CaptureExecutionContext from ExecutionContext.Capture, but I think I agree.
| READYTORUN_HELPER_InitClass = 0x116, | ||
| READYTORUN_HELPER_InitInstClass = 0x117, | ||
|
|
||
| READYTORUN_HELPER_AsyncHelpersAllocContinuation = 0x120, |
There was a problem hiding this comment.
| READYTORUN_HELPER_AsyncHelpersAllocContinuation = 0x120, | |
| // Helpers for runtime async | |
| READYTORUN_HELPER_AsyncHelpersAllocContinuation = 0x120, |
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.