diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 50c0d348bd0f3..3208abe82bdd3 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -548,6 +548,7 @@ enum CorInfoHelpFunc CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, + CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, /* Debugger */ @@ -1731,6 +1732,7 @@ struct CORINFO_THREAD_STATIC_BLOCKS_INFO uint32_t offsetOfThreadLocalStoragePointer; uint32_t offsetOfMaxThreadStaticBlocks; uint32_t offsetOfThreadStaticBlocks; + uint32_t offsetOfGCDataPointer; }; //---------------------------------------------------------------------------- @@ -2733,11 +2735,13 @@ class ICorStaticInfo CORINFO_FIELD_INFO *pResult ) = 0; + // Returns the index against which the field's thread static block in stored in TLS. virtual uint32_t getThreadLocalFieldInfo ( - CORINFO_FIELD_HANDLE field) = 0; + CORINFO_FIELD_HANDLE field, bool isGCType) = 0; + // Returns the thread static block information like offsets, etc. from current TLS. virtual void getThreadLocalStaticBlocksInfo ( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) = 0; + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) = 0; // Returns true iff "fldHnd" represents a static field. virtual bool isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) = 0; diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index ad73b66da0966..f3d93194df258 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -411,10 +411,12 @@ void getFieldInfo( CORINFO_FIELD_INFO* pResult) override; uint32_t getThreadLocalFieldInfo( - CORINFO_FIELD_HANDLE field) override; + CORINFO_FIELD_HANDLE field, + bool isGCtype) override; void getThreadLocalStaticBlocksInfo( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) override; + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, + bool isGCType) override; bool isFieldStatic( CORINFO_FIELD_HANDLE fldHnd) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 6e5df744de35a..f38a8f6139acf 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* 50246073-be42-4227-b9e1-edc585672820 */ - 0x50246073, - 0xbe42, - 0x4227, - {0xb9, 0xe1, 0xed, 0xc5, 0x85, 0x67, 0x28, 0x20} +constexpr GUID JITEEVersionIdentifier = { /* f63c2964-bae9-448f-baaf-9c9f2d4292f2 */ + 0xf63c2964, + 0xbae9, + 0x448f, + {0xba, 0xaf, 0x9c, 0x9f, 0x2d, 0x42, 0x92, 0xf2} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 1d498c3589347..1913a428da942 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -203,8 +203,9 @@ JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, JIT_GetSharedNonGCThreadStaticBase, CORINFO_HELP_SIG_REG_ONLY) - JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS, JIT_GetSharedNonGCThreadStaticBaseDynamicClass, CORINFO_HELP_SIG_REG_ONLY) + JITHELPER(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, JIT_GetSharedGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY) JITHELPER(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, JIT_GetSharedNonGCThreadStaticBaseOptimized, CORINFO_HELP_SIG_REG_ONLY) // Debugger diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index 990d8cabce1a2..da369eda01a37 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -972,19 +972,21 @@ void WrapICorJitInfo::getFieldInfo( } uint32_t WrapICorJitInfo::getThreadLocalFieldInfo( - CORINFO_FIELD_HANDLE field) + CORINFO_FIELD_HANDLE field, + bool isGCtype) { API_ENTER(getThreadLocalFieldInfo); - uint32_t temp = wrapHnd->getThreadLocalFieldInfo(field); + uint32_t temp = wrapHnd->getThreadLocalFieldInfo(field, isGCtype); API_LEAVE(getThreadLocalFieldInfo); return temp; } void WrapICorJitInfo::getThreadLocalStaticBlocksInfo( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, + bool isGCType) { API_ENTER(getThreadLocalStaticBlocksInfo); - wrapHnd->getThreadLocalStaticBlocksInfo(pInfo); + wrapHnd->getThreadLocalStaticBlocksInfo(pInfo, isGCType); API_LEAVE(getThreadLocalStaticBlocksInfo); } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index c03192ec9eac9..3b777c5b36a7c 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7818,7 +7818,6 @@ class Compiler void eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult); - uint32_t eeGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field); // Get the flags diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index acd41345799c9..83f90d4be5fd7 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -3518,6 +3518,7 @@ inline bool Compiler::IsSharedStaticHelper(GenTree* tree) helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE || helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE || helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR || + helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED || helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR || helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED || helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS || diff --git a/src/coreclr/jit/ee_il_dll.hpp b/src/coreclr/jit/ee_il_dll.hpp index 162d5479dff49..cfdc1f87c680e 100644 --- a/src/coreclr/jit/ee_il_dll.hpp +++ b/src/coreclr/jit/ee_il_dll.hpp @@ -44,12 +44,6 @@ void Compiler::eeGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, info.compCompHnd->getFieldInfo(pResolvedToken, info.compMethodHnd, accessFlags, pResult); } -FORCEINLINE -uint32_t Compiler::eeGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field) -{ - return info.compCompHnd->getThreadLocalFieldInfo(field); -} - /***************************************************************************** * * VOS info, method sigs, etc diff --git a/src/coreclr/jit/flowgraph.cpp b/src/coreclr/jit/flowgraph.cpp index a88e3c89800e5..cce98db9bc503 100644 --- a/src/coreclr/jit/flowgraph.cpp +++ b/src/coreclr/jit/flowgraph.cpp @@ -698,7 +698,8 @@ bool Compiler::fgIsCommaThrow(GenTree* tree, bool forFolding /* = false */) // cls - The class handle // helper - The helper function // typeIndex - The static block type index. Used only for -// CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED to cache +// CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED or +// CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED to cache // the static block in an array at index typeIndex. // // Return Value: @@ -715,6 +716,7 @@ GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfo switch (helper) { case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR: + case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED: bNeedClassID = false; FALLTHROUGH; @@ -795,7 +797,8 @@ GenTreeCall* Compiler::fgGetStaticsCCtorHelper(CORINFO_CLASS_HANDLE cls, CorInfo result = gtNewHelperCallNode(helper, type, opModuleIDArg, opClassIDArg); } - else if (helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) + else if ((helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) || + (helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED)) { result = gtNewHelperCallNode(helper, type, gtNewIconNode(typeIndex)); result->SetExpTLSFieldAccess(); diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index e920e769e9c32..fc71feb0090d8 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -410,7 +410,8 @@ bool Compiler::fgExpandRuntimeLookupsForCall(BasicBlock** pBlock, Statement* stm //------------------------------------------------------------------------------ // fgExpandThreadLocalAccess: Inline the CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED -// helper. See fgExpandThreadLocalAccessForCall for details. +// or CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED helper. See +// fgExpandThreadLocalAccessForCall for details. // // Returns: // PhaseStatus indicating what, if anything, was changed. @@ -446,7 +447,7 @@ PhaseStatus Compiler::fgExpandThreadLocalAccess() //------------------------------------------------------------------------------ // fgExpandThreadLocalAccessForCall : Expand the CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED -// that access fields marked with [ThreadLocal]. +// or CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, that access fields marked with [ThreadLocal]. // // Arguments: // pBlock - Block containing the helper call to expand. If expansion is performed, @@ -483,20 +484,31 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* assert(!"Unsupported scenario of optimizing TLS access on Arm32"); #endif + JITDUMP("Expanding thread static local access for [%06d] in " FMT_BB ":\n", dspTreeID(call), block->bbNum); + DISPTREE(call); + JITDUMP("\n"); + bool isGCThreadStatic = + eeGetHelperNum(call->gtCallMethHnd) == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED; + CORINFO_THREAD_STATIC_BLOCKS_INFO threadStaticBlocksInfo; - info.compCompHnd->getThreadLocalStaticBlocksInfo(&threadStaticBlocksInfo); - JITDUMP("getThreadLocalStaticBlocksInfo\n:"); + info.compCompHnd->getThreadLocalStaticBlocksInfo(&threadStaticBlocksInfo, isGCThreadStatic); + + uint32_t offsetOfMaxThreadStaticBlocksVal = 0; + uint32_t offsetOfThreadStaticBlocksVal = 0; + + JITDUMP("getThreadLocalStaticBlocksInfo (%s)\n:", isGCThreadStatic ? "GC" : "Non-GC"); + offsetOfMaxThreadStaticBlocksVal = threadStaticBlocksInfo.offsetOfMaxThreadStaticBlocks; + offsetOfThreadStaticBlocksVal = threadStaticBlocksInfo.offsetOfThreadStaticBlocks; + JITDUMP("tlsIndex= %u\n", (ssize_t)threadStaticBlocksInfo.tlsIndex.addr); - JITDUMP("offsetOfMaxThreadStaticBlocks= %u\n", threadStaticBlocksInfo.offsetOfMaxThreadStaticBlocks); JITDUMP("offsetOfThreadLocalStoragePointer= %u\n", threadStaticBlocksInfo.offsetOfThreadLocalStoragePointer); - JITDUMP("offsetOfThreadStaticBlocks= %u\n", threadStaticBlocksInfo.offsetOfThreadStaticBlocks); + JITDUMP("offsetOfMaxThreadStaticBlocks= %u\n", offsetOfMaxThreadStaticBlocksVal); + JITDUMP("offsetOfThreadStaticBlocks= %u\n", offsetOfThreadStaticBlocksVal); + JITDUMP("offsetOfGCDataPointer= %u\n", threadStaticBlocksInfo.offsetOfGCDataPointer); assert(threadStaticBlocksInfo.tlsIndex.accessType == IAT_VALUE); - assert(eeGetHelperNum(call->gtCallMethHnd) == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED); - - JITDUMP("Expanding thread static local access for [%06d] in " FMT_BB ":\n", dspTreeID(call), block->bbNum); - DISPTREE(call); - JITDUMP("\n"); + assert((eeGetHelperNum(call->gtCallMethHnd) == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) || + (eeGetHelperNum(call->gtCallMethHnd) == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED)); call->ClearExpTLSFieldAccess(); assert(call->gtArgs.CountArgs() == 1); @@ -508,6 +520,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* DebugInfo debugInfo = stmt->GetDebugInfo(); block = fgSplitBlockBeforeTree(block, stmt, call, &newFirstStmt, &callUse); *pBlock = block; + var_types callType = call->TypeGet(); assert(prevBb != nullptr && block != nullptr); // Block ops inserted by the split need to be morphed here since we are after morph. @@ -523,8 +536,8 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* // Grab a temp to store result (it's assigned from either fastPathBb or fallbackBb) unsigned threadStaticBlockLclNum = lvaGrabTemp(true DEBUGARG("TLS field access")); - lvaTable[threadStaticBlockLclNum].lvType = TYP_I_IMPL; - threadStaticBlockLcl = gtNewLclvNode(threadStaticBlockLclNum, call->TypeGet()); + lvaTable[threadStaticBlockLclNum].lvType = callType; + threadStaticBlockLcl = gtNewLclvNode(threadStaticBlockLclNum, callType); *callUse = gtClone(threadStaticBlockLcl); @@ -564,8 +577,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* GenTree* tlsLclValueUse = gtNewLclVarNode(tlsLclNum); // Create tree for "maxThreadStaticBlocks = tls[offsetOfMaxThreadStaticBlocks]" - GenTree* offsetOfMaxThreadStaticBlocks = - gtNewIconNode(threadStaticBlocksInfo.offsetOfMaxThreadStaticBlocks, TYP_I_IMPL); + GenTree* offsetOfMaxThreadStaticBlocks = gtNewIconNode(offsetOfMaxThreadStaticBlocksVal, TYP_I_IMPL); GenTree* maxThreadStaticBlocksRef = gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse), offsetOfMaxThreadStaticBlocks); GenTree* maxThreadStaticBlocksValue = @@ -577,7 +589,7 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* maxThreadStaticBlocksCond = gtNewOperNode(GT_JTRUE, TYP_VOID, maxThreadStaticBlocksCond); // Create tree for "threadStaticBlockBase = tls[offsetOfThreadStaticBlocks]" - GenTree* offsetOfThreadStaticBlocks = gtNewIconNode(threadStaticBlocksInfo.offsetOfThreadStaticBlocks, TYP_I_IMPL); + GenTree* offsetOfThreadStaticBlocks = gtNewIconNode(offsetOfThreadStaticBlocksVal, TYP_I_IMPL); GenTree* threadStaticBlocksRef = gtNewOperNode(GT_ADD, TYP_I_IMPL, gtCloneExpr(tlsLclValueUse), offsetOfThreadStaticBlocks); GenTree* threadStaticBlocksValue = @@ -642,6 +654,16 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* fgNewBBFromTreeAfter(BBJ_ALWAYS, threadStaticBlockNullCondBB, fallbackValueDef, debugInfo, true); // fastPathBb + if (isGCThreadStatic) + { + // Need to add extra indirection to access the data pointer. + + threadStaticBlockBaseLclValueUse = gtNewIndir(callType, threadStaticBlockBaseLclValueUse, GTF_IND_NONFAULTING); + threadStaticBlockBaseLclValueUse = + gtNewOperNode(GT_ADD, callType, threadStaticBlockBaseLclValueUse, + gtNewIconNode(threadStaticBlocksInfo.offsetOfGCDataPointer, TYP_I_IMPL)); + } + GenTree* fastPathValueDef = gtNewStoreLclVarNode(threadStaticBlockLclNum, gtCloneExpr(threadStaticBlockBaseLclValueUse)); BasicBlock* fastPathBb = fgNewBBFromTreeAfter(BBJ_ALWAYS, fallbackBb, fastPathValueDef, debugInfo, true); diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 2834cf78ab34e..22c25523f41dd 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -3963,7 +3963,15 @@ GenTree* Compiler::impImportStaticFieldAccess(CORINFO_RESOLVED_TOKEN* pResolvedT case CORINFO_FIELD_STATIC_TLS_MANAGED: - typeIndex = info.compCompHnd->getThreadLocalFieldInfo(pResolvedToken->hField); + if (pFieldInfo->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED) + { + typeIndex = info.compCompHnd->getThreadLocalFieldInfo(pResolvedToken->hField, false); + } + else + { + assert(pFieldInfo->helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED); + typeIndex = info.compCompHnd->getThreadLocalFieldInfo(pResolvedToken->hField, true); + } FALLTHROUGH; case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: diff --git a/src/coreclr/jit/utils.cpp b/src/coreclr/jit/utils.cpp index 12d520b14c44c..fb8266240ad74 100644 --- a/src/coreclr/jit/utils.cpp +++ b/src/coreclr/jit/utils.cpp @@ -1476,6 +1476,7 @@ void HelperCallProperties::init() case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR: case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR: case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR: + case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED: case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR: case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED: diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index b41e7cd5c2216..14be1b160a04c 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -12228,6 +12228,9 @@ VNFunc Compiler::fgValueNumberJitHelperMethodVNFunc(CorInfoHelpFunc helpFunc) case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR: vnf = VNF_GetsharedGcthreadstaticBaseNoctor; break; + case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED: + vnf = VNF_GetsharedGcthreadstaticBaseNoctorOptimized; + break; case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR: vnf = VNF_GetsharedNongcthreadstaticBaseNoctor; break; diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h index df804121eb98a..1c6c72bb87fa0 100644 --- a/src/coreclr/jit/valuenumfuncs.h +++ b/src/coreclr/jit/valuenumfuncs.h @@ -125,6 +125,7 @@ ValueNumFuncDef(GetgenericsNongcthreadstaticBase, 1, false, true, true) ValueNumFuncDef(GetsharedGcthreadstaticBase, 2, false, true, true) ValueNumFuncDef(GetsharedNongcthreadstaticBase, 2, false, true, true) ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctor, 2, false, true, true) +ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctorOptimized, 1, false, true, true) ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctor, 2, false, true, true) ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctorOptimized, 1, false, true, true) ValueNumFuncDef(GetsharedGcthreadstaticBaseDynamicclass, 2, false, true, true) diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs index 06bc0f6363a09..0693f3c1b69f1 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs @@ -187,6 +187,7 @@ which is the right helper to use to allocate an object of a given type. */ CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE, CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR, + CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR, CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED, CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS, diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 5c90ea273df43..2a16f1102fec0 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -2859,7 +2859,7 @@ private nuint printFieldName(CORINFO_FIELD_STRUCT_* fld, byte* buffer, nuint buf } #pragma warning disable CA1822 // Mark members as static - private uint getThreadLocalFieldInfo(CORINFO_FIELD_STRUCT_* fld) + private uint getThreadLocalFieldInfo(CORINFO_FIELD_STRUCT_* fld, bool isGCType) #pragma warning restore CA1822 // Mark members as static { // Implemented for JIT only for now. @@ -2868,7 +2868,7 @@ private uint getThreadLocalFieldInfo(CORINFO_FIELD_STRUCT_* fld) } #pragma warning disable CA1822 // Mark members as static - private void getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + private void getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) #pragma warning restore CA1822 // Mark members as static { // Implemented for JIT only for now. diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index ccfdf88b8797e..772a97e0cfb82 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -1465,12 +1465,12 @@ private static void _getFieldInfo(IntPtr thisHandle, IntPtr* ppException, CORINF } [UnmanagedCallersOnly] - private static uint _getThreadLocalFieldInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field) + private static uint _getThreadLocalFieldInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_FIELD_STRUCT_* field, byte isGCtype) { var _this = GetThis(thisHandle); try { - return _this.getThreadLocalFieldInfo(field); + return _this.getThreadLocalFieldInfo(field, isGCtype != 0); } catch (Exception ex) { @@ -1480,12 +1480,12 @@ private static uint _getThreadLocalFieldInfo(IntPtr thisHandle, IntPtr* ppExcept } [UnmanagedCallersOnly] - private static void _getThreadLocalStaticBlocksInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + private static void _getThreadLocalStaticBlocksInfo(IntPtr thisHandle, IntPtr* ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, byte isGCType) { var _this = GetThis(thisHandle); try { - _this.getThreadLocalStaticBlocksInfo(pInfo); + _this.getThreadLocalStaticBlocksInfo(pInfo, isGCType != 0); } catch (Exception ex) { @@ -2757,8 +2757,8 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[95] = (delegate* unmanaged)&_getFieldType; callbacks[96] = (delegate* unmanaged)&_getFieldOffset; callbacks[97] = (delegate* unmanaged)&_getFieldInfo; - callbacks[98] = (delegate* unmanaged)&_getThreadLocalFieldInfo; - callbacks[99] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; + callbacks[98] = (delegate* unmanaged)&_getThreadLocalFieldInfo; + callbacks[99] = (delegate* unmanaged)&_getThreadLocalStaticBlocksInfo; callbacks[100] = (delegate* unmanaged)&_isFieldStatic; callbacks[101] = (delegate* unmanaged)&_getArrayOrStringLength; callbacks[102] = (delegate* unmanaged)&_getBoundaries; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 18c24222c4fdf..71d8cd105dc60 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -1154,6 +1154,7 @@ public unsafe struct CORINFO_THREAD_STATIC_BLOCKS_INFO public uint offsetOfThreadLocalStoragePointer; public CORINFO_CONST_LOOKUP offsetOfMaxThreadStaticBlocks; public CORINFO_CONST_LOOKUP offsetOfThreadStaticBlocks; + public CORINFO_CONST_LOOKUP offsetOfGCDataPointer; }; // System V struct passing diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index 327255bd7eb58..89d87da12f848 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -257,8 +257,8 @@ FUNCTIONS CorInfoType getFieldType(CORINFO_FIELD_HANDLE field, CORINFO_CLASS_HANDLE* structType, CORINFO_CLASS_HANDLE memberParent) unsigned getFieldOffset(CORINFO_FIELD_HANDLE field) void getFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult) - uint32_t getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field) - void getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + uint32_t getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isGCtype) + void getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) bool isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) int getArrayOrStringLength(CORINFO_OBJECT_HANDLE objHnd) void getBoundaries(CORINFO_METHOD_HANDLE ftn, unsigned int* cILOffsets, uint32_t** pILOffsets, ICorDebugInfo::BoundaryTypes* implicitBoundaries) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index ec15c56b293aa..56fb164b35956 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -109,8 +109,8 @@ struct JitInterfaceCallbacks CorInfoType (* getFieldType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, CORINFO_CLASS_HANDLE* structType, CORINFO_CLASS_HANDLE memberParent); unsigned (* getFieldOffset)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field); void (* getFieldInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult); - uint32_t (* getThreadLocalFieldInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field); - void (* getThreadLocalStaticBlocksInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo); + uint32_t (* getThreadLocalFieldInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE field, bool isGCtype); + void (* getThreadLocalStaticBlocksInfo)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType); bool (* isFieldStatic)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_FIELD_HANDLE fldHnd); int (* getArrayOrStringLength)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_OBJECT_HANDLE objHnd); void (* getBoundaries)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE ftn, unsigned int* cILOffsets, uint32_t** pILOffsets, ICorDebugInfo::BoundaryTypes* implicitBoundaries); @@ -1165,19 +1165,21 @@ class JitInterfaceWrapper : public ICorJitInfo } virtual uint32_t getThreadLocalFieldInfo( - CORINFO_FIELD_HANDLE field) + CORINFO_FIELD_HANDLE field, + bool isGCtype) { CorInfoExceptionClass* pException = nullptr; - uint32_t temp = _callbacks->getThreadLocalFieldInfo(_thisHandle, &pException, field); + uint32_t temp = _callbacks->getThreadLocalFieldInfo(_thisHandle, &pException, field, isGCtype); if (pException != nullptr) throw pException; return temp; } virtual void getThreadLocalStaticBlocksInfo( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, + bool isGCType) { CorInfoExceptionClass* pException = nullptr; - _callbacks->getThreadLocalStaticBlocksInfo(_thisHandle, &pException, pInfo); + _callbacks->getThreadLocalStaticBlocksInfo(_thisHandle, &pException, pInfo, isGCType); if (pException != nullptr) throw pException; } diff --git a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h index c717ea0631c8d..0783fa52962a4 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h @@ -522,6 +522,7 @@ struct Agnostic_GetThreadLocalStaticBlocksInfo UINT offsetOfThreadLocalStoragePointer; UINT offsetOfMaxThreadStaticBlocks; UINT offsetOfThreadStaticBlocks; + UINT offsetOfGCDataPointer; }; struct Agnostic_GetThreadLocalFieldInfo diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index 615072268280b..9ea8c6ada013c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -38,7 +38,7 @@ LWM(EmbedFieldHandle, DWORDLONG, DLDL) LWM(EmbedGenericHandle, Agnostic_EmbedGenericHandle, Agnostic_CORINFO_GENERICHANDLE_RESULT) LWM(EmbedMethodHandle, DWORDLONG, DLDL) LWM(EmbedModuleHandle, DWORDLONG, DLDL) -LWM(GetThreadLocalFieldInfo, DWORDLONG, DWORD) +LWM(GetThreadLocalFieldInfo, DLD, DWORD) LWM(GetThreadLocalStaticBlocksInfo, DWORD, Agnostic_GetThreadLocalStaticBlocksInfo) DENSELWM(EmptyStringLiteral, DLD) DENSELWM(ErrorList, DWORD) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 83e298408bcea..aa491393c414b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -3601,34 +3601,39 @@ void MethodContext::repGetFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, } } -void MethodContext::recGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, uint32_t result) +void MethodContext::recGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType, uint32_t result) { if (GetThreadLocalFieldInfo == nullptr) - GetThreadLocalFieldInfo = new LightWeightMap(); + GetThreadLocalFieldInfo = new LightWeightMap(); - DWORDLONG key = 0; - - key = CastHandle(field); + DLD key; + ZeroMemory(&key, sizeof(key)); + key.A = CastHandle(field); + key.B = isGCType ? 0 : 1; GetThreadLocalFieldInfo->Add(key, result); DEBUG_REC(dmpGetThreadLocalFieldInfo(key, result)); } -void MethodContext::dmpGetThreadLocalFieldInfo(DWORDLONG key, DWORD value) +void MethodContext::dmpGetThreadLocalFieldInfo(DLD key, DWORD value) { - printf("GetThreadLocalFieldInfo key hnd-%016" PRIX64 ", result-%u", key, value); + printf("GetThreadLocalFieldInfo key hnd-%016" PRIX64 ",gctype-%d result-%u", key.A, key.B, value); } -uint32_t MethodContext::repGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field) +uint32_t MethodContext::repGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType) { - DWORDLONG key = CastHandle(field); - DWORD value = LookupByKeyOrMiss(GetThreadLocalFieldInfo, key, ": key %016" PRIX64 "", key); + DLD key; + ZeroMemory(&key, sizeof(key)); + + key.A = CastHandle(field); + key.B = isGCType ? 0 : 1; + DWORD value = LookupByKeyOrMiss(GetThreadLocalFieldInfo, key, ": key hnd-%016" PRIX64 ", gctype-%u", key.A, key.B); DEBUG_REP(dmpGetThreadLocalFieldInfo(key, value)); return value; } -void MethodContext::recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) +void MethodContext::recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) { if (GetThreadLocalStaticBlocksInfo == nullptr) GetThreadLocalStaticBlocksInfo = new LightWeightMap(); @@ -3641,31 +3646,36 @@ void MethodContext::recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOC value.offsetOfMaxThreadStaticBlocks = pInfo->offsetOfMaxThreadStaticBlocks; value.offsetOfThreadLocalStoragePointer = pInfo->offsetOfThreadLocalStoragePointer; value.offsetOfThreadStaticBlocks = pInfo->offsetOfThreadStaticBlocks; + value.offsetOfGCDataPointer = pInfo->offsetOfGCDataPointer; // This data is same for entire process, so just add it against key '0'. - GetThreadLocalStaticBlocksInfo->Add(0, value); - DEBUG_REC(dmpGetThreadLocalStaticBlocksInfo(0, value)); + DWORD key = isGCType ? 0 : 1; + GetThreadLocalStaticBlocksInfo->Add(key, value); + DEBUG_REC(dmpGetThreadLocalStaticBlocksInfo(key, value)); } void MethodContext::dmpGetThreadLocalStaticBlocksInfo(DWORD key, const Agnostic_GetThreadLocalStaticBlocksInfo& value) { - printf("GetThreadLocalStaticBlocksInfo key 0, value tlsIndex-%016" PRIX64 - ", offsetOfMaxThreadStaticBlocks-%u, offsetOfThreadLocalStoragePointer-%u, offsetOfThreadStaticBlocks-%u", - value.tlsIndex.handle, value.offsetOfMaxThreadStaticBlocks, value.offsetOfThreadLocalStoragePointer, - value.offsetOfThreadStaticBlocks); + printf("GetThreadLocalStaticBlocksInfo key %u, value tlsIndex-%016" PRIX64 + ", offsetOfThreadLocalStoragePointer-%u, offsetOfMaxThreadStaticBlocks-%u" + ", offsetOfThreadStaticBlocks-%u offsetOfGCDataPointer-%u", + key, value.tlsIndex.handle, value.offsetOfThreadLocalStoragePointer, + value.offsetOfMaxThreadStaticBlocks, value.offsetOfThreadStaticBlocks, value.offsetOfGCDataPointer); } -void MethodContext::repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) +void MethodContext::repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) { - Agnostic_GetThreadLocalStaticBlocksInfo value = LookupByKeyOrMiss(GetThreadLocalStaticBlocksInfo, 0, ": key %u", 0); + int key = isGCType ? 0 : 1; + Agnostic_GetThreadLocalStaticBlocksInfo value = LookupByKeyOrMiss(GetThreadLocalStaticBlocksInfo, key, ": key %u", key); - DEBUG_REP(dmpGetThreadLocalStaticBlocksInfo(0, value)); + DEBUG_REP(dmpGetThreadLocalStaticBlocksInfo(key, value)); - pInfo->tlsIndex.accessType = (InfoAccessType)value.tlsIndex.accessType; - pInfo->tlsIndex.addr = (void*)value.tlsIndex.handle; - pInfo->offsetOfMaxThreadStaticBlocks = value.offsetOfMaxThreadStaticBlocks; + pInfo->tlsIndex.accessType = (InfoAccessType)value.tlsIndex.accessType; + pInfo->tlsIndex.addr = (void*)value.tlsIndex.handle; + pInfo->offsetOfMaxThreadStaticBlocks = value.offsetOfMaxThreadStaticBlocks; pInfo->offsetOfThreadLocalStoragePointer = value.offsetOfThreadLocalStoragePointer; - pInfo->offsetOfThreadStaticBlocks = value.offsetOfThreadStaticBlocks; + pInfo->offsetOfThreadStaticBlocks = value.offsetOfThreadStaticBlocks; + pInfo->offsetOfGCDataPointer = value.offsetOfGCDataPointer; } void MethodContext::recEmbedMethodHandle(CORINFO_METHOD_HANDLE handle, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index 23f77fed33825..e6dacd31f2a3c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -485,13 +485,13 @@ class MethodContext CORINFO_ACCESS_FLAGS flags, CORINFO_FIELD_INFO* pResult); - void recGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, uint32_t result); - void dmpGetThreadLocalFieldInfo(DWORDLONG key, DWORD value); - uint32_t repGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field); + void recGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType, uint32_t result); + void dmpGetThreadLocalFieldInfo(DLD key, DWORD value); + uint32_t repGetThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType); - void recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo); + void recGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType); void dmpGetThreadLocalStaticBlocksInfo(DWORD key, const Agnostic_GetThreadLocalStaticBlocksInfo& value); - void repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo); + void repGetThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType); void recEmbedMethodHandle(CORINFO_METHOD_HANDLE handle, void** ppIndirection, CORINFO_METHOD_HANDLE result); void dmpEmbedMethodHandle(DWORDLONG key, DLDL value); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 132cb3b3556ab..c746be1fe5bd6 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1096,19 +1096,19 @@ void interceptor_ICJI::getFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, mc->recGetFieldInfo(pResolvedToken, callerHandle, flags, pResult); } -uint32_t interceptor_ICJI::getThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field) +uint32_t interceptor_ICJI::getThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType) { mc->cr->AddCall("getThreadLocalFieldInfo"); - uint32_t result = original_ICorJitInfo->getThreadLocalFieldInfo(field); - mc->recGetThreadLocalFieldInfo(field, result); + uint32_t result = original_ICorJitInfo->getThreadLocalFieldInfo(field, isGCType); + mc->recGetThreadLocalFieldInfo(field, isGCType, result); return result; } -void interceptor_ICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) +void interceptor_ICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) { mc->cr->AddCall("getThreadLocalStaticBlocksInfo"); - original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo); - mc->recGetThreadLocalStaticBlocksInfo(pInfo); + original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo, isGCType); + mc->recGetThreadLocalStaticBlocksInfo(pInfo, isGCType); } // Returns true iff "fldHnd" represents a static field. diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index 33746daa479e4..6d301f516f60b 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -794,17 +794,19 @@ void interceptor_ICJI::getFieldInfo( } uint32_t interceptor_ICJI::getThreadLocalFieldInfo( - CORINFO_FIELD_HANDLE field) + CORINFO_FIELD_HANDLE field, + bool isGCtype) { mcs->AddCall("getThreadLocalFieldInfo"); - return original_ICorJitInfo->getThreadLocalFieldInfo(field); + return original_ICorJitInfo->getThreadLocalFieldInfo(field, isGCtype); } void interceptor_ICJI::getThreadLocalStaticBlocksInfo( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, + bool isGCType) { mcs->AddCall("getThreadLocalStaticBlocksInfo"); - original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo); + original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo, isGCType); } bool interceptor_ICJI::isFieldStatic( diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index 78179769f31d4..7dd611b5283dc 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -696,15 +696,17 @@ void interceptor_ICJI::getFieldInfo( } uint32_t interceptor_ICJI::getThreadLocalFieldInfo( - CORINFO_FIELD_HANDLE field) + CORINFO_FIELD_HANDLE field, + bool isGCtype) { - return original_ICorJitInfo->getThreadLocalFieldInfo(field); + return original_ICorJitInfo->getThreadLocalFieldInfo(field, isGCtype); } void interceptor_ICJI::getThreadLocalStaticBlocksInfo( - CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) + CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, + bool isGCType) { - original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo); + original_ICorJitInfo->getThreadLocalStaticBlocksInfo(pInfo, isGCType); } bool interceptor_ICJI::isFieldStatic( diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 3fdd37cb879ed..16d52438b6c40 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -917,16 +917,16 @@ void MyICJI::getFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken, jitInstance->mc->repGetFieldInfo(pResolvedToken, callerHandle, flags, pResult); } -uint32_t MyICJI::getThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field) +uint32_t MyICJI::getThreadLocalFieldInfo(CORINFO_FIELD_HANDLE field, bool isGCType) { jitInstance->mc->cr->AddCall("getThreadLocalFieldInfo"); - return jitInstance->mc->repGetThreadLocalFieldInfo(field); + return jitInstance->mc->repGetThreadLocalFieldInfo(field, isGCType); } -void MyICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) +void MyICJI::getThreadLocalStaticBlocksInfo(CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) { jitInstance->mc->cr->AddCall("getThreadLocalStaticBlocksInfo"); - jitInstance->mc->repGetThreadLocalStaticBlocksInfo(pInfo); + jitInstance->mc->repGetThreadLocalStaticBlocksInfo(pInfo, isGCType); } // Returns true iff "fldHnd" represents a static field. diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index 144e8ac0ac841..d7210892f2ae5 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -670,7 +670,8 @@ void BaseDomain::InitThreadStaticBlockTypeMap() { STANDARD_VM_CONTRACT; - m_threadStaticBlockTypeIDMap.Init(); + m_NonGCThreadStaticBlockTypeIDMap.Init(); + m_GCThreadStaticBlockTypeIDMap.Init(); } #endif // HOST_WINDOWS @@ -4680,7 +4681,7 @@ PTR_MethodTable BaseDomain::LookupType(UINT32 id) { #ifdef HOST_WINDOWS //------------------------------------------------------------------------ -UINT32 BaseDomain::GetThreadStaticTypeIndex(PTR_MethodTable pMT) +UINT32 BaseDomain::GetNonGCThreadStaticTypeIndex(PTR_MethodTable pMT) { CONTRACTL { THROWS; @@ -4688,18 +4689,43 @@ UINT32 BaseDomain::GetThreadStaticTypeIndex(PTR_MethodTable pMT) PRECONDITION(pMT->GetDomain() == this); } CONTRACTL_END; - return m_threadStaticBlockTypeIDMap.GetTypeID(pMT, false); + return m_NonGCThreadStaticBlockTypeIDMap.GetTypeID(pMT, false); } //------------------------------------------------------------------------ -PTR_MethodTable BaseDomain::LookupThreadStaticBlockType(UINT32 id) { +PTR_MethodTable BaseDomain::LookupNonGCThreadStaticBlockType(UINT32 id) { CONTRACTL { NOTHROW; WRAPPER(GC_TRIGGERS); CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS); } CONTRACTL_END; - PTR_MethodTable pMT = m_threadStaticBlockTypeIDMap.LookupType(id); + PTR_MethodTable pMT = m_NonGCThreadStaticBlockTypeIDMap.LookupType(id); + + CONSISTENCY_CHECK(CheckPointer(pMT)); + return pMT; +} +//------------------------------------------------------------------------ +UINT32 BaseDomain::GetGCThreadStaticTypeIndex(PTR_MethodTable pMT) +{ + CONTRACTL { + THROWS; + GC_TRIGGERS; + PRECONDITION(pMT->GetDomain() == this); + } CONTRACTL_END; + + return m_GCThreadStaticBlockTypeIDMap.GetTypeID(pMT, false); +} + +//------------------------------------------------------------------------ +PTR_MethodTable BaseDomain::LookupGCThreadStaticBlockType(UINT32 id) { + CONTRACTL { + NOTHROW; + WRAPPER(GC_TRIGGERS); + CONSISTENCY_CHECK(id != TYPE_ID_THIS_CLASS); + } CONTRACTL_END; + + PTR_MethodTable pMT = m_GCThreadStaticBlockTypeIDMap.LookupType(id); CONSISTENCY_CHECK(CheckPointer(pMT)); return pMT; diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index 15c1f119ca7d3..ab928ca5975ab 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1223,9 +1223,10 @@ class BaseDomain #ifdef HOST_WINDOWS // MethodTable to `typeIndex` map. `typeIndex` is embedded in the code during codegen. - // During execution corresponding thread static data blocks are stored in `t_threadStaticBlocks` - // array at the `typeIndex`. - TypeIDMap m_threadStaticBlockTypeIDMap; + // During execution corresponding thread static data blocks are stored in `t_NonGCThreadStaticBlocks` + // and `t_GCThreadStaticBlocks` array at the `typeIndex`. + TypeIDMap m_NonGCThreadStaticBlockTypeIDMap; + TypeIDMap m_GCThreadStaticBlockTypeIDMap; #endif // HOST_WINDOWS @@ -1234,9 +1235,11 @@ class BaseDomain #ifdef HOST_WINDOWS void InitThreadStaticBlockTypeMap(); - UINT32 GetThreadStaticTypeIndex(PTR_MethodTable pMT); + UINT32 GetNonGCThreadStaticTypeIndex(PTR_MethodTable pMT); + UINT32 GetGCThreadStaticTypeIndex(PTR_MethodTable pMT); - PTR_MethodTable LookupThreadStaticBlockType(UINT32 id); + PTR_MethodTable LookupNonGCThreadStaticBlockType(UINT32 id); + PTR_MethodTable LookupGCThreadStaticBlockType(UINT32 id); #endif UINT32 GetTypeID(PTR_MethodTable pMT); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 084281763c010..d4ce2c9aa69ac 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -1779,13 +1779,23 @@ HCIMPLEND #ifdef _MSC_VER -__declspec(selectany) __declspec(thread) uint32_t t_maxThreadStaticBlocks; -__declspec(selectany) __declspec(thread) uint32_t t_threadStaticBlocksSize; -__declspec(selectany) __declspec(thread) void** t_threadStaticBlocks; +__declspec(selectany) __declspec(thread) uint32_t t_NonGCMaxThreadStaticBlocks; +__declspec(selectany) __declspec(thread) uint32_t t_GCMaxThreadStaticBlocks; + +__declspec(selectany) __declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize; +__declspec(selectany) __declspec(thread) uint32_t t_GCThreadStaticBlocksSize; + +__declspec(selectany) __declspec(thread) void** t_NonGCThreadStaticBlocks; +__declspec(selectany) __declspec(thread) void** t_GCThreadStaticBlocks; #else -EXTERN_C __thread uint32_t t_maxThreadStaticBlocks; -EXTERN_C __thread uint32_t t_threadStaticBlocksSize; -EXTERN_C __thread void** t_threadStaticBlocks; +EXTERN_C __thread uint32_t t_NonGCMaxThreadStaticBlocks; +EXTERN_C __thread uint32_t t_GCMaxThreadStaticBlocks; + +EXTERN_C __thread uint32_t t_NonGCThreadStaticBlocksSize; +EXTERN_C __thread uint32_t t_GCThreadStaticBlocksSize; + +EXTERN_C __thread void** t_NonGCThreadStaticBlocks; +EXTERN_C __thread void** t_GCThreadStaticBlocks; #endif // *** This helper corresponds to both CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE and @@ -1835,7 +1845,7 @@ HCIMPL1(void*, JIT_GetSharedNonGCThreadStaticBaseOptimized, UINT32 staticBlockIn HELPER_METHOD_FRAME_BEGIN_RET_0(); // Set up a frame - MethodTable * pMT = AppDomain::GetCurrentDomain()->LookupThreadStaticBlockType(staticBlockIndex); + MethodTable * pMT = AppDomain::GetCurrentDomain()->LookupNonGCThreadStaticBlockType(staticBlockIndex); _ASSERTE(!pMT->HasGenericsStaticsInfo()); // Get the TLM @@ -1849,30 +1859,30 @@ HCIMPL1(void*, JIT_GetSharedNonGCThreadStaticBaseOptimized, UINT32 staticBlockIn staticBlock = (void*) pMT->GetNonGCThreadStaticsBasePointer(); CONSISTENCY_CHECK(staticBlock != NULL); - if (t_threadStaticBlocksSize <= staticBlockIndex) + if (t_NonGCThreadStaticBlocksSize <= staticBlockIndex) { - UINT32 newThreadStaticBlocksSize = max(2 * t_threadStaticBlocksSize, staticBlockIndex + 1); + UINT32 newThreadStaticBlocksSize = max(2 * t_NonGCThreadStaticBlocksSize, staticBlockIndex + 1); void** newThreadStaticBlocks = (void**) new PTR_BYTE[newThreadStaticBlocksSize * sizeof(PTR_BYTE)]; - memset(newThreadStaticBlocks + t_threadStaticBlocksSize, 0, (newThreadStaticBlocksSize - t_threadStaticBlocksSize) * sizeof(PTR_BYTE)); + memset(newThreadStaticBlocks + t_NonGCThreadStaticBlocksSize, 0, (newThreadStaticBlocksSize - t_NonGCThreadStaticBlocksSize) * sizeof(PTR_BYTE)); - if (t_threadStaticBlocksSize > 0) + if (t_NonGCThreadStaticBlocksSize > 0) { - memcpy(newThreadStaticBlocks, t_threadStaticBlocks, t_threadStaticBlocksSize * sizeof(PTR_BYTE)); - delete t_threadStaticBlocks; + memcpy(newThreadStaticBlocks, t_NonGCThreadStaticBlocks, t_NonGCThreadStaticBlocksSize * sizeof(PTR_BYTE)); + delete t_NonGCThreadStaticBlocks; } - t_threadStaticBlocksSize = newThreadStaticBlocksSize; - t_threadStaticBlocks = newThreadStaticBlocks; + t_NonGCThreadStaticBlocksSize = newThreadStaticBlocksSize; + t_NonGCThreadStaticBlocks = newThreadStaticBlocks; } - void* currentEntry = t_threadStaticBlocks[staticBlockIndex]; + void* currentEntry = t_NonGCThreadStaticBlocks[staticBlockIndex]; // We could be coming here 2nd time after running the ctor when we try to get the static block. // In such case, just avoid adding the same entry. if (currentEntry != staticBlock) { _ASSERTE(currentEntry == nullptr); - t_threadStaticBlocks[staticBlockIndex] = staticBlock; - t_maxThreadStaticBlocks = max(t_maxThreadStaticBlocks, staticBlockIndex); + t_NonGCThreadStaticBlocks[staticBlockIndex] = staticBlock; + t_NonGCMaxThreadStaticBlocks = max(t_NonGCMaxThreadStaticBlocks, staticBlockIndex); } HELPER_METHOD_FRAME_END(); #else @@ -1920,6 +1930,71 @@ HCIMPL2(void*, JIT_GetSharedGCThreadStaticBase, DomainLocalModule *pDomainLocalM HCIMPLEND #include +// *** This helper corresponds CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED. +// Even though we always check if the class constructor has been run, we have a separate +// helper ID for the "no ctor" version because it allows the JIT to do some reordering that +// otherwise wouldn't be possible. +HCIMPL1(void*, JIT_GetSharedGCThreadStaticBaseOptimized, UINT32 staticBlockIndex) +{ + void* staticBlock = nullptr; + +#ifdef HOST_WINDOWS + FCALL_CONTRACT; + + HELPER_METHOD_FRAME_BEGIN_RET_0(); // Set up a frame + + MethodTable * pMT = AppDomain::GetCurrentDomain()->LookupGCThreadStaticBlockType(staticBlockIndex); + _ASSERTE(!pMT->HasGenericsStaticsInfo()); + + // Get the TLM + ThreadLocalModule * pThreadLocalModule = ThreadStatics::GetTLM(pMT); + _ASSERTE(pThreadLocalModule != NULL); + + // Check if the class constructor needs to be run + pThreadLocalModule->CheckRunClassInitThrowing(pMT); + + // Lookup the GC statics base handle and cache it + staticBlock = (void*) pMT->GetGCThreadStaticsBaseHandle(); + CONSISTENCY_CHECK(staticBlock != NULL); + + if (t_GCThreadStaticBlocksSize <= staticBlockIndex) + { + UINT32 newThreadStaticBlocksSize = max(2 * t_GCThreadStaticBlocksSize, staticBlockIndex + 1); + void** newThreadStaticBlocks = (void**) new PTR_BYTE[newThreadStaticBlocksSize * sizeof(PTR_BYTE)]; + memset(newThreadStaticBlocks + t_GCThreadStaticBlocksSize, 0, (newThreadStaticBlocksSize - t_GCThreadStaticBlocksSize) * sizeof(PTR_BYTE)); + + if (t_GCThreadStaticBlocksSize > 0) + { + memcpy(newThreadStaticBlocks, t_GCThreadStaticBlocks, t_GCThreadStaticBlocksSize * sizeof(PTR_BYTE)); + delete t_GCThreadStaticBlocks; + } + + t_GCThreadStaticBlocksSize = newThreadStaticBlocksSize; + t_GCThreadStaticBlocks = newThreadStaticBlocks; + } + + void* currentEntry = t_GCThreadStaticBlocks[staticBlockIndex]; + // We could be coming here 2nd time after running the ctor when we try to get the static block. + // In such case, just avoid adding the same entry. + if (currentEntry != staticBlock) + { + _ASSERTE(currentEntry == nullptr); + t_GCThreadStaticBlocks[staticBlockIndex] = staticBlock; + t_GCMaxThreadStaticBlocks = max(t_GCMaxThreadStaticBlocks, staticBlockIndex); + } + + // Get the data pointer of static block + staticBlock = (void*) pMT->GetGCThreadStaticsBasePointer(); + + HELPER_METHOD_FRAME_END(); +#else + _ASSERTE(!"JIT_GetSharedGCThreadStaticBaseOptimized not supported on non-windows."); +#endif // HOST_WINDOWS + + return staticBlock; +} +HCIMPLEND + // *** This helper corresponds to CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS #include diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index ae9d45fd28e2f..85d904b566cdd 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -70,8 +70,11 @@ EXTERN_C uint32_t _tls_index; #endif #ifdef _MSC_VER -__declspec(selectany) __declspec(thread) uint32_t t_maxThreadStaticBlocks; -__declspec(selectany) __declspec(thread) void** t_threadStaticBlocks; +__declspec(selectany) __declspec(thread) uint32_t t_NonGCMaxThreadStaticBlocks; +__declspec(selectany) __declspec(thread) uint32_t t_GCMaxThreadStaticBlocks; + +__declspec(selectany) __declspec(thread) void** t_NonGCThreadStaticBlocks; +__declspec(selectany) __declspec(thread) void** t_GCThreadStaticBlocks; #else EXTERN_C __thread uint32_t t_maxThreadStaticBlocks; EXTERN_C __thread void** t_threadStaticBlocks; @@ -1570,16 +1573,20 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, #ifdef HOST_WINDOWS #ifndef TARGET_ARM - bool canOptimizeHelper = (pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR) || - (pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE); // For windows, we convert the TLS access to the optimized helper where we will store // the static blocks in TLS directly and access them via inline code. - if (canOptimizeHelper && ((pField->GetFieldType() >= ELEMENT_TYPE_BOOLEAN) && (pField->GetFieldType() < ELEMENT_TYPE_STRING))) + if ((pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR) || + (pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE)) { fieldAccessor = CORINFO_FIELD_STATIC_TLS_MANAGED; - pResult->helper = CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED; } + else if ((pResult->helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR) || + (pResult->helper == CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE)) + { + fieldAccessor = CORINFO_FIELD_STATIC_TLS_MANAGED; + pResult->helper = CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR_OPTIMIZED; + } #endif // !TARGET_ARM #endif // HOST_WINDOWS } @@ -1768,7 +1775,7 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, #ifdef HOST_WINDOWS /*********************************************************************/ -uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field) +uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isGCType) { CONTRACTL { THROWS; @@ -1783,7 +1790,14 @@ uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field) FieldDesc* fieldDesc = (FieldDesc*)field; _ASSERTE(fieldDesc->IsThreadStatic()); - typeIndex = AppDomain::GetCurrentDomain()->GetThreadStaticTypeIndex(fieldDesc->GetEnclosingMethodTable()); + if (isGCType) + { + typeIndex = AppDomain::GetCurrentDomain()->GetGCThreadStaticTypeIndex(fieldDesc->GetEnclosingMethodTable()); + } + else + { + typeIndex = AppDomain::GetCurrentDomain()->GetNonGCThreadStaticTypeIndex(fieldDesc->GetEnclosingMethodTable()); + } assert(typeIndex != TypeIDProvider::INVALID_TYPE_ID); @@ -1792,7 +1806,7 @@ uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field) } /*********************************************************************/ -void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) +void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) { CONTRACTL { NOTHROW; @@ -1806,13 +1820,24 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo->tlsIndex.accessType = IAT_VALUE; pInfo->offsetOfThreadLocalStoragePointer = offsetof(_TEB, ThreadLocalStoragePointer); - pInfo->offsetOfThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_threadStaticBlocks); - pInfo->offsetOfMaxThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_maxThreadStaticBlocks); + if (isGCType) + { + pInfo->offsetOfThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_GCThreadStaticBlocks); + pInfo->offsetOfMaxThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_GCMaxThreadStaticBlocks); + } + else + { + pInfo->offsetOfThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_NonGCThreadStaticBlocks); + pInfo->offsetOfMaxThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_NonGCMaxThreadStaticBlocks); + } + + pInfo->offsetOfGCDataPointer = static_cast(PtrArray::GetDataOffset()); JIT_TO_EE_TRANSITION_LEAF(); } #else -uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field) + +uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isGCType) { CONTRACTL { NOTHROW; @@ -1823,7 +1848,7 @@ uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field) return 0; } -void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo) +void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo, bool isGCType) { CONTRACTL { NOTHROW; @@ -1838,6 +1863,7 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo->offsetOfThreadLocalStoragePointer = 0; pInfo->offsetOfThreadStaticBlocks = 0; pInfo->offsetOfMaxThreadStaticBlocks = 0; + pInfo->offsetOfGCDataPointer = 0; JIT_TO_EE_TRANSITION_LEAF(); } diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index acffd1b6141c7..634e05177c8a3 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -2285,6 +2285,7 @@ class MethodTable inline PTR_BYTE GetGCStaticsBasePointer(); inline PTR_BYTE GetNonGCThreadStaticsBasePointer(); inline PTR_BYTE GetGCThreadStaticsBasePointer(); + inline PTR_BYTE GetGCThreadStaticsBaseHandle(); #endif //!DACCESS_COMPILE inline PTR_BYTE GetNonGCThreadStaticsBasePointer(PTR_Thread pThread); diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index 55d0015f86790..3a11158e097d0 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -1157,6 +1157,32 @@ inline PTR_BYTE MethodTable::GetNonGCThreadStaticsBasePointer() return pTLM->GetNonGCStaticsBasePointer(this); } +//========================================================================================== +inline PTR_BYTE MethodTable::GetGCThreadStaticsBaseHandle() +{ + CONTRACTL + { + NOTHROW; + GC_NOTRIGGER; + MODE_COOPERATIVE; + } + CONTRACTL_END; + + // Get the current thread + PTR_Thread pThread = dac_cast(GetThread()); + + // Get the current module's ModuleIndex + ModuleIndex index = GetModuleForStatics()->GetModuleIndex(); + + PTR_ThreadLocalBlock pTLB = ThreadStatics::GetCurrentTLB(pThread); + + PTR_ThreadLocalModule pTLM = pTLB->GetTLMIfExists(index); + if (pTLM == NULL) + return NULL; + + return dac_cast(pTLM->GetPrecomputedGCStaticsBaseHandle()); +} + //========================================================================================== inline PTR_BYTE MethodTable::GetGCThreadStaticsBasePointer() {