diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/Object.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/Object.cs index b7e3d15bf6e8a1..08d6279a064bc9 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/Object.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/Object.cs @@ -45,9 +45,6 @@ internal MethodTable* MethodTable } } - [Runtime.CompilerServices.Intrinsic] - internal static extern MethodTable* MethodTableOf(); - internal EETypePtr EETypePtr { get diff --git a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp index 2d1a6971b10fb8..e30e8952389900 100644 --- a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp +++ b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp @@ -267,25 +267,6 @@ RuntimeInstance::TypeManagerList& RuntimeInstance::GetTypeManagerList() return m_TypeManagerList; } -TypeManager* RuntimeInstance::GetSingleTypeManager() -{ - auto head = m_TypeManagerList.GetHead(); - if (head != NULL && head->m_pNext == NULL) - { - return head->m_pTypeManager; - } - - return NULL; -} - -COOP_PINVOKE_HELPER(TypeManagerHandle, RhGetSingleTypeManager, ()) -{ - TypeManager* typeManager = GetRuntimeInstance()->GetSingleTypeManager(); - ASSERT(typeManager != NULL); - - return TypeManagerHandle::Create(typeManager); -} - // static bool RuntimeInstance::Initialize(HANDLE hPalInstance) { diff --git a/src/coreclr/nativeaot/Runtime/RuntimeInstance.h b/src/coreclr/nativeaot/Runtime/RuntimeInstance.h index 06db50839eebac..2de7c220f09128 100644 --- a/src/coreclr/nativeaot/Runtime/RuntimeInstance.h +++ b/src/coreclr/nativeaot/Runtime/RuntimeInstance.h @@ -99,7 +99,6 @@ class RuntimeInstance bool RegisterTypeManager(TypeManager * pTypeManager); TypeManagerList& GetTypeManagerList(); - TypeManager* GetSingleTypeManager(); OsModuleList* GetOsModuleList(); bool RegisterUnboxingStubs(PTR_VOID pvStartRange, uint32_t cbRange); diff --git a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S index c2247d8be5e24c..34acbfe3795e81 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S +++ b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.S @@ -44,22 +44,3 @@ LOCAL_LABEL(ProbeLoop): RESET_FRAME_WITH_RBP ret NESTED_END RhpStackProbe, _TEXT - -#ifndef TARGET_ANDROID -NESTED_ENTRY RhpGetInlinedThreadStaticBase, _TEXT, NoHandler - // On exit: - // rax - the thread static base for the given type - - // rdi = &tls_InlinedThreadStatics - INLINE_GET_TLS_VAR tls_InlinedThreadStatics - mov rdi, rax - - // get per-thread storage - mov rax, [rdi] - test rax, rax - jz C_FUNC(RhpGetInlinedThreadStaticBaseSlow) // rdi contains the storage ref - - // return it - ret -NESTED_END RhpGetInlinedThreadStaticBase, _TEXT -#endif diff --git a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm index c4f39f51345585..c3eb1fc2964eae 100644 --- a/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/amd64/MiscStubs.asm @@ -3,8 +3,6 @@ include AsmMacros.inc -EXTERN RhpGetInlinedThreadStaticBaseSlow : PROC - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; The following helper will access ("probe") a word on each page of the stack ; starting with the page right beneath rsp down to the one pointed to by r11. @@ -39,20 +37,4 @@ ProbeLoop: LEAF_END RhpStackProbe, _TEXT -LEAF_ENTRY RhpGetInlinedThreadStaticBase, _TEXT - ; On exit: - ; rax - the thread static base for the given type - - ;; rcx = &tls_InlinedThreadStatics, TRASHES r8 - INLINE_GET_TLS_VAR rcx, r8, tls_InlinedThreadStatics - - ;; get per-thread storage - mov rax, [rcx] - test rax, rax - jz RhpGetInlinedThreadStaticBaseSlow ;; rcx contains the storage ref - - ;; return it - ret -LEAF_END RhpGetInlinedThreadStaticBase, _TEXT - end diff --git a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S index 34af83ccf0b985..ea5d91a1a1c1f9 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S +++ b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.S @@ -3,24 +3,3 @@ #include #include "AsmOffsets.inc" - -#ifndef TARGET_ANDROID -NESTED_ENTRY RhpGetInlinedThreadStaticBase, _TEXT, NoHandler - // On exit: - // x0 - the thread static base for the given type - - // x1 = GetThread() - INLINE_GET_TLS_VAR x1, C_FUNC(tls_InlinedThreadStatics) - - // get per-thread storage - ldr x0, [x1] - cbnz x0, HaveValue - mov x0, x1 - b C_FUNC(RhpGetInlinedThreadStaticBaseSlow) - -HaveValue: - // return it - ret - -NESTED_END RhpGetInlinedThreadStaticBase, _TEXT -#endif diff --git a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm index cdb076b3d56b26..49baea4977259b 100644 --- a/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm +++ b/src/coreclr/nativeaot/Runtime/arm64/MiscStubs.asm @@ -3,25 +3,6 @@ #include "AsmMacros.h" - EXTERN RhpGetInlinedThreadStaticBaseSlow - TEXTAREA -;; On exit: -;; x0 - the thread static base for the given type - LEAF_ENTRY RhpGetInlinedThreadStaticBase - ;; x1 = &tls_InlinedThreadStatics, TRASHES x2 - INLINE_GET_TLS_VAR x1, x2, tls_InlinedThreadStatics - - ;; get per-thread storage - ldr x0, [x1] - cbnz x0, HaveValue - mov x0, x1 - b RhpGetInlinedThreadStaticBaseSlow - -HaveValue - ;; return it - ret - LEAF_END RhpGetInlinedThreadStaticBase - end diff --git a/src/coreclr/nativeaot/Runtime/threadstore.cpp b/src/coreclr/nativeaot/Runtime/threadstore.cpp index c65d9577095665..67a6949fd7fb06 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.cpp +++ b/src/coreclr/nativeaot/Runtime/threadstore.cpp @@ -430,11 +430,6 @@ C_ASSERT(sizeof(Thread) == sizeof(ThreadBuffer)); #ifndef _MSC_VER __thread ThreadBuffer tls_CurrentThread; - -// the root of inlined threadstatics storage -// there is only one now, -// eventually this will be emitted by ILC and we may have more than one such variable -__thread InlinedThreadStaticRoot tls_InlinedThreadStatics; #endif EXTERN_C ThreadBuffer* RhpGetThread() @@ -442,11 +437,6 @@ EXTERN_C ThreadBuffer* RhpGetThread() return &tls_CurrentThread; } -COOP_PINVOKE_HELPER(Object**, RhGetInlinedThreadStaticStorage, ()) -{ - return &tls_InlinedThreadStatics.m_threadStaticsBase; -} - #endif // !DACCESS_COMPILE #ifdef _WIN32 diff --git a/src/coreclr/nativeaot/Runtime/threadstore.inl b/src/coreclr/nativeaot/Runtime/threadstore.inl index 6fe750f4b01c01..29495046a98272 100644 --- a/src/coreclr/nativeaot/Runtime/threadstore.inl +++ b/src/coreclr/nativeaot/Runtime/threadstore.inl @@ -4,14 +4,8 @@ #ifdef _MSC_VER // a workaround to prevent tls_CurrentThread from becoming dynamically checked/initialized. EXTERN_C __declspec(selectany) __declspec(thread) ThreadBuffer tls_CurrentThread; - -// the root of inlined threadstatics storage -// there is only one now, -// eventually this will be emitted by ILC and we may have more than one such variable -EXTERN_C __declspec(selectany) __declspec(thread) InlinedThreadStaticRoot tls_InlinedThreadStatics; #else EXTERN_C __thread ThreadBuffer tls_CurrentThread; -EXTERN_C __thread InlinedThreadStaticRoot tls_InlinedThreadStatics; #endif // static diff --git a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc index 1aaf7c53ff6157..ab64ef9ce92b49 100644 --- a/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc +++ b/src/coreclr/nativeaot/Runtime/unix/unixasmmacrosamd64.inc @@ -288,9 +288,12 @@ C_FUNC(\Name): movq _\Var@TLVP(%rip), %rdi callq *(%rdi) #else - leaq \Var@TLSLD(%rip), %rdi + .byte 0x66 // data16 prefix - padding to have space for linker relaxations + leaq \Var@TLSGD(%rip), %rdi + .byte 0x66 // + .byte 0x66 // + .byte 0x48 // rex.W prefix, also for padding callq __tls_get_addr@PLT - addq $\Var@DTPOFF, %rax #endif .intel_syntax noprefix .endm diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs index 9734e2a0a2632f..7bfcbff517b22f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs @@ -17,28 +17,26 @@ namespace Internal.Runtime /// internal static class ThreadStatics { + [ThreadStatic] + private static object t_inlinedThreadStaticBase; + /// /// This method is called from a ReadyToRun helper to get base address of thread /// static storage for the given type. /// internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot* pModuleData, int typeTlsIndex) { - if (typeTlsIndex >= 0) - return GetUninlinedThreadStaticBaseForType(pModuleData, typeTlsIndex); - - ref object? threadStorage = ref RuntimeImports.RhGetInlinedThreadStaticStorage(); - if (threadStorage != null) - return threadStorage; + if (typeTlsIndex < 0) + return t_inlinedThreadStaticBase; - return GetInlinedThreadStaticBaseSlow(ref threadStorage); + return GetUninlinedThreadStaticBaseForType(pModuleData, typeTlsIndex); } - [RuntimeExport("RhpGetInlinedThreadStaticBaseSlow")] internal static unsafe object GetInlinedThreadStaticBaseSlow(ref object? threadStorage) { Debug.Assert(threadStorage == null); // Allocate an object that will represent a memory block for all thread static fields - TypeManagerHandle typeManager = RuntimeImports.RhGetSingleTypeManager(); + TypeManagerHandle typeManager = EETypePtr.EETypePtrOf().ToPointer()->TypeManager; object threadStaticBase = AllocateThreadStaticStorageForType(typeManager, 0); // register the storage location with the thread for GC reporting. @@ -46,6 +44,8 @@ internal static unsafe object GetInlinedThreadStaticBaseSlow(ref object? threadS // assign the storage block to the storage variable and return threadStorage = threadStaticBase; + t_inlinedThreadStaticBase = threadStaticBase; + return threadStaticBase; } @@ -55,13 +55,13 @@ internal static unsafe object GetUninlinedThreadStaticBaseForType(TypeManagerSlo int moduleIndex = pModuleData->ModuleIndex; Debug.Assert(moduleIndex >= 0); - object[][] threadStorage = RuntimeImports.RhGetThreadStaticStorage(); - if (threadStorage != null && threadStorage.Length > moduleIndex) + object[][] perThreadStorage = RuntimeImports.RhGetThreadStaticStorage(); + if (perThreadStorage != null && perThreadStorage.Length > moduleIndex) { - object[] moduleStorage = threadStorage[moduleIndex]; - if (moduleStorage != null && moduleStorage.Length > typeTlsIndex) + object[] perModuleStorage = perThreadStorage[moduleIndex]; + if (perModuleStorage != null && perModuleStorage.Length > typeTlsIndex) { - object threadStaticBase = moduleStorage[typeTlsIndex]; + object threadStaticBase = perModuleStorage[typeTlsIndex]; if (threadStaticBase != null) { return threadStaticBase; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 68b50d5bb966ee..c6ac7d60c9990b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -560,10 +560,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [RuntimeImport(RuntimeLibrary, "RhGetThreadStaticStorage")] internal static extern ref object[][] RhGetThreadStaticStorage(); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhGetInlinedThreadStaticStorage")] - internal static extern ref object? RhGetInlinedThreadStaticStorage(); - [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhRegisterInlinedThreadStaticRoot")] internal static extern void RhRegisterInlinedThreadStaticRoot(ref object? root); @@ -592,10 +588,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [RuntimeImport(RuntimeLibrary, "RhGetTargetOfUnboxingAndInstantiatingStub")] public static extern IntPtr RhGetTargetOfUnboxingAndInstantiatingStub(IntPtr pCode); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhGetSingleTypeManager")] - public static extern TypeManagerHandle RhGetSingleTypeManager(); - // // EH helpers // diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs index ff5cee89663c6b..67c9931305c132 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs @@ -291,6 +291,8 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0) case RelocType.IMAGE_REL_BASED_ABSOLUTE: case RelocType.IMAGE_REL_BASED_HIGHLOW: case RelocType.IMAGE_REL_SECREL: + case RelocType.IMAGE_REL_TLSGD: + case RelocType.IMAGE_REL_TPOFF: case RelocType.IMAGE_REL_FILE_ABSOLUTE: case RelocType.IMAGE_REL_BASED_ADDR32NB: case RelocType.IMAGE_REL_SYMBOL_SIZE: @@ -305,6 +307,14 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0) case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21: case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L: case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A: + + case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21: + case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12: + case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12: + case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL: + case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12: + case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC: case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR: Debug.Assert(delta == 0); diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs index 6f0c0bec5aba19..4545833ab449c2 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs @@ -46,7 +46,7 @@ public bool IsStandardSection public static readonly ObjectNodeSection ReadOnlyDataSection = new ObjectNodeSection("rdata", SectionType.ReadOnly); public static readonly ObjectNodeSection FoldableReadOnlyDataSection = new ObjectNodeSection("rdata", SectionType.ReadOnly); public static readonly ObjectNodeSection TextSection = new ObjectNodeSection("text", SectionType.Executable); - public static readonly ObjectNodeSection TLSSection = new ObjectNodeSection("TLS", SectionType.Writeable); + public static readonly ObjectNodeSection TLSSection = new ObjectNodeSection("tdata", SectionType.Writeable); public static readonly ObjectNodeSection BssSection = new ObjectNodeSection("bss", SectionType.Uninitialized); public static readonly ObjectNodeSection HydrationTargetSection = new ObjectNodeSection("hydrated", SectionType.Uninitialized); public static readonly ObjectNodeSection ManagedCodeWindowsContentSection = new ObjectNodeSection(".managedcode$I", SectionType.Executable); diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs index 25b94a37654218..b833c909ff5b79 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs @@ -23,12 +23,34 @@ public enum RelocType // This is a special NGEN-specific relocation type // for relative pointer (used to make NGen relocation // section smaller) - IMAGE_REL_SECREL = 0x80, // 32 bit offset from base of section containing target IMAGE_REL_BASED_ARM64_PAGEBASE_REL21 = 0x81, // ADRP IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A = 0x82, // ADD/ADDS (immediate) with zero shift, for page offset IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L = 0x83, // LDR (indexed, unsigned immediate), for page offset + // + // Relocation operators related to TLS access + // + + // Windows x64 + IMAGE_REL_SECREL = 0x104, + + // Linux x64 + // GD model + IMAGE_REL_TLSGD = 0x105, + // LE model + IMAGE_REL_TPOFF = 0x106, + + // Linux arm64 + // TLSDESC (dynamic) + IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21 = 0x107, + IMAGE_REL_AARCH64_TLSDESC_LD64_LO12 = 0x108, + IMAGE_REL_AARCH64_TLSDESC_ADD_LO12 = 0x109, + IMAGE_REL_AARCH64_TLSDESC_CALL = 0x10A, + // LE model + IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x10B, + IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x10C, + // // Relocations for R2R image production // @@ -459,6 +481,8 @@ public static unsafe long ReadValue(RelocType relocType, void* location) case RelocType.IMAGE_REL_BASED_REL32: case RelocType.IMAGE_REL_BASED_RELPTR32: case RelocType.IMAGE_REL_SECREL: + case RelocType.IMAGE_REL_TLSGD: + case RelocType.IMAGE_REL_TPOFF: case RelocType.IMAGE_REL_FILE_ABSOLUTE: case RelocType.IMAGE_REL_SYMBOL_SIZE: return *(int*)location; @@ -475,6 +499,20 @@ public static unsafe long ReadValue(RelocType relocType, void* location) return GetArm64Rel21((uint*)location); case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A: return GetArm64Rel12((uint*)location); + case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12: + case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12: + case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12: + case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC: + // TLS relocs do not have offsets + Debug.Assert((GetArm64Rel12((uint*)location) & 0xFF) == 0); + return 0; + case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21: + // TLS relocs do not have offsets + Debug.Assert((GetArm64Rel21((uint*)location) & 0xFF) == 0); + return 0; + case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL: + // TLS relocs do not have offsets + return 0; case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC: return (long)GetLoongArch64PC12((uint*)location); case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR: diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_ARM64/ARM64Emitter.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_ARM64/ARM64Emitter.cs index 45b5018b58fa8b..d516b578f83a11 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_ARM64/ARM64Emitter.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_ARM64/ARM64Emitter.cs @@ -176,10 +176,18 @@ public void EmitRET() public void EmitRETIfEqual() { + // b.ne #8 Builder.EmitUInt(0b01010100_0000000000000000010_0_0001u); EmitRET(); } + public void EmitRETIfNotEqual() + { + // b.eq #8 + Builder.EmitUInt(0b01010100_0000000000000000010_0_0000u); + EmitRET(); + } + public void EmitJE(ISymbolNode symbol) { uint offset = symbol.RepresentsIndirectionCell ? 6u : 2u; @@ -189,6 +197,15 @@ public void EmitJE(ISymbolNode symbol) EmitJMP(symbol); } + public void EmitJNE(ISymbolNode symbol) + { + uint offset = symbol.RepresentsIndirectionCell ? 6u : 2u; + + Builder.EmitUInt(0b01010100_0000000000000000000_0_0000u | offset << 5); + + EmitJMP(symbol); + } + private static bool InSignedByteRange(int i) { return i == (int)(sbyte)i; diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs index b88bb7f1002c57..321da23b856647 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_X64/X64Emitter.cs @@ -117,6 +117,20 @@ public void EmitJE(ISymbolNode symbol) } } + public void EmitJNE(ISymbolNode symbol) + { + if (symbol.RepresentsIndirectionCell) + { + throw new NotImplementedException(); + } + else + { + Builder.EmitByte(0x0f); + Builder.EmitByte(0x85); + Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_REL32); + } + } + public void EmitINT3() { Builder.EmitByte(0xCC); diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs index fd21b72a066a82..2907ba26b6cf27 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/Utilities/GCPointerMap.Algorithm.cs @@ -101,7 +101,7 @@ public static GCPointerMap FromStaticLayout(MetadataType type) return builder.ToGCMap(); } - private static void MapThreadStaticsForType(GCPointerMapBuilder builder, MetadataType type, int baseOffset) + private static void MapThreadStaticsForType(ref GCPointerMapBuilder builder, MetadataType type, int baseOffset) { foreach (FieldDesc field in type.GetFields()) { @@ -133,7 +133,7 @@ public static GCPointerMap FromThreadStaticLayout(MetadataType type) { GCPointerMapBuilder builder = new GCPointerMapBuilder(type.ThreadGcStaticFieldSize.AsInt, type.Context.Target.PointerSize); - MapThreadStaticsForType(builder, type, baseOffset: 0); + MapThreadStaticsForType(ref builder, type, baseOffset: 0); Debug.Assert(builder.ToGCMap().Size * type.Context.Target.PointerSize >= type.ThreadGcStaticFieldSize.AsInt); return builder.ToGCMap(); @@ -148,7 +148,7 @@ public static GCPointerMap FromInlinedThreadStatics( GCPointerMapBuilder builder = new GCPointerMapBuilder(threadStaticSize, pointerSize); foreach (var type in types) { - MapThreadStaticsForType(builder, type, offsets[type]); + MapThreadStaticsForType(ref builder, type, offsets[type]); } return builder.ToGCMap(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/HelperEntrypoint.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/HelperEntrypoint.cs index c739d0d7f0cccd..7a21199c8770e9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/HelperEntrypoint.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/HelperEntrypoint.cs @@ -9,5 +9,6 @@ public enum HelperEntrypoint EnsureClassConstructorRunAndReturnNonGCStaticBase, EnsureClassConstructorRunAndReturnThreadStaticBase, GetThreadStaticBaseForType, + GetInlinedThreadStaticBaseSlow, } } 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 415f887b0a3564..6f17af2ddf3b8b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -1041,7 +1041,8 @@ public IMethodNode ShadowConcreteMethod(MethodDesc method, bool isUnboxingStub = new string[] { "System.Runtime.CompilerServices", "ClassConstructorRunner", "CheckStaticClassConstructionReturnGCStaticBase" }, new string[] { "System.Runtime.CompilerServices", "ClassConstructorRunner", "CheckStaticClassConstructionReturnNonGCStaticBase" }, new string[] { "System.Runtime.CompilerServices", "ClassConstructorRunner", "CheckStaticClassConstructionReturnThreadStaticBase" }, - new string[] { "Internal.Runtime", "ThreadStatics", "GetThreadStaticBaseForType" } + new string[] { "Internal.Runtime", "ThreadStatics", "GetThreadStaticBaseForType" }, + new string[] { "Internal.Runtime", "ThreadStatics", "GetInlinedThreadStaticBaseSlow" }, }; private ISymbolNode[] _helperEntrypointSymbols; @@ -1288,6 +1289,8 @@ public string GetSymbolAlternateName(ISymbolNode node) protected internal TypeManagerIndirectionNode TypeManagerIndirection = new TypeManagerIndirectionNode(); + protected internal TlsRootNode TlsRoot = new TlsRootNode(); + public virtual void AttachToDependencyGraph(DependencyAnalyzerBase graph) { ReadyToRunHeader = new ReadyToRunHeaderNode(); @@ -1306,6 +1309,7 @@ public virtual void AttachToDependencyGraph(DependencyAnalyzerBase if (_inlinedThreadStatics.IsComputed()) { graph.AddRoot(_inlinedThreadStatiscNode, "Inlined threadstatics are used if present"); + graph.AddRoot(TlsRoot, "Inlined threadstatics are used if present"); } ReadyToRunHeader.Add(ReadyToRunSectionType.GCStaticRegion, GCStaticsRegion); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs index fb6adbae6840a4..9e7241048ff997 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs @@ -1079,6 +1079,13 @@ public static void EmitObject(string objectFilePath, IReadOnlyCollection 0; + public override bool IsShareable => false; + + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + public override ObjectNodeSection GetSection(NodeFactory factory) => ObjectNodeSection.TLSSection; + + public override bool StaticDependenciesAreComputed => true; + + public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) + { + ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); + objData.RequireInitialPointerAlignment(); + objData.AddSymbol(this); + + // root + objData.EmitZeroPointer(); + + // next + objData.EmitZeroPointer(); + + return objData.ToObjectData(); + } + + public override int ClassCode => -985742028; + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs index 772970bf145cae..f91853d1834014 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeThreadStaticIndexNode.cs @@ -83,7 +83,12 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo } } + // needed to construct storage objData.EmitPointerReloc(factory.TypeManagerIndirection); + + // tls storage ID for uninlined types. used to: + // - get the type from the type manager + // - get the slot from the per-type storage array objData.EmitNaturalInt(typeTlsIndex); return objData.ToObjectData(); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index ff83282e7f4bb4..fb5b51472d6bfc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -526,6 +526,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index ae5e9f1fbf53c1..6b71f44a599bd5 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -491,10 +491,9 @@ void RunScanner() builder.UsePreinitializationManager(preinitManager); } - // If we have a scanner, we can inline threadstatics storage using the information - // we collected at scanning time. - // Inlined storage implies a single type manager, thus we do not do it in multifile case. - if (!multiFile && !Get(_command.NoInlineTls)) + // If we have a scanner, we can inline threadstatics storage using the information we collected at scanning time. + if (!Get(_command.NoInlineTls) && + (targetOS == TargetOS.Linux || (targetArchitecture == TargetArchitecture.X64 && targetOS == TargetOS.Windows))) { builder.UseInlinedThreadStatics(scanResults.GetInlinedThreadStatics()); }