Skip to content

Conversation

@davidwrighton
Copy link
Member

@davidwrighton davidwrighton commented Nov 20, 2025

This PR adds runtime async support to the interpreter

Notable changes:

  1. Wrap async method bodies in a try/finally block to capture/restore the exec and sync contexts, just like synchronized methods.
  2. Add a series of instructions for doing a suspend/resume. This set is currently somewhat longer than ideal, and we could simplify this by having a set of managed helper functions to reduce the number of instructions needed.
  3. The continuation is filled in with a copy of the data from the stack.
  4. The calling convention is non-traditional for the extra return value. For the continuation argument, instead of representing it on the stack as part of the return value, we represent it as a field on the InterpreterFrame, and update and check that frame as needed. This allows the vast majority of the code in the compiler to ignore the concept of runtime-async.
  5. The call stub generator is also modified to pass the extra parameter, but more significantly, all of the stubs which call into the interpreter are setup to now capture the continuation argument and put it into the special return register.
  6. Tests have been updated to do less work when running under the interpreter. Some of the existing tests were designed specifically to trigger various rejit thresholds, and while that is a fine thing to test in the JIT, the interpreter is FAR slower, and needs a different approach.

TODO before merge
1. Remove the changes to enable RuntimeAsync by default.
2. Add documentation about how the interpreter async abi works
3. Add documentation about what a code generator needs to do to make runtime async work
4. I'm pretty sure IL peep handling has a bug handling any of the 2 byte opcodes. This needs to be tested.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds runtime async support to the CLR interpreter, enabling async/await functionality in interpreted code. The implementation wraps async method bodies in try/finally blocks for context management, adds specialized opcodes for suspend/resume operations, and introduces a non-traditional calling convention for passing continuation objects via a dedicated InterpreterFrame field.

Key changes:

  • Added async continuation handling with specialized interpreter opcodes
  • Modified call stubs across multiple architectures to support continuation return values
  • Adjusted test workloads to be more suitable for interpreter performance characteristics

Reviewed Changes

Copilot reviewed 54 out of 54 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/tests/async/*.csproj Added TestLibrary project references for interpreter detection
src/tests/async/*.cs Reduced Fibonacci test parameters when running under interpreter
src/tests/async/Directory.Build.targets SHOULD NOT MERGE: Deleted file enables async tests by default
src/coreclr/inc/clrconfigvalues.h SHOULD NOT MERGE: Changed RuntimeAsync default to 1
src/coreclr/vm//asmhelpers. Updated assembly helpers to pass continuation return parameter
src/coreclr/vm/*/asmconstants.h Updated CallStubHeader offset for new HasContinuationRet field
src/coreclr/vm/callstubgenerator.* Added HasContinuationRet support and continuation parameter handling
src/coreclr/vm/interpexec.* Added AsyncHelpers_ResumeInterpreterContinuation and continuation opcodes
src/coreclr/vm/frames.* Added continuation field and GC scanning to InterpreterFrame
src/coreclr/vm/object.h Defined ContinuationObject class structure
src/coreclr/vm/jitinterface.* Added getAsyncResumptionStub implementation for interpreter
src/coreclr/vm/prestub.cpp Added continuation return value population logic
src/coreclr/interpreter/. Major compiler changes for async support including interval maps and suspend/resume logic
src/coreclr/System.Private.CoreLib/* Added QCall for ResumeInterpreterContinuation
Comments suppressed due to low confidence (1)

src/tests/async/Directory.Build.targets:1

  • The deletion of this entire file enables async tests to build and run by default. However, the PR description explicitly states "NOTE: THIS PR has a few changes to enable RuntimeAsync by default, and build the async tests... those should not be merged". This file deletion should not be included in the final merge.

@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

@jakobbotsch
Copy link
Member

This looks great to me.

Copy link
Member

@janvorli janvorli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@davidwrighton davidwrighton enabled auto-merge (squash) December 4, 2025 18:16
@agocke
Copy link
Member

agocke commented Dec 4, 2025

Github bug -- all comments are resolved

@agocke agocke disabled auto-merge December 4, 2025 18:28
@agocke agocke merged commit 192bdc3 into dotnet:main Dec 4, 2025
140 of 145 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants