diff --git a/src/coreclr/inc/jithelpers.h b/src/coreclr/inc/jithelpers.h index 72748e42cbde03..ce37ad5c29ff70 100644 --- a/src/coreclr/inc/jithelpers.h +++ b/src/coreclr/inc/jithelpers.h @@ -30,7 +30,7 @@ #endif // pfnHelper is set to NULL if it is a stubbed helper. -// It will be set in InitJITHelpers2 +// It will be set in InitJITHelpers1 JITHELPER(CORINFO_HELP_UNDEF, NULL, METHOD__NIL) @@ -214,11 +214,7 @@ JITHELPER(CORINFO_HELP_GETCURRENTMANAGEDTHREADID, JIT_GetCurrentManagedThreadId, METHOD__NIL) -#ifdef TARGET_64BIT JITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, JIT_InitPInvokeFrame, METHOD__NIL) -#else - DYNAMICJITHELPER(CORINFO_HELP_INIT_PINVOKE_FRAME, NULL, METHOD__NIL) -#endif DYNAMICJITHELPER(CORINFO_HELP_MEMSET, NULL, METHOD__SPAN_HELPERS__MEMSET) DYNAMICJITHELPER(CORINFO_HELP_MEMZERO, NULL, METHOD__SPAN_HELPERS__MEMZERO) diff --git a/src/coreclr/vm/arm/cgencpu.h b/src/coreclr/vm/arm/cgencpu.h index 110669e5df45d9..914c37d6fea63d 100644 --- a/src/coreclr/vm/arm/cgencpu.h +++ b/src/coreclr/vm/arm/cgencpu.h @@ -52,9 +52,6 @@ struct ArgLocDesc; extern PCODE GetPreStubEntryPoint(); -// CPU-dependent functions -Stub * GenerateInitPInvokeFrameHelper(); - EXTERN_C void checkStack(void); #define THUMB_CODE 1 @@ -555,8 +552,6 @@ class StubLinkerCPU : public StubLinker ThumbEmitJumpRegister(thumbRegLr); } - void ThumbEmitGetThread(ThumbReg dest); - void ThumbEmitNop() { // nop diff --git a/src/coreclr/vm/arm/pinvokestubs.S b/src/coreclr/vm/arm/pinvokestubs.S index cc84c541a183bb..b18d20f7d0c768 100644 --- a/src/coreclr/vm/arm/pinvokestubs.S +++ b/src/coreclr/vm/arm/pinvokestubs.S @@ -154,6 +154,42 @@ LOCAL_LABEL(RarePath): LEAF_END JIT_PInvokeEnd, _TEXT +// ------------------------------------------------------------------ +// IN: +// InlinedCallFrame (r4) = pointer to the InlinedCallFrame data +// OUT: +// Thread (r5) = pointer to Thread +// +// + LEAF_ENTRY JIT_InitPInvokeFrame, _TEXT + + PROLOG_PUSH "{r0-r4, lr}" + + bl C_FUNC(GetThreadHelper) + mov r5, r0 + + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov r6, #FRAMETYPE_InlinedCallFrame + str r6, [r4] + + // pFrame->m_Next = pThread->m_pFrame; + ldr r6, [r5, #Thread_m_pFrame] + str r6, [r4, #Frame__m_Next] + + str r11, [r4, #InlinedCallFrame__m_pCalleeSavedFP] + str r9, [r4, #InlinedCallFrame__m_pSPAfterProlog] + mov r6, 0 + str r6, [r4, #InlinedCallFrame__m_pCallerReturnAddress] + add r6, sp, 24 + str r6, [r4, #InlinedCallFrame__m_pCallSiteSP] + + // pThread->m_pFrame = pFrame; + str r4, [r5, #Thread_m_pFrame] + + EPILOG_POP "{r0-r4, pc}" + + LEAF_END JIT_InitPInvokeFrame, _TEXT + // ------------------------------------------------------------------ // VarargPInvokeStub & VarargPInvokeGenILStub // There is a separate stub when the method has a hidden return buffer arg. diff --git a/src/coreclr/vm/arm/stubs.cpp b/src/coreclr/vm/arm/stubs.cpp index 0becb0440bac5c..7ed01427790c04 100644 --- a/src/coreclr/vm/arm/stubs.cpp +++ b/src/coreclr/vm/arm/stubs.cpp @@ -1105,88 +1105,6 @@ void ResolveHolder::Initialize(ResolveHolder* pResolveHolderRX, _ASSERTE(patcherTarget == (PCODE)NULL); } -Stub *GenerateInitPInvokeFrameHelper() -{ - CONTRACT(Stub*) - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - CPUSTUBLINKER sl; - CPUSTUBLINKER *psl = &sl; - - CORINFO_EE_INFO::InlinedCallFrameInfo FrameInfo; - InlinedCallFrame::GetEEInfo(&FrameInfo); - - ThumbReg regFrame = ThumbReg(4); - ThumbReg regThread = ThumbReg(5); - ThumbReg regScratch = ThumbReg(6); - ThumbReg regR9 = ThumbReg(9); - - // Erect frame to perform call to GetThread - psl->ThumbEmitProlog(1, sizeof(ArgumentRegisters), FALSE); // Save r4 for aligned stack - - // Save argument registers around the GetThread call. Don't bother with using ldm/stm since this inefficient path anyway. - for (int reg = 0; reg < 4; reg++) - psl->ThumbEmitStoreRegIndirect(ThumbReg(reg), thumbRegSp, offsetof(ArgumentRegisters, r) + sizeof(*ArgumentRegisters::r) * reg); - - psl->ThumbEmitGetThread(regThread); - - for (int reg = 0; reg < 4; reg++) - psl->ThumbEmitLoadRegIndirect(ThumbReg(reg), thumbRegSp, offsetof(ArgumentRegisters, r) + sizeof(*ArgumentRegisters::r) * reg); - - // mov [regFrame], FrameIdentifier::InlinedCallFrame - psl->ThumbEmitMovConstant(regScratch, (DWORD)FrameIdentifier::InlinedCallFrame); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, 0); - - // ldr regScratch, [regThread + offsetof(Thread, m_pFrame)] - // str regScratch, [regFrame + FrameInfo.offsetOfFrameLink] - psl->ThumbEmitLoadRegIndirect(regScratch, regThread, offsetof(Thread, m_pFrame)); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfFrameLink); - - // str FP, [regFrame + FrameInfo.offsetOfCalleeSavedFP] - psl->ThumbEmitStoreRegIndirect(thumbRegFp, regFrame, FrameInfo.offsetOfCalleeSavedFP); - - // str R9, [regFrame + FrameInfo.offsetOfSPAfterProlog] - psl->ThumbEmitStoreRegIndirect(regR9, regFrame, FrameInfo.offsetOfSPAfterProlog); - - // mov [regFrame + FrameInfo.offsetOfReturnAddress], 0 - psl->ThumbEmitMovConstant(regScratch, 0); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfReturnAddress); - - DWORD cbSavedRegs = sizeof(ArgumentRegisters) + 2 * 4; // r0-r3, r4, lr - psl->ThumbEmitAdd(regScratch, thumbRegSp, cbSavedRegs); - psl->ThumbEmitStoreRegIndirect(regScratch, regFrame, FrameInfo.offsetOfCallSiteSP); - - // mov [regThread + offsetof(Thread, m_pFrame)], regFrame - psl->ThumbEmitStoreRegIndirect(regFrame, regThread, offsetof(Thread, m_pFrame)); - - // leave current Thread in R4 - - psl->ThumbEmitEpilog(); - - // A single process-wide stub that will never unload - RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetStubHeap()); -} - -void StubLinkerCPU::ThumbEmitGetThread(ThumbReg dest) -{ - ThumbEmitMovConstant(ThumbReg(0), (TADDR)GetThreadHelper); - - ThumbEmitCallRegister(ThumbReg(0)); - - if (dest != ThumbReg(0)) - { - ThumbEmitMovRegReg(dest, ThumbReg(0)); - } -} - - // Emits code to adjust for a static delegate target. VOID StubLinkerCPU::EmitShuffleThunk(ShuffleEntry *pShuffleEntryArray) { diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 95001c07cc001e..4065b7cc281537 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -887,7 +887,6 @@ void EEStartupHelper() // Before setting up the execution manager initialize the first part // of the JIT helpers. InitJITHelpers1(); - InitJITHelpers2(); SyncBlockCache::Attach(); diff --git a/src/coreclr/vm/hosting.cpp b/src/coreclr/vm/hosting.cpp index 065b254dee4047..ed7cc1ee997a07 100644 --- a/src/coreclr/vm/hosting.cpp +++ b/src/coreclr/vm/hosting.cpp @@ -115,7 +115,7 @@ BOOL ClrVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWO // JIT_PatchedCode. Thus, their pages have the same protection, they live // in the same region (and thus, its size is the same). // - // In EEStartupHelper, when we setup the UEF and then invoke InitJitHelpers1 and InitJitHelpers2, + // In EEStartupHelper, when we setup the UEF and then invoke InitJitHelpers1, // they perform some optimizations that result in the memory page protection being changed. When // the UEF is to be invoked, the OS does the check on the UEF's cached details against the current // memory pages. This check used to fail when on 64bit retail builds when JIT_PatchedCode was diff --git a/src/coreclr/vm/i386/PInvokeStubs.asm b/src/coreclr/vm/i386/PInvokeStubs.asm index 67262c8b093b9a..6392029d83e6a6 100644 --- a/src/coreclr/vm/i386/PInvokeStubs.asm +++ b/src/coreclr/vm/i386/PInvokeStubs.asm @@ -98,4 +98,37 @@ RarePath: _JIT_PInvokeEnd@4 ENDP +; +; in: +; InlinedCallFrame (edi) = pointer to the InlinedCallFrame data +; out: +; Thread (esi) = pointer to Thread data +; +; +_JIT_InitPInvokeFrame@4 PROC public + + ;; esi = GetThread(). Trashes eax + INLINE_GETTHREAD esi, eax + + ;; edi = pFrame + ;; esi = pThread + + ;; set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov dword ptr [edi], FRAMETYPE_InlinedCallFrame + + ;; pFrame->m_Next = pThread->m_pFrame; + mov eax, dword ptr [esi + Thread_m_pFrame] + mov dword ptr [edi + Frame__m_Next], eax + + mov dword ptr [edi + InlinedCallFrame__m_pCalleeSavedFP], ebp + mov dword ptr [edi + InlinedCallFrame__m_pCallerReturnAddress], 0 + + ;; pThread->m_pFrame = pFrame; + mov dword ptr [esi + Thread_m_pFrame], edi + + ;; leave current Thread in ESI + ret + +_JIT_InitPInvokeFrame@4 ENDP + end diff --git a/src/coreclr/vm/i386/cgencpu.h b/src/coreclr/vm/i386/cgencpu.h index a7b22d2c4824ac..50ae84f4bed81d 100644 --- a/src/coreclr/vm/i386/cgencpu.h +++ b/src/coreclr/vm/i386/cgencpu.h @@ -30,9 +30,6 @@ class FramedMethodFrame; class Module; class ComCallMethodDesc; -// CPU-dependent functions -Stub * GenerateInitPInvokeFrameHelper(); - #define GetEEFuncEntryPoint(pfn) GFN_TADDR(pfn) #define COMMETHOD_PREPAD 8 // # extra bytes to allocate in addition to sizeof(ComCallMethodDesc) diff --git a/src/coreclr/vm/i386/cgenx86.cpp b/src/coreclr/vm/i386/cgenx86.cpp index 38c822d4373604..6cf48490b428df 100644 --- a/src/coreclr/vm/i386/cgenx86.cpp +++ b/src/coreclr/vm/i386/cgenx86.cpp @@ -862,52 +862,6 @@ WORD GetUnpatchedCodeData(LPCBYTE pAddr) #ifndef DACCESS_COMPILE -Stub *GenerateInitPInvokeFrameHelper() -{ - CONTRACT(Stub*) - { - STANDARD_VM_CHECK; - POSTCONDITION(CheckPointer(RETVAL)); - } - CONTRACT_END; - - CPUSTUBLINKER sl; - CPUSTUBLINKER *psl = &sl; - - CORINFO_EE_INFO::InlinedCallFrameInfo FrameInfo; - InlinedCallFrame::GetEEInfo(&FrameInfo); - - // EDI contains address of the frame on stack - - // mov esi, GetThread() - psl->X86EmitCurrentThreadFetch(kESI, (1 << kEDI) | (1 << kEBX) | (1 << kECX) | (1 << kEDX)); - - // mov [edi], InlinedCallFrame::GetFrameVtable() - psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, 0); - psl->Emit32((DWORD)FrameIdentifier::InlinedCallFrame); - - // mov eax, [esi + offsetof(Thread, m_pFrame)] - // mov [edi + FrameInfo.offsetOfFrameLink], eax - psl->X86EmitIndexRegLoad(kEAX, kESI, offsetof(Thread, m_pFrame)); - psl->X86EmitIndexRegStore(kEDI, FrameInfo.offsetOfFrameLink, kEAX); - - // mov [edi + FrameInfo.offsetOfCalleeSavedEbp], ebp - psl->X86EmitIndexRegStore(kEDI, FrameInfo.offsetOfCalleeSavedFP, kEBP); - - // mov [edi + FrameInfo.offsetOfReturnAddress], 0 - psl->X86EmitOffsetModRM(0xc7, (X86Reg)0x0, kEDI, FrameInfo.offsetOfReturnAddress); - psl->Emit32(0); - - // mov [esi + offsetof(Thread, m_pFrame)], edi - psl->X86EmitIndexRegStore(kESI, offsetof(Thread, m_pFrame), kEDI); - - // leave current Thread in ESI - psl->X86EmitReturn(0); - - // A single process-wide stub that will never unload - RETURN psl->Link(SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()); -} - ////////////////////////////////////////////////////////////////////////////// // // JITInterface diff --git a/src/coreclr/vm/i386/pinvokestubs.S b/src/coreclr/vm/i386/pinvokestubs.S index e9c99b7eab0a14..1bdbf242cf60da 100644 --- a/src/coreclr/vm/i386/pinvokestubs.S +++ b/src/coreclr/vm/i386/pinvokestubs.S @@ -28,3 +28,41 @@ LEAF_ENTRY JIT_PInvokeEnd, _TEXT int 3 ret LEAF_END JIT_PInvokeEnd, _TEXT + +// +// IN: +// InlinedCallFrame (edi) = pointer to the InlinedCallFrame data +// OUT: +// Thread (esi) = pointer to Thread data +// +// +LEAF_ENTRY JIT_InitPInvokeFrame, _TEXT + + // esi = GetThread(). Trashes eax + push ecx + push edx + call GetThreadHelper + pop edx + pop ecx + mov esi, eax + + // edi = pFrame + // esi = pThread + + // set first slot to the value of InlinedCallFrame identifier (checked by runtime code) + mov dword ptr [edi], FRAMETYPE_InlinedCallFrame + + // pFrame->m_Next = pThread->m_pFrame; + mov eax, dword ptr [esi + Thread_m_pFrame] + mov dword ptr [edi + Frame__m_Next], eax + + mov dword ptr [edi + InlinedCallFrame__m_pCalleeSavedFP], ebp + mov dword ptr [edi + InlinedCallFrame__m_pCallerReturnAddress], 0 + + // pThread->m_pFrame = pFrame; + mov dword ptr [esi + Thread_m_pFrame], edi + + // leave current Thread in ESI + ret + +LEAF_END JIT_InitPInvokeFrame, _TEXT diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 4eaed789a29231..bbb9173759f6d4 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -2144,58 +2144,6 @@ static const X86Reg c_argRegs[] = { #ifdef TARGET_X86 -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 TARGET_UNIX - - X86EmitPushRegs(preservedRegSet & ((1 << kEAX) | (1 << kEDX) | (1 << kECX))); - - // call GetThread - X86EmitCall(NewExternalCodeLabel((LPVOID)GetThreadHelper), 0); - - // 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 // TARGET_UNIX - - BYTE code[] = { 0x64,0x8b,0x05 }; // mov dstreg, dword ptr fs:[IMM32] - static const int regByteIndex = 2; - - code[regByteIndex] |= (dstreg << 3); - - EmitBytes(code, sizeof(code)); - Emit32(offsetof(TEB, ThreadLocalStoragePointer)); - - X86EmitIndexRegLoad(dstreg, dstreg, sizeof(void *) * _tls_index); - - X86EmitIndexRegLoad(dstreg, dstreg, (int)Thread::GetOffsetOfThreadStatic(&gCurrentThreadInfo)); - -#endif // TARGET_UNIX -} - #ifdef TARGET_UNIX namespace { diff --git a/src/coreclr/vm/i386/stublinkerx86.h b/src/coreclr/vm/i386/stublinkerx86.h index f60120d6faeb07..ee158190ec11e0 100644 --- a/src/coreclr/vm/i386/stublinkerx86.h +++ b/src/coreclr/vm/i386/stublinkerx86.h @@ -209,8 +209,6 @@ class StubLinkerCPU : public StubLinker VOID X86EmitCall(CodeLabel *target, int iArgBytes); VOID X86EmitReturn(WORD wArgBytes); - VOID X86EmitCurrentThreadFetch(X86Reg dstreg, unsigned preservedRegSet); - VOID X86EmitCurrentThreadAllocContextFetch(X86Reg dstreg, unsigned preservedRegSet); VOID X86EmitIndexRegLoad(X86Reg dstreg, X86Reg srcreg, int32_t ofs = 0); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 927268a4769291..92f2611616ad83 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -3605,16 +3605,3 @@ bool IndirectionAllowedForJitHelper(CorInfoHelpFunc ftnNum) return true; } - -/*********************************************************************/ -// Initialize the part of the JIT helpers that require much of the -// EE infrastructure to be in place. -/*********************************************************************/ -void InitJITHelpers2() -{ - STANDARD_VM_CONTRACT; - -#if defined(TARGET_X86) || defined(TARGET_ARM) - SetJitHelperFunction(CORINFO_HELP_INIT_PINVOKE_FRAME, (void *)GenerateInitPInvokeFrameHelper()->GetEntryPoint()); -#endif // TARGET_X86 || TARGET_ARM -} diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index b6d981df4a56ba..edbb2b36d0face 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -66,7 +66,6 @@ bool SigInfoFlagsAreValid (CORINFO_SIG_INFO *sig) void InitJITHelpers1(); -void InitJITHelpers2(); PCODE UnsafeJitFunction(PrepareCodeConfig* config, COR_ILMETHOD_DECODER* header, @@ -1158,10 +1157,8 @@ FCDECL2(Object*, JIT_Box, CORINFO_CLASS_HANDLE type, void* data); BOOL ObjIsInstanceOf(Object *pObject, TypeHandle toTypeHnd, BOOL throwCastException = FALSE); -#ifdef HOST_64BIT class InlinedCallFrame; -Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); -#endif +EXTERN_C Thread * JIT_InitPInvokeFrame(InlinedCallFrame *pFrame); #ifdef _DEBUG extern LONG g_JitCount;