Skip to content

JIT: add NativeAOT support for non-shared GVM devirtualization - #130202

Merged
jakobbotsch merged 13 commits into
dotnet:mainfrom
hez2010:gvm-devirt-nativeaot
Jul 14, 2026
Merged

JIT: add NativeAOT support for non-shared GVM devirtualization#130202
jakobbotsch merged 13 commits into
dotnet:mainfrom
hez2010:gvm-devirt-nativeaot

Conversation

@hez2010

@hez2010hez2010 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Under NativeAOT, only mark the fat pointer calls but defer the transformation until we are going to perform indirect calls transform, so that the JIT can recognize the tree for GVM devirtualization.

Unfortunately, we are not able to support late devirtualization and guarded devirtualization because fat pointer call transformation happens too early.

Shared GVMs are also not supported due to IL scanner limitations.

Example:

interfaceIGvm{voidTest<T>(Tvalue);}classGvm:IGvm{publicvoidTest<T>(Tvalue){Console.WriteLine(value);}}classProgram{staticvoidMain(string[]args){IGvmgvm1=newGvm();gvm1.Test(42);}}

Before:

G_M24006_IG01:pushrbxsubrsp,32G_M24006_IG02:learcx,[(reloc 0x420b30)] ; Gvmcall CORINFO_HELP_NEWSFASTmovrbx,raxmovrcx,rbxleardx,[(reloc 0x420b40)] ; IGvm:Test[int](int):thiscall CORINFO_HELP_GVMLOOKUP_FOR_SLOTtestal,2je SHORT G_M24006_IG04G_M24006_IG03:movrdx, qword ptr [rax+0x06]movrcx,rbxmovr8d,42call[rax-0x02]jmp SHORT G_M24006_IG05G_M24006_IG04:movrcx,rbxmovedx,42callraxG_M24006_IG05:nopG_M24006_IG06:addrsp,32poprbxret

After:

G_M24006_IG01:subrsp,40G_M24006_IG02:learcx,[(reloc 0x420bc0)] ; System.Int32call CORINFO_HELP_NEWSFASTmov dword ptr [rax+0x08],42movrcx,raxcall System.Console:WriteLine(System.Object)nopG_M24006_IG03:addrsp,40ret

Contributes to #112596

CopilotAI review requested due to automatic review settings July 4, 2026 15:25
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jul 4, 2026
@dotnet-policy-servicedotnet-policy-serviceBot added the community-contribution Indicates that the PR has been added by a community member label Jul 4, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

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

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Enables NativeAOT generic virtual method (GVM) devirtualization by preserving the helper-call-shaped indirection target long enough for the importer’s devirtualization logic to recognize it, while still supporting NativeAOT fat-pointer lowering later during indirect-call transformation.

Changes:

  • Stop spilling NativeAOT GVM ldvirtftn targets to a temp in the importer; instead only mark calls as fat-pointer candidates.
  • In indirect-call transformation, for generic-virtual fat-pointer candidates, split/spill as needed and then materialize the function pointer into a temp local before expanding the fat-pointer control-flow.
  • Ensure fat-pointer-candidate marking is cleared when a call is devirtualized to a direct call; additionally, skip guarded devirtualization for generic-virtual calls.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

FileDescription
src/coreclr/jit/indirectcalltransformer.cppAdds late temp materialization of GVM fat-pointer call targets (post-import) prior to fat-pointer expansion.
src/coreclr/jit/importercalls.cppRemoves early temp spill for NativeAOT GVM ldvirtftn calls; blocks GDV for generic-virtual calls; clears fat-pointer candidate on devirtualization.

Comment threadsrc/coreclr/jit/indirectcalltransformer.cpp Outdated
CopilotAI review requested due to automatic review settings July 4, 2026 15:54

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment threadsrc/coreclr/jit/indirectcalltransformer.cpp Outdated
Comment threadsrc/coreclr/jit/importercalls.cpp Outdated
CopilotAI review requested due to automatic review settings July 4, 2026 16:02

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/jit/importercalls.cpp Outdated
@hez2010

hez2010 commented Jul 4, 2026

Copy link
Copy Markdown
ContributorAuthor

It's hitting IL scanner issues like

error : VTable of type 'DerivedFtnn`1<System.Object>' not computed by the IL scanner. You can work around by running the compilation with scanner disabled. 

cc: @MichalStrehovsky does this ring a bell?

UPDATE: addressed in 2291537

CopilotAI review requested due to automatic review settings July 5, 2026 04:24

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

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

Comment threadsrc/coreclr/jit/indirectcalltransformer.cpp Outdated
Comment threadsrc/coreclr/tools/aot/ILCompiler.Compiler/Compiler/ILScanner.cs Outdated
CopilotAI review requested due to automatic review settings July 5, 2026 04:30
CopilotAI review requested due to automatic review settings July 7, 2026 10:49
CopilotAI reviewed Jul 7, 2026

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@hez2010

hez2010 commented Jul 7, 2026

Copy link
Copy Markdown
ContributorAuthor

@MichalStrehovsky

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@MichalStrehovskyMichalStrehovsky left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The CorInfoImpl.cs change looks good to me!

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@hez2010

Copy link
Copy Markdown
ContributorAuthor

Test failures are unrelated.

@jakobbotsch PTAL.

CopilotAI review requested due to automatic review settings July 10, 2026 15:51

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@hez2010

Copy link
Copy Markdown
ContributorAuthor

CI failures seem unrelated.

@MichalStrehovsky

Copy link
Copy Markdown
Member

/azp run runtime-nativeaot-outerloop

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines successfully started running 1 pipeline(s).

@hez2010

Copy link
Copy Markdown
ContributorAuthor

naot outerloop failure seems to be #130647?

@jakobbotsch

Copy link
Copy Markdown
Member

/ba-g Failure was #130647

@jakobbotsch
jakobbotsch merged commit a20e145 into dotnet:mainJul 14, 2026
152 of 161 checks passed
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
When resolving an instantiated interface GVM, we passed down the method
generic instantiation. However, interface slot selection needs to be
done on the GVM definition, otherwise it could resolve to whatever the
first compatible interface slot we saw. This can produce the incorrect
devirtualized target when a type implements an interface GVM with
multiple variant-compatible instantiations.
Fixed it by stripping the method instantiation before resolving the
interface slot.
The CoreCLR native type system already handles such cases well so we
don't have any issue there.
Found this issue while I was working on GVM devirt for NAOT in #130202.
See added tests for repro: previously it failed for the `CallOnBase`
cases. Tests are added to both the managed type system and the normal
JIT tests to prevent future regressions in either side.
cc: @MichalStrehovsky
@dotnet-milestone-botdotnet-milestone-botBot added this to the 11.0-preview7 milestone Jul 15, 2026
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Aug 15, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMIcommunity-contributionIndicates that the PR has been added by a community member

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@hez2010@MichalStrehovsky@jakobbotsch