Fix scenarios involving GVM on reflection-blocked methods#122497
Merged
MichalStrehovsky merged 2 commits intodotnet:mainfrom Dec 13, 2025
Merged
Fix scenarios involving GVM on reflection-blocked methods#122497MichalStrehovsky merged 2 commits intodotnet:mainfrom
MichalStrehovsky merged 2 commits intodotnet:mainfrom
Conversation
GVM dispatch didn't work when calling an async GVM from a dynamic context (e.g. we are in a GVM and trying to call another GVM). "A generic virtual method was called" is synonymous with "we need a `RuntimeMethodHandle` of a GVM" in the compiler since the GVM dispatch sequence uses the `RuntimeMethodHandle` to identify the GVM slot. Whenever we generate a `RuntimeMethodHandle` (either the static one, or the one in native layout used when runtime type loading) we need to consider it a GVM call. We were correctly considering it in the static case (https://github.com/dotnet/runtime/blob/bed0cadfbf6a7067e24e302549829a45475cd224/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs#L57), however we missed the dynamic case (native layout information for `RuntimeMethodHandle` I'm updating here). We were getting away with this because the line above the one I'm updating (`factory.MetadataManager.GetDependenciesDueToLdToken`) would drop a `ReflectedMethodNode` into the graph that also means "GVM method is called". However we will not get a `ReflectedMethodNode` for something that is reflection-blocked, such as async variants. So we need to explicitly spell out the dependency so that this works for runtime async.
Contributor
|
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes GVM (Generic Virtual Method) dispatch when calling async GVMs from dynamic contexts. The issue occurs because the compiler needs a RuntimeMethodHandle for GVM dispatch, which requires explicit GVM dependencies to be tracked. While static RuntimeMethodHandle generation correctly tracked this, the dynamic case (native layout) was missing the explicit dependency for reflection-blocked methods like async variants.
Key changes:
- Added explicit GVM dependency tracking in
NativeLayoutMethodLdTokenGenericDictionarySlotNodefor dynamic GVM calls - Enabled runtime-async feature in UnitTests to allow testing of this scenario
- Added test coverage for async GVM scenarios that exercise the fixed code path
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs | Added explicit GVM dependency when generating native layout information for RuntimeMethodHandle of virtual generic methods |
| src/tests/nativeaot/SmokeTests/UnitTests/UnitTests.csproj | Enabled runtime-async feature flag to support testing async GVM scenarios |
| src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs | Added test class and invocation to verify async GVM dispatch works correctly in dynamic contexts |
jkotas
approved these changes
Dec 12, 2025
This was referenced Dec 12, 2025
Open
sbomer
approved these changes
Dec 12, 2025
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GVM dispatch didn't work when calling an async GVM from a dynamic context (e.g. we are in a GVM and trying to call another GVM).
"A generic virtual method was called" is synonymous with "we need a
RuntimeMethodHandleof a GVM" in the compiler since the GVM dispatch sequence uses theRuntimeMethodHandleto identify the GVM slot.Whenever we generate a
RuntimeMethodHandle(either the static one, or the one in native layout used when runtime type loading) we need to consider it a GVM call. We were correctly considering it in the static case (runtime/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs
Line 57 in bed0cad
RuntimeMethodHandleI'm updating here).We were getting away with this because the line above the one I'm updating (
factory.MetadataManager.GetDependenciesDueToLdToken) would drop aReflectedMethodNodeinto the graph that also means "GVM method is called". However we will not get aReflectedMethodNodefor something that is reflection-blocked, such as async variants. So we need to explicitly spell out the dependency so that this works for runtime async.Cc @dotnet/ilc-contrib