diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index 4848fc409ff11..99889eee097c0 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -1088,7 +1088,7 @@ GenerateProfileHelper ProfileTailcall, PROFILE_TAILCALL NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler PROLOG_WITH_TRANSITION_BLOCK - addi.d $a0, $sp, __PWTB_TransitionBlock // TransitionBlock * + addi.d $a0, $sp, __PWTB_TransitionBlock // TransitionBlock * ori $a1, $t1, 0 // stub-identifying token bl C_FUNC(OnCallCountThresholdReached) ori $t4,$a0,0 @@ -1112,3 +1112,18 @@ LEAF_ENTRY GetThreadStaticsVariableOffset, _TEXT EPILOG_RETURN LEAF_END GetThreadStaticsVariableOffset, _TEXT // ------------------------------------------------------------------ + +// ------------------------------------------------------------------ +// size_t GetTLSResolverAddress() + +// Helper to get the TLS resolver address. This will be then used to determine if we have a static or dynamic resolver. +LEAF_ENTRY GetTLSResolverAddress, _TEXT + // $fp,$ra + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, 16 + pcalau12i $a0, %desc_pc_hi20(t_ThreadStatics) + addi.d $a0, $a0, %desc_pc_lo12(t_ThreadStatics) + ld.d $a0, $a0, %desc_ld(t_ThreadStatics) + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, 16 + EPILOG_RETURN +LEAF_END GetTLSResolverAddress, _TEXT +// ------------------------------------------------------------------ diff --git a/src/coreclr/vm/threadstatics.cpp b/src/coreclr/vm/threadstatics.cpp index 31d0c53f74ef9..14252ca2ae06c 100644 --- a/src/coreclr/vm/threadstatics.cpp +++ b/src/coreclr/vm/threadstatics.cpp @@ -784,9 +784,9 @@ void FreeTLSIndicesForLoaderAllocator(LoaderAllocator *pLoaderAllocator) static void* GetTlsIndexObjectAddress(); -#if !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_ARM64) +#if !defined(TARGET_OSX) && defined(TARGET_UNIX) && (defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)) extern "C" size_t GetTLSResolverAddress(); -#endif // !TARGET_OSX && TARGET_UNIX && TARGET_ARM64 +#endif // !TARGET_OSX && TARGET_UNIX && (TARGET_ARM64 || TARGET_LOONGARCH64) bool CanJITOptimizeTLSAccess() { @@ -833,6 +833,28 @@ bool CanJITOptimizeTLSAccess() } #endif } +#elif defined(TARGET_LOONGARCH64) + // Optimization is enabled for linux/loongarch64 only for static resolver. + // For static resolver, the TP offset is same for all threads. + // For dynamic resolver, TP offset returned is for the current thread and + // will be different for the other threads. + uint32_t* resolverAddress = reinterpret_cast(GetTLSResolverAddress()); + + if ( + // ld.d a0, a0, 8 + (resolverAddress[0] == 0x28c02084) && + // ret + (resolverAddress[1] == 0x4c000020) + ) + { + optimizeThreadStaticAccess = true; +#ifdef _DEBUG + if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_AssertNotStaticTlsResolver) != 0) + { + _ASSERTE(!"Detected static resolver in use when not expected"); + } +#endif + } #else optimizeThreadStaticAccess = true; #if !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_AMD64)