Skip to content

Conversation

@MichalStrehovsky
Copy link
Member

  • Since generic virtual method dispatch is based on RuntimeMethodHandle, we need a RuntimeMethodHandle for async variants. Emit the bit in the compiler, at runtime (when type loading), and read it when needed. Reflection stack should never see this RuntimeMethodHandle.
  • Add AsyncVariant property on MethodDesc (since runtime type system does this for unboxing methods too).
  • Add a flag that distinguishes async variants in native layout. This is not specific to GVMs, it also covers other cases of runtime generic dictionary building, such as MakeGenericMethod.
  • Add a flag that distinguishes these in generic method dictionary hashtables (both static and built at runtime)
  • Lots of piping through the extra bool

Cc @dotnet/ilc-contrib

* Since generic virtual method dispatch is based on `RuntimeMethodHandle`, we need a `RuntimeMethodHandle` for async variants. Emit the bit in the compiler, at runtime (when type loading), and read it when needed. Reflection stack should never see this `RuntimeMethodHandle`.
* Add `AsyncVariant` property on `MethodDesc` (since runtime type system does this for unboxing methods too).
* Add a flag that distinguishes async variants in native layout. This is not specific to GVMs, it also covers other cases of runtime generic dictionary building, such as `MakeGenericMethod`.
* Add a flag that distinguishes these in generic method dictionary hashtables (both static and built at runtime)
* Lots of piping through the extra bool
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas
See info in area-owners.md if you want to be subscribed.

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 pull request adds support for async generic virtual methods by introducing an IsAsyncVariant flag throughout the runtime type system. The core mechanism involves emitting and reading special RuntimeMethodHandles for async variants while ensuring they remain transparent to the reflection stack.

Key Changes

  • Added AsyncVariant property to MethodDesc and related type system classes to track async method variants
  • Introduced IsAsyncVariant flag constants in multiple locations (RuntimeMethodHandle, GenericMethodsHashtable, NativeFormat MethodFlags) to distinguish async variants in data structures
  • Modified GVM metadata emission to skip async variants since they duplicate metadata
  • Updated all method resolution and instantiation code paths to thread the asyncVariant boolean parameter through

Reviewed Changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
TypeGVMEntriesNode.cs Filters out async variants when scanning for GVM entries to avoid metadata duplication
RuntimeMethodHandleNode.cs Stores async variant flag in the instantiation length field, retrieves actual method target for metadata
NativeLayoutVertexNode.cs Marks methods with IsAsyncVariant flag and retrieves correct metadata token
GenericMethodsHashtableNode.cs Encodes async variant flag in the token field of hashtable entries
RuntimeConstants.cs Defines IsAsyncVariant constants for RuntimeMethodHandle and GenericMethodsHashtable
NativeFormat.cs Adds IsAsyncVariant flag to MethodFlags enum
TypeSystemContext.Runtime.cs Adds asyncVariant to method key comparison and resolution logic
RuntimeMethodDesc.cs Implements AsyncVariant property and threads it through method resolution
RuntimeMethodDesc.Canon.cs Passes AsyncVariant when resolving canonical method target
MethodDesc.Runtime.cs Defines virtual AsyncVariant property with default false implementation
InstantiatedMethod.Runtime.cs Delegates AsyncVariant property to method definition
TypeLoaderEnvironment.cs Updates method component retrieval to include asyncVariant output parameter
TypeLoaderEnvironment.Metadata.cs Passes isAsyncVariant: false in virtual resolve scenarios
TypeLoaderEnvironment.LdTokenResultLookup.cs Adds async variant handling and assertion that reflection never sees async variants
TypeLoaderEnvironment.GVMResolution.cs Threads async variant flag through GVM resolution
TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs Decodes async variant flag from hashtable and static data, stores in method entries
TypeBuilder.cs Stores async variant flag when registering generic method entries
NativeLayoutInfoLoadContext.cs Reads async variant flag from native layout and passes to method resolution
GenericDictionaryCell.cs Passes AsyncVariant when creating RuntimeMethodHandle
ExecutionEnvironmentImplementation.MappingTables.cs Asserts async variants are not visible to reflection
RuntimeMethodHandle.cs Restructures MethodHandleInfo to store flags packed with NumGenericArgs

…ypeSystem/InstantiatedMethod.Runtime.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

Worth doing outer loop run or size check to validate that the async variants are not getting pulled in unexpectedly?

@MichalStrehovsky
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovsky
Copy link
Member Author

Worth doing outer loop run or size check to validate that the async variants are not getting pulled in unexpectedly?

Triggered outerloop. rt-sz runs will be on the floor until we start producing .NET 11 bits unfortunately.

@MichalStrehovsky
Copy link
Member Author

Worth doing outer loop run or size check to validate that the async variants are not getting pulled in unexpectedly?

Triggered outerloop. rt-sz runs will be on the floor until we start producing .NET 11 bits unfortunately.

Libs outerloop looks good. The CoreCLR test tree outerloop is on the floor, fix in #121541.

Let's not merge yet, I did a self-review and there's one more thing I want to fix.

@MichalStrehovsky
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovsky
Copy link
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovsky
Copy link
Member Author

/ba-g timeouts

@MichalStrehovsky MichalStrehovsky merged commit 3927844 into dotnet:main Nov 12, 2025
100 of 119 checks passed
@MichalStrehovsky MichalStrehovsky deleted the gvmasync branch November 12, 2025 21:47
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