Skip to content

Speed up virtual method resolution in the compiler#130405

Merged
MichalStrehovsky merged 3 commits into
dotnet:mainfrom
MichalStrehovsky:fasterresolve
Jul 14, 2026
Merged

Speed up virtual method resolution in the compiler#130405
MichalStrehovsky merged 3 commits into
dotnet:mainfrom
MichalStrehovsky:fasterresolve

Conversation

@MichalStrehovsky

Copy link
Copy Markdown
Member

We enumerate virtual slots and resolve slots to implementations several times, so cache makes it worth it.

Compiling dotnet new webapiaot went from 7.4 seconds to 6.2 seconds. Compiling DynamicGenerics test: 2.45 seconds to 2.09 seconds.

We can probably do the same for interface resolution but don't want a bigger review than what's necessary.

The two prep commits could also be separate:

  • FindSlotDefiningMethodForVirtualMethod never worked for instantiated methods but we had no asserts checking we're not feeding it instantiated methods and this not working is only detectable in IL (and maybe VB.NET?). C# always calls virtuals through the slot defining method. Added assert, fixed fallout.
  • FindVirtualFunctionTargetMethodOnObjectType did something nonsensical when fed uninstantiated generic method. Fixed that.

Copilot AI review requested due to automatic review settings July 9, 2026 12:31
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib
See info in area-owners.md if you want to be subscribed.

@MichalStrehovsky

Copy link
Copy Markdown
Member Author

/azp run runtime-nativeaot-outerloop

@azure-pipelines

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

Copilot AI 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

This PR changes the CoreCLR AOT compiler toolchain’s virtual method resolution to reduce repeated slot enumeration/lookup work by introducing a cached vtable/slot→implementation mapping, and tightens invariants around “slot defining method” helpers to avoid incorrect behavior for instantiated methods.

Changes:

  • Add CachingVirtualMethodAlgorithm and switch async-aware virtual resolution to use it for cached slot enumeration and virtual target lookup.
  • Fix/clarify virtual resolution behavior for generic method definitions vs instantiated methods (and add an invariant assert in FindSlotDefiningMethodForVirtualMethod).
  • Adjust a number of call sites to normalize to method definitions before slot-defining resolution.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/coreclr/tools/Common/TypeSystem/Common/MetadataVirtualMethodAlgorithm.cs Adjusts virtual target resolution instantiation logic; adds an invariant assert requiring method definitions for slot-defining lookup.
src/coreclr/tools/Common/Compiler/GenericCycleDetection/GraphBuilder.cs Normalizes inputs to slot-defining lookup to use method definitions.
src/coreclr/tools/Common/Compiler/DependencyAnalysis/GVMDependenciesNode.cs Updates debug assertion to compare slot-defining methods at method-definition level.
src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.Async.cs Switches async-aware virtual resolution to derive from the new caching algorithm.
src/coreclr/tools/Common/Compiler/CachingVirtualMethodAlgorithm.cs New caching virtual method algorithm that memoizes vtable slot declarations and implementations per type definition.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj Includes the new caching algorithm source into the ReadyToRun tool project.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs Adjusts GVM dependency keying to work with method-definition slot normalization.
src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj Includes the new caching algorithm source into the NativeAOT compiler tool project.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedMetadataManager.cs Updates slot-defining assertion to operate on method definitions.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs Normalizes slot-defining method handling for instantiated methods during reflection virtual invoke dependency computation.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs Normalizes delegate virtual-dispatch target selection through method definitions and re-applies instantiation.

Comment thread src/coreclr/tools/Common/Compiler/CachingVirtualMethodAlgorithm.cs
Comment thread src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs
@MichalStrehovsky

Copy link
Copy Markdown
Member Author

/azp run runtime-coreclr crossgen2-composite

@azure-pipelines

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

@MichalStrehovsky

Copy link
Copy Markdown
Member Author

The only unaccounted failure is unrelated and getting fixed in #130381 so this looks good to go.

@MichalStrehovsky

Copy link
Copy Markdown
Member Author

/ba-g the crossgen outerloop issue was fixed in #130381

@MichalStrehovsky
MichalStrehovsky merged commit 97c5d1f into dotnet:main Jul 14, 2026
155 of 165 checks passed
@MichalStrehovsky
MichalStrehovsky deleted the fasterresolve branch July 14, 2026 00:59
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 11.0-preview7 milestone Jul 14, 2026
eiriktsarpalis pushed a commit that referenced this pull request Jul 15, 2026
We enumerate virtual slots and resolve slots to implementations several
times, so cache makes it worth it.

Compiling `dotnet new webapiaot` went from 7.4 seconds to 6.2 seconds.
Compiling `DynamicGenerics` test: 2.45 seconds to 2.09 seconds.

We can probably do the same for interface resolution but don't want a
bigger review than what's necessary.

The two prep commits could also be separate:

* FindSlotDefiningMethodForVirtualMethod never worked for instantiated
methods but we had no asserts checking we're not feeding it instantiated
methods and this not working is only detectable in IL (and maybe
VB.NET?). C# always calls virtuals through the slot defining method.
Added assert, fixed fallout.
* FindVirtualFunctionTargetMethodOnObjectType did something nonsensical
when fed uninstantiated generic method. Fixed that.
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.

3 participants