Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Wrighton <davidwr@microsoft.com>2017-10-25 00:31:50 +0300
committerDavid Wrighton <davidwr@microsoft.com>2017-10-25 00:31:50 +0300
commit789e00c53bf1d0786150ce5d8b6cb3cb0301a9ec (patch)
tree69e873e7b17007e81b77c462ead177a7850fb82e /src/ILCompiler.Compiler
parentdce2dbd1b167199c80fd5d871e0ef8c30972b3ae (diff)
Fixes for dependency tracking around EETypes and templates
- The existence of a static field block for a type which has canonically equivalent reflectable implementation requires the type that contains the static field to be necessary. This allows FieldInfo.GetValue/SetValue to work correctly - If a constructed type has a generic virtual method defined upon it, and universal generics is enabled, force the virtual method to have a universal shared generic implementation - Add a helper routine for getting the maximally constructed type symbol. [tfs-changeset: 1679063]
Diffstat (limited to 'src/ILCompiler.Compiler')
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/Compilation.cs9
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs4
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs104
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs12
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs6
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs8
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs11
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs3
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs1
-rw-r--r--src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs5
12 files changed, 133 insertions, 34 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
index 19fde9b0b..443716a15 100644
--- a/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/Compilation.cs
@@ -334,14 +334,7 @@ namespace ILCompiler
public void AddCompilationRoot(TypeDesc type, string reason)
{
- if (!ConstructedEETypeNode.CreationAllowed(type))
- {
- _graph.AddRoot(_factory.NecessaryTypeSymbol(type), reason);
- }
- else
- {
- _graph.AddRoot(_factory.ConstructedTypeSymbol(type), reason);
- }
+ _graph.AddRoot(_factory.MaximallyConstructableType(type), reason);
}
public void RootThreadStaticBaseForType(TypeDesc type, string reason)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
index cd5b438ad..afca8fa75 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs
@@ -56,8 +56,12 @@ namespace ILCompiler.DependencyAnalysis
// Track generic virtual methods that will get added to the GVM tables
if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
+ {
dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type), "Type with generic virtual methods"));
+ AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
+ }
+
return dependencyList;
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
index 350214ec6..0237f9b8b 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs
@@ -119,6 +119,8 @@ namespace ILCompiler.DependencyAnalysis
if (TypeGVMEntriesNode.TypeNeedsGVMTableEntries(_type))
{
dependencyList.Add(new DependencyListEntry(factory.TypeGVMEntries(_type), "Type with generic virtual methods"));
+
+ AddDependenciesForUniversalGVMSupport(factory, _type, ref dependencyList);
}
if (factory.TypeSystemContext.HasLazyStaticConstructor(_type))
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
index 2d22f146e..2fba4a059 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs
@@ -146,10 +146,41 @@ namespace ILCompiler.DependencyAnalysis
public override bool IsShareable => IsTypeNodeShareable(_type);
+ private bool CanonFormTypeMayExist
+ {
+ get
+ {
+ if (!_type.HasInstantiation)
+ return false;
+
+ if (!_type.Context.SupportsCanon)
+ return false;
+
+ // If type is already in canon form, a canonically equivalent type cannot exist
+ if (_type.IsCanonicalSubtype(CanonicalFormKind.Any))
+ return false;
+
+ // If we reach here, a universal canon variant can exist (if universal canon is supported)
+ if (_type.Context.SupportsUniversalCanon)
+ return true;
+
+ // Attempt to convert to canon. If the type changes, then the CanonForm exists
+ return (_type.ConvertToCanonForm(CanonicalFormKind.Specific) != _type);
+ }
+ }
+
public sealed override bool HasConditionalStaticDependencies
{
get
{
+ // If the type is can be converted to some interesting canon type, and this is the non-constructed variant of an EEType
+ // we may need to trigger the fully constructed type to exist to make the behavior of the type consistent
+ // in reflection and generic template expansion scenarios
+ if (CanonFormTypeMayExist && ProjectNDependencyBehavior.EnableFullAnalysis)
+ {
+ return true;
+ }
+
if (!EmitVirtualSlotsAndInterfaces)
return false;
@@ -170,9 +201,22 @@ namespace ILCompiler.DependencyAnalysis
}
}
- public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
+ public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
{
- Debug.Assert(EmitVirtualSlotsAndInterfaces);
+ IEETypeNode maximallyConstructableType = factory.MaximallyConstructableType(_type);
+
+ if (maximallyConstructableType != this)
+ {
+ // EEType upgrading from necessary to constructed if some template instantation exists that matches up
+ if (CanonFormTypeMayExist)
+ {
+ yield return new CombinedDependencyListEntry(maximallyConstructableType, factory.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Trigger full type generation if canonical form exists");
+
+ if (_type.Context.SupportsUniversalCanon)
+ yield return new CombinedDependencyListEntry(maximallyConstructableType, factory.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Universal)), "Trigger full type generation if universal canonical form exists");
+ }
+ yield break;
+ }
DefType defType = _type.GetClosestDefType();
@@ -1028,6 +1072,62 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public static void AddDependenciesForStaticsNode(NodeFactory factory, TypeDesc type, ref DependencyList dependencies)
+ {
+ if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis)
+ return;
+
+ // To ensure that the behvior of FieldInfo.GetValue/SetValue remains correct,
+ // if a type may be reflectable, and it is generic, if a canonical instantiation of reflection
+ // can exist which can refer to the associated type of this static base, ensure that type
+ // has an EEType. (Which will allow the static field lookup logic to find the right type)
+ if (type.HasInstantiation && factory.MetadataManager.SupportsReflection && !factory.MetadataManager.IsReflectionBlocked(type))
+ {
+ // This current implementation is slightly generous, as it does not attempt to restrict
+ // the created types to the maximum extent by investigating reflection data and such. Here we just
+ // check if we support use of a canonically equivalent type to perform reflection.
+ // We don't check to see if reflection is enabled on the type.
+ if (factory.TypeSystemContext.SupportsUniversalCanon
+ || (factory.TypeSystemContext.SupportsCanon && (type != type.ConvertToCanonForm(CanonicalFormKind.Specific))))
+ {
+ if (dependencies == null)
+ dependencies = new DependencyList();
+
+ dependencies.Add(factory.NecessaryTypeSymbol(type), "Static block owning type is necessary for canonically equivalent reflection");
+ }
+ }
+ }
+
+ protected static void AddDependenciesForUniversalGVMSupport(NodeFactory factory, TypeDesc type, ref DependencyList dependencies)
+ {
+ if (factory.TypeSystemContext.SupportsUniversalCanon)
+ {
+ if ((factory.Target.Abi == TargetAbi.ProjectN) && !ProjectNDependencyBehavior.EnableFullAnalysis)
+ return;
+
+ foreach (MethodDesc method in type.GetMethods())
+ {
+ if (!method.IsVirtual || !method.HasInstantiation)
+ continue;
+
+ if (method.IsAbstract)
+ continue;
+
+ TypeDesc[] universalCanonArray = new TypeDesc[method.Instantiation.Length];
+ for (int i = 0; i < universalCanonArray.Length; i++)
+ universalCanonArray[i] = factory.TypeSystemContext.UniversalCanonType;
+
+ MethodDesc universalCanonMethodNonCanonicalized = method.MakeInstantiatedMethod(new Instantiation(universalCanonArray));
+ MethodDesc universalCanonGVMMethod = universalCanonMethodNonCanonicalized.GetCanonMethodTarget(CanonicalFormKind.Universal);
+
+ if (dependencies == null)
+ dependencies = new DependencyList();
+
+ dependencies.Add(new DependencyListEntry(factory.MethodEntrypoint(universalCanonGVMMethod), "USG GVM Method"));
+ }
+ }
+ }
+
private struct SlotCounter
{
private int _startBytes;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs
index e80d799de..64c99b3b1 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs
@@ -75,6 +75,8 @@ namespace ILCompiler.DependencyAnalysis
}
dependencyList.Add(factory.GCStaticIndirection(_type), "GC statics indirection");
+ EETypeNode.AddDependenciesForStaticsNode(factory, _type, ref dependencyList);
+
return dependencyList;
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs
index 8ccbd0c08..d6a4b295c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs
@@ -62,11 +62,7 @@ namespace ILCompiler.DependencyAnalysis
{
// If the type does not have fully constructed type, don't track its dependencies.
// TODO: Remove the workaround once we stop using the STS dependency analysis.
- IDependencyNode node;
- if (ConstructedEETypeNode.CreationAllowed(type))
- node = factory.ConstructedTypeSymbol(type);
- else
- node = factory.NecessaryTypeSymbol(type);
+ IDependencyNode node = factory.MaximallyConstructableType(type);
if (!node.Marked)
continue;
@@ -111,11 +107,7 @@ namespace ILCompiler.DependencyAnalysis
{
// If the type does not have fully constructed type, don't track its dependencies.
// TODO: Remove the workaround once we stop using the STS dependency analysis.
- IDependencyNode node;
- if (ConstructedEETypeNode.CreationAllowed(templateType))
- node = factory.ConstructedTypeSymbol(templateType);
- else
- node = factory.NecessaryTypeSymbol(templateType);
+ IDependencyNode node = factory.MaximallyConstructableType(templateType);
if (!node.Marked)
return;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
index 2b181fa90..1ade913fe 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
@@ -920,11 +920,7 @@ namespace ILCompiler.DependencyAnalysis
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
{
- ISymbolNode typeNode;
- if (!ConstructedEETypeNode.CreationAllowed(_type))
- typeNode = context.NecessaryTypeSymbol(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
- else
- typeNode = context.ConstructedTypeSymbol(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
+ ISymbolNode typeNode = context.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
yield return new DependencyListEntry(typeNode, "Template EEType");
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
index 91bcfdb34..6d267094e 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs
@@ -533,6 +533,14 @@ namespace ILCompiler.DependencyAnalysis
private NodeCache<TypeDesc, IEETypeNode> _clonedTypeSymbols;
+ public IEETypeNode MaximallyConstructableType(TypeDesc type)
+ {
+ if (ConstructedEETypeNode.CreationAllowed(type))
+ return ConstructedTypeSymbol(type);
+ else
+ return NecessaryTypeSymbol(type);
+ }
+
public IEETypeNode ConstructedClonedTypeSymbol(TypeDesc type)
{
Debug.Assert(!TypeCannotHaveEEType(type));
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs
index 359930727..7feef9bba 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs
@@ -102,14 +102,17 @@ namespace ILCompiler.DependencyAnalysis
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
+ DependencyList dependencyList = null;
+
if (factory.TypeSystemContext.HasEagerStaticConstructor(_type))
{
- var result = new DependencyList();
- result.Add(factory.EagerCctorIndirection(_type.GetStaticConstructor()), "Eager .cctor");
- return result;
+ dependencyList = new DependencyList();
+ dependencyList.Add(factory.EagerCctorIndirection(_type.GetStaticConstructor()), "Eager .cctor");
}
- return null;
+ EETypeNode.AddDependenciesForStaticsNode(factory, _type, ref dependencyList);
+
+ return dependencyList;
}
public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs
index 9a66b0e43..eed926b2c 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs
@@ -53,7 +53,7 @@ namespace ILCompiler.DependencyAnalysis
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory)
{
- List<DependencyListEntry> result = new List<DependencyListEntry>();
+ DependencyList result = new DependencyList();
result.Add(new DependencyListEntry(GetGCStaticEETypeNode(factory), "ThreadStatic EEType"));
@@ -62,6 +62,7 @@ namespace ILCompiler.DependencyAnalysis
result.Add(new DependencyListEntry(factory.EagerCctorIndirection(_type.GetStaticConstructor()), "Eager .cctor"));
}
+ EETypeNode.AddDependenciesForStaticsNode(factory, _type, ref result);
return result;
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs
index c998cb55f..ccf216622 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs
@@ -43,6 +43,7 @@ namespace ILCompiler.DependencyAnalysis
}
dependencyList.Add(((UtcNodeFactory)factory).TypeThreadStaticGCDescNode(_type), "GC Desc");
+ EETypeNode.AddDependenciesForStaticsNode(factory, _type, ref dependencyList);
return dependencyList;
}
diff --git a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
index b30e9e7b4..cf4df3cd0 100644
--- a/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
+++ b/src/ILCompiler.Compiler/src/IL/ILImporter.Scanner.cs
@@ -753,10 +753,7 @@ namespace Internal.IL
}
else
{
- if (ConstructedEETypeNode.CreationAllowed(type))
- _dependencies.Add(_factory.ConstructedTypeSymbol(type), "ldtoken");
- else
- _dependencies.Add(_factory.NecessaryTypeSymbol(type), "ldtoken");
+ _dependencies.Add(_factory.MaximallyConstructableType(type), "ldtoken");
}
// If this is a ldtoken Type / GetValueInternal sequence, we're done.