Use dispatch cells for generic virtual method dispatch#129609
Open
MichalStrehovsky wants to merge 5 commits into
Open
Use dispatch cells for generic virtual method dispatch#129609MichalStrehovsky wants to merge 5 commits into
MichalStrehovsky wants to merge 5 commits into
Conversation
Contributor
|
Tagging subscribers to this area: @agocke, @dotnet/ilc-contrib |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR reworks NativeAOT generic virtual method (GVM) dispatch to use dispatch cells (aligning it more closely with interface dispatch), adds new ReadyToRun sections/nodes to emit GVM dispatch-cell metadata, and updates the JIT/AOT toolchain to consume the new helper + lookup shapes.
Changes:
- Introduces GVM dispatch-cell sections/metadata in the compiler output and routes GVM lookups through a dispatch-cell-based helper.
- Refactors “interface dispatch cell” infrastructure into a generalized “dispatch cell” concept used for both interface dispatch and GVM dispatch.
- Moves parts of dispatch resolution into CoreLib (classlib function table) and adds new per-architecture “resolve” helper entrypoints.
Reviewed changes
Copilot reviewed 70 out of 70 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/tools/Common/Internal/Runtime/RuntimeConstants.cs | Introduces GvmDispatchCellFlags for encoding async-variant bit in GVM dispatch-cell metadata. |
| src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs | Adds new ReadyToRun section types for GVM dispatch-cell regions. |
| src/coreclr/tools/Common/Internal/Runtime/InterfaceDispatchCellCachePointerFlags.cs | Removes unused interface-dispatch cache-pointer flags enum. |
| src/coreclr/tools/Common/Internal/Runtime/DispatchCell.cs | Adds shared dispatch-cell structs (including dynamic dispatch-cell layouts). |
| src/coreclr/tools/Common/Internal/NativeFormat/NativeFormat.cs | Allocates FixupSignatureKind.GvmDispatchCell. |
| src/coreclr/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs | Adds ordered node kinds for GVM dispatch-cell sections. |
| src/coreclr/tools/Common/Compiler/DependencyAnalysis/GVMDependenciesNode.cs | Marks compilation with an analysis characteristic when GVMs are present. |
| src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs | Switches call-info emission to use dispatch-cell helpers/const lookups for interface+GVM cases. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs | Uses dispatch-cell symbol node instead of interface-only dispatch cell. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs | Consolidates cell cache from interface-only to general dispatch cells. |
| src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj | Adds new dispatch-cell nodes/sections; removes old interface-dispatch-cell node source. |
| src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs | Updates dependency scanning for dispatch-cell-based GVM/interface lookups. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs | Tracks generalized dispatch cells; emits new GVM dispatch-cell sections into the R2R header. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs | Maps GVMLookupForSlot to the new RhpDispatchResolve entrypoint. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunHelperNode.cs | Emits dispatch-cell references for interface dispatch helper. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X86/X86ReadyToRunGenericHelperNode.cs | Routes generic helper ID from VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunHelperNode.cs | Emits dispatch-cell references for interface dispatch helper. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_X64/X64ReadyToRunGenericHelperNode.cs | Routes generic helper ID from VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunHelperNode.cs | Emits dispatch-cell references for interface dispatch helper. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64ReadyToRunGenericHelperNode.cs | Routes generic helper ID from VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunHelperNode.cs | Emits dispatch-cell references for interface dispatch helper. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64ReadyToRunGenericHelperNode.cs | Routes generic helper ID from VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs | Emits dispatch-cell references for interface dispatch helper. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunGenericHelperNode.cs | Routes generic helper ID from VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs | Emits dispatch-cell references for interface dispatch helper. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs | Routes generic helper ID from VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs | Removes async-variant encoding from runtime method handle node emission. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs | Renames helper ID VirtualDispatchCell to DispatchCell. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs | Updates generic-lookup signatures/comparisons to use dispatch-cell lookup kind. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs | Adds native-layout dictionary slot node for GVM dispatch-cell fixup signatures. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.GenericLookups.cs | Generalizes “virtual dispatch cell” generic lookup result into “dispatch cell”. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs | Generalizes dispatch-cell node cache/factory API. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs | Adds NativeLayoutGvmDispatchGenericDictionarySlotNode implementation. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellInfoSectionNode.cs | Updates section emission to operate on generalized dispatch cells (filters out GVM instantiations). |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GvmDispatchCellInfoSectionNode.cs | Adds new section emitting GVM dispatch-cell info (token+flags+instantiation). |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs | Renames/expands dispatch-cell lookup result to support interface and GVM. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DispatchCellSectionNode.cs | Splits dispatch-cell BSS into interface vs GVM sections via filtering. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DispatchCellNode.cs | Generalizes interface dispatch cell node into a dispatch cell node. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DelegateCreationInfo.cs | Switches delegate creation for GVM/interface targets to dispatch-cell-based lookup. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs | Updates runtime-lookup decision for the new dispatch-cell helper ID. |
| src/coreclr/nativeaot/Test.CoreLib/src/Test.CoreLib.csproj | Links in shared dispatch-cell type(s) and adds a ResolveDispatch export stub. |
| src/coreclr/nativeaot/Test.CoreLib/src/Internal/Runtime/Dispatch.cs | Adds Test.CoreLib ResolveDispatch export (currently stubbed). |
| src/coreclr/nativeaot/System.Private.TypeLoader/src/System.Private.TypeLoader.csproj | Adds AnalysisCharacteristicAttribute compilation input. |
| src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs | Updates GVM token handle construction call signature. |
| src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.LdTokenResultLookup.cs | Removes async-variant handling from runtime-method-handle ldtoken cache machinery. |
| src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.GVMResolution.cs | Reworks GVM resolution input shape (declaring type + handle + instantiation list + async flag). |
| src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.cs | Adds GenericVirtualMethodsPresent analysis characteristic gate and new callback signature. |
| src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs | Allocates dynamic dispatch-cell layouts for interface cells and new GVM dispatch cells. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeMethodHandle.cs | Removes async-variant flag from handle layout; adds helper to resolve GVM targets via callbacks. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/TypeLoaderExports.cs | Removes old GVMLookupForSlot cache-based implementation. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/System/Delegate.cs | Updates GVM delegate initialization to go through dispatch-cell-based resolution. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj | Links dispatch-cell types and adds CoreLib ResolveDispatch implementation source. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Dispatch.cs | Implements ResolveDispatch and static/dynamic dispatch-cell resolution. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/OpenMethodResolver.cs | Updates open-method resolver to resolve GVM targets via the new handle helper. |
| src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/TypeLoaderCallbacks.cs | Changes callback signature for resolving GVM targets (more explicit components). |
| src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml | Adds compat suppressions for new public dispatch-cell types. |
| src/coreclr/nativeaot/Runtime/riscv64/DispatchResolve.S | Adds RhpDispatchResolve entrypoint (returns target rather than dispatching). |
| src/coreclr/nativeaot/Runtime/loongarch64/DispatchResolve.S | Adds RhpDispatchResolve entrypoint (returns target rather than dispatching). |
| src/coreclr/nativeaot/Runtime/i386/DispatchResolve.asm | Adds x86 RhpDispatchResolve (cache probe + fallback to worker). |
| src/coreclr/nativeaot/Runtime/EHHelpers.cpp | Teaches EH helper classification about RhpDispatchResolve AV locations/addresses. |
| src/coreclr/nativeaot/Runtime/arm64/DispatchResolve.S | Factors common macro + adds RhpDispatchResolve variant (returning target). |
| src/coreclr/nativeaot/Runtime/arm64/DispatchResolve.asm | Adds RhpDispatchResolve variant and calls RhpCidResolve_Worker for return-only slow path. |
| src/coreclr/nativeaot/Runtime/arm/DispatchResolve.S | Adds ARM32 RhpDispatchResolve with a barrier before reading cached code. |
| src/coreclr/nativeaot/Runtime/amd64/DispatchResolve.S | Adds RhpDispatchResolve macro variant (returning target). |
| src/coreclr/nativeaot/Runtime/amd64/DispatchResolve.asm | Adds RhpDispatchResolve macro variant and optimized slow path. |
| src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/InternalCalls.cs | Adds ClassLibFunctionId.ResolveDispatch entry. |
| src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs | Routes cache misses to classlib ResolveDispatch and exports RhpCidResolve_Worker. |
| src/coreclr/nativeaot/Bootstrap/main.cpp | Exposes ResolveDispatch in the classlib function table. |
| src/coreclr/jit/importer.cpp | Switches NativeAOT GVM ldvirtftn import to pass dispatch cell instead of runtime method handle. |
| src/coreclr/inc/corinfo.h | Updates helper comment to document dispatch-cell argument for GVM lookup helper. |
Comment on lines
+15
to
+22
| internal static class Dispatch | ||
| { | ||
| [RuntimeExport("ResolveDispatch")] | ||
| internal static unsafe MethodTable* ResolveDispatch(object pObject, DispatchCell* pCell) | ||
| { | ||
| // Assume this is a static dispatch cell first | ||
| foreach (TypeManagerHandle typeManager in StartupCodeHelpers.GetLoadedModules()) | ||
| { |
Comment on lines
+23
to
+33
| var pDispatchCellRegion = (DispatchCell*)RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.InterfaceDispatchCellRegion, out int length); | ||
| if (pCell >= pDispatchCellRegion && pCell < (byte*)pDispatchCellRegion + length) | ||
| { | ||
| return ResolveStaticInterfaceDispatch(typeManager, pObject, (nint)(pCell - pDispatchCellRegion)); | ||
| } | ||
|
|
||
| pDispatchCellRegion = (DispatchCell*)RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.GvmDispatchCellRegion, out length); | ||
| if (pCell >= pDispatchCellRegion && pCell < (byte*)pDispatchCellRegion + length) | ||
| { | ||
| return ResolveGvmDispatch(typeManager, pObject, (nint)(pCell - pDispatchCellRegion)); | ||
| } |
Comment on lines
+32
to
+38
| ld t0, 0(a0) | ||
|
|
||
| ld t1, 0(a1) // load cached MethodTable | ||
| bne t0, t1, LOCAL_LABEL(ResolveInterfaceMethod) | ||
|
|
||
| ld a0, 8(a1) // return cached monomorphic resolved code address | ||
| ret |
Comment on lines
+31
to
+37
| ld.d $t0, $a0, 0 | ||
|
|
||
| ld.d $t1, $a1, 0 // load cached MethodTable | ||
| bne $t0, $t1, LOCAL_LABEL(ResolveInterfaceMethod) | ||
|
|
||
| ld.d $a0, $a1, 8 // return cached monomorphic resolved code address | ||
| jirl $r0, $ra, 0 |
Member
Author
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Comment on lines
+44
to
+46
| private static nint GVMLookupForSlot(object o, RuntimeMethodHandle method) | ||
| => method.ResolveGenericVirtualMethodTarget(o); | ||
|
|
Member
Author
|
/azp run runtime-nativeaot-outerloop |
|
Azure Pipelines successfully started running 1 pipeline(s). |
This was referenced Jun 24, 2026
Open
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This puts generic virtual method dispatch on the same plan as interface method dispatch.
Benefits:
RuntimeMethodHandlefor async method variants that reflection should never see is goneThis is three commits: