diff options
author | Simon Nattress <nattress@gmail.com> | 2017-10-30 19:41:15 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-30 19:41:15 +0300 |
commit | 5d7e4af8df1262b7b8ab8cd0b805c9f498d3493a (patch) | |
tree | 855f61ef66d2abe9f4e642fa4fed58c4b90813c3 /src/ILCompiler.Compiler | |
parent | 32c17228dea98ba5428a8dc5419170904c69a13b (diff) |
Stabilize object file images (#4818)
* Determinism test harness
Add a /determinism mode to runtest.cmd that will invoke ILC twice with different random determinism seeds. This causes graph expansion to be randomized based on seed (though deterministic for a given seed).
* Add Utf8String.CompareTo
Implementation taken from S.P.CoreLib. All the loop unrolling optimizations were excluded; we re-implement them if this function becomes a perf bottleneck.
* Define the mechanisms for determinism
To ensure deterministic output, all nodes that are emitted to the binary are sorted after compilation when retrieving the final marked nodes list. The overall approach is to sort nodes of the same type together (ie, all EETypeNodes come before NonGcStaticsNodes). Within nodes of the same type, a comparison function uses a CompilerComparer to compare the key identifying data of a node. For example, an EETypeNode is defined by a TypeDesc. The CompilerComparer provides a stable comparison function for comparing various type system primitives. Some nodes need to be emitted in an early and specific order for compiler correctness; this is provided by partitioning all sorted nodes into two phases: the first phase containined specifically ordered nodes, and a second phase for all other nodes whose ordering in the output binary doesn't matter.
Add SortableDependencyNode abstract class which provides the sortability layer on top of a DependencyNodeCore. Both ObjectNode and EmbeddedObjectNode derive from SortableDependencyNode to provide sortability across all nodes that are emitted to the output binary.
Introduce `ISortableSymbolNode` to provide sortability for nodes that are currently referred to in the compiler via the ISymbolNode interface. Such nodes are actually `ObjectNode` or `EmbeddedObjectNode` instances that we've lost type information for. Instances that implement `ISortableSymbolNode` redirect to the matching SortableDependencyNode methods.
Add `EmbeddedDataContainerNode` as a base class of `ArrayOfEmbeddedDataNode` to allow comparison of different instantiations.
Refactor the interface dispatch map index calculation so it's done when the dispatch map is emitted at the end of compilation. Previously it was done when the indirection cell in the dispatch map array got marked. This mechanism is incompatible with generating stable dispatch map indices. The arrays of embedded nodes now stabilize IDs as they emit their final data. This introduces an output ordering dependency - OptionalEETypeNodes must be emitted after the dispatch map since they encode dispatch map indices. Manually enforce this with C++ code generation, since it doesn't emit the real dispatch map structure and builds its own.
Modify InterfaceDispatchMapNode to use the type name in name mangling instead of an index into the dispatch map table.
Modify ObjectDumper to also amit a sha256 hash of each node's data. This dump is used to diff the map files and prove determinism.
* Fill out ordering functions for all nodes
Most of these are not very interesting. Here's the overall approach:
- Every different type of node needs a unique ClassCode. These were generated using Math.Random.
- The various metadata / native layout nodes plus arrays of EmbeddedObjectNodes get placed in the Ordered phase with specific ordering of each.
- All other nodes go in the Unordered phase
- To order nodes of the same type, the data that represents the key for the node in NodeFactory is compared. Ie, for an EEType, that would be its defining TypeDesc, whereas a FrozenStringNode is defined by the string it represents).
- The marked nodes list also contains raw DependencyNodeCore<T> nodes, which aren't emitted. Those are all shuffled after the emitted nodes and not sorted amongst themselves. That hasn't proven to be a problem with determinism and saves a bunch of hopefully unnecessary comparisons.
Diffstat (limited to 'src/ILCompiler.Compiler')
102 files changed, 1085 insertions, 152 deletions
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" /> |