Skip to content

Commit d40b283

Browse files
committed
Use existing InstantiateDependencies for generic lookups to create shadow nodes
1 parent b0923a9 commit d40b283

File tree

5 files changed

+101
-30
lines changed

5 files changed

+101
-30
lines changed

src/coreclr/tools/Common/Compiler/DependencyAnalysis/ShadowGenericMethodNode.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,7 @@ public override bool StaticDependenciesAreComputed
4444

4545
public ShadowGenericMethodNode(MethodDesc method, IMethodNode canonicalMethod)
4646
{
47-
if (method.ToString().Contains("MyRepro"))
48-
{
49-
System.Console.Error.WriteLine("ShadowGenericMethodNode: " + method.ToString());
50-
}
5147
Debug.Assert(!method.IsRuntimeDeterminedExactMethod);
52-
Debug.Assert(canonicalMethod.Method.IsSharedByGenericInstantiations);
5348
Debug.Assert(canonicalMethod.Method == method.GetCanonMethodTarget(CanonicalFormKind.Specific));
5449
Method = method;
5550
CanonicalMethodNode = canonicalMethod;

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,6 @@ public abstract class GenericLookupResult
7373
protected abstract int ClassCode { get; }
7474
public abstract ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultContext dictionary);
7575

76-
/// <summary>
77-
/// Returns true if this lookup result would produce a concrete (non-canonical) result
78-
/// when instantiated with the given context. This is used to filter out dependencies
79-
/// that would still be canonical after instantiation.
80-
/// </summary>
81-
public virtual bool LookupResultIsConcreteAfterInstantiation(GenericLookupResultContext dictionary)
82-
{
83-
return true;
84-
}
85-
8676
public abstract void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb);
8777
public abstract override string ToString();
8878
protected abstract int CompareToImpl(GenericLookupResult other, TypeSystemComparer comparer);
@@ -515,12 +505,6 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo
515505
return factory.MethodGenericDictionary(instantiatedMethod);
516506
}
517507

518-
public override bool LookupResultIsConcreteAfterInstantiation(GenericLookupResultContext dictionary)
519-
{
520-
var instantiatedMethod = _method.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(dictionary.TypeInstantiation, dictionary.MethodInstantiation);
521-
return !instantiatedMethod.IsSharedByGenericInstantiations;
522-
}
523-
524508
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
525509
{
526510
sb.Append("MethodDictionary_"u8);
@@ -702,12 +686,6 @@ public override ISymbolNode GetTarget(NodeFactory factory, GenericLookupResultCo
702686
return factory.TypeNonGCStaticsSymbol(instantiatedType);
703687
}
704688

705-
public override bool LookupResultIsConcreteAfterInstantiation(GenericLookupResultContext dictionary)
706-
{
707-
var instantiatedType = _type.GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(dictionary.TypeInstantiation, dictionary.MethodInstantiation);
708-
return !instantiatedType.IsCanonicalSubtype(CanonicalFormKind.Any);
709-
}
710-
711689
public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
712690
{
713691
sb.Append("NonGCStaticBase_"u8);

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Internal.TypeSystem;
1111

1212
using ILCompiler.DependencyAnalysisFramework;
13+
using Internal.ReadyToRunConstants;
1314

1415
namespace ILCompiler.DependencyAnalysis
1516
{
@@ -126,14 +127,100 @@ private bool TriggersLazyStaticConstructor(NodeFactory factory)
126127
return factory.PreinitializationManager.HasLazyStaticConstructor(type.ConvertToCanonForm(CanonicalFormKind.Specific));
127128
}
128129

130+
private static bool ContainsCanonicalTypes(Instantiation instantiation)
131+
{
132+
foreach (TypeDesc arg in instantiation)
133+
{
134+
if (arg.IsCanonicalSubtype(CanonicalFormKind.Any))
135+
return true;
136+
}
137+
return false;
138+
}
139+
129140
public IEnumerable<DependencyListEntry> InstantiateDependencies(NodeFactory factory, Instantiation typeInstantiation, Instantiation methodInstantiation)
130141
{
131142
DependencyList result = new DependencyList();
132143

133144
var lookupContext = new GenericLookupResultContext(_dictionaryOwner, typeInstantiation, methodInstantiation);
134-
if (!_lookupSignature.LookupResultIsConcreteAfterInstantiation(lookupContext))
145+
146+
// Check if the instantiation is not fully concrete (contains canonical types like __Canon)
147+
bool isNotConcreteInstantiation = ContainsCanonicalTypes(typeInstantiation) || ContainsCanonicalTypes(methodInstantiation);
148+
149+
if (isNotConcreteInstantiation)
135150
{
136-
return result.ToArray();
151+
switch (_id)
152+
{
153+
case ReadyToRunHelperId.MethodHandle:
154+
case ReadyToRunHelperId.MethodDictionary:
155+
case ReadyToRunHelperId.VirtualDispatchCell:
156+
case ReadyToRunHelperId.MethodEntry:
157+
{
158+
MethodDesc instantiatedMethod = ((MethodDesc)_target).GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
159+
if (instantiatedMethod.IsCanonicalMethod(CanonicalFormKind.Any))
160+
{
161+
if (!instantiatedMethod.IsAbstract)
162+
{
163+
result.Add(new DependencyListEntry(
164+
factory.ShadowGenericMethod(instantiatedMethod),
165+
"Partially instantiated generic dictionary dependencies"));
166+
}
167+
return result.ToArray();
168+
}
169+
}
170+
break;
171+
172+
case ReadyToRunHelperId.TypeHandle:
173+
case ReadyToRunHelperId.NecessaryTypeHandle:
174+
case ReadyToRunHelperId.MetadataTypeHandle:
175+
case ReadyToRunHelperId.TypeHandleForCasting:
176+
case ReadyToRunHelperId.GetGCStaticBase:
177+
case ReadyToRunHelperId.GetNonGCStaticBase:
178+
case ReadyToRunHelperId.GetThreadStaticBase:
179+
case ReadyToRunHelperId.DefaultConstructor:
180+
case ReadyToRunHelperId.ObjectAllocator:
181+
{
182+
TypeDesc instantiatedType = ((TypeDesc)_target).GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(typeInstantiation, methodInstantiation);
183+
if (instantiatedType.IsCanonicalSubtype(CanonicalFormKind.Any))
184+
{
185+
return result.ToArray();
186+
}
187+
}
188+
break;
189+
190+
case ReadyToRunHelperId.FieldHandle:
191+
{
192+
FieldDesc field = (FieldDesc)_target;
193+
TypeDesc instantiatedOwningType = field.OwningType.GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(typeInstantiation, methodInstantiation);
194+
if (instantiatedOwningType.IsCanonicalSubtype(CanonicalFormKind.Any))
195+
{
196+
return result.ToArray();
197+
}
198+
}
199+
break;
200+
201+
case ReadyToRunHelperId.DelegateCtor:
202+
{
203+
DelegateCreationInfo createInfo = (DelegateCreationInfo)_target;
204+
MethodDesc instantiatedMethod = createInfo.PossiblyUnresolvedTargetMethod.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
205+
if (instantiatedMethod.IsCanonicalMethod(CanonicalFormKind.Any))
206+
{
207+
return result.ToArray();
208+
}
209+
}
210+
break;
211+
212+
case ReadyToRunHelperId.ConstrainedDirectCall:
213+
{
214+
ConstrainedCallInfo callInfo = (ConstrainedCallInfo)_target;
215+
MethodDesc instantiatedMethod = callInfo.Method.GetNonRuntimeDeterminedMethodFromRuntimeDeterminedMethodViaSubstitution(typeInstantiation, methodInstantiation);
216+
TypeDesc instantiatedConstrainedType = callInfo.ConstrainedType.GetNonRuntimeDeterminedTypeFromRuntimeDeterminedSubtypeViaSubstitution(typeInstantiation, methodInstantiation);
217+
if (instantiatedMethod.IsCanonicalMethod(CanonicalFormKind.Any) || instantiatedConstrainedType.IsCanonicalSubtype(CanonicalFormKind.Any))
218+
{
219+
return result.ToArray();
220+
}
221+
}
222+
break;
223+
}
137224
}
138225

139226
switch (_id)

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ public static void AddDependenciesDueToReflectability(ref DependencyList depende
6565

6666
if (!method.IsAbstract)
6767
{
68-
dependencies.Add(factory.ShadowGenericMethod(method), "Shadow generic reflectable method");
68+
if (method.IsSharedByGenericInstantiations)
69+
{
70+
dependencies.Add(factory.ShadowGenericMethod(method), "Shadow generic reflectable method");
71+
}
6972
dependencies.Add(factory.AddressTakenMethodEntrypoint(method), "Body of a reflectable method");
7073
}
7174

src/coreclr/tools/aot/ILCompiler.RyuJit/Compiler/RyuJitCompilation.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor
124124
// Determine the list of method we actually need to compile
125125
var methodsToCompile = new List<MethodCodeNode>();
126126
var canonicalMethodsToCompile = new HashSet<MethodDesc>();
127+
var methodNodesToCompile = new HashSet<MethodCodeNode>();
127128

128129
foreach (DependencyNodeCore<NodeFactory> dependency in obj)
129130
{
@@ -144,6 +145,13 @@ protected override void ComputeDependencyNodeDependencies(List<DependencyNodeCor
144145
continue;
145146
}
146147

148+
// Don't add the same node twice (can happen when both a MethodCodeNode and
149+
// a ShadowGenericMethodNode referencing the same canonical method are in the list)
150+
if (!methodNodesToCompile.Add(methodCodeNodeNeedingCode))
151+
{
152+
continue;
153+
}
154+
147155
methodsToCompile.Add(methodCodeNodeNeedingCode);
148156
}
149157

0 commit comments

Comments
 (0)