diff options
111 files changed, 1234 insertions, 166 deletions
diff --git a/src/BuildIntegration/Microsoft.NETCore.Native.targets b/src/BuildIntegration/Microsoft.NETCore.Native.targets index 3ad2e68a7..6e522fe48 100644 --- a/src/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/BuildIntegration/Microsoft.NETCore.Native.targets @@ -106,6 +106,7 @@ See the LICENSE file in the project root for more information. <IlcArg Condition="$(IlcMultiModule) == 'true'" Include="--multifile" /> <IlcArg Condition="$(Optimize) == 'true'" Include="-O" /> <IlcArg Condition="$(DebugSymbols) == 'true'" Include="-g" /> + <IlcArg Condition="$(IlcGenerateMapFile) == 'true'" Include="--map:$(NativeIntermediateOutputPath)%(ManagedBinary.Filename).map.xml" /> </ItemGroup> <MakeDir Directories="$(NativeIntermediateOutputPath)" /> diff --git a/src/Common/src/Internal/Text/Utf8String.cs b/src/Common/src/Internal/Text/Utf8String.cs index 3587a2c92..47e701350 100644 --- a/src/Common/src/Internal/Text/Utf8String.cs +++ b/src/Common/src/Internal/Text/Utf8String.cs @@ -8,7 +8,7 @@ using System.Text; namespace Internal.Text { - public struct Utf8String : IEquatable<Utf8String> + public struct Utf8String : IEquatable<Utf8String>, IComparable<Utf8String> { private byte[] _value; @@ -112,5 +112,40 @@ namespace Internal.Text } } } + + private static int Compare(Utf8String strA, Utf8String strB) + { + int length = Math.Min(strA.Length, strB.Length); + + unsafe + { + fixed (byte* ap = strA._value) + fixed (byte* bp = strB._value) + { + byte* a = ap; + byte* b = bp; + + while (length > 0) + { + if (*a != *b) + return *a - *b; + a += 1; + b += 1; + length -= 1; + } + + // At this point, we have compared all the characters in at least one string. + // The longer string will be larger. + // We could optimize and compare lengths before iterating strings, but we want + // Foo and Foo1 to be sorted adjacent to eachother. + return strA.Length - strB.Length; + } + } + } + + public int CompareTo(Utf8String other) + { + return Compare(this, other); + } } } diff --git a/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs b/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs index 58d7c8c69..342e1f834 100644 --- a/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs +++ b/src/Common/src/TypeSystem/Common/Utilities/GCPointerMap.cs @@ -13,7 +13,7 @@ namespace Internal.TypeSystem /// Represents a bitmap of GC pointers within a memory region divided into /// pointer-sized cells. /// </summary> - public partial struct GCPointerMap : IEquatable<GCPointerMap> + public partial struct GCPointerMap : IEquatable<GCPointerMap>, IComparable<GCPointerMap> { // Each bit in this array represents a pointer-sized cell. private int[] _gcFlags; @@ -130,6 +130,21 @@ namespace Internal.TypeSystem sb.Append(bit ? '1' : '0'); return sb.ToString(); } + + public int CompareTo(GCPointerMap other) + { + if (_numCells != other._numCells) + return _numCells - other._numCells; + + for (int i = 0; i < _gcFlags.Length; i++) + { + if (_gcFlags[i] != other._gcFlags[i]) + return _gcFlags[i] - other._gcFlags[i]; + } + + Debug.Assert(Equals(other)); + return 0; + } } /// <summary> diff --git a/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs index 493883b5d..b93fafd42 100644 --- a/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs +++ b/src/ILCompiler.Compiler/src/Compiler/CompilationBuilder.cs @@ -85,10 +85,9 @@ namespace ILCompiler public abstract CompilationBuilder UseBackendOptions(IEnumerable<string> options); - protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory) + protected DependencyAnalyzerBase<NodeFactory> CreateDependencyGraph(NodeFactory factory, IComparer<DependencyNodeCore<NodeFactory>> comparer = null) { - // TODO: add graph sorter when we go multi-threaded - return _dependencyTrackingLevel.CreateDependencyGraph(factory); + return _dependencyTrackingLevel.CreateDependencyGraph(factory, comparer); } public ILScannerBuilder GetILScannerBuilder(CompilationModuleGroup compilationGroup = null) diff --git a/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs b/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs index f7f1994fd..6fc5afe9f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DelegateCreationInfo.cs @@ -313,5 +313,33 @@ namespace ILCompiler { return Constructor.GetHashCode() ^ TargetMethod.GetHashCode(); } + +#if !SUPPORT_JIT + internal int CompareTo(DelegateCreationInfo other, TypeSystemComparer comparer) + { + var compare = _targetKind - other._targetKind; + if (compare != 0) + return compare; + + compare = comparer.Compare(TargetMethod, other.TargetMethod); + if (compare != 0) + return compare; + + compare = comparer.Compare(Constructor.Method, other.Constructor.Method); + if (compare != 0) + return compare; + + if (Thunk == other.Thunk) + return 0; + + if (Thunk == null) + return -1; + + if (other.Thunk == null) + return 1; + + return comparer.Compare(Thunk.Method, other.Thunk.Method); + } +#endif } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs index 613cc6358..68da99d9e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayMapNode.cs @@ -77,5 +77,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs index 64936d5fe..927710fad 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs @@ -21,25 +21,18 @@ namespace ILCompiler.DependencyAnalysis /// by placing a starting symbol, followed by contents of <typeparamref name="TEmbedded"/> nodes (optionally /// sorted using provided comparer), followed by ending symbol. /// </summary> - public class ArrayOfEmbeddedDataNode<TEmbedded> : ObjectNode, IHasStartSymbol + public class ArrayOfEmbeddedDataNode<TEmbedded> : EmbeddedDataContainerNode, IHasStartSymbol where TEmbedded : EmbeddedObjectNode { private HashSet<TEmbedded> _nestedNodes = new HashSet<TEmbedded>(); private List<TEmbedded> _nestedNodesList = new List<TEmbedded>(); - private ObjectAndOffsetSymbolNode _startSymbol; - private ObjectAndOffsetSymbolNode _endSymbol; private IComparer<TEmbedded> _sorter; - public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<TEmbedded> nodeSorter) + public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<TEmbedded> nodeSorter) : base(startSymbolMangledName, endSymbolMangledName) { - _startSymbol = new ObjectAndOffsetSymbolNode(this, 0, startSymbolMangledName, true); - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, endSymbolMangledName, true); _sorter = nodeSorter; } - - public ObjectAndOffsetSymbolNode StartSymbol => _startSymbol; - public ObjectAndOffsetSymbolNode EndSymbol => _endSymbol; - + public void AddEmbeddedObject(TEmbedded symbol) { lock (_nestedNodes) @@ -52,13 +45,7 @@ namespace ILCompiler.DependencyAnalysis } } - public int IndexOfEmbeddedObject(TEmbedded symbol) - { - Debug.Assert(_sorter == null); - return _nestedNodesList.IndexOf(symbol); - } - - protected override string GetName(NodeFactory factory) => $"Region {_startSymbol.GetMangledName(factory.NameMangler)}"; + protected override string GetName(NodeFactory factory) => $"Region {StartSymbol.GetMangledName(factory.NameMangler)}"; public override ObjectNodeSection Section => ObjectNodeSection.DataSection; public override bool IsShareable => false; @@ -69,10 +56,14 @@ namespace ILCompiler.DependencyAnalysis protected virtual void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) { + int index = 0; foreach (TEmbedded node in NodesList) { if (!relocsOnly) + { node.InitializeOffsetFromBeginningOfArray(builder.CountBytes); + node.InitializeIndexFromBeginningOfArray(index++); + } node.EncodeData(ref builder, factory, relocsOnly); if (node is ISymbolDefinitionNode) @@ -90,12 +81,12 @@ namespace ILCompiler.DependencyAnalysis if (_sorter != null) _nestedNodesList.Sort(_sorter); - builder.AddSymbol(_startSymbol); + builder.AddSymbol(StartSymbol); GetElementDataForNodes(ref builder, factory, relocsOnly); - _endSymbol.SetSymbolOffset(builder.CountBytes); - builder.AddSymbol(_endSymbol); + EndSymbol.SetSymbolOffset(builder.CountBytes); + builder.AddSymbol(EndSymbol); ObjectData objData = builder.ToObjectData(); return objData; @@ -114,15 +105,9 @@ namespace ILCompiler.DependencyAnalysis return dependencies; } - } - // TODO: delete this once we review each use of this and put it on the generic plan with the - // right element type - public class ArrayOfEmbeddedDataNode : ArrayOfEmbeddedDataNode<EmbeddedObjectNode> - { - public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer<EmbeddedObjectNode> nodeSorter) - : base(startSymbolMangledName, endSymbolMangledName, nodeSorter) - { - } + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + + protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs index d6d4f3885..45271af23 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs @@ -14,7 +14,7 @@ namespace ILCompiler.DependencyAnalysis /// of node each pointer within the vector points to. /// </summary> public sealed class ArrayOfEmbeddedPointersNode<TTarget> : ArrayOfEmbeddedDataNode<EmbeddedPointerIndirectionNode<TTarget>> - where TTarget : ISymbolNode + where TTarget : ISortableSymbolNode { private int _nextId; private string _startSymbolMangledName; @@ -44,16 +44,15 @@ namespace ILCompiler.DependencyAnalysis return new EmbeddedPointerIndirectionWithSymbolNode(this, target, GetNextId()); } - public EmbeddedObjectNode NewNodeWithSymbol(TTarget target, OnMarkedDelegate callback) - { - return new EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode(this, target, GetNextId(), callback); - } - int GetNextId() { return System.Threading.Interlocked.Increment(ref _nextId); } + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + + protected internal override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedPointersNode; + private class PointerIndirectionNodeComparer : IComparer<EmbeddedPointerIndirectionNode<TTarget>> { private IComparer<TTarget> _innerComparer; @@ -96,6 +95,8 @@ namespace ILCompiler.DependencyAnalysis new DependencyListEntry(_parentNode, "Pointer region") }; } + + protected internal override int ClassCode => -66002498; } private class EmbeddedPointerIndirectionWithSymbolNode : SimpleEmbeddedPointerIndirectionNode, ISymbolDefinitionNode @@ -113,27 +114,10 @@ namespace ILCompiler.DependencyAnalysis int ISymbolDefinitionNode.Offset => OffsetFromBeginningOfArray; - public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + public override void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix).Append(_parentNode._startSymbolMangledName).Append("_").Append(_id.ToStringInvariant()); } } - - private class EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode : EmbeddedPointerIndirectionWithSymbolNode - { - private OnMarkedDelegate _onMarkedCallback; - - public EmbeddedPointerIndirectionWithSymbolAndOnMarkedCallbackNode(ArrayOfEmbeddedPointersNode<TTarget> futureParent, TTarget target, int id, OnMarkedDelegate onMarkedCallback) - : base(futureParent, target, id) - { - _onMarkedCallback = onMarkedCallback; - } - - protected override void OnMarked(NodeFactory factory) - { - base.OnMarked(factory); - _onMarkedCallback(this); - } - } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs index 705dc4705..70349bdbf 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs @@ -41,5 +41,7 @@ namespace ILCompiler.DependencyAnalysis AlignNextObject(ref builder, factory); builder.EmitZeroPointer(); } + + protected internal override int ClassCode => -1771336339; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs index 1d7afc2e4..5f2b27f5c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlobNode.cs @@ -5,6 +5,7 @@ using System; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -39,5 +40,14 @@ namespace ILCompiler.DependencyAnalysis } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + +#if !SUPPORT_JIT + protected internal override int ClassCode => -470351029; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _name.CompareTo(((BlobNode)other)._name); + } +#endif } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs index be1d8e4b5..2955b3d0e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/BlockReflectionTypeMapNode.cs @@ -83,5 +83,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.BlockReflectionTypeMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs index bd5bf6e73..520781f53 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalDefinitionEETypeNode.cs @@ -42,5 +42,7 @@ namespace ILCompiler.DependencyAnalysis // Canonical definition types will have their base size set to the minimum protected override int BaseSize => MinimumObjectSize; + + protected internal override int ClassCode => -1851030036; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs index 9bd1ad7c1..2383df231 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs @@ -135,5 +135,7 @@ namespace ILCompiler.DependencyAnalysis base.ComputeValueTypeFieldPadding(); } + + protected internal override int ClassCode => -1798018602; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs index 0165aada1..2ee6b9cf9 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs @@ -81,5 +81,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ClassConstructorContextMap; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs index 0d7feae9a..d64319e90 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ClonedConstructedEETypeNode.cs @@ -34,5 +34,7 @@ namespace ILCompiler.DependencyAnalysis // objData.EmitPointerReloc(factory.NecessaryTypeSymbol(_type)); } + + protected internal override int ClassCode => -288888778; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs new file mode 100644 index 000000000..5e0139a42 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/CompilerComparer.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// 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 System.Diagnostics; + +using Internal.TypeSystem; + +namespace ILCompiler.DependencyAnalysis +{ + public class CompilerComparer : TypeSystemComparer + { + public int Compare(ISortableSymbolNode x, ISortableSymbolNode y) + { + if (x == y) + { + return 0; + } + + int codeX = x.ClassCode; + int codeY = y.ClassCode; + if (codeX == codeY) + { + Debug.Assert(x.GetType() == y.GetType()); + + int result = x.CompareToImpl(y, this); + + // We did a reference equality check above so an "Equal" result is not expected + Debug.Assert(result != 0); + + return result; + } + else + { + Debug.Assert(x.GetType() != y.GetType()); + return codeX > codeY ? -1 : 1; + } + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index 0237f9b8b..4bfd1ea7f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -198,5 +198,7 @@ namespace ILCompiler.DependencyAnalysis if (!CreationAllowed(type)) ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } + + protected internal override int ClassCode => 590142654; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs index 81e8eb38d..417d14e60 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DefaultConstructorMapNode.cs @@ -74,6 +74,10 @@ namespace ILCompiler.DependencyAnalysis public override ObjectNodeSection Section => _externalReferences.Section; public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => false; public override bool StaticDependenciesAreComputed => true; + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.DefaultConstructorMapNode; + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs index c90050a63..11318ad2f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs @@ -6,6 +6,7 @@ using System; using Internal.NativeFormat; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -74,5 +75,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.DelegateMarshallingStubMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs index f914be78b..d18e2eb59 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/DynamicInvokeTemplateDataNode.cs @@ -122,5 +122,8 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.DynamicInvokeTemplateDataNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs index db578fb17..140aed4e2 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeNode.cs @@ -119,18 +119,13 @@ namespace ILCompiler.DependencyAnalysis get { return _optionalFieldsBuilder.IsAtLeastOneFieldUsed(); } } - internal byte[] GetOptionalFieldsData(NodeFactory factory) + internal byte[] GetOptionalFieldsData() { return _optionalFieldsBuilder.GetBytes(); } public override bool StaticDependenciesAreComputed => true; - - public void SetDispatchMapIndex(int index) - { - _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.DispatchMap, checked((uint)index)); - } - + public static string GetMangledName(TypeDesc type, NameMangler nameMangler) { return nameMangler.NodeMangler.EEType(type); @@ -798,6 +793,11 @@ namespace ILCompiler.DependencyAnalysis /// </summary> protected internal virtual void ComputeOptionalEETypeFields(NodeFactory factory, bool relocsOnly) { + if (!relocsOnly && _type.RuntimeInterfaces.Length > 0 && factory.InterfaceDispatchMap(_type).Marked) + { + _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.DispatchMap, checked((uint)factory.InterfaceDispatchMapIndirection(Type).IndexFromBeginningOfArray)); + } + ComputeRareFlags(factory); ComputeNullableValueOffset(); if (!relocsOnly) @@ -1150,6 +1150,20 @@ namespace ILCompiler.DependencyAnalysis } } + protected internal override int ClassCode => 1521789141; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((EETypeNode)other)._type); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } + private struct SlotCounter { private int _startBytes; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs index 1cf45d914..0cc9ef205 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EETypeOptionalFieldsNode.cs @@ -2,7 +2,11 @@ // 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 System.Diagnostics; + using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -53,10 +57,17 @@ namespace ILCompiler.DependencyAnalysis if (!relocsOnly) { _owner.ComputeOptionalEETypeFields(factory, relocsOnly: false); - objData.EmitBytes(_owner.GetOptionalFieldsData(factory)); + objData.EmitBytes(_owner.GetOptionalFieldsData()); } return objData.ToObjectData(); } + + protected internal override int ClassCode => 821718028; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return SortableDependencyNode.CompareImpl(_owner, ((EETypeOptionalFieldsNode)other)._owner, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs new file mode 100644 index 000000000..bc9d9975d --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Internal.TypeSystem; + +namespace ILCompiler.DependencyAnalysis +{ + /// <summary> + /// Represents a node that contains a set of embedded objects. The main function is + /// to serve as a base class, providing symbol name boundaries and node ordering. + /// </summary> + public abstract class EmbeddedDataContainerNode : ObjectNode + { + private ObjectAndOffsetSymbolNode _startSymbol; + private ObjectAndOffsetSymbolNode _endSymbol; + private string _startSymbolMangledName; + + public ObjectAndOffsetSymbolNode StartSymbol => _startSymbol; + public ObjectAndOffsetSymbolNode EndSymbol => _endSymbol; + + protected EmbeddedDataContainerNode(string startSymbolMangledName, string endSymbolMangledName) + { + _startSymbolMangledName = startSymbolMangledName; + _startSymbol = new ObjectAndOffsetSymbolNode(this, 0, startSymbolMangledName, true); + _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, endSymbolMangledName, true); + } + + protected internal override int ClassCode => -1410622237; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _startSymbolMangledName.CompareTo(((EmbeddedDataContainerNode)other)._startSymbolMangledName); + } + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs index 3d5c5c310..3ea5ebf83 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs @@ -10,17 +10,19 @@ using Debug = System.Diagnostics.Debug; namespace ILCompiler.DependencyAnalysis { - public abstract class EmbeddedObjectNode : DependencyNodeCore<NodeFactory> + public abstract class EmbeddedObjectNode : SortableDependencyNode { private const int InvalidOffset = int.MinValue; private int _offset; + private int _index; public IHasStartSymbol ContainingNode { get; set; } public EmbeddedObjectNode() { _offset = InvalidOffset; + _index = InvalidOffset; } public int OffsetFromBeginningOfArray @@ -32,12 +34,27 @@ namespace ILCompiler.DependencyAnalysis } } + public int IndexFromBeginningOfArray + { + get + { + Debug.Assert(_index != InvalidOffset); + return _index; + } + } + internal void InitializeOffsetFromBeginningOfArray(int offset) { Debug.Assert(_offset == InvalidOffset || _offset == offset); _offset = offset; } + internal void InitializeIndexFromBeginningOfArray(int index) + { + Debug.Assert(_index == InvalidOffset || _index == index); + _index = index; + } + public virtual bool IsShareable => false; public virtual bool RepresentsIndirectionCell => false; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs index 64af3f244..766a73706 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/EmbeddedPointerIndirectionNode.cs @@ -5,14 +5,16 @@ using System; using System.Collections.Generic; +using Internal.Text; + namespace ILCompiler.DependencyAnalysis { /// <summary> /// An <see cref="EmbeddedObjectNode"/> whose sole value is a pointer to a different <see cref="ISymbolNode"/>. /// <typeparamref name="TTarget"/> represents the node type this pointer points to. /// </summary> - public abstract class EmbeddedPointerIndirectionNode<TTarget> : EmbeddedObjectNode - where TTarget : ISymbolNode + public abstract class EmbeddedPointerIndirectionNode<TTarget> : EmbeddedObjectNode, ISortableSymbolNode + where TTarget : ISortableSymbolNode { private TTarget _targetNode; @@ -36,5 +38,20 @@ namespace ILCompiler.DependencyAnalysis // At minimum, Target needs to be reported as a static dependency by inheritors. public abstract override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory); + + int ISymbolNode.Offset => 0; + + public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + { + sb.Append("_embedded_ptr_"); + Target.AppendMangledName(nameMangler, sb); + } + + int ISortableSymbolNode.ClassCode => -2055384490; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(_targetNode, ((EmbeddedPointerIndirectionNode<TTarget>)other)._targetNode); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs index 4625c6bd3..57313c7a9 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs @@ -151,5 +151,8 @@ namespace ILCompiler.DependencyAnalysis return true; } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ExactMethodInstantiationsNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs index 2e3de600d..f35a57d1c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternSymbolNode.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 System.Collections.Generic; using ILCompiler.DependencyAnalysisFramework; @@ -13,7 +14,7 @@ namespace ILCompiler.DependencyAnalysis /// <summary> /// Represents a symbol that is defined externally and statically linked to the output obj file. /// </summary> - public class ExternSymbolNode : DependencyNodeCore<NodeFactory>, ISymbolNode + public class ExternSymbolNode : DependencyNodeCore<NodeFactory>, ISortableSymbolNode { private Utf8String _name; @@ -39,5 +40,14 @@ namespace ILCompiler.DependencyAnalysis public override IEnumerable<DependencyListEntry> GetStaticDependencies(NodeFactory factory) => null; public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; + +#if !SUPPORT_JIT + int ISortableSymbolNode.ClassCode => 1092559304; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return _name.CompareTo(((ExternSymbolNode)other)._name); + } +#endif } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs index 038f643b4..84c17aab5 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs @@ -122,6 +122,14 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ExternalReferencesTableNode; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return string.Compare(_blobName, ((ExternalReferencesTableNode)other)._blobName); + } + struct SymbolAndDelta : IEquatable<SymbolAndDelta> { public readonly ISymbolNode Symbol; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs index 77d71b6b7..a4127e63d 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs @@ -78,7 +78,7 @@ namespace ILCompiler.DependencyAnalysis builder.EmitPointerReloc(factory.MethodEntrypoint(canonMethod, _isUnboxingStub)); // Find out what's the context to use - ISymbolNode contextParameter; + ISortableSymbolNode contextParameter; if (canonMethod.RequiresInstMethodDescArg()) { contextParameter = factory.MethodGenericDictionary(Method); @@ -96,5 +96,23 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => 190463489; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + var compare = _isUnboxingStub.CompareTo(((FatFunctionPointerNode)other)._isUnboxingStub); + if (compare != 0) + return compare; + + return comparer.Compare(Method, ((FatFunctionPointerNode)other).Method); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs index 0c3cea2f5..23b0992bd 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenArrayNode.cs @@ -100,5 +100,12 @@ namespace ILCompiler.DependencyAnalysis { factory.FrozenSegmentRegion.AddEmbeddedObject(this); } + + protected internal override int ClassCode => 1789429316; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _preInitFieldInfo.CompareTo(((FrozenArrayNode)other)._preInitFieldInfo, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs index e58879302..1fa63fc51 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/FrozenStringNode.cs @@ -90,5 +90,12 @@ namespace ILCompiler.DependencyAnalysis { factory.FrozenSegmentRegion.AddEmbeddedObject(this); } + + protected internal override int ClassCode => -1733946122; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return string.CompareOrdinal(_data, ((FrozenStringNode)other)._data); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs index f38bb7d2c..07d482d3e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticDescNode.cs @@ -170,6 +170,19 @@ namespace ILCompiler.DependencyAnalysis Debug.Assert(numSeries == NumSeries); } + + internal int CompareTo(GCStaticDescNode other, TypeSystemComparer comparer) + { + var compare = _isThreadStatic.CompareTo(other._isThreadStatic); + return compare != 0 ? compare : comparer.Compare(_type, other._type); + } + + protected internal override int ClassCode => 2142332918; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((GCStaticDescNode)other)._type); + } } public class GCStaticDescRegionNode : ArrayOfEmbeddedDataNode<GCStaticDescNode> @@ -232,5 +245,12 @@ namespace ILCompiler.DependencyAnalysis { return "Standalone" + _standaloneGCStaticDesc.GetMangledName(context.NameMangler); } + + protected internal override int ClassCode => 2091208431; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _standaloneGCStaticDesc.CompareTo(((StandaloneGCStaticDescRegionNode)other)._standaloneGCStaticDesc, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs index 7df1ca127..bea0665cd 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticEETypeNode.cs @@ -100,5 +100,12 @@ namespace ILCompiler.DependencyAnalysis return dataBuilder.ToObjectData(); } + + protected internal override int ClassCode => 1304929125; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _gcMap.CompareTo(((GCStaticEETypeNode)other)._gcMap); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs index 64c99b3b1..7e7432644 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsNode.cs @@ -12,7 +12,7 @@ using GCStaticRegionConstants = Internal.Runtime.GCStaticRegionConstants; namespace ILCompiler.DependencyAnalysis { - public class GCStaticsNode : ObjectNode, IExportableSymbolNode + public class GCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode { private MetadataType _type; private List<PreInitFieldInfo> _preInitFieldInfos; @@ -129,5 +129,19 @@ namespace ILCompiler.DependencyAnalysis } } } + + protected internal override int ClassCode => -522346696; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((GCStaticsNode)other)._type); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs index 5f76e5967..653a18fa0 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GCStaticsPreInitDataNode.cs @@ -112,5 +112,12 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => 1148300665; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((GCStaticsPreInitDataNode)other)._type); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs index 5594f71e9..cff9f3746 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericCompositionNode.cs @@ -99,6 +99,12 @@ namespace ILCompiler.DependencyAnalysis } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + protected internal override int ClassCode => -762680703; + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _details.CompareToImpl(((GenericCompositionNode)other)._details, comparer); + } } internal struct GenericCompositionDetails : IEquatable<GenericCompositionDetails> @@ -174,6 +180,36 @@ namespace ILCompiler.DependencyAnalysis return true; } + public int CompareToImpl(GenericCompositionDetails other, TypeSystemComparer comparer) + { + var compare = Instantiation.Length.CompareTo(other.Instantiation.Length); + if (compare != 0) + return compare; + + if (Variance == null && other.Variance != null) + return -1; + + if (Variance != null && other.Variance == null) + return 1; + + for (int i = 0; i < Instantiation.Length; i++) + { + compare = comparer.Compare(Instantiation[i], other.Instantiation[i]); + if (compare != 0) + return compare; + + if (Variance != null) + { + compare = Variance[i].CompareTo(other.Variance[i]); + if (compare != 0) + return compare; + } + } + + Debug.Assert(Equals(other)); + return 0; + } + public override bool Equals(object obj) { return obj is GenericCompositionDetails && Equals((GenericCompositionDetails)obj); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs index d1b3d7073..d40972210 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDefinitionEETypeNode.cs @@ -75,5 +75,7 @@ namespace ILCompiler.DependencyAnalysis return dataBuilder.ToObjectData(); } + + protected internal override int ClassCode => -160325006; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs index 8e300741d..48b7105ec 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericDictionaryNode.cs @@ -16,7 +16,7 @@ namespace ILCompiler.DependencyAnalysis /// at runtime to look up runtime artifacts that depend on the concrete /// context the generic type or method was instantiated with. /// </summary> - public abstract class GenericDictionaryNode : ObjectNode, IExportableSymbolNode + public abstract class GenericDictionaryNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode { private readonly NodeFactory _factory; @@ -85,6 +85,13 @@ namespace ILCompiler.DependencyAnalysis { return this.GetMangledName(factory.NameMangler); } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } public sealed class TypeGenericDictionaryNode : GenericDictionaryNode @@ -198,6 +205,13 @@ namespace ILCompiler.DependencyAnalysis _owningType = owningType; } + + protected internal override int ClassCode => 889700584; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_owningType, ((TypeGenericDictionaryNode)other)._owningType); + } } public sealed class MethodGenericDictionaryNode : GenericDictionaryNode @@ -287,5 +301,12 @@ namespace ILCompiler.DependencyAnalysis _owningMethod = owningMethod; } + + protected internal override int ClassCode => -1245704203; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_owningMethod, ((MethodGenericDictionaryNode)other)._owningMethod); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs index fda2463d4..870f48998 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs @@ -125,5 +125,8 @@ namespace ILCompiler.DependencyAnalysis ISymbolNode dictionaryNode = factory.MethodGenericDictionary(method); dependencies.Add(new DependencyListEntry(dictionaryNode, "GenericMethodsHashtable entry dictionary")); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.GenericMethodsHashtableNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs index daaae6f00..7a92d5dce 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs @@ -117,5 +117,8 @@ namespace ILCompiler.DependencyAnalysis return false; } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.GenericMethodsTemplateMap; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs index 17602c002..f48ec5dd7 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs @@ -67,5 +67,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(streamBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.GenericTypesHashtableNode; } }
\ No newline at end of file diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs index d6a4b295c..2be294a15 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs @@ -159,5 +159,8 @@ namespace ILCompiler.DependencyAnalysis return false; } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.GenericTypesTemplateMap; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs index 9910403eb..7e7e582a4 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -144,5 +144,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(streamBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.GenericVirtualMethodTableNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IEETypeNode.cs index 6da67b63a..4aee5b975 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IEETypeNode.cs @@ -9,7 +9,7 @@ namespace ILCompiler.DependencyAnalysis /// <summary> /// A dependency analysis node that represents a runtime type data structure. /// </summary> - public interface IEETypeNode : ISymbolNode + public interface IEETypeNode : ISortableSymbolNode { TypeDesc Type { get; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodNode.cs index be4edd793..393ee4adf 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IMethodNode.cs @@ -9,7 +9,7 @@ namespace ILCompiler.DependencyAnalysis /// <summary> /// A dependency analysis node that represents a method. /// </summary> - public interface IMethodNode : ISymbolNode + public interface IMethodNode : ISortableSymbolNode { MethodDesc Method { get; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs index 7cfaf2344..af38e11d6 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ISymbolNode.cs @@ -32,6 +32,16 @@ namespace ILCompiler.DependencyAnalysis bool RepresentsIndirectionCell { get; } } + + public interface ISortableSymbolNode : ISymbolNode + { +#if !SUPPORT_JIT + int ClassCode { get; } + int CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer); +#endif + } + + /// <summary> /// Represents a definition of a symbol within an <see cref="ObjectNode"/>. The symbol will be defined /// at the specified offset from the beginning of the <see cref="ObjectNode"/> that reports this as one of diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs index b62b4a511..77bd897ea 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/IndirectionNode.cs @@ -14,11 +14,11 @@ namespace ILCompiler.DependencyAnalysis /// </summary> public class IndirectionNode : ObjectNode, ISymbolDefinitionNode { - private ISymbolNode _indirectedNode; + private ISortableSymbolNode _indirectedNode; private int _offsetDelta; private TargetDetails _target; - public IndirectionNode(TargetDetails target, ISymbolNode indirectedNode, int offsetDelta) + public IndirectionNode(TargetDetails target, ISortableSymbolNode indirectedNode, int offsetDelta) { _indirectedNode = indirectedNode; _offsetDelta = offsetDelta; @@ -60,5 +60,12 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => -1401349230; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(this._indirectedNode, ((IndirectionNode)other)._indirectedNode); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs index dd18ffaff..9a4c0fd9c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs @@ -114,5 +114,13 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -2023802120; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + var compare = comparer.Compare(_targetMethod, ((InterfaceDispatchCellNode)other)._targetMethod); + return compare != 0 ? compare : string.Compare(_callSiteIdentifier, ((InterfaceDispatchCellNode)other)._callSiteIdentifier); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs index d49256a05..e2f6a6535 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs @@ -11,29 +11,20 @@ using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { - public class InterfaceDispatchMapNode : ObjectNode, ISymbolDefinitionNode + public class InterfaceDispatchMapNode : ObjectNode, ISymbolDefinitionNode, ISortableSymbolNode { - const int IndexNotSet = int.MaxValue; - - int _dispatchMapTableIndex; TypeDesc _type; public InterfaceDispatchMapNode(TypeDesc type) { _type = type; - _dispatchMapTableIndex = IndexNotSet; } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { - if (_dispatchMapTableIndex == IndexNotSet) - { - throw new InvalidOperationException("MangledName called before InterfaceDispatchMap index was initialized."); - } - - sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchMap_").Append(_dispatchMapTableIndex.ToStringInvariant()); + sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchMap_").Append(nameMangler.SanitizeName(nameMangler.GetMangledTypeName(_type))); } public int Offset => 0; @@ -51,21 +42,7 @@ namespace ILCompiler.DependencyAnalysis return ObjectNodeSection.DataSection; } } - - public void SetDispatchMapIndex(NodeFactory factory, int index) - { - _dispatchMapTableIndex = index; - IEETypeNode eeTypeNode = factory.ConstructedTypeSymbol(_type); - - if (eeTypeNode is ImportedEETypeSymbolNode) - { - Debug.Assert(_type == factory.TypeSystemContext.GetWellKnownType(WellKnownType.String)); - eeTypeNode = factory.ConstructedClonedTypeSymbol(_type); - } - - ((EETypeNode)eeTypeNode).SetDispatchMapIndex(_dispatchMapTableIndex); - } - + protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { var result = new DependencyList(); @@ -125,5 +102,19 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => 848664602; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((InterfaceDispatchMapNode)other)._type); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs index f6cef6f8c..3fd60f7bd 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -213,5 +213,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(streamBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.InterfaceGenericVirtualMethodTableNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs index 6c8c687d9..abc13496c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/JumpStubNode.cs @@ -2,12 +2,6 @@ // 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.Text; - namespace ILCompiler.DependencyAnalysis { public abstract partial class JumpStubNode : AssemblyStubNode @@ -28,5 +22,7 @@ namespace ILCompiler.DependencyAnalysis } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + protected internal override int ClassCode => 737788182; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs index 843d58358..69b1bd764 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/LoopHijackFlagNode.cs @@ -35,6 +35,8 @@ namespace ILCompiler.DependencyAnalysis public override bool StaticDependenciesAreComputed => true; + protected internal override int ClassCode => -266743363; + public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { // Emit a 4-byte integer flag with initial value of 0. diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs index 559fe5210..46bb90e09 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MetadataNode.cs @@ -5,6 +5,7 @@ using System; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -57,5 +58,8 @@ namespace ILCompiler.DependencyAnalysis _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.MetadataNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs index bfa57cfa3..46dacad9e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodAssociatedDataNode.cs @@ -41,6 +41,13 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; public override bool IsShareable => _methodNode.Method is InstantiatedMethod || EETypeNode.IsTypeNodeShareable(_methodNode.Method.OwningType); + protected internal override int ClassCode => 1055183914; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_methodNode, ((MethodAssociatedDataNode)other)._methodNode); + } + public virtual void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append("_associatedData_").Append(nameMangler.GetMangledMethodName(_methodNode.Method)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs index 228cf2401..69832904e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/MethodCodeNode.cs @@ -152,5 +152,19 @@ namespace ILCompiler.DependencyAnalysis Debug.Assert(_debugVarInfos == null); _debugVarInfos = debugVarInfos; } + + protected internal override int ClassCode => 788492407; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_method, ((MethodCodeNode)other)._method); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs index 544bcc2ec..ed629af32 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ModulesSectionNode.cs @@ -2,6 +2,8 @@ // 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.Text; using Internal.TypeSystem; @@ -52,5 +54,7 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -1225116970; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs index 2d029ae06..bed4f3fe4 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs @@ -7,6 +7,7 @@ using System.Collections.Generic; using Internal.Text; using Internal.NativeFormat; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -93,5 +94,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(_writerSavedBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.NativeLayoutInfoNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs index 6c593d929..2c1dd5f4d 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NativeLayoutSignatureNode.cs @@ -84,5 +84,38 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => 1887049331; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + NativeLayoutSignatureNode otherSignature = (NativeLayoutSignatureNode)other; + if (_identity is MethodDesc) + { + if (otherSignature._identity is TypeDesc || otherSignature._identity is FieldDesc) + return -1; + return comparer.Compare((MethodDesc)_identity, (MethodDesc)((NativeLayoutSignatureNode)other)._identity); + } + else if (_identity is TypeDesc) + { + if (otherSignature._identity is MethodDesc) + return 1; + + if (otherSignature._identity is FieldDesc) + return -1; + + return comparer.Compare((TypeDesc)_identity, (TypeDesc)((NativeLayoutSignatureNode)other)._identity); + } + else if (_identity is FieldDesc) + { + if (otherSignature._identity is MethodDesc || otherSignature._identity is TypeDesc) + return 1; + return comparer.Compare((FieldDesc)_identity, (FieldDesc)((NativeLayoutSignatureNode)other)._identity); + } + else + { + throw new NotSupportedException("New type system entity needs a comparison"); + } + } } }
\ No newline at end of file diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs index 022225777..2a72b509b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NecessaryCanonicalEETypeNode.cs @@ -9,7 +9,7 @@ using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { - /// <summary> + /// <summary> /// The node is used in ProjectX to represent a canonical type that does not have a vtable. /// </summary> internal sealed class NecessaryCanonicalEETypeNode : EETypeNode @@ -26,5 +26,7 @@ namespace ILCompiler.DependencyAnalysis { return _type.BaseType != null ? factory.NecessaryTypeSymbol(GetFullCanonicalTypeForCanonicalType(_type.BaseType)) : null; } + + protected internal override int ClassCode => 1505000724; } }
\ No newline at end of file diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs index 978d5a5db..6cde0dc8e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NodeFactory.cs @@ -214,7 +214,7 @@ namespace ILCompiler.DependencyAnalysis return new ImportedEETypeSymbolNode(this, type); }); - _nonGCStatics = new NodeCache<MetadataType, ISymbolNode>((MetadataType type) => + _nonGCStatics = new NodeCache<MetadataType, ISortableSymbolNode>((MetadataType type) => { if (_compilationModuleGroup.ContainsType(type)) { @@ -230,7 +230,7 @@ namespace ILCompiler.DependencyAnalysis } }); - _GCStatics = new NodeCache<MetadataType, ISymbolNode>((MetadataType type) => + _GCStatics = new NodeCache<MetadataType, ISortableSymbolNode>((MetadataType type) => { if (_compilationModuleGroup.ContainsType(type)) { @@ -362,7 +362,7 @@ namespace ILCompiler.DependencyAnalysis return new ReadyToRunGenericLookupFromTypeNode(this, data.HelperId, data.Target, data.DictionaryOwner); }); - _indirectionNodes = new NodeCache<ISymbolNode, ISymbolNode>(indirectedNode => + _indirectionNodes = new NodeCache<ISortableSymbolNode, ISymbolNode>(indirectedNode => { return new IndirectionNode(Target, indirectedNode, 0); }); @@ -399,11 +399,7 @@ namespace ILCompiler.DependencyAnalysis _interfaceDispatchMapIndirectionNodes = new NodeCache<TypeDesc, EmbeddedObjectNode>((TypeDesc type) => { - var dispatchMap = InterfaceDispatchMap(type); - return DispatchMapTable.NewNodeWithSymbol(dispatchMap, (indirectionNode) => - { - dispatchMap.SetDispatchMapIndex(this, DispatchMapTable.IndexOfEmbeddedObject(indirectionNode)); - }); + return DispatchMapTable.NewNodeWithSymbol(InterfaceDispatchMap(type)); }); _genericCompositions = new NodeCache<GenericCompositionDetails, GenericCompositionNode>((GenericCompositionDetails details) => @@ -431,7 +427,7 @@ namespace ILCompiler.DependencyAnalysis return _vtableSliceProvider.GetSlice(type); }); - _methodGenericDictionaries = new NodeCache<MethodDesc, ISymbolNode>(method => + _methodGenericDictionaries = new NodeCache<MethodDesc, ISortableSymbolNode>(method => { if (CompilationModuleGroup.ContainsMethodDictionary(method)) { @@ -443,7 +439,7 @@ namespace ILCompiler.DependencyAnalysis } }); - _typeGenericDictionaries = new NodeCache<TypeDesc, ISymbolNode>(type => + _typeGenericDictionaries = new NodeCache<TypeDesc, ISortableSymbolNode>(type => { if (CompilationModuleGroup.ContainsType(type)) { @@ -560,17 +556,17 @@ namespace ILCompiler.DependencyAnalysis return _importedTypeSymbols.GetOrAdd(type); } - private NodeCache<MetadataType, ISymbolNode> _nonGCStatics; + private NodeCache<MetadataType, ISortableSymbolNode> _nonGCStatics; - public ISymbolNode TypeNonGCStaticsSymbol(MetadataType type) + public ISortableSymbolNode TypeNonGCStaticsSymbol(MetadataType type) { Debug.Assert(!TypeCannotHaveEEType(type)); return _nonGCStatics.GetOrAdd(type); } - private NodeCache<MetadataType, ISymbolNode> _GCStatics; + private NodeCache<MetadataType, ISortableSymbolNode> _GCStatics; - public ISymbolNode TypeGCStaticsSymbol(MetadataType type) + public ISortableSymbolNode TypeGCStaticsSymbol(MetadataType type) { Debug.Assert(!TypeCannotHaveEEType(type)); return _GCStatics.GetOrAdd(type); @@ -673,7 +669,7 @@ namespace ILCompiler.DependencyAnalysis private NodeCache<string, ExternSymbolNode> _externSymbols; - public ISymbolNode ExternSymbol(string name) + public ISortableSymbolNode ExternSymbol(string name) { return _externSymbols.GetOrAdd(name); } @@ -699,14 +695,14 @@ namespace ILCompiler.DependencyAnalysis return _vTableNodes.GetOrAdd(type); } - private NodeCache<MethodDesc, ISymbolNode> _methodGenericDictionaries; - public ISymbolNode MethodGenericDictionary(MethodDesc method) + private NodeCache<MethodDesc, ISortableSymbolNode> _methodGenericDictionaries; + public ISortableSymbolNode MethodGenericDictionary(MethodDesc method) { return _methodGenericDictionaries.GetOrAdd(method); } - private NodeCache<TypeDesc, ISymbolNode> _typeGenericDictionaries; - public ISymbolNode TypeGenericDictionary(TypeDesc type) + private NodeCache<TypeDesc, ISortableSymbolNode> _typeGenericDictionaries; + public ISortableSymbolNode TypeGenericDictionary(TypeDesc type) { return _typeGenericDictionaries.GetOrAdd(type); } @@ -902,9 +898,9 @@ namespace ILCompiler.DependencyAnalysis return _genericReadyToRunHelpersFromType.GetOrAdd(new ReadyToRunGenericHelperKey(id, target, dictionaryOwner)); } - private NodeCache<ISymbolNode, ISymbolNode> _indirectionNodes; + private NodeCache<ISortableSymbolNode, ISymbolNode> _indirectionNodes; - public ISymbolNode Indirection(ISymbolNode symbol) + public ISymbolNode Indirection(ISortableSymbolNode symbol) { if (symbol.RepresentsIndirectionCell) { @@ -997,13 +993,13 @@ namespace ILCompiler.DependencyAnalysis public ArrayOfEmbeddedPointersNode<GCStaticsNode> GCStaticsRegion = new ArrayOfEmbeddedPointersNode<GCStaticsNode>( "__GCStaticRegionStart", - "__GCStaticRegionEnd", - null); + "__GCStaticRegionEnd", + new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer())); - public ArrayOfEmbeddedDataNode ThreadStaticsRegion = new ArrayOfEmbeddedDataNode( + public ArrayOfEmbeddedDataNode<ThreadStaticsNode> ThreadStaticsRegion = new ArrayOfEmbeddedDataNode<ThreadStaticsNode>( "__ThreadStaticRegionStart", "__ThreadStaticRegionEnd", - null); + new SortableDependencyNode.EmbeddedObjectNodeComparer(new CompilerComparer())); public ArrayOfEmbeddedPointersNode<IMethodNode> EagerCctorTable = new ArrayOfEmbeddedPointersNode<IMethodNode>( "__EagerCctorStart", @@ -1013,12 +1009,12 @@ namespace ILCompiler.DependencyAnalysis public ArrayOfEmbeddedPointersNode<InterfaceDispatchMapNode> DispatchMapTable = new ArrayOfEmbeddedPointersNode<InterfaceDispatchMapNode>( "__DispatchMapTableStart", "__DispatchMapTableEnd", - null); + new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer())); public ArrayOfEmbeddedDataNode<EmbeddedObjectNode> FrozenSegmentRegion = new ArrayOfFrozenObjectsNode<EmbeddedObjectNode>( "__FrozenSegmentRegionStart", "__FrozenSegmentRegionEnd", - null); + new SortableDependencyNode.EmbeddedObjectNodeComparer(new CompilerComparer())); public ReadyToRunHeaderNode ReadyToRunHeader; diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs index 7feef9bba..5e271e53b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/NonGCStaticsNode.cs @@ -18,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis /// with the class constructor context if the type has a class constructor that /// needs to be triggered before the type members can be accessed. /// </summary> - public class NonGCStaticsNode : ObjectNode, IExportableSymbolNode + public class NonGCStaticsNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode { private MetadataType _type; private NodeFactory _factory; @@ -177,5 +177,19 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => -1173104872; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((NonGCStaticsNode)other)._type); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs index 09610d9d3..6dcf96ae8 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ObjectNode.cs @@ -4,11 +4,13 @@ using System; using System.Collections.Generic; + using ILCompiler.DependencyAnalysisFramework; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { - public abstract class ObjectNode : DependencyNodeCore<NodeFactory> + public abstract partial class ObjectNode : SortableDependencyNode { public class ObjectData { diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs index ef1dc0aa8..797032e3e 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeMethodFixupNode.cs @@ -5,6 +5,7 @@ using System; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -73,5 +74,16 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => -1592006940; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + var compare = string.Compare(_moduleName, ((PInvokeMethodFixupNode)other)._moduleName); + if (compare != 0) + return compare; + + return string.Compare(_entryPointName, ((PInvokeMethodFixupNode)other)._entryPointName); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs index 939e2b037..bf83f13b1 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/PInvokeModuleFixupNode.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -48,5 +49,12 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => 159930099; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return string.Compare(_moduleName, ((PInvokeModuleFixupNode)other)._moduleName); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs index 99e717c40..d07760db4 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunGenericHelperNode.cs @@ -206,6 +206,52 @@ namespace ILCompiler.DependencyAnalysis return conditionalDependencies; } + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + var compare = _id.CompareTo(((ReadyToRunGenericHelperNode)other)._id); + if (compare != 0) + return compare; + + if (_dictionaryOwner is MethodDesc) + { + if (((ReadyToRunGenericHelperNode)other)._dictionaryOwner is TypeDesc) + return -1; + + compare = comparer.Compare((MethodDesc)_dictionaryOwner, (MethodDesc)((ReadyToRunGenericHelperNode)other)._dictionaryOwner); + } + else + { + if (((ReadyToRunGenericHelperNode)other)._dictionaryOwner is MethodDesc) + return 1; + + compare = comparer.Compare((TypeDesc)_dictionaryOwner, (TypeDesc)((ReadyToRunGenericHelperNode)other)._dictionaryOwner); + } + + if (compare != 0) + return compare; + + switch (_id) + { + case ReadyToRunHelperId.TypeHandle: + case ReadyToRunHelperId.GetGCStaticBase: + case ReadyToRunHelperId.GetNonGCStaticBase: + case ReadyToRunHelperId.GetThreadStaticBase: + case ReadyToRunHelperId.DefaultConstructor: + return comparer.Compare((TypeDesc)_target, (TypeDesc)((ReadyToRunGenericHelperNode)other)._target); + case ReadyToRunHelperId.MethodHandle: + case ReadyToRunHelperId.MethodDictionary: + case ReadyToRunHelperId.VirtualDispatchCell: + case ReadyToRunHelperId.MethodEntry: + return comparer.Compare((MethodDesc)_target, (MethodDesc)((ReadyToRunGenericHelperNode)other)._target); + case ReadyToRunHelperId.FieldHandle: + return comparer.Compare((FieldDesc)_target, (FieldDesc)((ReadyToRunGenericHelperNode)other)._target); + case ReadyToRunHelperId.DelegateCtor: + return ((DelegateCreationInfo)_target).CompareTo((DelegateCreationInfo)((ReadyToRunGenericHelperNode)other)._target, comparer); + default: + throw new NotImplementedException(); + } + } } public partial class ReadyToRunGenericLookupFromDictionaryNode : ReadyToRunGenericHelperNode @@ -226,6 +272,8 @@ namespace ILCompiler.DependencyAnalysis sb.Append("__GenericLookupFromDict_").Append(mangledContextName).Append("_"); AppendLookupSignatureMangledName(nameMangler, sb); } + + protected internal override int ClassCode => 1055354299; } public partial class ReadyToRunGenericLookupFromTypeNode : ReadyToRunGenericHelperNode @@ -246,5 +294,7 @@ namespace ILCompiler.DependencyAnalysis sb.Append("__GenericLookupFromType_").Append(mangledContextName).Append("_"); AppendLookupSignatureMangledName(nameMangler, sb); } + + protected internal override int ClassCode => 913214059; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs index f54e71e70..6c2fd6d73 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.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 System.Collections.Generic; using Internal.Runtime; @@ -126,5 +127,7 @@ namespace ILCompiler.DependencyAnalysis return builder.ToObjectData(); } + + protected internal override int ClassCode => -534800244; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs index 94671a88f..6bcbd7aeb 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReadyToRunHelperNode.cs @@ -188,5 +188,36 @@ namespace ILCompiler.DependencyAnalysis return null; } + +#if !SUPPORT_JIT + protected internal override int ClassCode => -911637948; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + var compare = _id.CompareTo(((ReadyToRunHelperNode)other)._id); + if (compare != 0) + return compare; + + switch (_id) + { + case ReadyToRunHelperId.NewHelper: + case ReadyToRunHelperId.NewArr1: + case ReadyToRunHelperId.IsInstanceOf: + case ReadyToRunHelperId.CastClass: + case ReadyToRunHelperId.GetNonGCStaticBase: + case ReadyToRunHelperId.GetGCStaticBase: + case ReadyToRunHelperId.GetThreadStaticBase: + return comparer.Compare((TypeDesc)_target, (TypeDesc)((ReadyToRunHelperNode)other)._target); + case ReadyToRunHelperId.VirtualCall: + case ReadyToRunHelperId.ResolveVirtualFunction: + return comparer.Compare((MethodDesc)_target, (MethodDesc)((ReadyToRunHelperNode)other)._target); + case ReadyToRunHelperId.DelegateCtor: + return ((DelegateCreationInfo)_target).CompareTo((DelegateCreationInfo)((ReadyToRunHelperNode)other)._target, comparer); + default: + throw new NotImplementedException(); + } + + } +#endif } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs index bdcfa44cd..9705515b6 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs @@ -228,5 +228,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ReflectionFieldMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs index d58053e77..2d92af22a 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -194,5 +194,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ReflectionInvokeMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs index c2d9617bb..00b1e9739 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs @@ -241,5 +241,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ReflectionVirtualInvokeMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs index 8ee203e1a..9ff7a7243 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceDataNode.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Internal.Text; -using Internal.TypeSystem.Ecma; using System; using System.Collections.Generic; using System.Diagnostics; @@ -11,6 +9,10 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using Internal.Text; +using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; + namespace ILCompiler.DependencyAnalysis { /// <summary> @@ -141,6 +143,9 @@ namespace ILCompiler.DependencyAnalysis _endSymbol.SetSymbolOffset(resourceBlob.Length); return resourceBlob; } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ResourceDataNode; } /// <summary> diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs index 175b101f1..053a3112b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ResourceIndexNode.cs @@ -6,6 +6,7 @@ using System; using Internal.NativeFormat; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -96,5 +97,8 @@ namespace ILCompiler.DependencyAnalysis _endSymbol.SetSymbolOffset(blob.Length); return blob; } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.ResourceIndexNode; } }
\ No newline at end of file diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs index 83bd6b0b7..d3a3672ea 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeDeterminedMethodNode.cs @@ -61,5 +61,12 @@ namespace ILCompiler.DependencyAnalysis public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; + + int ISortableSymbolNode.ClassCode => 258139501; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(_canonicalMethodNode, ((RuntimeDeterminedMethodNode)other)._canonicalMethodNode); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs index 7d47a0afa..c1285477f 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeFieldHandleNode.cs @@ -63,5 +63,12 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -1326215725; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_targetField, ((RuntimeFieldHandleNode)other)._targetField); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs index 920947aba..79bf416c3 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/RuntimeMethodHandleNode.cs @@ -76,5 +76,12 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -274400625; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_targetMethod, ((RuntimeMethodHandleNode)other)._targetMethod); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs index f37857ee6..43d27c344 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ScannedMethodNode.cs @@ -62,5 +62,12 @@ namespace ILCompiler.DependencyAnalysis public override bool InterestingForDynamicDependencyAnalysis => false; public override bool HasDynamicDependencies => false; public override bool HasConditionalStaticDependencies => false; + + int ISortableSymbolNode.ClassCode => -1381809560; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(Method, ((ScannedMethodNode)other).Method); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs index 43c1f4adf..40d7cc978 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteMethodNode.cs @@ -98,5 +98,16 @@ namespace ILCompiler.DependencyAnalysis public sealed override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; + + int ISortableSymbolNode.ClassCode => -1440570971; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + var compare = comparer.Compare(Method, ((ShadowConcreteMethodNode)other).Method); + if (compare != 0) + return compare; + + return comparer.Compare(CanonicalMethodNode, ((ShadowConcreteMethodNode)other).CanonicalMethodNode); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs index ae9f233d6..fe973fdb3 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ShadowConcreteUnboxingThunkNode.cs @@ -69,5 +69,16 @@ namespace ILCompiler.DependencyAnalysis public sealed override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; public sealed override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; + + int ISortableSymbolNode.ClassCode => -501699818; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + var compare = comparer.Compare(Method, ((ShadowConcreteUnboxingThunkNode)other).Method); + if (compare != 0) + return compare; + + return comparer.Compare(_canonicalThunk, ((ShadowConcreteUnboxingThunkNode)other)._canonicalThunk); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs new file mode 100644 index 000000000..66e2e7e60 --- /dev/null +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/SortableDependencyNode.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// 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 System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.CompilerServices; + +using ILCompiler.DependencyAnalysisFramework; +using Internal.TypeSystem; + +namespace ILCompiler.DependencyAnalysis +{ + public abstract class SortableDependencyNode : DependencyNodeCore<NodeFactory> + { +#if !SUPPORT_JIT + /// <summary> + /// Allows grouping of <see cref="ObjectNode"/> instances such that all nodes in a lower phase + /// will be ordered before nodes in a later phase. + /// </summary> + protected internal virtual int Phase => (int)ObjectNodePhase.Unordered; + + /// <summary> + /// Gets an identifier that is the same for all instances of this <see cref="ObjectNode"/> + /// descendant, but different from the <see cref="ClassCode"/> of any other descendant. + /// </summary> + /// <remarks> + /// This is really just a number, ideally produced by "new Random().Next(int.MinValue, int.MaxValue)". + /// If two manage to conflict (which is pretty unlikely), just make a new one... + /// </remarks> + protected internal abstract int ClassCode { get; } + + // Note to implementers: the type of `other` is actually the same as the type of `this`. + protected internal virtual int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + throw new NotImplementedException("Multiple nodes of this type are not supported"); + } + + protected enum ObjectNodePhase + { + /// <summary> + /// Nodes should only be placed in this phase if they have strict output ordering requirements that + /// affect compiler correctness. Today that includes native layout tables. + /// </summary> + Ordered, + Unordered + } + + protected enum ObjectNodeOrder + { + // + // The ordering of this sequence of nodes is deliberate and currently required for + // compiler correctness. + // + MetadataNode, + ResourceDataNode, + ResourceIndexNode, + TypeMetadataMapNode, + ClassConstructorContextMap, + DynamicInvokeTemplateDataNode, + ReflectionInvokeMapNode, + DelegateMarshallingStubMapNode, + StructMarshallingStubMapNode, + ArrayMapNode, + ReflectionFieldMapNode, + NativeLayoutInfoNode, + ExactMethodInstantiationsNode, + GenericTypesHashtableNode, + GenericMethodsHashtableNode, + GenericVirtualMethodTableNode, + InterfaceGenericVirtualMethodTableNode, + GenericMethodsTemplateMap, + GenericTypesTemplateMap, + BlockReflectionTypeMapNode, + StaticsInfoHashtableNode, + ReflectionVirtualInvokeMapNode, + ExternalReferencesTableNode, + ArrayOfEmbeddedPointersNode, + DefaultConstructorMapNode, + ArrayOfEmbeddedDataNode + } + + public class EmbeddedObjectNodeComparer : IComparer<EmbeddedObjectNode> + { + private CompilerComparer _comparer; + + public EmbeddedObjectNodeComparer(CompilerComparer comparer) + { + _comparer = comparer; + } + + public int Compare(EmbeddedObjectNode x, EmbeddedObjectNode y) + { + return CompareImpl(x, y, _comparer); + } + } + + /// <summary> + /// This comparer is used to sort the marked node list. We only care about ordering ObjectNodes + /// for emission into the binary, so any EmbeddedObjectNode or DependencyNodeCore objects are + /// skipped for efficiency. + /// </summary> + public class ObjectNodeComparer : IComparer<DependencyNodeCore<NodeFactory>> + { + private CompilerComparer _comparer; + + public ObjectNodeComparer(CompilerComparer comparer) + { + _comparer = comparer; + } + + public int Compare(DependencyNodeCore<NodeFactory> x1, DependencyNodeCore<NodeFactory> y1) + { + ObjectNode x = x1 as ObjectNode; + ObjectNode y = y1 as ObjectNode; + + if (x == y) + { + return 0; + } + + // Sort non-object nodes after ObjectNodes + if (x == null) + return 1; + + if (y == null) + return -1; + + return CompareImpl(x, y, _comparer); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int CompareImpl(SortableDependencyNode x, SortableDependencyNode y, CompilerComparer comparer) + { + int phaseX = x.Phase; + int phaseY = y.Phase; + + if (phaseX == phaseY) + { + int codeX = x.ClassCode; + int codeY = y.ClassCode; + if (codeX == codeY) + { + Debug.Assert(x.GetType() == y.GetType() || + (x.GetType().IsConstructedGenericType && y.GetType().IsConstructedGenericType + && x.GetType().GetGenericTypeDefinition() == y.GetType().GetGenericTypeDefinition())); + + int result = x.CompareToImpl(y, comparer); + + // We did a reference equality check above so an "Equal" result is not expected + Debug.Assert(result != 0 || x == y); + + return result; + } + else + { + Debug.Assert(x.GetType() != y.GetType()); + return codeX - codeY; + } + } + else + { + return phaseX - phaseY; + } + } +#endif + } +} diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs index 31fc9451d..22122f7ed 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs @@ -147,5 +147,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.StaticsInfoHashtableNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs index 6318cdcb1..8a071dbcd 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StringAllocatorMethodNode.cs @@ -65,5 +65,12 @@ namespace ILCompiler.DependencyAnalysis public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory context) => null; protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + int ISortableSymbolNode.ClassCode => 1991750873; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(_allocationMethod, ((StringAllocatorMethodNode)other)._allocationMethod); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs index 48227ea5b..604e25076 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs @@ -6,6 +6,7 @@ using System; using Internal.NativeFormat; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -103,5 +104,8 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + protected internal override int ClassCode => (int)ObjectNodeOrder.StructMarshallingStubMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs index eae1bc2be..1c201ebe3 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMInitialInterfaceDispatchStubNode.cs @@ -51,5 +51,7 @@ namespace ILCompiler.DependencyAnalysis { throw new NotImplementedException(); } + + protected internal override int ClassCode => 588185132; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs index 469c1473b..ab1450d1b 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsIndexNode.cs @@ -5,6 +5,7 @@ using System; using Internal.Text; +using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; @@ -17,7 +18,7 @@ namespace ILCompiler.DependencyAnalysis // The TLS slot index allocated for this module by the OS loader. We keep a pointer to this // value in the module header. - public class ThreadStaticsIndexNode : ObjectNode, IExportableSymbolNode + public class ThreadStaticsIndexNode : ObjectNode, IExportableSymbolNode, ISortableSymbolNode { string _prefix; @@ -80,6 +81,20 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -968500265; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return string.Compare(_prefix, ((ThreadStaticsIndexNode)other)._prefix); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } // The data structure used by the OS loader to load TLS chunks. @@ -166,5 +181,12 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -754150753; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return string.Compare(_prefix, ((ThreadStaticsDirectoryNode)other)._prefix); + } } }
\ No newline at end of file diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs index eed926b2c..357dde0fe 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsNode.cs @@ -75,5 +75,12 @@ namespace ILCompiler.DependencyAnalysis builder.RequireInitialPointerAlignment(); builder.EmitPointerReloc(GetGCStaticEETypeNode(factory)); } + + protected internal override int ClassCode => 2091208431; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((ThreadStaticsNode)other)._type); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs index 8dd47f642..83fef35ea 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/ThreadStaticsOffsetNode.cs @@ -14,7 +14,7 @@ namespace ILCompiler.DependencyAnalysis /// Represents the offset of the thread static region of a given type from the TLS section start. /// The node is used for cross-module thread statics reference /// </summary> - public class ThreadStaticsOffsetNode : EmbeddedObjectNode, IExportableSymbolNode + public class ThreadStaticsOffsetNode : EmbeddedObjectNode, IExportableSymbolNode, ISortableSymbolNode { private MetadataType _type; @@ -73,5 +73,19 @@ namespace ILCompiler.DependencyAnalysis { builder.EmitReloc(factory.TypeThreadStaticsSymbol(_type), RelocType.IMAGE_REL_SECREL); } + + protected internal override int ClassCode => 419394032; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((ThreadStaticsOffsetNode)other)._type); + } + + int ISortableSymbolNode.ClassCode => 419394032; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs index 781975087..4199c29fb 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeManagerIndirectionNode.cs @@ -2,7 +2,10 @@ // 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.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -30,5 +33,7 @@ namespace ILCompiler.DependencyAnalysis objData.EmitZeroPointer(); return objData.ToObjectData(); } + + protected internal override int ClassCode => -2028598574; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs index 9a682d9d1..ea58dd350 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs @@ -6,6 +6,7 @@ using System; using Internal.NativeFormat; using Internal.Text; +using Internal.TypeSystem; namespace ILCompiler.DependencyAnalysis { @@ -80,5 +81,9 @@ namespace ILCompiler.DependencyAnalysis return new ObjectData(hashTableBytes, Array.Empty<Relocation>(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); } + + protected internal override int Phase => (int)ObjectNodePhase.Ordered; + + protected internal override int ClassCode => (int)ObjectNodeOrder.TypeMetadataMapNode; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs index 6586d1ce8..11ac06f2c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs @@ -58,7 +58,7 @@ namespace ILCompiler.DependencyAnalysis if (!relocsOnly) { var node = factory.TypeThreadStaticsSymbol(_type); - typeTlsIndex = factory.ThreadStaticsRegion.IndexOfEmbeddedObject((ThreadStaticsNode)node); + typeTlsIndex = ((ThreadStaticsNode)node).IndexFromBeginningOfArray; } objData.EmitPointerReloc(factory.TypeManagerIndirection); @@ -66,5 +66,12 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => -149601250; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(_type, ((TypeThreadStaticIndexNode)other)._type); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs index b51d50bef..2208f7b1a 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UnboxingStubNode.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; using Internal.Text; using Internal.TypeSystem; @@ -60,6 +59,20 @@ namespace ILCompiler.DependencyAnalysis } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + protected internal override int ClassCode => -1846923013; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return comparer.Compare(Method, ((UnboxingStubNode)other).Method); + } + + int ISortableSymbolNode.ClassCode => ClassCode; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return CompareToImpl((ObjectNode)other, comparer); + } } // @@ -98,5 +111,12 @@ namespace ILCompiler.DependencyAnalysis return objData.ToObjectData(); } + + protected internal override int ClassCode => 1102274050; + + protected internal override int CompareToImpl(SortableDependencyNode other, CompilerComparer comparer) + { + return _isEndSymbol.CompareTo(((WindowsUnboxingStubsRegionNode)other)._isEndSymbol); + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs index 5c085d192..454ed3a41 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcNodeFactory.cs @@ -102,7 +102,7 @@ namespace ILCompiler return new GCStaticDescNode(type, true); }); - _threadStaticsOffset = new NodeCache<MetadataType, ISymbolNode>((MetadataType type) => + _threadStaticsOffset = new NodeCache<MetadataType, ISortableSymbolNode>((MetadataType type) => { if (CompilationModuleGroup.ContainsType(type)) { @@ -236,7 +236,7 @@ namespace ILCompiler CompilationUnitPrefix + "__ThreadStaticGCDescStart", CompilationUnitPrefix + "__ThreadStaticGCDescEnd"); - public ArrayOfEmbeddedDataNode ThreadStaticsOffsetRegion = new ArrayOfEmbeddedDataNode( + public ArrayOfEmbeddedDataNode<ThreadStaticsOffsetNode> ThreadStaticsOffsetRegion = new ArrayOfEmbeddedDataNode<ThreadStaticsOffsetNode>( CompilationUnitPrefix + "__ThreadStaticOffsetRegionStart", CompilationUnitPrefix + "__ThreadStaticOffsetRegionEnd", null); @@ -285,16 +285,16 @@ namespace ILCompiler } } - private NodeCache<MetadataType, ISymbolNode> _threadStaticsOffset; + private NodeCache<MetadataType, ISortableSymbolNode> _threadStaticsOffset; - public ISymbolNode TypeThreadStaticsOffsetSymbol(MetadataType type) + public ISortableSymbolNode TypeThreadStaticsOffsetSymbol(MetadataType type) { return _threadStaticsOffset.GetOrAdd(type); } private NodeCache<MetadataType, ImportedThreadStaticsIndexNode> _importedThreadStaticsIndices; - public ISymbolNode TypeThreadStaticsIndexSymbol(TypeDesc type) + public ISortableSymbolNode TypeThreadStaticsIndexSymbol(TypeDesc type) { if (CompilationModuleGroup.ContainsType(type)) { diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs index ccf216622..64cae3942 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/UtcThreadStaticsNode.cs @@ -60,5 +60,7 @@ namespace ILCompiler.DependencyAnalysis builder.AddSymbol(this); return builder.ToObjectData(); } + + protected internal override int ClassCode => -1421136129; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs index 2d15dde09..5ac16bbb3 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugILImagesSection.cs @@ -30,6 +30,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => 2051656903; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs index d056ac340..5d3ebd6e7 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugManagedNativeDictionaryInfoSection.cs @@ -30,6 +30,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => 1502860768; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs index 5481e9e9b..49f75a100 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMergedAssemblyRecordsSection.cs @@ -31,6 +31,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => -1250136545; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs index 3a7065c22..7d4396fc7 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodInfoSection.cs @@ -149,5 +149,7 @@ namespace ILCompiler.DependencyAnalysis { return "___DebugMethodInfoSection"; } + + protected internal override int ClassCode => 513099721; } } diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs index 57d29e640..c351d54e8 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugMethodMapSection.cs @@ -30,6 +30,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => -2063194124; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs index c2e38a183..71435021c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugNeedTypeIndicesStoreNode.cs @@ -21,6 +21,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => 1275723356; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs index 8b38611f6..7f393b2d4 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugPseudoAssemblySection.cs @@ -29,6 +29,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => 920778380; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs index 912721e7e..660559ccb 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeRecordsSection.cs @@ -33,6 +33,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => -2081034825; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs index 1337c162e..0ec387d9c 100644 --- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs +++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/WindowsDebugTypeSignatureMapSection.cs @@ -31,6 +31,8 @@ namespace ILCompiler.DependencyAnalysis public int Offset => 0; + protected internal override int ClassCode => 1029840999; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(GetName(null)); diff --git a/src/ILCompiler.Compiler/src/Compiler/ObjectDumper.cs b/src/ILCompiler.Compiler/src/Compiler/ObjectDumper.cs index 2dc9b64a2..194d92693 100644 --- a/src/ILCompiler.Compiler/src/Compiler/ObjectDumper.cs +++ b/src/ILCompiler.Compiler/src/Compiler/ObjectDumper.cs @@ -4,6 +4,7 @@ using System; using System.IO; +using System.Security.Cryptography; using System.Xml; using Internal.Text; @@ -17,7 +18,7 @@ namespace ILCompiler public class ObjectDumper : IObjectDumper { private readonly string _fileName; - + private SHA256 _sha256; private XmlWriter _writer; public ObjectDumper(string fileName) @@ -33,6 +34,7 @@ namespace ILCompiler Indent = true, }; + _sha256 = SHA256.Create(); _writer = XmlWriter.Create(File.CreateText(_fileName), settings); _writer.WriteStartElement("ObjectNodes"); } @@ -69,7 +71,7 @@ namespace ILCompiler } _writer.WriteAttributeString("Length", objectData.Data.Length.ToStringInvariant()); - + _writer.WriteAttributeString("Hash", HashData(objectData.Data)); _writer.WriteEndElement(); var nodeWithCodeInfo = node as INodeWithCodeInfo; @@ -78,6 +80,7 @@ namespace ILCompiler _writer.WriteStartElement("GCInfo"); _writer.WriteAttributeString("Name", name); _writer.WriteAttributeString("Length", nodeWithCodeInfo.GCInfo.Length.ToStringInvariant()); + _writer.WriteAttributeString("Hash", HashData(nodeWithCodeInfo.GCInfo)); _writer.WriteEndElement(); if (nodeWithCodeInfo.EHInfo != null) @@ -85,11 +88,17 @@ namespace ILCompiler _writer.WriteStartElement("EHInfo"); _writer.WriteAttributeString("Name", name); _writer.WriteAttributeString("Length", nodeWithCodeInfo.EHInfo.Data.Length.ToStringInvariant()); + _writer.WriteAttributeString("Hash", HashData(nodeWithCodeInfo.EHInfo.Data)); _writer.WriteEndElement(); } } } + private string HashData(byte[] data) + { + return BitConverter.ToString(_sha256.ComputeHash(data)).Replace("-", "").ToLower(); + } + internal void End() { _writer.WriteEndElement(); diff --git a/src/ILCompiler.Compiler/src/Compiler/PreInitFieldInfo.cs b/src/ILCompiler.Compiler/src/Compiler/PreInitFieldInfo.cs index da47f3539..00ec7d470 100644 --- a/src/ILCompiler.Compiler/src/Compiler/PreInitFieldInfo.cs +++ b/src/ILCompiler.Compiler/src/Compiler/PreInitFieldInfo.cs @@ -369,5 +369,24 @@ namespace ILCompiler { return fieldInfo1.Field.Offset.AsInt - fieldInfo2.Field.Offset.AsInt; } + + public int CompareTo(PreInitFieldInfo other, TypeSystemComparer comparer) + { + if (Length != other.Length) + return Length - other.Length; + + var compare = comparer.Compare(Field, other.Field); + if (compare != 0) + return compare; + + Debug.Assert(Data.Length == other.Data.Length); + for (int i = 0; i < Length; i++) + { + if (Data[i] != other.Data[i]) + return Data[i] - other.Data[i]; + } + + return 0; + } } } diff --git a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs index 6e5385f67..fbd06eabc 100644 --- a/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs +++ b/src/ILCompiler.Compiler/src/Compiler/RyuJitCompilationBuilder.cs @@ -90,7 +90,7 @@ namespace ILCompiler var factory = new RyuJitNodeFactory(_context, _compilationGroup, _metadataManager, interopStubManager, _nameMangler, _vtableSliceProvider, _dictionaryLayoutProvider); var jitConfig = new JitConfigProvider(jitFlagBuilder.ToArray(), _ryujitOptions); - DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory); + DependencyAnalyzerBase<NodeFactory> graph = CreateDependencyGraph(factory, new ObjectNode.ObjectNodeComparer(new CompilerComparer())); return new RyuJitCompilation(graph, factory, _compilationRoots, _debugInformationProvider, _logger, jitConfig); } } diff --git a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj index f12c17ad6..a259242a4 100644 --- a/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj +++ b/src/ILCompiler.Compiler/src/ILCompiler.Compiler.csproj @@ -1,4 +1,4 @@ -<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" Condition="'$(IsProjectNLibrary)' != 'true'" /> <PropertyGroup> <OutputType>Library</OutputType> @@ -113,7 +113,9 @@ <Compile Include="Compiler\DependencyAnalysis\WindowsDebugPseudoAssemblySection.cs" /> <Compile Include="Compiler\DependencyAnalysis\WindowsDebugTypeRecordsSection.cs" /> <Compile Include="Compiler\DependencyAnalysis\WindowsDebugTypeSignatureMapSection.cs" /> + <Compile Include="Compiler\DependencyAnalysis\CompilerComparer.cs" /> <Compile Include="Compiler\DependencyAnalysis\CustomAttributeBasedDependencyAlgorithm.cs" /> + <Compile Include="Compiler\DependencyAnalysis\EmbeddedDataContainerNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\FieldMetadataNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\ILScanNodeFactory.cs" /> <Compile Include="Compiler\DependencyAnalysis\IMethodBodyNode.cs" /> @@ -122,6 +124,7 @@ <Compile Include="Compiler\DependencyAnalysis\LoopHijackFlagNode.cs" /> <Compile Include="Compiler\DictionaryLayoutProvider.cs" /> <Compile Include="Compiler\EmptyInteropStubManager.cs" /> + <Compile Include="Compiler\DependencyAnalysis\SortableDependencyNode.cs" /> <Compile Include="Compiler\PreInitFieldInfo.cs" /> <Compile Include="Compiler\DependencyAnalysis\FrozenArrayNode.cs" /> <Compile Include="Compiler\DependencyAnalysis\GCStaticsPreInitDataNode.cs" /> diff --git a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs index 16ab08d5d..70a138649 100644 --- a/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs +++ b/src/ILCompiler.CppCodeGen/src/Compiler/DependencyAnalysis/CppMethodCodeNode.cs @@ -75,5 +75,12 @@ namespace ILCompiler.DependencyAnalysis public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; + + int ISortableSymbolNode.ClassCode => 1643555522; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(_method, ((CppMethodCodeNode)other)._method); + } } } diff --git a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs index 22b3352bc..be4301303 100644 --- a/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs +++ b/src/ILCompiler.CppCodeGen/src/CppCodeGen/CppWriter.cs @@ -1005,6 +1005,10 @@ namespace ILCompiler.CppCodeGen //RTR header needs to be declared after all modules have already been output string rtrHeader = string.Empty; + // GetData stabilizes the indices of the embedded objects. This must be done manually + // for C++ codegen since we don't currently emit the DispatchMapTable node directly. + factory.DispatchMapTable.GetData(factory, false); + // Iterate through nodes foreach (var node in nodeIterator.GetNodes()) { diff --git a/src/ILCompiler.DependencyAnalysisFramework/src/DependencyAnalyzer.cs b/src/ILCompiler.DependencyAnalysisFramework/src/DependencyAnalyzer.cs index d0aaf7a6d..13b20dac4 100644 --- a/src/ILCompiler.DependencyAnalysisFramework/src/DependencyAnalyzer.cs +++ b/src/ILCompiler.DependencyAnalysisFramework/src/DependencyAnalyzer.cs @@ -40,6 +40,7 @@ namespace ILCompiler.DependencyAnalysisFramework private Dictionary<DependencyNodeCore<DependencyContextType>, HashSet<DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry>> _conditional_dependency_store = new Dictionary<DependencyNodeCore<DependencyContextType>, HashSet<DependencyNodeCore<DependencyContextType>.CombinedDependencyListEntry>>(); private bool _markingCompleted = false; + private Random _stackPopRandomizer = null; private struct DynamicDependencyNode { @@ -68,6 +69,11 @@ namespace ILCompiler.DependencyAnalysisFramework { _dependencyContext = dependencyContext; _resultSorter = resultSorter; + + if (int.TryParse(Environment.GetEnvironmentVariable("CoreRT_DeterminismSeed"), out int seed)) + { + _stackPopRandomizer = new Random(seed); + } } /// <summary> @@ -274,7 +280,33 @@ namespace ILCompiler.DependencyAnalysisFramework { if (_marker.MarkNode(node, reason1, reason2, reason)) { - _markStack.Push(node); + // Pop the top node of the mark stack + if (_stackPopRandomizer == null) + { + _markStack.Push(node); + } + else + { + // + // Expose output file determinism bugs in our system by randomizing the order nodes are pushed + // on to the mark stack. + // + int randomNodeIndex = _stackPopRandomizer.Next(_markStack.Count); + var tempStack = new Stack<DependencyNodeCore<DependencyContextType>>(); + + for (int i = 0; i < randomNodeIndex; i++) + { + tempStack.Push(_markStack.Pop()); + } + + _markStack.Push(node); + + while (tempStack.Count > 0) + { + _markStack.Push(tempStack.Pop()); + } + } + _markedNodes.Add(node); node.CallOnMarked(_dependencyContext); diff --git a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs index 8d92bf996..0cfd4382c 100644 --- a/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs +++ b/src/ILCompiler.WebAssembly/src/Compiler/DependencyAnalysis/WebAssemblyMethodCodeNode.cs @@ -67,5 +67,12 @@ namespace ILCompiler.DependencyAnalysis public override IEnumerable<CombinedDependencyListEntry> GetConditionalStaticDependencies(NodeFactory factory) => null; public override IEnumerable<CombinedDependencyListEntry> SearchDynamicDependencies(List<DependencyNodeCore<NodeFactory>> markedNodes, int firstNode, NodeFactory factory) => null; + + int ISortableSymbolNode.ClassCode => -1502960727; + + int ISortableSymbolNode.CompareToImpl(ISortableSymbolNode other, CompilerComparer comparer) + { + return comparer.Compare(_method, ((WebAssemblyMethodCodeNode)other)._method); + } } } diff --git a/src/System.Private.Jit/src/System.Private.Jit.csproj b/src/System.Private.Jit/src/System.Private.Jit.csproj index 3bd997c29..db1d659f2 100644 --- a/src/System.Private.Jit/src/System.Private.Jit.csproj +++ b/src/System.Private.Jit/src/System.Private.Jit.csproj @@ -122,6 +122,7 @@ <Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\ObjectNodeSection.cs" /> <Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\ReadyToRunHelperNode.cs" /> <Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\Relocation.cs" /> + <Compile Include="$(ILCompilerBasePath)\Compiler\DependencyAnalysis\SortableDependencyNode.cs" /> <Compile Include="$(ILCompilerBasePath)\Compiler\DelegateCreationInfo.cs" /> <Compile Include="$(ILCompilerBasePath)\Compiler\JitHelper.cs" /> <Compile Include="$(ILCompilerBasePath)\Compiler\GenericDictionaryLookup.cs" /> diff --git a/tests/runtest.cmd b/tests/runtest.cmd index 606b2c0f3..85544ec5c 100644 --- a/tests/runtest.cmd +++ b/tests/runtest.cmd @@ -53,6 +53,7 @@ if /i "%1" == "/test" (set CoreRT_TestName=%2&shift&shift&goto ArgLoop) if /i "%1" == "/runtest" (set CoreRT_TestRun=%2&shift&shift&goto ArgLoop) if /i "%1" == "/dotnetclipath" (set CoreRT_CliDir=%2&shift&shift&goto ArgLoop) if /i "%1" == "/multimodule" (set CoreRT_MultiFileConfiguration=MultiModule&shift&goto ArgLoop) +if /i "%1" == "/determinism" (set CoreRT_DeterminismMode=true&shift&goto ArgLoop) echo Invalid command line argument: %1 goto :Usage @@ -68,6 +69,8 @@ echo /coreclr : Download and run the CoreCLR repo tests echo /coreclrsingletest ^<absolute\path\to\test.exe^> echo : Run a single CoreCLR repo test echo /multimodule : Compile the framework as a .lib and link tests against it (only supports ryujit) +echo /determinism : Compile the test twice with randomized dependency node mark stack to validate +echo compiler determinism in multi-threaded compilation. echo. echo --- CoreCLR Subset --- echo Top200 : Runs broad coverage / CI validation (~200 tests). @@ -260,24 +263,54 @@ goto :eof ) ) - echo msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" !extraArgs! !__SourceFileProj! - echo. - msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" !extraArgs! !__SourceFileProj! - endlocal + if "%CoreRT_DeterminismMode%"=="true" ( + set /a CoreRT_DeterminismSeed=%RANDOM%*32768+%RANDOM% + echo Running determinism baseline scenario with seed !CoreRT_DeterminismSeed! - set __SavedErrorLevel=%ErrorLevel% - if "%CoreRT_TestRun%"=="false" (goto :SkipTestRun) - if "%__Mode%" == "wasm" (goto :SkipTestRun) + echo msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" "/p:IlcGenerateMapFile=true" !extraArgs! !__SourceFileProj! + echo. + msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" "/p:IlcGenerateMapFile=true" !extraArgs! !__SourceFileProj! + + set __SavedErrorLevel=!ErrorLevel! + if not "!__SavedErrorLevel!"=="0" (goto :SkipTestRun) + + REM Back up the map file and delete the obj file so the MSBuild targets won't skip ILC target + rename !__SourceFolder!\obj\%CoreRT_BuildType%\%CoreRT_BuildArch%\native\!__SourceFileName!.map.xml !__SourceFileName!.baseline.map.xml + del !__SourceFolder!\obj\%CoreRT_BuildType%\%CoreRT_BuildArch%\native\!__SourceFileName!.obj + + set /a CoreRT_DeterminismSeed=%RANDOM%*32768+%RANDOM% + + echo Running determinism comparison scenario with seed !CoreRT_DeterminismSeed! + echo msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" "/p:IlcGenerateMapFile=true" !extraArgs! !__SourceFileProj! + echo. + msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" "/p:IlcGenerateMapFile=true" !extraArgs! !__SourceFileProj! + endlocal + set __SavedErrorLevel=!ErrorLevel! + if not "!__SavedErrorLevel!"=="0" (goto :SkipTestRun) + + fc !__SourceFolder!\obj\%CoreRT_BuildType%\%CoreRT_BuildArch%\native\!__SourceFileName!.baseline.map.xml !__SourceFolder!\obj\%CoreRT_BuildType%\%CoreRT_BuildArch%\native\!__SourceFileName!.map.xml + set __SavedErrorLevel=!ErrorLevel! - if "%__SavedErrorLevel%"=="0" ( + ) else ( + echo msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" !extraArgs! !__SourceFileProj! echo. - echo Running test !__SourceFileName! - call !__SourceFile!.cmd !__SourceFolder!\bin\%CoreRT_BuildType%\%CoreRT_BuildArch%\native !__SourceFileName!.exe + msbuild /m /ConsoleLoggerParameters:ForceNoAlign "/p:IlcPath=%CoreRT_ToolchainDir%" "/p:Configuration=%CoreRT_BuildType%" "/p:Platform=%CoreRT_BuildArch%" "/p:RepoLocalBuild=true" "/p:FrameworkLibPath=%~dp0..\bin\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\lib" "/p:FrameworkObjPath=%~dp0..\bin\obj\%CoreRT_BuildOS%.%CoreRT_BuildArch%.%CoreRT_BuildType%\Framework" !extraArgs! !__SourceFileProj! + endlocal + set __SavedErrorLevel=!ErrorLevel! + if "%CoreRT_TestRun%"=="false" (goto :SkipTestRun) + if "%__Mode%" == "wasm" (goto :SkipTestRun) + + if "%__SavedErrorLevel%"=="0" ( + echo. + echo Running test !__SourceFileName! + call !__SourceFile!.cmd !__SourceFolder!\bin\%CoreRT_BuildType%\%CoreRT_BuildArch%\native !__SourceFileName!.exe + set __SavedErrorLevel=!ErrorLevel! + ) ) :SkipTestRun - if "%__SavedErrorLevel%"=="0" ( + if "!__SavedErrorLevel!"=="0" ( set /a __%__Mode%PassedTests=!__%__Mode%PassedTests!+1 echo ^<test name="!__SourceFile!" type="!__SourceFileName!:%__Mode%" method="Main" result="Pass" /^> >> %__CoreRTTestBinDir%\testResults.tmp ) ELSE ( |