Speed up virtual method resolution in the compiler#130405
Conversation
…ated generic method
Compiling DynamicGenerics.obj went from taking 2.44 seconds to 2.16 seconds.
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
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
CachingVirtualMethodAlgorithmand 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. |
|
/azp run runtime-coreclr crossgen2-composite |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
The only unaccounted failure is unrelated and getting fixed in #130381 so this looks good to go. |
|
/ba-g the crossgen outerloop issue was fixed in #130381 |
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.
We enumerate virtual slots and resolve slots to implementations several times, so cache makes it worth it.
Compiling
dotnet new webapiaotwent from 7.4 seconds to 6.2 seconds. CompilingDynamicGenericstest: 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: