Skip to content

Commit bdaff9d

Browse files
Limit expansion in TemplateConstructableTypes
The template type loader is a limited type loader that we use in native AOT to support scenarios such as `MakeGenericType`. We keep around extra MethodTables and metadata to be able to construct new type instantiations (e.g. `List<string>`) at runtime from template instantiations (e.g. `List<__Canon>`) we made at compile time. The template instantiation is a `MethodTable` like any other that we make a copy of and patch up with the help of the metadata ("native layout metadata"). Patching up involves e.g. building interface list (`List<string>` should have `IList<string>` in the interface list). This patching up may involve loading more new types from templates (e.g. the mentioned `IList<string>` that needs to be loadable from a `IList<__Canon>` template MethodTable). The job of the compiler is to figure out all the templates we might need (recursively) to build a type. This is done in places using a rather non-exact `TemplateConstructableTypes` call that just decomposes the type and makes templates for _everything_. Some of these might not be actually needed. This is an attempt to somewhat limit it.
1 parent 9fa2ecb commit bdaff9d

File tree

2 files changed

+12
-43
lines changed

2 files changed

+12
-43
lines changed

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

Lines changed: 6 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -650,27 +650,6 @@ protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory)
650650
IMethodNode methodEntryPointNode = factory.AddressTakenMethodEntrypoint(_method, IsUnboxingStub);
651651
return methodEntryPointNode;
652652
}
653-
654-
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
655-
{
656-
DependencyList dependencies = (DependencyList)base.GetStaticDependencies(context);
657-
658-
foreach (var arg in _method.Instantiation)
659-
{
660-
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(arg))
661-
{
662-
dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable Method Instantiation"));
663-
}
664-
}
665-
666-
667-
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType))
668-
{
669-
dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable OwningType"));
670-
}
671-
672-
return dependencies;
673-
}
674653
}
675654

676655
public sealed class NativeLayoutDictionarySignatureNode : NativeLayoutSavedVertexNode
@@ -788,19 +767,6 @@ public NativeLayoutTemplateMethodLayoutVertexNode(NodeFactory factory, MethodDes
788767

789768
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
790769
{
791-
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType))
792-
{
793-
yield return new DependencyListEntry(dependency, "method OwningType itself must be template loadable");
794-
}
795-
796-
foreach (var type in _method.Instantiation)
797-
{
798-
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(type))
799-
{
800-
yield return new DependencyListEntry(dependency, "method's instantiation arguments must be template loadable");
801-
}
802-
}
803-
804770
foreach (GenericParameterDesc genericParam in _method.GetTypicalMethodDefinition().Instantiation)
805771
{
806772
foreach (TypeDesc typeConstraint in genericParam.TypeConstraints)
@@ -1103,6 +1069,7 @@ public abstract class NativeLayoutTypeSignatureBasedGenericDictionarySlotNode :
11031069

11041070
public NativeLayoutTypeSignatureBasedGenericDictionarySlotNode(NodeFactory factory, TypeDesc type)
11051071
{
1072+
Debug.Assert(type.IsRuntimeDeterminedSubtype);
11061073
_signature = factory.NativeLayout.TypeSignatureVertex(type);
11071074
_type = type;
11081075
}
@@ -1239,6 +1206,7 @@ public sealed class NativeLayoutInterfaceDispatchGenericDictionarySlotNode : Nat
12391206

12401207
public NativeLayoutInterfaceDispatchGenericDictionarySlotNode(NodeFactory factory, MethodDesc method)
12411208
{
1209+
Debug.Assert(method.IsRuntimeDeterminedExactMethod);
12421210
_signature = factory.NativeLayout.TypeSignatureVertex(method.OwningType);
12431211
_method = method;
12441212
}
@@ -1250,16 +1218,14 @@ public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(No
12501218
{
12511219
yield return new DependencyListEntry(_signature, "TypeSignature");
12521220

1253-
MethodDesc method = _method;
1254-
if (method.IsRuntimeDeterminedExactMethod)
1255-
method = method.GetCanonMethodTarget(CanonicalFormKind.Specific);
1221+
MethodDesc canonMethod = _method.GetCanonMethodTarget(CanonicalFormKind.Specific);
12561222

1257-
if (!factory.VTable(method.OwningType).HasKnownVirtualMethodUse)
1223+
if (!factory.VTable(canonMethod.OwningType).HasKnownVirtualMethodUse)
12581224
{
1259-
yield return new DependencyListEntry(factory.VirtualMethodUse(method), "Slot number");
1225+
yield return new DependencyListEntry(factory.VirtualMethodUse(canonMethod), "Slot number");
12601226
}
12611227

1262-
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(method.OwningType))
1228+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType))
12631229
{
12641230
yield return new DependencyListEntry(dependency, "template construction dependency");
12651231
}

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,12 @@ private void CreateNodeCaches()
150150
// of just necessary. (Which is what the actual templates signatures will ensure)
151151
public IEnumerable<IDependencyNode> TemplateConstructableTypes(TypeDesc type)
152152
{
153+
if (!type.IsRuntimeDeterminedSubtype)
154+
{
155+
yield return _factory.MaximallyConstructableType(type);
156+
yield break;
157+
}
158+
153159
// Array types are the only parameterized types that have templates
154160
if (type.IsSzArray && !type.IsArrayTypeWithoutGenericInterfaces())
155161
{
@@ -160,8 +166,6 @@ public IEnumerable<IDependencyNode> TemplateConstructableTypes(TypeDesc type)
160166
{
161167
yield return _factory.NativeLayout.TemplateTypeLayout(arrayCanonicalType);
162168
}
163-
164-
yield return _factory.MaximallyConstructableType(arrayCanonicalType);
165169
}
166170

167171
while (type.IsParameterizedType)
@@ -184,7 +188,6 @@ public IEnumerable<IDependencyNode> TemplateConstructableTypes(TypeDesc type)
184188
}
185189

186190
TypeDesc canonicalType = type.ConvertToCanonForm(CanonicalFormKind.Specific);
187-
yield return _factory.MaximallyConstructableType(canonicalType);
188191

189192
// Add a dependency on the template for this type, if the canonical type should be generated into this binary.
190193
if (canonicalType.IsCanonicalSubtype(CanonicalFormKind.Any) && !_factory.NecessaryTypeSymbol(canonicalType).RepresentsIndirectionCell)

0 commit comments

Comments
 (0)