Skip to content

[R2R] Expand discovery of non-generic virtual methods on generic types#128652

Open
BrzVlad wants to merge 2 commits into
dotnet:mainfrom
BrzVlad:feature-r2r-generics-non-gvm
Open

[R2R] Expand discovery of non-generic virtual methods on generic types#128652
BrzVlad wants to merge 2 commits into
dotnet:mainfrom
BrzVlad:feature-r2r-generics-non-gvm

Conversation

@BrzVlad

@BrzVlad BrzVlad commented May 27, 2026

Copy link
Copy Markdown
Member

We determine the full set of used generic methods by tracking all types from the app via InheritedVirtualMethodsNode and GVM callsites via GVMDependencies node. The GVMDependencies node then tries to resolve the method on all types from the app, which are a dynamic dependency for this node. This only handles generic methods so, non-generic methods on generic types are not resolved with this mechansim.

This PR completes the support. This is done by adding conditional dependencies to InheritedVirtualMethodsNode. For a generic type, we determine all virtual/interface method slots and the resolved target method. Then we add a conditional dependency that says that the resolved method is included if the slot defining method is used in the app. We detect if the slot defining method is used by creating a VirtualMethodUseNode at callsites.

Methods failing to compile before, from this set of tests: https://gist.github.com/BrzVlad/7ea5987ec494705ac7b4b6aaf1325fe7

Test1Base`1[int]:Test1Method()
Test2C`1[int]:Test2Method()
ITest3WithDim`1[int]:ITest3Base.Test3Method()
Test4A`1[int]:ITest4<T>.Test4Method()
Test5B`1[int]:Test5Method()
Test6B`1[int]:Test6Method()
ITest7`1[int]:Test7Method()

Copilot AI review requested due to automatic review settings May 27, 2026 15:48
@github-actions github-actions Bot added the area-crossgen2-coreclr only use for closed issues label May 27, 2026
@BrzVlad

BrzVlad commented May 27, 2026

Copy link
Copy Markdown
Member Author

/azp run runtime-coreclr crossgen2 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 extends crossgen2/ReadyToRun virtual-dispatch dependency discovery so that non-generic virtual method slots on generic type instantiations can trigger compilation of the correct concrete implementations (in addition to the existing GVM (generic virtual method) mechanism).

Changes:

  • Introduces a new VirtualMethodUseNode marker and a corresponding cache on NodeFactory.
  • Marks non-GVM virtual slots as “used” from MethodFixupSignature for VirtualEntry fixups.
  • Adds conditional static dependencies to InheritedVirtualMethodsNode to compile per-type implementations when a corresponding slot is marked used, and broadens type discovery in TypeFixupSignature to enqueue the node.

Reviewed changes

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

Show a summary per file
File Description
src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj Adds the new VirtualMethodUseNode source file to the project.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs New dependency-analysis marker node representing a used non-GVM virtual slot.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs Adds a node cache + factory method for VirtualMethodUseNode.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs Expands type discovery to add InheritedVirtualMethodsNode when virtual slots/interfaces are present.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs Marks non-GVM virtual slots as used for VirtualEntry fixups to enable conditional compilation.
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/InheritedVirtualMethodsNode.cs Adds conditional static dependencies to compile implementations based on VirtualMethodUseNode conditions (class + interface paths).

BrzVlad added 2 commits June 9, 2026 08:01
We determine the full set of used generic methods by tracking all types from the app via InheritedVirtualMethodsNode and GVM callsites via GVMDependencies node. The GVMDependencies node then tries to resolve the method on all types from the app, which are a dynamic dependency for this node. This only handles generic methods so, non-generic methods on generic types are not resolved with this mechansim.

This PR completes the support. This is done by adding conditional dependencies to InheritedVirtualMethodsNode. For a generic type, we determine all virtual/interface method slots and the resolved target method. Then we add a conditional dependency that says that the resolved method is included if the slot defining method is used in the app. We detect if the slot defining method is used by creating a VirtualMethodUseNode at callsites.
It serves the same purpose both for R2R and NativeAOT
Copilot AI review requested due to automatic review settings June 9, 2026 05:01
@BrzVlad BrzVlad force-pushed the feature-r2r-generics-non-gvm branch from f924912 to ff3d0a6 Compare June 9, 2026 05:01
@BrzVlad

BrzVlad commented Jun 9, 2026

Copy link
Copy Markdown
Member Author

/azp run runtime-coreclr crossgen2 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

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

Comments suppressed due to low confidence (1)

src/coreclr/tools/Common/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs:22

  • Changing VirtualMethodUseNode to public introduces new public surface area in compiler infrastructure. Unless this is intentionally a supported API, it should stay internal (and ideally be hidden behind a base return type) to avoid committing to it long-term and to avoid requiring API-approval tracking.


private NodeCache<MethodDesc, VirtualMethodUseNode> _virtualMethodUseNodes;

public VirtualMethodUseNode VirtualMethodUse(MethodDesc method)
Comment on lines 219 to +223
if (!_typeDesc.IsGenericDefinition &&
!_typeDesc.IsInterface &&
_typeDesc.IsDefType &&
(factory.CompilationCurrentPhase == 0) &&
factory.CompilationModuleGroup.VersionsWithType(_typeDesc) &&
TypeHasGVMSlots(_typeDesc))
factory.CompilationModuleGroup.VersionsWithType(_typeDesc))
Comment on lines +95 to +99
// For non-GVM virtual method calls, mark the virtual slot as used so that
// conditional dependencies on InheritedVirtualMethodsNode can trigger compilation
// of concrete implementations.
if (_fixupKind == ReadyToRunFixupKind.VirtualEntry &&
Method.IsVirtual &&
public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null;

public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

@MichalStrehovsky this would be the equivalent of EETypeNode.GetConditionalStaticDependencies. The code here share some logic with it as well as with the resolving of target method from GVMDependenciesNode. Unfortunately, I couldn't see an easy way to reuse the pieces from there, also without degrading clarity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-crossgen2-coreclr only use for closed issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants