diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2017-03-24 21:12:58 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-03-24 21:12:58 +0300 |
commit | b6e0092e2bb2ca1e7294bbab330fdf8eae7937de (patch) | |
tree | fd609f06cf85439fc6db9fbf2ff5d5eef004775b | |
parent | a486a29f3c56b061c73d47ea60a44862ab3ef6a2 (diff) | |
parent | 95f600019cf301cd69e0121ee6a06ae99f343945 (diff) |
Merge pull request #3090 from dotnet-bot/from-tfs
Merge changes from TFS
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!"); |