diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs index eeba7d3c1d1cdf..7611bf9459aed0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs @@ -70,7 +70,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) // the most popular targets. ISymbolDefinitionNode firstSymbol = null; var relocOccurences = new Dictionary(); - foreach (ObjectNode.ObjectData o in factory.MetadataManager.GetDehydratableData()) + foreach (ObjectData o in factory.MetadataManager.GetDehydratableData()) { firstSymbol ??= o.DefinedSymbols[0]; @@ -209,17 +209,14 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { Debug.Assert(sourcePosition == reloc.Offset); -#if DEBUG + long delta; unsafe { fixed (byte* pData = &o.Data[reloc.Offset]) { - long delta = Relocation.ReadValue(reloc.RelocType, pData); - // Extra work needed to be able to encode/decode relocs with deltas - Debug.Assert(delta == 0); + delta = Relocation.ReadValue(reloc.RelocType, pData); } } -#endif // The size of the relocation is included in the ObjectData bytes. Skip the literal bytes. sourcePosition += Relocation.GetSize(reloc.RelocType); @@ -228,7 +225,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (target is ISymbolNodeWithLinkage withLinkage) target = withLinkage.NodeForLinkage(factory); - if (relocs.TryGetValue(target, out int targetIndex)) + if (delta == 0 && relocs.TryGetValue(target, out int targetIndex)) { // Reloc goes through the lookup table int relocCommand = reloc.RelocType switch @@ -252,7 +249,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) bool hasNextReloc; do { - builder.EmitReloc(target, RelocType.IMAGE_REL_BASED_RELPTR32); + builder.EmitReloc(target, RelocType.IMAGE_REL_BASED_RELPTR32, checked((int)delta)); numRelocs++; hasNextReloc = false; @@ -276,8 +273,16 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (nextTarget is ISymbolNodeWithLinkage nextTargetWithLinkage) nextTarget = nextTargetWithLinkage.NodeForLinkage(factory); + unsafe + { + fixed (byte* pData = &o.Data[reloc.Offset]) + { + delta = Relocation.ReadValue(reloc.RelocType, pData); + } + } + // We don't have a short code for it? - if (relocs.ContainsKey(nextTarget)) + if (delta == 0 && relocs.ContainsKey(nextTarget)) break; // This relocation is good - we'll generate it as part of the run diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs index b1b7fc8ad7ec7a..1e52c4d0bedc89 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs @@ -10,7 +10,7 @@ namespace ILCompiler.DependencyAnalysis { - public class InterfaceDispatchCellNode : EmbeddedObjectNode, ISymbolDefinitionNode + public sealed class InterfaceDispatchCellNode : EmbeddedObjectNode, ISymbolDefinitionNode { private readonly MethodDesc _targetMethod; private readonly string _callSiteIdentifier; @@ -113,11 +113,6 @@ public override void EncodeData(ref ObjectDataBuilder objData, NodeFactory facto } } - protected override void OnMarked(NodeFactory factory) - { - factory.InterfaceDispatchCellSection.AddEmbeddedObject(this); - } - public override int ClassCode => -2023802120; public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs index f83a168e08895c..644b639f8cb588 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; - +using Internal.Text; using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; @@ -14,17 +14,15 @@ namespace ILCompiler.DependencyAnalysis /// Represents a section of the executable where interface dispatch cells and their slot information /// is stored. /// - public class InterfaceDispatchCellSectionNode : ArrayOfEmbeddedDataNode + public class InterfaceDispatchCellSectionNode : DehydratableObjectNode, ISymbolDefinitionNode { - public InterfaceDispatchCellSectionNode(NodeFactory factory) - : base("__InterfaceDispatchCellSection_Start", "__InterfaceDispatchCellSection_End", new DispatchCellComparer(factory)) - { - } - - protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, NodeFactory factory, bool relocsOnly) + protected override ObjectData GetDehydratableData(NodeFactory factory, bool relocsOnly) { if (relocsOnly) - return; + return new ObjectData(Array.Empty(), Array.Empty(), 1, Array.Empty()); + + var builder = new ObjectDataBuilder(factory, relocsOnly); + builder.AddSymbol(this); // The interface dispatch cell has an alignment requirement of 2 * [Pointer size] as part of the // synchronization mechanism of the two values in the runtime. @@ -48,7 +46,7 @@ protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, No // int runLength = 0; int currentSlot = NoSlot; - foreach (InterfaceDispatchCellNode node in NodesList) + foreach (InterfaceDispatchCellNode node in new SortedSet(factory.MetadataManager.GetInterfaceDispatchCells(), new DispatchCellComparer(factory))) { MethodDesc targetMethod = node.TargetMethod; int targetSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType); @@ -83,10 +81,23 @@ protected override void GetElementDataForNodes(ref ObjectDataBuilder builder, No builder.EmitZeroPointer(); builder.EmitNaturalInt(currentSlot); } + + return builder.ToObjectData(); } + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + => sb.Append(nameMangler.CompilationUnitPrefix).Append("__InterfaceDispatchCellSection_Start"); + protected override ObjectNodeSection GetDehydratedSection(NodeFactory factory) => ObjectNodeSection.DataSection; + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + public override int ClassCode => -1389343; + public int Offset => 0; + + public override bool IsShareable => false; + + public override bool StaticDependenciesAreComputed => true; + /// /// Comparer that groups interface dispatch cells by their slot number. /// diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index efd7f86102b1ff..61f08f6761bb42 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -50,7 +50,6 @@ public NodeFactory( MetadataManager = metadataManager; LazyGenericsPolicy = lazyGenericsPolicy; _importedNodeProvider = importedNodeProvider; - InterfaceDispatchCellSection = new InterfaceDispatchCellSectionNode(this); PreinitializationManager = preinitializationManager; } @@ -1129,7 +1128,7 @@ public string GetSymbolAlternateName(ISymbolNode node) internal ModuleInitializerListNode ModuleInitializerList = new ModuleInitializerListNode(); - public InterfaceDispatchCellSectionNode InterfaceDispatchCellSection { get; } + public InterfaceDispatchCellSectionNode InterfaceDispatchCellSection = new InterfaceDispatchCellSectionNode(); public ReadyToRunHeaderNode ReadyToRunHeader; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 87d51cd0eeca86..0e94c509d913b3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -49,6 +49,7 @@ public abstract class MetadataManager : ICompilationRootProvider protected readonly ManifestResourceBlockingPolicy _resourceBlockingPolicy; protected readonly DynamicInvokeThunkGenerationPolicy _dynamicInvokeThunkGenerationPolicy; + private readonly List _interfaceDispatchCells = new List(); private readonly SortedSet _cctorContextsGenerated = new SortedSet(CompilerComparer.Instance); private readonly SortedSet _typesWithEETypesGenerated = new SortedSet(TypeSystemComparer.Instance); private readonly SortedSet _typesWithConstructedEETypesGenerated = new SortedSet(TypeSystemComparer.Instance); @@ -258,6 +259,11 @@ protected virtual void Graph_NewMarkedNode(DependencyNodeCore obj) _reflectableMethods.Add(method); } + if (obj is InterfaceDispatchCellNode dispatchCell) + { + _interfaceDispatchCells.Add(dispatchCell); + } + if (obj is StructMarshallingDataNode structMarshallingDataNode) { _typesWithStructMarshalling.Add(structMarshallingDataNode.Type); @@ -654,6 +660,11 @@ public IEnumerable> GetStackTraceMapping(NodeFactory return _stackTraceMappings; } + internal IEnumerable GetInterfaceDispatchCells() + { + return _interfaceDispatchCells; + } + internal IEnumerable GetCctorContextMapping() { return _cctorContextsGenerated;