Place dispatch cells in dehydrated section (#78748)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Wed, 30 Nov 2022 05:48:03 +0000 (14:48 +0900)
committerGitHub <noreply@github.com>
Wed, 30 Nov 2022 05:48:03 +0000 (14:48 +0900)
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellSectionNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs

index eeba7d3..7611bf9 100644 (file)
@@ -70,7 +70,7 @@ namespace ILCompiler.DependencyAnalysis
             // the most popular targets.
             ISymbolDefinitionNode firstSymbol = null;
             var relocOccurences = new Dictionary<ISymbolNode, int>();
-            foreach (ObjectNode.ObjectData o in factory.MetadataManager.GetDehydratableData())
+            foreach (ObjectData o in factory.MetadataManager.GetDehydratableData())
             {
                 firstSymbol ??= o.DefinedSymbols[0];
 
@@ -209,17 +209,14 @@ namespace ILCompiler.DependencyAnalysis
                     {
                         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 @@ namespace ILCompiler.DependencyAnalysis
                         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 @@ namespace ILCompiler.DependencyAnalysis
                             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 @@ namespace ILCompiler.DependencyAnalysis
                                     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
index b1b7fc8..1e52c4d 100644 (file)
@@ -10,7 +10,7 @@ using Internal.TypeSystem;
 
 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 @@ namespace ILCompiler.DependencyAnalysis
             }
         }
 
-        protected override void OnMarked(NodeFactory factory)
-        {
-            factory.InterfaceDispatchCellSection.AddEmbeddedObject(this);
-        }
-
         public override int ClassCode => -2023802120;
 
         public override int CompareToImpl(ISortableNode other, CompilerComparer comparer)
index f83a168..644b639 100644 (file)
@@ -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.
     /// </summary>
-    public class InterfaceDispatchCellSectionNode : ArrayOfEmbeddedDataNode<InterfaceDispatchCellNode>
+    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<byte>(), Array.Empty<Relocation>(), 1, Array.Empty<ISymbolDefinitionNode>());
+
+            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 @@ namespace ILCompiler.DependencyAnalysis
             //
             int runLength = 0;
             int currentSlot = NoSlot;
-            foreach (InterfaceDispatchCellNode node in NodesList)
+            foreach (InterfaceDispatchCellNode node in new SortedSet<InterfaceDispatchCellNode>(factory.MetadataManager.GetInterfaceDispatchCells(), new DispatchCellComparer(factory)))
             {
                 MethodDesc targetMethod = node.TargetMethod;
                 int targetSlot = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, targetMethod.OwningType);
@@ -83,10 +81,23 @@ namespace ILCompiler.DependencyAnalysis
                 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;
+
         /// <summary>
         /// Comparer that groups interface dispatch cells by their slot number.
         /// </summary>
index a8a0d2a..3ba7a53 100644 (file)
@@ -50,7 +50,6 @@ namespace ILCompiler.DependencyAnalysis
             MetadataManager = metadataManager;
             LazyGenericsPolicy = lazyGenericsPolicy;
             _importedNodeProvider = importedNodeProvider;
-            InterfaceDispatchCellSection = new InterfaceDispatchCellSectionNode(this);
             PreinitializationManager = preinitializationManager;
         }
 
@@ -1115,7 +1114,7 @@ namespace ILCompiler.DependencyAnalysis
 
         internal ModuleInitializerListNode ModuleInitializerList = new ModuleInitializerListNode();
 
-        public InterfaceDispatchCellSectionNode InterfaceDispatchCellSection { get; }
+        public InterfaceDispatchCellSectionNode InterfaceDispatchCellSection = new InterfaceDispatchCellSectionNode();
 
         public ReadyToRunHeaderNode ReadyToRunHeader;
 
index 87d51cd..0e94c50 100644 (file)
@@ -49,6 +49,7 @@ namespace ILCompiler
         protected readonly ManifestResourceBlockingPolicy _resourceBlockingPolicy;
         protected readonly DynamicInvokeThunkGenerationPolicy _dynamicInvokeThunkGenerationPolicy;
 
+        private readonly List<InterfaceDispatchCellNode> _interfaceDispatchCells = new List<InterfaceDispatchCellNode>();
         private readonly SortedSet<NonGCStaticsNode> _cctorContextsGenerated = new SortedSet<NonGCStaticsNode>(CompilerComparer.Instance);
         private readonly SortedSet<TypeDesc> _typesWithEETypesGenerated = new SortedSet<TypeDesc>(TypeSystemComparer.Instance);
         private readonly SortedSet<TypeDesc> _typesWithConstructedEETypesGenerated = new SortedSet<TypeDesc>(TypeSystemComparer.Instance);
@@ -258,6 +259,11 @@ namespace ILCompiler
                     _reflectableMethods.Add(method);
             }
 
+            if (obj is InterfaceDispatchCellNode dispatchCell)
+            {
+                _interfaceDispatchCells.Add(dispatchCell);
+            }
+
             if (obj is StructMarshallingDataNode structMarshallingDataNode)
             {
                 _typesWithStructMarshalling.Add(structMarshallingDataNode.Type);
@@ -654,6 +660,11 @@ namespace ILCompiler
             return _stackTraceMappings;
         }
 
+        internal IEnumerable<InterfaceDispatchCellNode> GetInterfaceDispatchCells()
+        {
+            return _interfaceDispatchCells;
+        }
+
         internal IEnumerable<NonGCStaticsNode> GetCctorContextMapping()
         {
             return _cctorContextsGenerated;