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:
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>2017-03-24 21:12:58 +0300
committerGitHub <noreply@github.com>2017-03-24 21:12:58 +0300
commitb6e0092e2bb2ca1e7294bbab330fdf8eae7937de (patch)
treefd609f06cf85439fc6db9fbf2ff5d5eef004775b
parenta486a29f3c56b061c73d47ea60a44862ab3ef6a2 (diff)
parent95f600019cf301cd69e0121ee6a06ae99f343945 (diff)
Merge pull request #3090 from dotnet-bot/from-tfs
Merge changes from TFS
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs14
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs15
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs89
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs2
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs57
-rw-r--r--tests/src/Simple/Generics/Generics.cs46
6 files changed, 157 insertions, 66 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs
index 355d05bcc..f97c43a49 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DictionaryLayoutNode.cs
@@ -84,6 +84,20 @@ namespace ILCompiler.DependencyAnalysis
}
}
+ public virtual ICollection<NativeLayoutVertexNode> GetTemplateEntries(NodeFactory factory)
+ {
+ if (_layout == null)
+ ComputeLayout();
+
+ ArrayBuilder<NativeLayoutVertexNode> templateEntries = new ArrayBuilder<NativeLayoutVertexNode>();
+ for (int i = 0; i < _layout.Length; i++)
+ {
+ templateEntries.Add(_layout[i].TemplateDictionaryNode(factory));
+ }
+
+ return templateEntries.ToArray();
+ }
+
[Conditional("DEBUG")]
private void Validate()
{
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
index 240945815..e15c11b47 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericLookupResult.cs
@@ -467,7 +467,7 @@ namespace ILCompiler.DependencyAnalysis
{
if (factory.Target.Abi == TargetAbi.CoreRT)
{
- throw new NotImplementedException();
+ return factory.NativeLayout.NotSupportedDictionarySlot;
}
else
{
@@ -523,7 +523,7 @@ namespace ILCompiler.DependencyAnalysis
{
if (factory.Target.Abi == TargetAbi.CoreRT)
{
- throw new NotImplementedException();
+ return factory.NativeLayout.NotSupportedDictionarySlot;
}
else
{
@@ -611,7 +611,7 @@ namespace ILCompiler.DependencyAnalysis
public override NativeLayoutVertexNode TemplateDictionaryNode(NodeFactory factory)
{
- throw new NotImplementedException();
+ return factory.NativeLayout.NotSupportedDictionarySlot;
}
}
@@ -645,7 +645,14 @@ namespace ILCompiler.DependencyAnalysis
public override NativeLayoutVertexNode TemplateDictionaryNode(NodeFactory factory)
{
- return factory.NativeLayout.GcStaticDictionarySlot(_type);
+ if (factory.Target.Abi == TargetAbi.CoreRT)
+ {
+ return factory.NativeLayout.NotSupportedDictionarySlot;
+ }
+ else
+ {
+ return factory.NativeLayout.GcStaticDictionarySlot(_type);
+ }
}
public override GenericLookupResultReferenceType LookupResultReferenceType(NodeFactory factory)
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
index 298f24a25..1d09e9bda 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
@@ -676,7 +676,6 @@ namespace ILCompiler.DependencyAnalysis
public sealed class NativeLayoutTemplateMethodLayoutVertexNode : NativeLayoutSavedVertexNode
{
private MethodDesc _method;
- private Dictionary<int, NativeLayoutVertexNode> _genericDictionaryEntries = new Dictionary<int, NativeLayoutVertexNode>();
protected override string GetName(NodeFactory factory) => "NativeLayoutTemplateMethodLayoutVertexNode" + factory.NameMangler.GetMangledMethodName(_method);
@@ -688,21 +687,6 @@ namespace ILCompiler.DependencyAnalysis
Debug.Assert(method.GetCanonMethodTarget(CanonicalFormKind.Specific) == method, "Assert that the canonical method passed in is in standard canonical form");
}
- public void AddGenericDictionaryEntry(int slot, NativeLayoutVertexNode description)
- {
- lock (_genericDictionaryEntries)
- {
- if (!_genericDictionaryEntries.ContainsKey(slot))
- {
- _genericDictionaryEntries.Add(slot, description);
- }
- else
- {
- Debug.Assert(_genericDictionaryEntries[slot] == description);
- }
- }
- }
-
public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
{
return Array.Empty<DependencyListEntry>();
@@ -719,25 +703,17 @@ namespace ILCompiler.DependencyAnalysis
VertexBag layoutInfo = new VertexBag();
- KeyValuePair<int, NativeLayoutVertexNode>[] dictionaryEntries = new KeyValuePair<int, NativeLayoutVertexNode>[_genericDictionaryEntries.Count];
- int index = 0;
- foreach (KeyValuePair<int, NativeLayoutVertexNode> entry in _genericDictionaryEntries)
- {
- dictionaryEntries[index++] = entry;
- }
- Array.Sort(dictionaryEntries, CompareDictionaryEntries);
-
- if (!_method.IsCanonicalMethod(CanonicalFormKind.Universal) && (dictionaryEntries.Length > 0))
+ DictionaryLayoutNode associatedLayout = factory.GenericDictionaryLayout(_method);
+ ICollection<NativeLayoutVertexNode> templateLayout = associatedLayout.GetTemplateEntries(factory);
+
+ if (!_method.IsCanonicalMethod(CanonicalFormKind.Universal) && (templateLayout.Count > 0))
{
List<NativeLayoutVertexNode> dictionaryVertices = new List<NativeLayoutVertexNode>();
- int indexer = 0;
- foreach (KeyValuePair<int, NativeLayoutVertexNode> dictionaryEntry in dictionaryEntries)
+ foreach (NativeLayoutVertexNode dictionaryEntry in templateLayout)
{
- Debug.Assert(dictionaryEntry.Key == indexer);
- Debug.Assert(dictionaryEntry.Value.Marked); // We don't mark these in the static dependencies as the discovery order does not permit that, but they should be marked by the time we write.
- dictionaryVertices.Add(dictionaryEntry.Value);
- indexer++;
+ Debug.Assert(dictionaryEntry.Marked); // We don't mark these in the static dependencies as the discovery order does not permit that, but they should be marked by the time we write.
+ dictionaryVertices.Add(dictionaryEntry);
}
NativeLayoutVertexNode dictionaryLayout = factory.NativeLayout.PlacedVertexSequence(dictionaryVertices);
@@ -746,7 +722,6 @@ namespace ILCompiler.DependencyAnalysis
factory.MetadataManager.NativeLayoutInfo.TemplatesSection.Place(layoutInfo);
- _genericDictionaryEntries = null; // WriteVertex is only to be used once, and no dictionary entries should be modified after writing the vertex.
return SetSavedVertex(layoutInfo);
}
}
@@ -755,7 +730,6 @@ namespace ILCompiler.DependencyAnalysis
{
private DefType _type;
private bool _isUniversalCanon;
- Dictionary<int, NativeLayoutVertexNode> _genericDictionaryEntries = new Dictionary<int, NativeLayoutVertexNode>();
protected override string GetName(NodeFactory factory) => "NativeLayoutTemplateTypeLayoutVertexNode_" + factory.NameMangler.GetMangledTypeName(_type);
@@ -767,15 +741,6 @@ namespace ILCompiler.DependencyAnalysis
_type = type.ConvertToSharedRuntimeDeterminedForm();
}
- public void AddGenericDictionaryEntry(int slot, NativeLayoutVertexNode description)
- {
- lock (_genericDictionaryEntries)
- {
- if (!_genericDictionaryEntries.ContainsKey(slot))
- _genericDictionaryEntries.Add(slot, description);
- }
- }
-
private ISymbolNode GetStaticsNode(NodeFactory context, out BagElementKind staticsBagKind)
{
ISymbolNode symbol;
@@ -968,14 +933,9 @@ namespace ILCompiler.DependencyAnalysis
VertexBag layoutInfo = new VertexBag();
- KeyValuePair<int, NativeLayoutVertexNode>[] dictionaryEntries = new KeyValuePair<int, NativeLayoutVertexNode>[_genericDictionaryEntries.Count];
- int index = 0;
- foreach (KeyValuePair<int, NativeLayoutVertexNode> entry in _genericDictionaryEntries)
- {
- dictionaryEntries[index++] = entry;
- }
- Array.Sort(dictionaryEntries, CompareDictionaryEntries);
-
+ DictionaryLayoutNode associatedLayout = factory.GenericDictionaryLayout(_type.ConvertToCanonForm(CanonicalFormKind.Specific));
+ ICollection<NativeLayoutVertexNode> templateLayout = associatedLayout.GetTemplateEntries(factory);
+
NativeWriter writer = GetNativeWriter(factory);
// Interfaces
@@ -992,17 +952,14 @@ namespace ILCompiler.DependencyAnalysis
layoutInfo.Append(BagElementKind.ImplementedInterfaces, implementedInterfaces.WriteVertex(factory));
}
- if (!_isUniversalCanon && (dictionaryEntries.Length > 0))
+ if (!_isUniversalCanon && (templateLayout.Count > 0))
{
List<NativeLayoutVertexNode> dictionaryVertices = new List<NativeLayoutVertexNode>();
- int indexer = 0;
- foreach (KeyValuePair<int, NativeLayoutVertexNode> dictionaryEntry in dictionaryEntries)
+ foreach (NativeLayoutVertexNode dictionaryEntry in templateLayout)
{
- Debug.Assert(dictionaryEntry.Key == indexer);
- Debug.Assert(dictionaryEntry.Value.Marked); // We don't mark these in the static dependencies as the discovery order does not permit that, but they should be marked by the time we write.
- dictionaryVertices.Add(dictionaryEntry.Value);
- indexer++;
+ Debug.Assert(dictionaryEntry.Marked); // We don't mark these in the static dependencies as the discovery order does not permit that, but they should be marked by the time we write.
+ dictionaryVertices.Add(dictionaryEntry);
}
NativeLayoutVertexNode dictionaryLayout = factory.NativeLayout.PlacedVertexSequence(dictionaryVertices);
@@ -1182,7 +1139,6 @@ namespace ILCompiler.DependencyAnalysis
}
factory.MetadataManager.NativeLayoutInfo.TemplatesSection.Place(layoutInfo);
- _genericDictionaryEntries = null; // WriteVertex is only to be used once, and no dictionary entries should be modified after writing the vertex.
return SetSavedVertex(layoutInfo);
}
@@ -1731,4 +1687,21 @@ namespace ILCompiler.DependencyAnalysis
return _wrappedNode.WriteVertex(factory);
}
}
+
+ public sealed class NativeLayoutNotSupportedDictionarySlotNode : NativeLayoutGenericDictionarySlotNode
+ {
+ protected override FixupSignatureKind SignatureKind => FixupSignatureKind.NotYetSupported;
+
+ public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory context)
+ {
+ return null;
+ }
+
+ protected override string GetName(NodeFactory context) => "NativeLayoutNotSupportedDictionarySlotNode";
+
+ protected override Vertex WriteSignatureVertex(NativeWriter writer, NodeFactory factory)
+ {
+ return writer.GetUnsignedConstant(0xDEADBEEF);
+ }
+ }
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs
index e3dde7a83..c309aad75 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.NativeLayout.cs
@@ -419,6 +419,8 @@ namespace ILCompiler.DependencyAnalysis
return _methodDictionary_GenericDictionarySlots.GetOrAdd(method);
}
+ public readonly NativeLayoutNotSupportedDictionarySlotNode NotSupportedDictionarySlot = new NativeLayoutNotSupportedDictionarySlotNode();
+
private struct MethodEntrypointSlotKey : IEquatable<MethodEntrypointSlotKey>
{
public readonly bool Unboxing;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
index 13eeca93c..2cbc03b14 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using Internal.Text;
using Internal.TypeSystem;
@@ -112,17 +113,65 @@ namespace ILCompiler.DependencyAnalysis
protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory)
{
- DependencyList dependencies = null;
+ DependencyList dependencies = new DependencyList();
foreach (DependencyNodeCore<NodeFactory> dependency in _lookupSignature.NonRelocDependenciesFromUsage(factory))
{
- if (dependencies == null)
- dependencies = new DependencyList();
-
dependencies.Add(new DependencyListEntry(dependency, "GenericLookupResultDependency"));
}
+ // Root the template for the type while we're hitting its dictionary cells. In the future, we may
+ // want to control this via type reflectability instead.
+ if (_dictionaryOwner is MethodDesc)
+ {
+ dependencies.Add(factory.NativeLayout.TemplateMethodLayout((MethodDesc)_dictionaryOwner), "Type loader template");
+ }
+ else
+ {
+ DefType actualTemplateType = GenericTypesTemplateMap.GetActualTemplateTypeForType(factory, (TypeDesc)_dictionaryOwner);
+ dependencies.Add(factory.NativeLayout.TemplateTypeLayout(actualTemplateType), "Type loader template");
+ }
+
return dependencies;
}
+
+ public override bool HasConditionalStaticDependencies => true;
+ public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory)
+ {
+ List<CombinedDependencyListEntry> conditionalDependencies = new List<CombinedDependencyListEntry>();
+ NativeLayoutSavedVertexNode templateLayout;
+ if (_dictionaryOwner is MethodDesc)
+ {
+ templateLayout = factory.NativeLayout.TemplateMethodLayout((MethodDesc)_dictionaryOwner);
+ conditionalDependencies.Add(new CombinedDependencyListEntry(_lookupSignature.TemplateDictionaryNode(factory),
+ templateLayout,
+ "Type loader template"));
+ }
+ else
+ {
+ DefType actualTemplateType = GenericTypesTemplateMap.GetActualTemplateTypeForType(factory, (TypeDesc)_dictionaryOwner);
+ templateLayout = factory.NativeLayout.TemplateTypeLayout(actualTemplateType);
+ conditionalDependencies.Add(new CombinedDependencyListEntry(_lookupSignature.TemplateDictionaryNode(factory),
+ templateLayout,
+ "Type loader template"));
+ }
+
+ if (_id == ReadyToRunHelperId.GetGCStaticBase || _id == ReadyToRunHelperId.GetThreadStaticBase)
+ {
+ // If the type has a lazy static constructor, we also need the non-GC static base to be available as
+ // a template dictionary node.
+ TypeDesc type = (TypeDesc)_target;
+ Debug.Assert(templateLayout != null);
+ if (factory.TypeSystemContext.HasLazyStaticConstructor(type))
+ {
+ GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(type);
+ conditionalDependencies.Add(new CombinedDependencyListEntry(nonGcRegionLookup.TemplateDictionaryNode(factory),
+ templateLayout,
+ "Type loader template"));
+ }
+ }
+
+ return conditionalDependencies;
+ }
}
public partial class ReadyToRunGenericLookupFromDictionaryNode : ReadyToRunGenericHelperNode
diff --git a/tests/src/Simple/Generics/Generics.cs b/tests/src/Simple/Generics/Generics.cs
index e82ee01ee..7b75dac93 100644
--- a/tests/src/Simple/Generics/Generics.cs
+++ b/tests/src/Simple/Generics/Generics.cs
@@ -1125,6 +1125,7 @@ class Program
class TestFieldAccess
{
class ClassType { }
+ class ClassType2 { }
struct StructType { }
class Foo<T>
@@ -1154,6 +1155,19 @@ class Program
public object m_objectField;
}
+ // Remove this and use Foo once we have type loader support for all necessary dictionary slots
+ class FooDynamic<T>
+ {
+ static FooDynamic()
+ {
+ Console.WriteLine("FooDynamic<" + typeof(T).Name + "> cctor");
+ }
+
+ public static int s_intField;
+ public static float s_floatField;
+ public static long s_longField1;
+ }
+
class Bar
{
static Bar()
@@ -1192,6 +1206,37 @@ class Program
}
}
+ private static void TestDynamicStaticFields()
+ {
+ FooDynamic<object>.s_intField = 1234;
+ FooDynamic<object>.s_floatField = 12.34f;
+ FooDynamic<object>.s_longField1 = 0x1111;
+
+ var fooDynamicOfClassType = typeof(FooDynamic<>).MakeGenericType(typeof(ClassType)).GetTypeInfo();
+ var fooDynamicOfClassType2 = typeof(FooDynamic<>).MakeGenericType(typeof(ClassType2)).GetTypeInfo();
+
+ FieldInfo fi = fooDynamicOfClassType.GetDeclaredField("s_intField");
+ FieldInfo fi2 = fooDynamicOfClassType2.GetDeclaredField("s_intField");
+ fi.SetValue(null, 1111);
+ fi2.SetValue(null, 2222);
+ Verify(1111, (int)fi.GetValue(null));
+ Verify(2222, (int)fi2.GetValue(null));
+
+ fi = fooDynamicOfClassType.GetDeclaredField("s_floatField");
+ fi2 = fooDynamicOfClassType2.GetDeclaredField("s_floatField");
+ fi.SetValue(null, 1.1f);
+ fi2.SetValue(null, 2.2f);
+ Verify(1.1f, (float)fi.GetValue(null));
+ Verify(2.2f, (float)fi2.GetValue(null));
+
+ fi = fooDynamicOfClassType.GetDeclaredField("s_longField1");
+ fi2 = fooDynamicOfClassType2.GetDeclaredField("s_longField1");
+ fi.SetValue(null, 0x11111111);
+ fi2.SetValue(null, 0x22222222);
+ Verify(0x11111111, (long)fi.GetValue(null));
+ Verify(0x22222222, (long)fi2.GetValue(null));
+ }
+
private static void TestStaticFields()
{
Foo<ClassType>.s_intField = 11223344;
@@ -1410,6 +1455,7 @@ class Program
{
TestStaticFields();
TestInstanceFields();
+ TestDynamicStaticFields();
if (s_NumErrors != 0)
throw new Exception(s_NumErrors + " errors!");