summaryrefslogtreecommitdiff
path: root/src/vm/i386
diff options
context:
space:
mode:
authorJan Kotas <jkotas@microsoft.com>2017-10-11 13:04:43 -0700
committerGitHub <noreply@github.com>2017-10-11 13:04:43 -0700
commit27a25bd37fa1fe6201c27709b1884e1b328f8beb (patch)
tree18b7773a7d8e18cca609417940804d8dff491da2 /src/vm/i386
parentd07f1b24c4a69e6a205f8510f3dcfae0ad96aae8 (diff)
downloadcoreclr-27a25bd37fa1fe6201c27709b1884e1b328f8beb.tar.gz
coreclr-27a25bd37fa1fe6201c27709b1884e1b328f8beb.tar.bz2
coreclr-27a25bd37fa1fe6201c27709b1884e1b328f8beb.zip
Delete !FEATURE_IMPLICIT_TLS (#14398)
Linux and Windows arm64 are using the regular C/C++ thread local statics. This change unifies the remaining Windows architectures to be on the same plan.
Diffstat (limited to 'src/vm/i386')
-rw-r--r--src/vm/i386/asmconstants.h3
-rw-r--r--src/vm/i386/asmhelpers.asm63
-rw-r--r--src/vm/i386/cgencpu.h15
-rw-r--r--src/vm/i386/cgenx86.cpp2
-rw-r--r--src/vm/i386/jithelp.asm51
-rw-r--r--src/vm/i386/jitinterfacex86.cpp47
-rw-r--r--src/vm/i386/stublinkerx86.cpp229
-rw-r--r--src/vm/i386/stublinkerx86.h8
8 files changed, 40 insertions, 378 deletions
diff --git a/src/vm/i386/asmconstants.h b/src/vm/i386/asmconstants.h
index f7d5f709dc..aa420428f7 100644
--- a/src/vm/i386/asmconstants.h
+++ b/src/vm/i386/asmconstants.h
@@ -317,9 +317,6 @@ ASMCONSTANTS_C_ASSERT(ASM__VTABLE_SLOTS_PER_CHUNK == VTABLE_SLOTS_PER_CHUNK)
#define ASM__VTABLE_SLOTS_PER_CHUNK_LOG2 3
ASMCONSTANTS_C_ASSERT(ASM__VTABLE_SLOTS_PER_CHUNK_LOG2 == VTABLE_SLOTS_PER_CHUNK_LOG2)
-#define TLS_GETTER_MAX_SIZE_ASM DBG_FRE(0x20, 0x10)
-ASMCONSTANTS_C_ASSERT(TLS_GETTER_MAX_SIZE_ASM == TLS_GETTER_MAX_SIZE)
-
#define JIT_TailCall_StackOffsetToFlags 0x08
#define CallDescrData__pSrc 0x00
diff --git a/src/vm/i386/asmhelpers.asm b/src/vm/i386/asmhelpers.asm
index 9df33219ac..17d521fb92 100644
--- a/src/vm/i386/asmhelpers.asm
+++ b/src/vm/i386/asmhelpers.asm
@@ -47,23 +47,10 @@ endif ; FEATURE_COMINTEROP
EXTERN __alloca_probe:PROC
EXTERN _NDirectImportWorker@4:PROC
EXTERN _UMThunkStubRareDisableWorker@8:PROC
-ifndef FEATURE_IMPLICIT_TLS
-ifdef ENABLE_GET_THREAD_GENERIC_FULL_CHECK
-; This is defined in C (threads.cpp) and enforces EE_THREAD_NOT_REQUIRED contracts
-GetThreadGenericFullCheck EQU ?GetThreadGenericFullCheck@@YGPAVThread@@XZ
-EXTERN GetThreadGenericFullCheck:PROC
-endif ; ENABLE_GET_THREAD_GENERIC_FULL_CHECK
-
-EXTERN _gThreadTLSIndex:DWORD
-EXTERN _gAppDomainTLSIndex:DWORD
-endif ; FEATURE_IMPLICIT_TLS
EXTERN _VarargPInvokeStubWorker@12:PROC
EXTERN _GenericPInvokeCalliStubWorker@12:PROC
-EXTERN _GetThread@0:PROC
-EXTERN _GetAppDomain@0:PROC
-
ifdef MDA_SUPPORTED
EXTERN _PInvokeStackImbalanceWorker@8:PROC
endif
@@ -716,56 +703,6 @@ doRet:
FASTCALL_ENDFUNC HelperMethodFrameRestoreState
-ifndef FEATURE_IMPLICIT_TLS
-;---------------------------------------------------------------------------
-; Portable GetThread() function: used if no platform-specific optimizations apply.
-; This is in assembly code because we count on edx not getting trashed on calls
-; to this function.
-;---------------------------------------------------------------------------
-; Thread* __stdcall GetThreadGeneric(void);
-GetThreadGeneric PROC stdcall public USES ecx edx
-
-ifdef _DEBUG
- cmp dword ptr [_gThreadTLSIndex], -1
- jnz @F
- int 3
-@@:
-endif
-ifdef ENABLE_GET_THREAD_GENERIC_FULL_CHECK
- ; non-PAL, debug-only GetThreadGeneric should defer to GetThreadGenericFullCheck
- ; to do extra contract enforcement. (See GetThreadGenericFullCheck for details.)
- ; This code is intentionally not added to asmhelper.s, as this enforcement is only
- ; implemented for non-PAL builds.
- call GetThreadGenericFullCheck
-else
- push dword ptr [_gThreadTLSIndex]
- call dword ptr [__imp__TlsGetValue@4]
-endif
- ret
-GetThreadGeneric ENDP
-
-;---------------------------------------------------------------------------
-; Portable GetAppdomain() function: used if no platform-specific optimizations apply.
-; This is in assembly code because we count on edx not getting trashed on calls
-; to this function.
-;---------------------------------------------------------------------------
-; Appdomain* __stdcall GetAppDomainGeneric(void);
-GetAppDomainGeneric PROC stdcall public USES ecx edx
-
-ifdef _DEBUG
- cmp dword ptr [_gAppDomainTLSIndex], -1
- jnz @F
- int 3
-@@:
-endif
-
- push dword ptr [_gAppDomainTLSIndex]
- call dword ptr [__imp__TlsGetValue@4]
- ret
-GetAppDomainGeneric ENDP
-endif
-
-
ifdef FEATURE_HIJACK
; A JITted method's return address was hijacked to return to us here.
diff --git a/src/vm/i386/cgencpu.h b/src/vm/i386/cgencpu.h
index 5360b3eb0e..ffdfb82b14 100644
--- a/src/vm/i386/cgencpu.h
+++ b/src/vm/i386/cgencpu.h
@@ -108,14 +108,6 @@ BOOL Runtime_Test_For_SSE2();
#define ENREGISTERED_RETURNTYPE_INTEGER_MAXSIZE 4
#define CALLDESCR_ARGREGS 1 // CallDescrWorker has ArgumentRegister parameter
-// Max size of patched TLS helpers
-#ifdef _DEBUG
-// Debug build needs extra space for last error trashing
-#define TLS_GETTER_MAX_SIZE 0x20
-#else
-#define TLS_GETTER_MAX_SIZE 0x10
-#endif
-
//=======================================================================
// IMPORTANT: This value is used to figure out how much to allocate
// for a fixed array of FieldMarshaler's. That means it must be at least
@@ -558,6 +550,12 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode)
return TRUE;
}
+//
+// JIT HELPER ALIASING FOR PORTABILITY.
+//
+// Create alias for optimized implementations of helpers provided on this platform
+//
+
// optimized static helpers generated dynamically at runtime
// #define JIT_GetSharedGCStaticBase
// #define JIT_GetSharedNonGCStaticBase
@@ -573,4 +571,5 @@ inline BOOL ClrFlushInstructionCache(LPCVOID pCodeAddr, size_t sizeOfCode)
#define JIT_NewCrossContext JIT_NewCrossContext
#define JIT_Stelem_Ref JIT_Stelem_Ref
#endif // FEATURE_PAL
+
#endif // __cgenx86_h__
diff --git a/src/vm/i386/cgenx86.cpp b/src/vm/i386/cgenx86.cpp
index 3b523c9c28..c91a716137 100644
--- a/src/vm/i386/cgenx86.cpp
+++ b/src/vm/i386/cgenx86.cpp
@@ -1076,7 +1076,7 @@ Stub *GenerateInitPInvokeFrameHelper()
unsigned negSpace = FrameInfo.offsetOfFrameVptr;
// mov esi, GetThread()
- psl->X86EmitCurrentThreadFetch(kESI, (1<<kEDI)|(1<<kEBX)|(1<<kECX)|(1<<kEDX));
+ psl->X86EmitCurrentThreadFetch(kESI);
// mov [edi + FrameInfo.offsetOfGSCookie], GetProcessGSCookie()
psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, FrameInfo.offsetOfGSCookie - negSpace);
diff --git a/src/vm/i386/jithelp.asm b/src/vm/i386/jithelp.asm
index 85e824040a..5d64b18c94 100644
--- a/src/vm/i386/jithelp.asm
+++ b/src/vm/i386/jithelp.asm
@@ -2,11 +2,6 @@
; The .NET Foundation licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
-; ==++==
-;
-
-;
-; ==--==
; ***********************************************************************
; File: JIThelp.asm
;
@@ -70,13 +65,11 @@ endif
EXTERN _g_TailCallFrameVptr:DWORD
EXTERN @JIT_FailFast@0:PROC
EXTERN _s_gsCookie:DWORD
+EXTERN _GetThread@0:PROC
EXTERN @JITutil_IsInstanceOfInterface@8:PROC
EXTERN @JITutil_ChkCastInterface@8:PROC
EXTERN @JITutil_IsInstanceOfAny@8:PROC
EXTERN @JITutil_ChkCastAny@8:PROC
-ifdef FEATURE_IMPLICIT_TLS
-EXTERN _GetThread@0:PROC
-endif
ifdef WRITE_BARRIER_CHECK
; Those global variables are always defined, but should be 0 for Server GC
@@ -963,13 +956,15 @@ NewArgs equ 20
; extra space is incremented as we push things on the stack along the way
ExtraSpace = 0
- call _GetThread@0; eax = Thread*
- push eax ; Thread*
+ push 0 ; Thread*
; save ArgumentRegisters
push ecx
push edx
+ call _GetThread@0; eax = Thread*
+ mov [esp + 8], eax
+
ExtraSpace = 12 ; pThread, ecx, edx
ifdef FEATURE_HIJACK
@@ -1247,44 +1242,8 @@ _JIT_PatchedCodeStart@0 proc public
ret
_JIT_PatchedCodeStart@0 endp
-;
-; Optimized TLS getters
-;
-
- ALIGN 4
-
-ifndef FEATURE_IMPLICIT_TLS
-_GetThread@0 proc public
- ; This will be overwritten at runtime with optimized GetThread implementation
- jmp short _GetTLSDummy@0
- ; Just allocate space that will be filled in at runtime
- db (TLS_GETTER_MAX_SIZE_ASM - 2) DUP (0CCh)
-_GetThread@0 endp
-
- ALIGN 4
-
-_GetAppDomain@0 proc public
- ; This will be overwritten at runtime with optimized GetAppDomain implementation
- jmp short _GetTLSDummy@0
- ; Just allocate space that will be filled in at runtime
- db (TLS_GETTER_MAX_SIZE_ASM - 2) DUP (0CCh)
-_GetAppDomain@0 endp
-
-_GetTLSDummy@0 proc public
- xor eax,eax
- ret
-_GetTLSDummy@0 endp
-
ALIGN 4
-_ClrFlsGetBlock@0 proc public
- ; This will be overwritten at runtime with optimized ClrFlsGetBlock implementation
- jmp short _GetTLSDummy@0
- ; Just allocate space that will be filled in at runtime
- db (TLS_GETTER_MAX_SIZE_ASM - 2) DUP (0CCh)
-_ClrFlsGetBlock@0 endp
-endif
-
;**********************************************************************
; Write barriers generated at runtime
diff --git a/src/vm/i386/jitinterfacex86.cpp b/src/vm/i386/jitinterfacex86.cpp
index 8463b084ac..1b470c9533 100644
--- a/src/vm/i386/jitinterfacex86.cpp
+++ b/src/vm/i386/jitinterfacex86.cpp
@@ -539,7 +539,7 @@ void JIT_TrialAlloc::EmitCore(CPUSTUBLINKER *psl, CodeLabel *noLock, CodeLabel *
&& "EAX should contain size for allocation and it doesnt!!!");
// Fetch current thread into EDX, preserving EAX and ECX
- psl->X86EmitCurrentThreadFetch(kEDX, (1<<kEAX)|(1<<kECX));
+ psl->X86EmitCurrentThreadFetch(kEDX);
// Try the allocation.
@@ -1253,7 +1253,7 @@ FastPrimitiveArrayAllocatorFuncPtr fastPrimitiveArrayAllocator = UnframedAllocat
// "init" should be the address of a routine which takes an argument of
// the module domain ID, the class domain ID, and returns the static base pointer
-void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck, bool bGCStatic, bool bSingleAppDomain)
+void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCtorCheck, bool bGCStatic)
{
STANDARD_VM_CONTRACT;
@@ -1267,35 +1267,6 @@ void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCto
psl->Emit8(0x89);
psl->Emit8(0xc8);
- if(!bSingleAppDomain)
- {
- // Check tag
- CodeLabel *cctorCheck = psl->NewCodeLabel();
-
-
- // test eax, 1
- psl->Emit8(0xa9);
- psl->Emit32(1);
-
- // jz cctorCheck
- psl->X86EmitCondJump(cctorCheck, X86CondCode::kJZ);
-
- // mov eax GetAppDomain()
- psl->X86EmitCurrentAppDomainFetch(kEAX, (1<<kECX)|(1<<kEDX));
-
- // mov eax [eax->m_sDomainLocalBlock.m_pModuleSlots]
- psl->X86EmitIndexRegLoad(kEAX, kEAX, (__int32) AppDomain::GetOffsetOfModuleSlotsPointer());
-
- // Note: weird address arithmetic effectively does:
- // shift over 1 to remove tag bit (which is always 1), then multiply by 4.
- // mov eax [eax + ecx*2 - 2]
- psl->X86EmitOp(0x8b, kEAX, kEAX, -2, kECX, 2);
-
- // cctorCheck:
- psl->EmitLabel(cctorCheck);
-
- }
-
if (bCCtorCheck)
{
// test [eax + edx + offsetof(DomainLocalModule, m_pDataBlob], ClassInitFlags::INITIALIZED_FLAG // Is class inited
@@ -1356,7 +1327,7 @@ void EmitFastGetSharedStaticBase(CPUSTUBLINKER *psl, CodeLabel *init, bool bCCto
}
-void *GenFastGetSharedStaticBase(bool bCheckCCtor, bool bGCStatic, bool bSingleAppDomain)
+void *GenFastGetSharedStaticBase(bool bCheckCCtor, bool bGCStatic)
{
STANDARD_VM_CONTRACT;
@@ -1372,7 +1343,7 @@ void *GenFastGetSharedStaticBase(bool bCheckCCtor, bool bGCStatic, bool bSingleA
init = sl.NewExternalCodeLabel((LPVOID)JIT_GetSharedNonGCStaticBase);
}
- EmitFastGetSharedStaticBase(&sl, init, bCheckCCtor, bGCStatic, bSingleAppDomain);
+ EmitFastGetSharedStaticBase(&sl, init, bCheckCCtor, bGCStatic);
Stub *pStub = sl.Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap());
@@ -1521,16 +1492,14 @@ void InitJITHelpers1()
//UnframedAllocateString;
}
- bool bSingleAppDomain = IsSingleAppDomain();
-
// Replace static helpers with faster assembly versions
- pMethodAddresses[6] = GenFastGetSharedStaticBase(true, true, bSingleAppDomain);
+ pMethodAddresses[6] = GenFastGetSharedStaticBase(true, true);
SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE, pMethodAddresses[6]);
- pMethodAddresses[7] = GenFastGetSharedStaticBase(true, false, bSingleAppDomain);
+ pMethodAddresses[7] = GenFastGetSharedStaticBase(true, false);
SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE, pMethodAddresses[7]);
- pMethodAddresses[8] = GenFastGetSharedStaticBase(false, true, bSingleAppDomain);
+ pMethodAddresses[8] = GenFastGetSharedStaticBase(false, true);
SetJitHelperFunction(CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR, pMethodAddresses[8]);
- pMethodAddresses[9] = GenFastGetSharedStaticBase(false, false, bSingleAppDomain);
+ pMethodAddresses[9] = GenFastGetSharedStaticBase(false, false);
SetJitHelperFunction(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR, pMethodAddresses[9]);
ETW::MethodLog::StubsInitialized(pMethodAddresses, (PVOID *)pHelperNames, ETW_NUM_JIT_HELPERS);
diff --git a/src/vm/i386/stublinkerx86.cpp b/src/vm/i386/stublinkerx86.cpp
index b77609822b..3b376be26d 100644
--- a/src/vm/i386/stublinkerx86.cpp
+++ b/src/vm/i386/stublinkerx86.cpp
@@ -2320,7 +2320,7 @@ static const X86Reg c_argRegs[] = {
#ifndef CROSSGEN_COMPILE
-#if defined(_DEBUG) && (defined(_TARGET_AMD64_) || defined(_TARGET_X86_)) && !defined(FEATURE_PAL)
+#if defined(_DEBUG) && !defined(FEATURE_PAL)
void StubLinkerCPU::EmitJITHelperLoggingThunk(PCODE pJitHelper, LPVOID helperFuncCount)
{
STANDARD_VM_CONTRACT;
@@ -2358,181 +2358,36 @@ void StubLinkerCPU::EmitJITHelperLoggingThunk(PCODE pJitHelper, LPVOID helperFun
#endif
X86EmitTailcallWithSinglePop(NewExternalCodeLabel(pJitHelper), kECX);
}
-#endif // _DEBUG && (_TARGET_AMD64_ || _TARGET_X86_) && !FEATURE_PAL
+#endif // _DEBUG && !FEATURE_PAL
-#ifndef FEATURE_IMPLICIT_TLS
-//---------------------------------------------------------------
-// Emit code to store the current Thread structure in dstreg
-// preservedRegSet is a set of registers to be preserved
-// TRASHES EAX, EDX, ECX unless they are in preservedRegSet.
-// RESULTS dstreg = current Thread
-//---------------------------------------------------------------
-VOID StubLinkerCPU::X86EmitTLSFetch(DWORD idx, X86Reg dstreg, unsigned preservedRegSet)
+#if !defined(FEATURE_STUBS_AS_IL)
+VOID StubLinkerCPU::X86EmitCurrentThreadFetch(X86Reg dstreg)
{
CONTRACTL
{
STANDARD_VM_CHECK;
- // It doesn't make sense to have the destination register be preserved
- PRECONDITION((preservedRegSet & (1<<dstreg)) == 0);
AMD64_ONLY(PRECONDITION(dstreg < 8)); // code below doesn't support high registers
}
CONTRACTL_END;
- TLSACCESSMODE mode = GetTLSAccessMode(idx);
-
-#ifdef _DEBUG
- {
- static BOOL f = TRUE;
- f = !f;
- if (f)
- {
- mode = TLSACCESS_GENERIC;
- }
- }
-#endif
-
- switch (mode)
- {
- case TLSACCESS_WNT:
- {
- unsigned __int32 tlsofs = offsetof(TEB, TlsSlots) + (idx * sizeof(void*));
-#ifdef _TARGET_AMD64_
- BYTE code[] = {0x65,0x48,0x8b,0x04,0x25}; // mov dstreg, qword ptr gs:[IMM32]
- static const int regByteIndex = 3;
-#elif defined(_TARGET_X86_)
- BYTE code[] = {0x64,0x8b,0x05}; // mov dstreg, dword ptr fs:[IMM32]
- static const int regByteIndex = 2;
-#endif
- code[regByteIndex] |= (dstreg << 3);
-
- EmitBytes(code, sizeof(code));
- Emit32(tlsofs);
- }
- break;
-
- case TLSACCESS_GENERIC:
-
- X86EmitPushRegs(preservedRegSet & ((1<<kEAX)|(1<<kEDX)|(1<<kECX)));
-
- X86EmitPushImm32(idx);
#ifdef _TARGET_AMD64_
- X86EmitPopReg (kECX); // arg in reg
-#endif
-
- // call TLSGetValue
- X86EmitCall(NewExternalCodeLabel((LPVOID) TlsGetValue), sizeof(void*));
-
- // mov dstreg, eax
- X86EmitMovRegReg(dstreg, kEAX);
-
- X86EmitPopRegs(preservedRegSet & ((1<<kEAX)|(1<<kEDX)|(1<<kECX)));
-
- break;
-
- default:
- _ASSERTE(0);
- }
-
-#ifdef _DEBUG
- // Trash caller saved regs that we were not told to preserve, and that aren't the dstreg.
- preservedRegSet |= 1<<dstreg;
- if (!(preservedRegSet & (1<<kEAX)))
- X86EmitDebugTrashReg(kEAX);
- if (!(preservedRegSet & (1<<kEDX)))
- X86EmitDebugTrashReg(kEDX);
- if (!(preservedRegSet & (1<<kECX)))
- X86EmitDebugTrashReg(kECX);
-#endif
-
-}
-#endif // FEATURE_IMPLICIT_TLS
-
-VOID StubLinkerCPU::X86EmitCurrentThreadFetch(X86Reg dstreg, unsigned preservedRegSet)
-{
- CONTRACTL
- {
- STANDARD_VM_CHECK;
-
- // It doesn't make sense to have the destination register be preserved
- PRECONDITION((preservedRegSet & (1<<dstreg)) == 0);
- AMD64_ONLY(PRECONDITION(dstreg < 8)); // code below doesn't support high registers
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_IMPLICIT_TLS
-
- X86EmitPushRegs(preservedRegSet & ((1<<kEAX)|(1<<kEDX)|(1<<kECX)));
-
- //TODO: Inline the instruction instead of a call
- // call GetThread
- X86EmitCall(NewExternalCodeLabel((LPVOID) GetThread), sizeof(void*));
-
- // mov dstreg, eax
- X86EmitMovRegReg(dstreg, kEAX);
-
- X86EmitPopRegs(preservedRegSet & ((1<<kEAX)|(1<<kEDX)|(1<<kECX)));
-
-#ifdef _DEBUG
- // Trash caller saved regs that we were not told to preserve, and that aren't the dstreg.
- preservedRegSet |= 1<<dstreg;
- if (!(preservedRegSet & (1<<kEAX)))
- X86EmitDebugTrashReg(kEAX);
- if (!(preservedRegSet & (1<<kEDX)))
- X86EmitDebugTrashReg(kEDX);
- if (!(preservedRegSet & (1<<kECX)))
- X86EmitDebugTrashReg(kECX);
-#endif // _DEBUG
-
-#else // FEATURE_IMPLICIT_TLS
-
- X86EmitTLSFetch(GetThreadTLSIndex(), dstreg, preservedRegSet);
-
-#endif // FEATURE_IMPLICIT_TLS
-
-}
-
-VOID StubLinkerCPU::X86EmitCurrentAppDomainFetch(X86Reg dstreg, unsigned preservedRegSet)
-{
- CONTRACTL
- {
- STANDARD_VM_CHECK;
-
- // It doesn't make sense to have the destination register be preserved
- PRECONDITION((preservedRegSet & (1<<dstreg)) == 0);
- AMD64_ONLY(PRECONDITION(dstreg < 8)); // code below doesn't support high registers
- }
- CONTRACTL_END;
-
-#ifdef FEATURE_IMPLICIT_TLS
- X86EmitPushRegs(preservedRegSet & ((1<<kEAX)|(1<<kEDX)|(1<<kECX)));
-
- //TODO: Inline the instruction instead of a call
- // call GetThread
- X86EmitCall(NewExternalCodeLabel((LPVOID) GetAppDomain), sizeof(void*));
-
- // mov dstreg, eax
- X86EmitMovRegReg(dstreg, kEAX);
-
- X86EmitPopRegs(preservedRegSet & ((1<<kEAX)|(1<<kEDX)|(1<<kECX)));
-
-#ifdef _DEBUG
- // Trash caller saved regs that we were not told to preserve, and that aren't the dstreg.
- preservedRegSet |= 1<<dstreg;
- if (!(preservedRegSet & (1<<kEAX)))
- X86EmitDebugTrashReg(kEAX);
- if (!(preservedRegSet & (1<<kEDX)))
- X86EmitDebugTrashReg(kEDX);
- if (!(preservedRegSet & (1<<kECX)))
- X86EmitDebugTrashReg(kECX);
+ BYTE code[] = { 0x65,0x48,0x8b,0x04,0x25 }; // mov dstreg, qword ptr gs:[IMM32]
+ static const int regByteIndex = 3;
+#elif defined(_TARGET_X86_)
+ BYTE code[] = { 0x64,0x8b,0x05 }; // mov dstreg, dword ptr fs:[IMM32]
+ static const int regByteIndex = 2;
#endif
+ code[regByteIndex] |= (dstreg << 3);
-#else // FEATURE_IMPLICIT_TLS
+ EmitBytes(code, sizeof(code));
+ Emit32(offsetof(TEB, ThreadLocalStoragePointer));
- X86EmitTLSFetch(GetAppDomainTLSIndex(), dstreg, preservedRegSet);
+ X86EmitIndexRegLoad(dstreg, dstreg, sizeof(void *) * (g_TlsIndex & 0xFFFF));
-#endif // FEATURE_IMPLICIT_TLS
+ X86EmitIndexRegLoad(dstreg, dstreg, (g_TlsIndex & 0x7FFF0000) >> 16);
}
+#endif // !FEATURE_STUBS_AS_IL
#if defined(_TARGET_X86_)
@@ -2861,56 +2716,7 @@ VOID StubLinkerCPU::EmitSetup(CodeLabel *pForwardRef)
{
STANDARD_VM_CONTRACT;
-#ifdef FEATURE_IMPLICIT_TLS
- DWORD idx = 0;
- TLSACCESSMODE mode = TLSACCESS_GENERIC;
-#else
- DWORD idx = GetThreadTLSIndex();
- TLSACCESSMODE mode = GetTLSAccessMode(idx);
-#endif
-
-#ifdef _DEBUG
- {
- static BOOL f = TRUE;
- f = !f;
- if (f)
- {
- mode = TLSACCESS_GENERIC;
- }
- }
-#endif
-
- switch (mode)
- {
- case TLSACCESS_WNT:
-#ifndef FEATURE_PAL
- {
- unsigned __int32 tlsofs = offsetof(TEB, TlsSlots) + (idx * sizeof(void*));
-
- static const BYTE code[] = {0x64,0x8b,0x1d}; // mov ebx, dword ptr fs:[IMM32]
- EmitBytes(code, sizeof(code));
- Emit32(tlsofs);
- }
-#else // !FEATURE_PAL
- _ASSERTE("TLSACCESS_WNT mode is not supported");
-#endif // !FEATURE_PAL
- break;
-
- case TLSACCESS_GENERIC:
-#ifdef FEATURE_IMPLICIT_TLS
- X86EmitCall(NewExternalCodeLabel((LPVOID) GetThread), sizeof(void*));
-#else
- X86EmitPushImm32(idx);
-
- // call TLSGetValue
- X86EmitCall(NewExternalCodeLabel((LPVOID) TlsGetValue), sizeof(void*));
-#endif
- // mov ebx,eax
- Emit16(0xc389);
- break;
- default:
- _ASSERTE(0);
- }
+ X86EmitCurrentThreadFetch(kEBX);
// cmp ebx, 0
static const BYTE b[] = { 0x83, 0xFB, 0x0};
@@ -3150,8 +2956,7 @@ VOID StubLinkerCPU::EmitMethodStubProlog(TADDR pFrameVptr, int transitionBlockOf
#endif // _TARGET_X86_
// ebx <-- GetThread()
- // Trashes X86TLSFetch_TRASHABLE_REGS
- X86EmitCurrentThreadFetch(kEBX, 0);
+ X86EmitCurrentThreadFetch(kEBX);
#if _DEBUG
diff --git a/src/vm/i386/stublinkerx86.h b/src/vm/i386/stublinkerx86.h
index 76d1f95845..d523bb0461 100644
--- a/src/vm/i386/stublinkerx86.h
+++ b/src/vm/i386/stublinkerx86.h
@@ -219,11 +219,7 @@ class StubLinkerCPU : public StubLinker
VOID X86EmitLeaRIP(CodeLabel *target, X86Reg reg);
#endif
- static const unsigned X86TLSFetch_TRASHABLE_REGS = (1<<kEAX) | (1<<kEDX) | (1<<kECX);
- VOID X86EmitTLSFetch(DWORD idx, X86Reg dstreg, unsigned preservedRegSet);
-
- VOID X86EmitCurrentThreadFetch(X86Reg dstreg, unsigned preservedRegSet);
- VOID X86EmitCurrentAppDomainFetch(X86Reg dstreg, unsigned preservedRegSet);
+ VOID X86EmitCurrentThreadFetch(X86Reg dstreg);
VOID X86EmitIndexRegLoad(X86Reg dstreg, X86Reg srcreg, __int32 ofs = 0);
VOID X86EmitIndexRegStore(X86Reg dstreg, __int32 ofs, X86Reg srcreg);
@@ -421,7 +417,7 @@ class StubLinkerCPU : public StubLinker
VOID EmitDebugBreak();
#endif // !FEATURE_STUBS_AS_IL
-#if defined(_DEBUG) && (defined(_TARGET_AMD64_) || defined(_TARGET_X86_)) && !defined(FEATURE_PAL)
+#if defined(_DEBUG) && !defined(FEATURE_PAL)
//===========================================================================
// Emits code to log JITHelper access
void EmitJITHelperLoggingThunk(PCODE pJitHelper, LPVOID helperFuncCount);