Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.

Commit cc4c035

Browse files
committed
Add dependency analysis that better ensures that templates are useable
- In PrecomputedMetadataManager - root Canonical Method instantiation in addition to UniversalCanon instantiation of all specified inputs - For virtual template virtual methods, root the method itself if it isn't abstract in addition to rooting the virtual method use - ArrayMapNode - There must be no entries in the ArrayMap which are merely Necessary. This will cause the runtime to possibly use those directly if there is an attempt to create an array dynamically. (This results in NecessaryEETypeNodes allocated on the GC heap, which leads to crashes in the GC heap) - EETypeNode - Previous change to this file attempted to avoid having a check on EmitVirtualSlotsAndInterfaces... turns out its still necessary or the compiler crashes in some cases. - GVMDependenciesNode - Enable GVM analysis on ProjectN in EnableFullAnalysis mode - NativeLayoutVertexNode.cs - Add dependencies to each NativeLayoutGenericDictionarySlotNode to require that all types referred to directly from slots are sufficiently loaded as to ensure that the template type loader can process those types. - Add dependencies to the TypeTemplate and MethodTemplate node to ensure that the template itself is safely describable - Add dependencies to the TypeTemplate to ensure that the base type and interfaces of a type are properly describable - Add dependencies to NativeLayoutTemplateMethodSignatureVertexNode so that the various uses of that node will work correctly - NodeFactory.NativeLayout - Add helpers used to identify the nodes needed to ensure that a given type are template loadable. - DefaultConstructorMapNode - Add handling for ensuring that not just the constructor method, but also it's type is constructed [tfs-changeset: 1679633]
1 parent b7d43e7 commit cc4c035

File tree

7 files changed

+221
-22
lines changed

7 files changed

+221
-22
lines changed

src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
5252
Section hashTableSection = writer.NewSection();
5353
hashTableSection.Place(typeMapHashTable);
5454

55-
foreach (var type in factory.MetadataManager.GetTypesWithEETypes())
55+
foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes())
5656
{
5757
if (!type.IsSzArray)
5858
continue;
@@ -62,8 +62,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
6262
if (!arrayType.ElementType.IsValueType)
6363
continue;
6464

65-
// Go with a necessary type symbol. It will be upgraded to a constructed one if a constructed was emitted.
66-
IEETypeNode arrayTypeSymbol = factory.NecessaryTypeSymbol(arrayType);
65+
// Look at the constructed type symbol. If a constructed type wasn't emitted, then the array map entry isn't valid for use
66+
IEETypeNode arrayTypeSymbol = factory.ConstructedTypeSymbol(arrayType);
6767

6868
Vertex vertex = writer.GetUnsignedConstant(_externalReferences.GetIndex(arrayTypeSymbol));
6969

src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ public DefaultConstructorFromLazyNode(TypeDesc type)
4141

4242
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
4343
{
44+
yield return new DependencyListEntry(
45+
context.MaximallyConstructableType(TypeNeedingDefaultCtor),
46+
"DefaultConstructorNode type");
47+
4448
yield return new DependencyListEntry(
4549
context.MethodEntrypoint(TypeNeedingDefaultCtor.GetDefaultConstructor(), TypeNeedingDefaultCtor.IsValueType),
4650
"DefaultConstructorNode");

src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalSt
218218
yield break;
219219
}
220220

221+
if (!EmitVirtualSlotsAndInterfaces)
222+
yield break;
223+
221224
DefType defType = _type.GetClosestDefType();
222225

223226
// If we're producing a full vtable, none of the dependencies are conditional.

src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GVMDependenciesNode.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependenci
107107
List<CombinedDependencyListEntry> dynamicDependencies = new List<CombinedDependencyListEntry>();
108108

109109
// Disable dependence tracking for ProjectN
110-
if (factory.Target.Abi == TargetAbi.ProjectN)
110+
if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis)
111111
{
112112
return dynamicDependencies;
113113
}

src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs

Lines changed: 150 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,27 @@ protected override IMethodNode GetMethodEntrypointNode(NodeFactory factory, out
689689
unboxingStub = false;
690690
return methodEntryPointNode;
691691
}
692+
693+
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
694+
{
695+
DependencyList dependencies = (DependencyList)base.GetStaticDependencies(context);
696+
697+
foreach (var arg in _method.Instantiation)
698+
{
699+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(arg))
700+
{
701+
dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable Method Instantiation"));
702+
}
703+
}
704+
705+
706+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType))
707+
{
708+
dependencies.Add(new DependencyListEntry(dependency, "Dependencies to make a generic method template viable OwningType"));
709+
}
710+
711+
return dependencies;
712+
}
692713
}
693714

