-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Support async generic virtual methods #121524
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
* 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
|
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas |
There was a problem hiding this 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
AsyncVariantproperty toMethodDescand related type system classes to track async method variants - Introduced
IsAsyncVariantflag 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
asyncVariantboolean 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 |
...clr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs
Show resolved
Hide resolved
...der/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs
Show resolved
Hide resolved
...der/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.ConstructedGenericMethodsLookup.cs
Show resolved
Hide resolved
src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs
Show resolved
Hide resolved
...lr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/InstantiatedMethod.Runtime.cs
Outdated
Show resolved
Hide resolved
…ypeSystem/InstantiatedMethod.Runtime.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
jkotas
left a comment
There was a problem hiding this 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?
src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/TypeSystem/RuntimeMethodDesc.cs
Show resolved
Hide resolved
...coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs
Show resolved
Hide resolved
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
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. |
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/ba-g timeouts |
RuntimeMethodHandle, we need aRuntimeMethodHandlefor async variants. Emit the bit in the compiler, at runtime (when type loading), and read it when needed. Reflection stack should never see thisRuntimeMethodHandle.AsyncVariantproperty onMethodDesc(since runtime type system does this for unboxing methods too).MakeGenericMethod.Cc @dotnet/ilc-contrib