diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs index a6897c8b11ba25..4debbad687ed12 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs @@ -856,22 +856,7 @@ internal bool HasDispatchMap { get { - if (NumInterfaces == 0) - return false; - byte* optionalFields = OptionalFieldsPtr; - - const uint NoDispatchMap = 0xffffffff; - uint idxDispatchMap = NoDispatchMap; - if (optionalFields != null) - idxDispatchMap = OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.DispatchMap, NoDispatchMap); - - if (idxDispatchMap == NoDispatchMap) - { - if (IsDynamicType) - return DynamicTemplateType->HasDispatchMap; - return false; - } - return true; + return (_uFlags & (uint)EETypeFlags.HasDispatchMap) != 0; } } @@ -879,25 +864,23 @@ internal DispatchMap* DispatchMap { get { - if (NumInterfaces == 0) - return null; - byte* optionalFields = OptionalFieldsPtr; - const uint NoDispatchMap = 0xffffffff; - uint idxDispatchMap = NoDispatchMap; - if (optionalFields != null) - idxDispatchMap = OptionalFieldsReader.GetInlineField(optionalFields, EETypeOptionalFieldTag.DispatchMap, NoDispatchMap); - if (idxDispatchMap == NoDispatchMap) - { - if (IsDynamicType) - return DynamicTemplateType->DispatchMap; + if (!HasDispatchMap) return null; - } - if (SupportsRelativePointers) - return (DispatchMap*)FollowRelativePointer((int*)TypeManager.DispatchMap + idxDispatchMap); - else - return ((DispatchMap**)TypeManager.DispatchMap)[idxDispatchMap]; + if (IsDynamicType || !SupportsRelativePointers) + return GetField>(EETypeField.ETF_DispatchMap).Value; + + return GetField>(EETypeField.ETF_DispatchMap).Value; } +#if TYPE_LOADER_IMPLEMENTATION + set + { + Debug.Assert(IsDynamicType && HasDispatchMap); + + fixed (MethodTable* pThis = &this) + *(DispatchMap**)((byte*)pThis + GetFieldOffset(EETypeField.ETF_DispatchMap)) = value; + } +#endif } // Get the address of the finalizer method for finalizable types. @@ -1345,6 +1328,15 @@ public uint GetFieldOffset(EETypeField eField) cbOffset += relativeOrFullPointerOffset; } + // Followed by pointer to the dispatch map + if (eField == EETypeField.ETF_DispatchMap) + { + Debug.Assert(HasDispatchMap); + return cbOffset; + } + if (HasDispatchMap) + cbOffset += relativeOrFullPointerOffset; + // Followed by the pointer to the finalizer method. if (eField == EETypeField.ETF_Finalizer) { @@ -1450,6 +1442,7 @@ public ref T GetField(uint offset) internal static uint GetSizeofEEType( ushort cVirtuals, ushort cInterfaces, + bool fHasDispatchMap, bool fHasFinalizer, bool fRequiresOptionalFields, bool fHasSealedVirtuals, @@ -1464,6 +1457,7 @@ internal static uint GetSizeofEEType( (sizeof(MethodTable*) * cInterfaces) + sizeof(IntPtr) + // TypeManager (SupportsWritableData ? sizeof(IntPtr) : 0) + // WritableData + (fHasDispatchMap ? sizeof(UIntPtr) : 0) + (fHasFinalizer ? sizeof(UIntPtr) : 0) + (fRequiresOptionalFields ? sizeof(IntPtr) : 0) + (fHasSealedVirtuals ? sizeof(IntPtr) : 0) + diff --git a/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeManagerHandle.cs b/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeManagerHandle.cs index 9780acd39f72a9..d1559fce550ea5 100644 --- a/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeManagerHandle.cs +++ b/src/coreclr/nativeaot/Common/src/Internal/Runtime/TypeManagerHandle.cs @@ -20,7 +20,6 @@ private struct TypeManager { public IntPtr OsHandle; public IntPtr ReadyToRunHeader; - public IntPtr DispatchMap; } public TypeManagerHandle(IntPtr handleValue) @@ -48,13 +47,5 @@ public unsafe IntPtr OsModuleBase return _handleValue->OsHandle; } } - - public unsafe IntPtr DispatchMap - { - get - { - return _handleValue->DispatchMap; - } - } } } diff --git a/src/coreclr/nativeaot/Runtime/TypeManager.cpp b/src/coreclr/nativeaot/Runtime/TypeManager.cpp index a8e372956aedd9..8458f883be2b59 100644 --- a/src/coreclr/nativeaot/Runtime/TypeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/TypeManager.cpp @@ -45,7 +45,6 @@ TypeManager::TypeManager(HANDLE osModule, ReadyToRunHeader * pHeader, void** pCl int length; m_pStaticsGCDataSection = (uint8_t*)GetModuleSection(ReadyToRunSectionType::GCStaticRegion, &length); m_pThreadStaticsDataSection = (uint8_t*)GetModuleSection(ReadyToRunSectionType::ThreadStaticRegion, &length); - m_pDispatchMapTable = (DispatchMap **)GetModuleSection(ReadyToRunSectionType::InterfaceDispatchTable, &length); } void * TypeManager::GetModuleSection(ReadyToRunSectionType sectionId, int * length) diff --git a/src/coreclr/nativeaot/Runtime/TypeManager.h b/src/coreclr/nativeaot/Runtime/TypeManager.h index 84d1ead3de344f..91a38ffbbacf98 100644 --- a/src/coreclr/nativeaot/Runtime/TypeManager.h +++ b/src/coreclr/nativeaot/Runtime/TypeManager.h @@ -4,14 +4,11 @@ #include "ModuleHeaders.h" #include "ICodeManager.h" -class DispatchMap; - class TypeManager { // NOTE: Part of this layout is a contract with the managed side in TypeManagerHandle.cs HANDLE m_osModule; ReadyToRunHeader * m_pHeader; - DispatchMap** m_pDispatchMapTable; uint8_t* m_pStaticsGCDataSection; uint8_t* m_pThreadStaticsDataSection; void** m_pClasslibFunctions; diff --git a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h index 7d0c985486c9d1..86281a25627ca8 100644 --- a/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h +++ b/src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h @@ -43,7 +43,7 @@ enum class ReadyToRunSectionType StringTable = 200, GCStaticRegion = 201, ThreadStaticRegion = 202, - InterfaceDispatchTable = 203, + // unused = 203, TypeManagerIndirection = 204, EagerCctor = 205, FrozenObjectRegion = 206, diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs index 0509ea7217f960..fe136fabc5427d 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs @@ -155,6 +155,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo int baseSize = 0; bool isValueType; + bool hasDispatchMap; bool hasFinalizer; bool isNullable; bool isArray; @@ -172,6 +173,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo baseSize = (int)pTemplateEEType->RawBaseSize; isValueType = pTemplateEEType->IsValueType; hasFinalizer = pTemplateEEType->IsFinalizable; + hasDispatchMap = pTemplateEEType->HasDispatchMap; isNullable = pTemplateEEType->IsNullable; flags = pTemplateEEType->Flags; isArray = pTemplateEEType->IsArray; @@ -225,9 +227,6 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo if (rareFlags != 0) optionalFields.SetFieldValue(EETypeOptionalFieldTag.RareFlags, rareFlags); - // Dispatch map is fetched from template type - optionalFields.ClearField(EETypeOptionalFieldTag.DispatchMap); - // Compute size of optional fields encoding cbOptionalFieldsSize = optionalFields.Encode(); @@ -251,6 +250,7 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo int cbEEType = (int)MethodTable.GetSizeofEEType( numVtableSlots, runtimeInterfacesLength, + hasDispatchMap, hasFinalizer, cbOptionalFieldsSize > 0, hasSealedVTable, @@ -300,6 +300,12 @@ private static void CreateEETypeWorker(MethodTable* pTemplateEEType, uint hashCo for (int i = 0; i < numVtableSlots; i++) pVtable[i] = pTemplateVtable[i]; + // Copy dispatch map from the template type + if (hasDispatchMap) + { + pEEType->DispatchMap = pTemplateEEType->DispatchMap; + } + // Copy Pointer to finalizer method from the template type if (hasFinalizer) { diff --git a/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs b/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs index 29a1044f2c8068..98b77ccfd9bb10 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs @@ -16,7 +16,10 @@ internal enum EETypeFlags : uint /// EETypeKindMask = 0x00030000, - // Unused = 0x00040000, + /// + /// Type has an associated dispatch map. + /// + HasDispatchMap = 0x00040000, /// /// This type was dynamically allocated at runtime. @@ -177,6 +180,7 @@ internal enum EETypeField ETF_InterfaceMap, ETF_TypeManagerIndirection, ETF_WritableData, + ETF_DispatchMap, ETF_Finalizer, ETF_OptionalFieldsPtr, ETF_SealedVirtualSlots, @@ -236,11 +240,6 @@ internal enum EETypeOptionalFieldTag : byte /// RareFlags, - /// - /// Index of the dispatch map pointer in the DispatchMap table - /// - DispatchMap, - /// /// Padding added to a value type when allocated on the GC heap /// diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index f1985389496664..a6369493929245 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -78,7 +78,7 @@ public enum ReadyToRunSectionType StringTable = 200, // Unused GCStaticRegion = 201, ThreadStaticRegion = 202, - InterfaceDispatchTable = 203, + // Unused = 203, TypeManagerIndirection = 204, EagerCctor = 205, FrozenObjectRegion = 206, diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs index 500192714f719e..7a6467a96e9e85 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/CanonicalEETypeNode.cs @@ -42,9 +42,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact DefType closestDefType = _type.GetClosestDefType(); - if (MightHaveInterfaceDispatchMap(factory)) - dependencyList.Add(factory.InterfaceDispatchMap(_type), "Canonical interface dispatch map"); - dependencyList.Add(factory.VTable(closestDefType), "VTable"); if (_type.IsCanonicalSubtype(CanonicalFormKind.Universal)) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index 1e9e3144d2be0d..716c2047b237f9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -36,12 +36,6 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact DefType closestDefType = _type.GetClosestDefType(); - if (MightHaveInterfaceDispatchMap(factory)) - { - TypeDesc canonType = _type.ConvertToCanonForm(CanonicalFormKind.Specific); - dependencyList.Add(factory.InterfaceDispatchMap(canonType), "Interface dispatch map"); - } - if (_type.IsArray) { // Array MethodTable depends on System.Array's virtuals. Array EETypes don't point to diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index 01cde356ab263e..6498c340e5cc53 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -689,6 +689,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo OutputTypeManagerIndirection(factory, ref objData); OutputWritableData(factory, ref objData); + OutputDispatchMap(factory, ref objData); OutputFinalizerMethod(factory, ref objData); OutputOptionalFields(factory, ref objData); OutputSealedVTable(factory, relocsOnly, ref objData); @@ -740,6 +741,11 @@ private void OutputFlags(NodeFactory factory, ref ObjectDataBuilder objData, boo flags |= (uint)EETypeFlags.HasSealedVTableEntriesFlag; } + if (MightHaveInterfaceDispatchMap(factory)) + { + flags |= (uint)EETypeFlags.HasDispatchMap; + } + if (HasOptionalFields) { flags |= (uint)EETypeFlags.OptionalFieldsFlag; @@ -1200,17 +1206,23 @@ private void OutputFunctionPointerParameters(NodeFactory factory, ref ObjectData } } + private void OutputDispatchMap(NodeFactory factory, ref ObjectDataBuilder objData) + { + if (MightHaveInterfaceDispatchMap(factory)) + { + ISymbolNode dispatchMap = factory.InterfaceDispatchMap(_type.ConvertToCanonForm(CanonicalFormKind.Specific)); + if (factory.Target.SupportsRelativePointers) + objData.EmitReloc(dispatchMap, RelocType.IMAGE_REL_BASED_RELPTR32); + else + objData.EmitPointerReloc(dispatchMap); + } + } + /// /// Populate the OptionalFieldsRuntimeBuilder if any optional fields are required. /// protected internal virtual void ComputeOptionalEETypeFields(NodeFactory factory, bool relocsOnly) { - if (!relocsOnly && MightHaveInterfaceDispatchMap(factory)) - { - TypeDesc canonType = _type.ConvertToCanonForm(CanonicalFormKind.Specific); - _optionalFieldsBuilder.SetFieldValue(EETypeOptionalFieldTag.DispatchMap, checked((uint)factory.InterfaceDispatchMapIndirection(canonType).IndexFromBeginningOfArray)); - } - ComputeRareFlags(factory); ComputeNullableValueOffset(); ComputeValueTypeFieldPadding(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs index 14011621e4cf5f..38104d7ab015c9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs @@ -50,7 +50,6 @@ public override ObjectNodeSection GetSection(NodeFactory factory) protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) { var result = new DependencyList(); - result.Add(factory.InterfaceDispatchMapIndirection(_type), "Interface dispatch map indirection node"); // VTable slots of implemented interfaces are consulted during emission foreach (TypeDesc runtimeInterface in _type.RuntimeInterfaces) 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 043f2aed75eb54..c726a9dc0a66d5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -391,11 +391,6 @@ private void CreateNodeCaches() return new EmbeddedTrimmingDescriptorNode(module); }); - _interfaceDispatchMapIndirectionNodes = new NodeCache((TypeDesc type) => - { - return DispatchMapTable.NewNodeWithSymbol(InterfaceDispatchMap(type)); - }); - _genericCompositions = new NodeCache((Instantiation details) => { return new GenericCompositionNode(details); @@ -759,13 +754,6 @@ internal InterfaceDispatchMapNode InterfaceDispatchMap(TypeDesc type) return _interfaceDispatchMaps.GetOrAdd(type); } - private NodeCache _interfaceDispatchMapIndirectionNodes; - - public EmbeddedObjectNode InterfaceDispatchMapIndirection(TypeDesc type) - { - return _interfaceDispatchMapIndirectionNodes.GetOrAdd(type); - } - private NodeCache _genericCompositions; internal ISymbolNode GenericComposition(Instantiation details) @@ -1248,11 +1236,6 @@ public string GetSymbolAlternateName(ISymbolNode node) "__EagerCctorEnd", null); - public ArrayOfEmbeddedPointersNode DispatchMapTable = new ArrayOfEmbeddedPointersNode( - "__DispatchMapTableStart", - "__DispatchMapTableEnd", - new SortableDependencyNode.ObjectNodeComparer(CompilerComparer.Instance)); - public ArrayOfFrozenObjectsNode FrozenSegmentRegion = new ArrayOfFrozenObjectsNode(); internal ModuleInitializerListNode ModuleInitializerList = new ModuleInitializerListNode(); @@ -1276,7 +1259,6 @@ public virtual void AttachToDependencyGraph(DependencyAnalyzerBase graph.AddRoot(ThreadStaticsRegion, "ThreadStaticsRegion is always generated"); graph.AddRoot(EagerCctorTable, "EagerCctorTable is always generated"); graph.AddRoot(TypeManagerIndirection, "TypeManagerIndirection is always generated"); - graph.AddRoot(DispatchMapTable, "DispatchMapTable is always generated"); graph.AddRoot(FrozenSegmentRegion, "FrozenSegmentRegion is always generated"); graph.AddRoot(InterfaceDispatchCellSection, "Interface dispatch cell section is always generated"); graph.AddRoot(ModuleInitializerList, "Module initializer list is always generated"); @@ -1285,7 +1267,6 @@ public virtual void AttachToDependencyGraph(DependencyAnalyzerBase ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticRegion, ThreadStaticsRegion, ThreadStaticsRegion.StartSymbol, ThreadStaticsRegion.EndSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.EagerCctor, EagerCctorTable, EagerCctorTable.StartSymbol, EagerCctorTable.EndSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.TypeManagerIndirection, TypeManagerIndirection, TypeManagerIndirection); - ReadyToRunHeader.Add(ReadyToRunSectionType.InterfaceDispatchTable, DispatchMapTable, DispatchMapTable.StartSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.FrozenObjectRegion, FrozenSegmentRegion, FrozenSegmentRegion, FrozenSegmentRegion.EndSymbol); ReadyToRunHeader.Add(ReadyToRunSectionType.ModuleInitializerList, ModuleInitializerList, ModuleInitializerList, ModuleInitializerList.EndSymbol);