694715
public sealed class NativeLayoutDictionarySignatureNode : NativeLayoutSavedVertexNode
@@ -810,10 +831,20 @@ public NativeLayoutTemplateMethodLayoutVertexNode(NodeFactory factory, MethodDes
810831

811832
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
812833
{
813-
return new DependencyListEntry[]
834+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_method.OwningType))
814835
{
815-
new DependencyListEntry(context.GenericDictionaryLayout(_method), "Dictionary layout"),
816-
};
836+
yield return new DependencyListEntry(dependency, "method OwningType itself must be template loadable");
837+
}
838+
839+
foreach (var type in _method.Instantiation)
840+
{
841+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(type))
842+
{
843+
yield return new DependencyListEntry(dependency, "method's instantiation arguments must be template loadable");
844+
}
845+
}
846+
847+
yield return new DependencyListEntry(context.GenericDictionaryLayout(_method), "Dictionary layout");
817848
}
818849

819850
private int CompareDictionaryEntries(KeyValuePair<int, NativeLayoutVertexNode> left, KeyValuePair<int, NativeLayoutVertexNode> right)
@@ -924,11 +955,21 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
924955

925956
yield return new DependencyListEntry(typeNode, "Template EEType");
926957

958+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_type))
959+
{
960+
yield return new DependencyListEntry(dependency, "type itslef must be template loadable");
961+
}
962+
927963
yield return new DependencyListEntry(context.GenericDictionaryLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific).GetClosestDefType()), "Dictionary layout");
928964

929965
foreach (TypeDesc iface in _type.RuntimeInterfaces)
930966
{
931967
yield return new DependencyListEntry(context.NativeLayout.TypeSignatureVertex(iface), "template interface list");
968+
969+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(iface))
970+
{
971+
yield return new DependencyListEntry(dependency, "interface type dependency must be template loadable");
972+
}
932973
}
933974

934975
if (context.TypeSystemContext.HasLazyStaticConstructor(_type))
@@ -954,6 +995,11 @@ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFacto
954995
if (_type.BaseType != null && _type.BaseType.IsRuntimeDeterminedSubtype)
955996
{
956997
yield return new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(_type.BaseType)), "template base type");
998+
999+
foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(_type.BaseType))
1000+
{
1001+
yield return new DependencyListEntry(dependency, "base type must be template loadable");
1002+
}
9571003
}
9581004
else if (_type.IsDelegate && _isUniversalCanon)
9591005
{
@@ -1440,7 +1486,12 @@ public NativeLayoutTypeSignatureBasedGenericDictionarySlotNode(NodeFactory facto
14401486

14411487
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
14421488
{
1443-
return new DependencyListEntry[1] { new DependencyListEntry(_signature, "TypeSignature") };
1489+
yield return new DependencyListEntry(_signature, "TypeSignature");
1490+
1491+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_type))
1492+
{
1493+
yield return new DependencyListEntry(dependency, "template construction dependency");
1494+
}
14441495
}
14451496

14461497
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1579,7 +1630,12 @@ public NativeLayoutStaticsGenericDictionarySlotNode(NodeFactory factory, TypeDes
15791630
protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.StaticData;
15801631
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
15811632
{
1582-
return new DependencyListEntry[1] { new DependencyListEntry(_signature, "TypeSignature") };
1633+
yield return new DependencyListEntry(_signature, "TypeSignature");
1634+
1635+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_type))
1636+
{
1637+
yield return new DependencyListEntry(dependency, "template construction dependency");
1638+
}
15831639
}
15841640

15851641
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1632,6 +1688,11 @@ public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(No
16321688
{
16331689
yield return new DependencyListEntry(factory.VirtualMethodUse(method), "Slot number");
16341690
}
1691+
1692+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(method.OwningType))
1693+
{
1694+
yield return new DependencyListEntry(dependency, "template construction dependency");
1695+
}
16351696
}
16361697

16371698
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1678,7 +1739,18 @@ public NativeLayoutMethodDictionaryGenericDictionarySlotNode(NodeFactory factory
16781739
protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.MethodDictionary;
16791740
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
16801741
{
1681-
return new DependencyListEntry[] { new DependencyListEntry(_wrappedNode, "wrappednode") };
1742+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType))
1743+
{
1744+
yield return new DependencyListEntry(dependency, "template construction dependency for method OwningType");
1745+
}
1746+
1747+
foreach (var type in _method.Instantiation)
1748+
{
1749+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type))
1750+
yield return new DependencyListEntry(dependency, "template construction dependency for method Instantiation types");
1751+
}
1752+
1753+
yield return new DependencyListEntry(_wrappedNode, "wrappednode");
16821754
}
16831755

16841756
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1702,7 +1774,12 @@ public NativeLayoutFieldOffsetGenericDictionarySlotNode(FieldDesc field)
17021774

17031775
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
17041776
{
1705-
return new DependencyListEntry[1] { new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Field Containing Type Signature") };
1777+
yield return new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_field.OwningType), "Field Containing Type Signature");
1778+
1779+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType))
1780+
{
1781+
yield return new DependencyListEntry(dependency, "template construction dependency");
1782+
}
17061783
}
17071784

17081785
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1731,7 +1808,12 @@ public NativeLayoutFieldLdTokenGenericDictionarySlotNode(FieldDesc field)
17311808

