Expand discovery of generic methods on r2r#127510
Draft
BrzVlad wants to merge 3 commits intodotnet:mainfrom
Draft
Expand discovery of generic methods on r2r#127510BrzVlad wants to merge 3 commits intodotnet:mainfrom
BrzVlad wants to merge 3 commits intodotnet:mainfrom
Conversation
When dependency analysis reaches a virtual invocation, we add this method to the dynamic dependency analysis, so that we end up including all possible implementations on other types.
Contributor
There was a problem hiding this comment.
Pull request overview
This PR expands ReadyToRun (R2R) compilation discovery for generic virtual/interface calls by adding dynamic dependency analysis that resolves additional concrete implementations as new application-used types are discovered in the dependency graph.
Changes:
- Added shared
TypeExtensionshelpers to resolve canonical interface implementations and class virtual overrides on concrete types. - Introduced two new R2R dependency-analysis nodes (
InheritedVirtualMethodsNode,ReadyToRunVirtualMethodDependenciesNode) and wired them into the R2R node factory and build. - Hooked type and method fixup signatures to (a) mark relevant concrete types and (b) track virtual callsites that should trigger dynamic discovery; refactored NativeAOT
GVMDependenciesNodeto reuse the new resolution helpers.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/coreclr/tools/Common/Compiler/TypeExtensions.cs | Adds reusable helpers for resolving canonical interface implementations and class virtual overrides on concrete types. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj | Includes the new dependency-analysis node source files in the R2R build. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunVirtualMethodDependenciesNode.cs | New dynamic-dependency node that discovers and adds compiled-method dependencies for resolved implementations as types are discovered. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs | Adds node caches/factory methods for the new marker and virtual-call dependency nodes. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs | Adds a phase-0 marker dependency so discovered concrete types participate in later virtual dispatch implementation discovery. |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/MethodFixupSignature.cs | Adds a virtual-call dependency node for eligible generic virtual/interface VirtualEntry fixups (with a guard to skip async variants). |
| src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/InheritedVirtualMethodsNode.cs | New “interesting” marker node representing a concrete type for virtual dispatch discovery. |
| src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GVMDependenciesNode.cs | Refactors interface/class override discovery to use the new TypeExtensions helpers. |
Comment on lines
+76
to
+84
| // FIXME Including async methods can lead to crash when compiling Async variant: [S.P.CoreLib] System.IO.TextWriter + SyncTextWriter.DisposeAsync() | ||
| // Crash is assertion in constructStringLiteral that gets called when compiling an IL stub. | ||
| // | ||
| // For generic virtual method calls, create a virtual dependency node that will | ||
| // dynamically discover implementations on types as they are added to the graph. | ||
| if (_fixupKind == ReadyToRunFixupKind.VirtualEntry && | ||
| Method.IsVirtual && | ||
| !Method.IsFinal && | ||
| !Method.IsAsyncVariant() && |
Comment on lines
+96
to
+101
| hasNonCanonArgs = true; | ||
| } | ||
| foreach (TypeDesc arg in canonMethod.OwningType.Instantiation) | ||
| { | ||
| if (arg != context.CanonType) | ||
| hasNonCanonArgs = true; |
Comment on lines
+50
to
+56
| List<CombinedDependencyListEntry> dynamicDependencies = new List<CombinedDependencyListEntry>(); | ||
|
|
||
| bool methodIsShared = _method.IsSharedByGenericInstantiations; | ||
|
|
||
| for (int i = firstNode; i < markedNodes.Count; i++) | ||
| { | ||
| DependencyNodeCore<NodeFactory> entry = markedNodes[i]; |
This was referenced Apr 28, 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.
Called methods are obtained from
MethodFixupSignatureand are stored intoReadyToRunVirtualMethodDependenciesNode. These will be nodes thatHasDynamicDependenciesso the dependency analysis will do additional iterations for these nodes on the newly added nodes that areInterestingForDynamicDependencyAnalysis. These will beInheritedVirtualMethodsNodeadded as part ofTypeFixupSignature. They will represent types used by the application. We resolve the target method for calling the virtual/interface method on the existing types. This attempts to reuse code that NativeAOT also used for this purpose. If we are able to obtain a new method, we include it in the compilation.