diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs index e286aa17bbebd1..016c0e7f270458 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs @@ -87,7 +87,7 @@ private partial bool TryHandleIntrinsic( } else { - _reflectionMarker.RuntimeDeterminedDependencies.Add(new MakeGenericTypeSite(typeInstantiated)); + _reflectionMarker.RuntimeDeterminedDependencies.Add((_callingMethod, new MakeGenericTypeSite(typeInstantiated))); } } } @@ -160,7 +160,7 @@ private partial bool TryHandleIntrinsic( } else { - _reflectionMarker.RuntimeDeterminedDependencies.Add(new MakeGenericMethodSite(methodInstantiated)); + _reflectionMarker.RuntimeDeterminedDependencies.Add((_callingMethod, new MakeGenericMethodSite(methodInstantiated))); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs index cb05aa36cb6099..eefe7999dcb9a4 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs @@ -30,7 +30,7 @@ public class ReflectionMarker public NodeFactory Factory { get; } public FlowAnnotations Annotations { get; } public DependencyList Dependencies { get => _dependencies; } - public List RuntimeDeterminedDependencies { get; } = new List(); + public List<(MethodDesc OwningMethod, INodeWithRuntimeDeterminedDependencies Dependency)> RuntimeDeterminedDependencies { get; } = new List<(MethodDesc, INodeWithRuntimeDeterminedDependencies)>(); internal enum AccessKind { diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs index b2eb6834f97b5b..c9a3cd14f19770 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMethodBodyScanner.cs @@ -124,7 +124,7 @@ protected override void Scan(MethodIL methodIL, ref InterproceduralState interpr base.Scan(methodIL, ref interproceduralState); } - public static DependencyList ScanAndProcessReturnValue(NodeFactory factory, FlowAnnotations annotations, Logger logger, MethodIL methodIL, out List runtimeDependencies) + public static DependencyList ScanAndProcessReturnValue(NodeFactory factory, FlowAnnotations annotations, Logger logger, MethodIL methodIL, out List<(MethodDesc OwningMethod, INodeWithRuntimeDeterminedDependencies Dependency)> runtimeDependencies) { #if !ILTRIM methodIL = AsyncMaskingILProvider.WrapIL(methodIL); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs index 026b9a54028948..07533b6b600921 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedMethodNode.cs @@ -19,7 +19,7 @@ namespace ILCompiler.DependencyAnalysis public class DataflowAnalyzedMethodNode : DependencyNodeCore { private readonly MethodIL _methodIL; - private List _runtimeDependencies; + private List<(MethodDesc OwningMethod, INodeWithRuntimeDeterminedDependencies Dependency)> _runtimeDependencies; public DataflowAnalyzedMethodNode(MethodIL methodIL) { @@ -39,29 +39,30 @@ public override IEnumerable GetStaticDependencies(NodeFacto { // Something wrong with the input - missing references, etc. // The method body likely won't compile either, so we don't care. - _runtimeDependencies = new List(); + _runtimeDependencies = new List<(MethodDesc, INodeWithRuntimeDeterminedDependencies)>(); return Array.Empty(); } } public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) { - MethodDesc analyzedMethod = _methodIL.OwningMethod; - - // Look for any generic specialization of this method. If any are found, specialize any dataflow dependencies. + // Look for any generic specialization of this method or its compiler-generated callees (local methods, lambdas). + // If any are found, specialize the dataflow dependencies that originated from that method. for (int i = firstNode; i < markedNodes.Count; i++) { if (markedNodes[i] is not IMethodBodyNode methodBody) continue; MethodDesc method = methodBody.Method; - if (method.GetTypicalMethodDefinition() != analyzedMethod) - continue; + MethodDesc typicalMethod = method.GetTypicalMethodDefinition(); - // Instantiate all runtime dependencies for the found generic specialization + // Instantiate runtime dependencies whose owning method matches this method body's typical definition foreach (var n in _runtimeDependencies) { - foreach (var d in n.InstantiateDependencies(factory, method.OwningType.Instantiation, method.Instantiation, isConcreteInstantiation: !method.IsSharedByGenericInstantiations)) + if (n.OwningMethod != typicalMethod) + continue; + + foreach (var d in n.Dependency.InstantiateDependencies(factory, method.OwningType.Instantiation, method.Instantiation, isConcreteInstantiation: !method.IsSharedByGenericInstantiations)) { yield return new CombinedDependencyListEntry(d.Node, null, d.Reason); } diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Dataflow.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Dataflow.cs index c275b2a8b2c9d0..b4b4239c8bc240 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Dataflow.cs +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/Dataflow.cs @@ -31,6 +31,7 @@ public static int Run() TestMakeGenericConstrainedDataflow.Run(); TestMarshalIntrinsics.Run(); Regression97758.Run(); + TestMakeGenericDataflowInLocalMethod.Run(); return 100; } @@ -792,6 +793,28 @@ public static void Run() Foo.Trigger(); } } + + class TestMakeGenericDataflowInLocalMethod + { + class Gen { } + + struct Atom { } + + class GenMethods + { + public static void Bridge() { } + } + + public static void Run() + { + MakeGenericType(); + MakeGenericMethod(); + + static object MakeGenericType() => Activator.CreateInstance(typeof(Gen<>).MakeGenericType(typeof(T))); + + static void MakeGenericMethod() => typeof(GenMethods).GetMethod(nameof(GenMethods.Bridge)).MakeGenericMethod(typeof(T)).Invoke(null, []); + } + } } static class Assert