17321809
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
17331810
{
1734-
return new DependencyListEntry[1] { new DependencyListEntry(factory.NativeLayout.FieldLdTokenVertex(_field), "Field Signature") };
1811+
yield return new DependencyListEntry(factory.NativeLayout.FieldLdTokenVertex(_field), "Field Signature");
1812+
1813+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_field.OwningType))
1814+
{
1815+
yield return new DependencyListEntry(dependency, "template construction dependency");
1816+
}
17351817
}
17361818

17371819
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1764,7 +1846,12 @@ public NativeLayoutVTableOffsetGenericDictionarySlotNode(MethodDesc method)
17641846

17651847
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
17661848
{
1767-
return new DependencyListEntry[1] { new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_slotDefiningMethod.OwningType), "Method VTableOffset Containing Type Signature") };
1849+
yield return new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_slotDefiningMethod.OwningType), "Method VTableOffset Containing Type Signature");
1850+
1851+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_slotDefiningMethod.OwningType))
1852+
{
1853+
yield return new DependencyListEntry(dependency, "template construction dependency");
1854+
}
17681855
}
17691856

17701857
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1792,7 +1879,18 @@ public NativeLayoutMethodLdTokenGenericDictionarySlotNode(MethodDesc method)
17921879

17931880
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
17941881
{
1795-
return new DependencyListEntry[1] { new DependencyListEntry(factory.NativeLayout.MethodLdTokenVertex(_method), "Method Signature") };
1882+
yield return new DependencyListEntry(factory.NativeLayout.MethodLdTokenVertex(_method), "Method Signature");
1883+
1884+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType))
1885+
{
1886+
yield return new DependencyListEntry(dependency, "template construction dependency for method OwningType");
1887+
}
1888+
1889+
foreach (var type in _method.Instantiation)
1890+
{
1891+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type))
1892+
yield return new DependencyListEntry(dependency, "template construction dependency for method Instantiation types");
1893+
}
17961894
}
17971895

17981896
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1821,7 +1919,19 @@ protected sealed override string GetName(NodeFactory factory) =>
18211919

18221920
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
18231921
{
1824-
return new DependencyListEntry[1] { new DependencyListEntry(factory.NativeLayout.MethodSignatureVertex(_signature), "Method Signature") };
1922+
yield return new DependencyListEntry(factory.NativeLayout.MethodSignatureVertex(_signature), "Method Signature");
1923+
1924+
for (int i = 0; i < _signature.Length; i++)
1925+
{
1926+
foreach (var dep in factory.NativeLayout.UniversalTemplateConstructableTypes(_signature[i]))
1927+
{
1928+
yield return new DependencyListEntry(dep, "template construction dependency");
1929+
}
1930+
}
1931+
foreach (var dep in factory.NativeLayout.UniversalTemplateConstructableTypes(_signature.ReturnType))
1932+
{
1933+
yield return new DependencyListEntry(dep, "template construction dependency");
1934+
}
18251935
}
18261936

18271937
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1868,10 +1978,23 @@ public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(No
18681978
constrainedMethodDescriptorNode = factory.NativeLayout.TypeSignatureVertex(_constrainedMethod.OwningType);
18691979
}
18701980

1871-
return new DependencyListEntry[] {
1872-
new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_constraintType), "ConstraintType"),
1873-
new DependencyListEntry(constrainedMethodDescriptorNode, "ConstrainedMethodType"),
1874-
};
1981+
yield return new DependencyListEntry(factory.NativeLayout.TypeSignatureVertex(_constraintType), "ConstraintType");
1982+
1983+
yield return new DependencyListEntry(constrainedMethodDescriptorNode, "ConstrainedMethodType");
1984+
1985+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constrainedMethod.OwningType))
1986+
{
1987+
yield return new DependencyListEntry(dependency, "template construction dependency constrainedMethod OwningType");
1988+
}
1989+
1990+
foreach (var type in _constrainedMethod.Instantiation)
1991+
{
1992+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type))
1993+
yield return new DependencyListEntry(dependency, "template construction dependency constrainedMethod Instantiation type");
1994+
}
1995+
1996+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_constraintType))
1997+
yield return new DependencyListEntry(dependency, "template construction dependency constraintType");
18751998
}
18761999

18772000
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
@@ -1932,7 +2055,18 @@ public NativeLayoutMethodEntrypointGenericDictionarySlotNode(NodeFactory factory
19322055
protected sealed override FixupSignatureKind SignatureKind => FixupSignatureKind.Method;
19332056
public sealed override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
19342057
{
1935-
return new DependencyListEntry[] { new DependencyListEntry(_wrappedNode, "wrappednode") };
2058+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(_method.OwningType))
2059+
{
2060+
yield return new DependencyListEntry(dependency, "template construction dependency for method OwningType");
2061+
}
2062+
2063+
foreach (var type in _method.Instantiation)
2064+
{
2065+
foreach (var dependency in factory.NativeLayout.TemplateConstructableTypes(type))
2066+
yield return new DependencyListEntry(dependency, "template construction dependency for method Instantiation types");
2067+
}
2068+
2069+
yield return new DependencyListEntry(_wrappedNode, "wrappednode");
19362070
}
19372071

19382072
protected sealed override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)

0 commit comments

Comments
 (0)