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:
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GVMDependenciesNode.cs20
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs16
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs7
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs37
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs42
5 files changed, 117 insertions, 5 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GVMDependenciesNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GVMDependenciesNode.cs
index cff7fe56f..31a0f6821 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GVMDependenciesNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GVMDependenciesNode.cs
@@ -20,6 +20,8 @@ namespace ILCompiler.DependencyAnalysis
/// </summary>
public class GVMDependenciesNode : DependencyNodeCore<NodeFactory>
{
+ private const int UniversalCanonGVMDepthHeuristic_NonCanonDepth = 2;
+ private const int UniversalCanonGVMDepthHeuristic_CanonDepth = 2;
private readonly MethodDesc _method;
public MethodDesc Method => _method;
@@ -61,6 +63,12 @@ namespace ILCompiler.DependencyAnalysis
{
MethodDesc canonMethodTarget = instantiatedMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
+ if (context.TypeSystemContext.SupportsUniversalCanon && canonMethodTarget.IsGenericDepthGreaterThan(UniversalCanonGVMDepthHeuristic_CanonDepth))
+ {
+ // fall back to using the universal generic variant of the generic method
+ yield break;
+ }
+
bool getUnboxingStub = instantiatedMethod.OwningType.IsValueType;
yield return new DependencyListEntry(context.MethodEntrypoint(canonMethodTarget, getUnboxingStub), "GVM Dependency - Canon method");
@@ -68,15 +76,17 @@ namespace ILCompiler.DependencyAnalysis
{
// Dependency includes the generic method dictionary of the instantiation, and all its dependencies. This is done by adding the
// ShadowConcreteMethod to the list of dynamic dependencies. The generic dictionary will be reported as a dependency of the ShadowConcreteMethod
- // TODO: detect large recursive generics and fallback to USG templates
Debug.Assert(!instantiatedMethod.IsCanonicalMethod(CanonicalFormKind.Any));
+
+ if (context.TypeSystemContext.SupportsUniversalCanon && instantiatedMethod.IsGenericDepthGreaterThan(UniversalCanonGVMDepthHeuristic_NonCanonDepth))
+ {
+ // fall back to using the universal generic variant of the generic method
+ yield break;
+ }
+
yield return new DependencyListEntry(context.ShadowConcreteMethod(instantiatedMethod), "GVM Dependency - Dictionary");
}
}
- else
- {
- // TODO: universal generics
- }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
index 915ceb88d..6c1be4884 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
@@ -992,6 +992,16 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ if (_type.BaseType != null && !_type.BaseType.IsRuntimeDeterminedSubtype)
+ {
+ TypeDesc baseType = _type.BaseType;
+ do
+ {
+ yield return new DependencyListEntry(context.MaximallyConstructableType(baseType), "base types of canonical types must have their full vtables");
+ baseType = baseType.BaseType;
+ } while (baseType != null);
+ }
+
if (_type.BaseType != null && _type.BaseType.IsRuntimeDeterminedSubtype)
{
yield return new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(_type.BaseType)), "template base type");
@@ -1034,6 +1044,12 @@ namespace ILCompiler.DependencyAnalysis
else
{
typeForFieldLayout = new DependencyListEntry(context.NativeLayout.PlacedSignatureVertex(context.NativeLayout.TypeSignatureVertex(field.FieldType)), "universal field layout type");
+
+ // And ensure the type can be properly laid out
+ foreach (var dependency in context.NativeLayout.TemplateConstructableTypes(field.FieldType))
+ {
+ yield return new DependencyListEntry(dependency, "template construction dependency");
+ }
}
yield return typeForFieldLayout;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs
index 196e7836d..5392ad1cd 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs
@@ -229,6 +229,13 @@ namespace ILCompiler.DependencyAnalysis
TypeDesc canonicalType = type.ConvertToCanonForm(CanonicalFormKind.Specific);
yield return _factory.MaximallyConstructableType(canonicalType);
+ // Add a dependency on the template for this type, if the canonical type should be generated into this binary.
+ if (canonicalType.IsCanonicalSubtype(CanonicalFormKind.Any) && !_factory.NecessaryTypeSymbol(canonicalType).RepresentsIndirectionCell)
+ {
+ if (!_factory.TypeSystemContext.IsCanonicalDefinitionType(canonicalType, CanonicalFormKind.Any))
+ yield return _factory.NativeLayout.TemplateTypeLayout(canonicalType);
+ }
+
foreach (TypeDesc instantiationType in type.Instantiation)
{
foreach (var dependency in TemplateConstructableTypes(instantiationType))
diff --git a/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs b/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs
index 57cfa1786..15070a4b4 100644
--- a/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/MethodExtensions.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using Internal.TypeSystem;
using Internal.TypeSystem.Ecma;
@@ -76,5 +77,41 @@ namespace ILCompiler
{
return method.IsPInvoke && ((method is Internal.IL.Stubs.PInvokeTargetNativeMethod) || Internal.IL.McgInteropSupport.IsPregeneratedInterop(method));
}
+
+ /// <summary>
+ /// What is the maximum number of steps that need to be taken from this type to its most contained generic type.
+ /// i.e.
+ /// SomeGenericType&lt;System.Int32&gt;.Method&lt;System.Int32&gt; => 1
+ /// SomeType.Method&lt;System.Int32&gt; => 0
+ /// SomeType.Method&lt;List&lt;System.Int32&gt;&gt; => 1
+ /// </summary>
+ public static int GetGenericDepth(this MethodDesc method)
+ {
+ int genericDepth = method.OwningType.GetGenericDepth();
+ foreach (TypeDesc type in method.Instantiation)
+ {
+ genericDepth = Math.Max(genericDepth, type.GetGenericDepth());
+ }
+ return genericDepth;
+ }
+
+ /// <summary>
+ /// Determine if a type has a generic depth greater than a given value
+ /// </summary>
+ /// <param name="depth"></param>
+ /// <returns></returns>
+ public static bool IsGenericDepthGreaterThan(this MethodDesc method, int depth)
+ {
+ if (method.OwningType.IsGenericDepthGreaterThan(depth))
+ return true;
+
+ foreach (TypeDesc type in method.Instantiation)
+ {
+ if (type.IsGenericDepthGreaterThan(depth))
+ return true;
+ }
+
+ return false;
+ }
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs b/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
index 49719733f..5cf56d172 100644
--- a/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/TypeExtensions.cs
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+using System;
using Internal.IL;
using Internal.TypeSystem;
@@ -141,5 +142,46 @@ namespace ILCompiler
Debug.Assert(false);
return -1;
}
+
+ /// <summary>
+ /// What is the maximum number of steps that need to be taken from this type to its most contained generic type.
+ /// i.e.
+ /// System.Int32 => 0
+ /// List&lt;System.Int32&gt; => 1
+ /// Dictionary&lt;System.Int32,System.Int32&gt; => 1
+ /// Dictionary&lt;List&lt;System.Int32&gt;,&lt;System.Int32&gt; => 2
+ /// </summary>
+ public static int GetGenericDepth(this TypeDesc type)
+ {
+ if (type.HasInstantiation)
+ {
+ int maxGenericDepthInInstantiation = 0;
+ foreach (TypeDesc instantiationType in type.Instantiation)
+ {
+ maxGenericDepthInInstantiation = Math.Max(instantiationType.GetGenericDepth(), maxGenericDepthInInstantiation);
+ }
+
+ return maxGenericDepthInInstantiation + 1;
+ }
+
+ return 0;
+ }
+
+ /// <summary>
+ /// Determine if a type has a generic depth greater than a given value
+ /// </summary>
+ public static bool IsGenericDepthGreaterThan(this TypeDesc type, int depth)
+ {
+ if (depth < 0)
+ return true;
+
+ foreach (TypeDesc instantiationType in type.Instantiation)
+ {
+ if (instantiationType.IsGenericDepthGreaterThan(depth - 1))
+ return true;
+ }
+
+ return false;
+ }
}
}