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 (NOTE: THIS PR has a few changes to enable RuntimeAsync by default, and build the async tests... those should not be merged)

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.


// Runtime-async
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 0, "Enables runtime async method support")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 1, "Enables runtime async method support")
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

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

This change enables RuntimeAsync by default (changing from 0 to 1). The PR description explicitly states "NOTE: THIS PR has a few changes to enable RuntimeAsync by default... those should not be merged". This change should not be included in the final merge.

Suggested change
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 1, "Enables runtime async method support")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 0, "Enables runtime async method support")

Copilot uses AI. Check for mistakes.
}
else
{
// pMT is an object reference type, simple report the address directly.
Copy link

Copilot AI Nov 20, 2025

Choose a reason for hiding this comment

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

The comment on line 1475 says "pMT is an object reference type, simple report the address directly" but contains a typo: "simple" should be "simply".

Suggested change
// pMT is an object reference type, simple report the address directly.
// pMT is an object reference type, simply report the address directly.

Copilot uses AI. Check for mistakes.
@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.

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.

2 participants