Skip to content

Fix scenarios involving GVM on reflection-blocked methods#122497

Merged
MichalStrehovsky merged 2 commits intodotnet:mainfrom
MichalStrehovsky:gvmfix
Dec 13, 2025
Merged

Fix scenarios involving GVM on reflection-blocked methods#122497
MichalStrehovsky merged 2 commits intodotnet:mainfrom
MichalStrehovsky:gvmfix

Conversation

@MichalStrehovsky
Copy link
Member

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 (

dependencies.Add(factory.GVMDependencies(canonMethod), "GVM dependencies for runtime method handle");
), 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.

Cc @dotnet/ilc-contrib

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.
@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 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 NativeLayoutMethodLdTokenGenericDictionarySlotNode for 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

@MichalStrehovsky MichalStrehovsky merged commit 512c425 into dotnet:main Dec 13, 2025
104 checks passed
@MichalStrehovsky MichalStrehovsky deleted the gvmfix branch December 13, 2025 12:40
@github-actions github-actions bot locked and limited conversation to collaborators Jan 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants