From 3628bd308c8ba916945d65509fd20cea2909ebc1 Mon Sep 17 00:00:00 2001 From: Egor Chesakov Date: Fri, 30 Mar 2018 20:43:28 -0700 Subject: [PATCH] Fix#16827 Stack probing for Linux (#17360) * Add stack probing algorithm that moves sp while touching pages under _TARGET_UNIX_ only --- src/jit/codegencommon.cpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp index 72a91d9..c1bcff0 100644 --- a/src/jit/codegencommon.cpp +++ b/src/jit/codegencommon.cpp @@ -6325,7 +6325,9 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni } #endif // !_TARGET_XARCH_ +#if CPU_LOAD_STORE_ARCH || !defined(_TARGET_UNIX_) instGen_Set_Reg_To_Zero(EA_PTRSIZE, initReg); +#endif // // Can't have a label inside the ReJIT padding area @@ -6381,6 +6383,7 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni #else // !CPU_LOAD_STORE_ARCH +#ifndef _TARGET_UNIX_ // Code size for each instruction. We need this because the // backward branch is hard-coded with the number of bytes to branch. // The encoding differs based on the architecture and what register is @@ -6419,6 +6422,60 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni #endif // !_TARGET_AMD64_ inst_IV(INS_jge, bytesForBackwardJump); // Branch backwards to start of loop +#else // _TARGET_UNIX_ + // Code size for each instruction. We need this because the + // backward branch is hard-coded with the number of bytes to branch. + // The encoding differs based on the architecture and what register is + // used (namely, using RAX has a smaller encoding). + // + // For x86 + // lea eax, [esp - frameSize] + // loop: + // lea esp, [esp - pageSize] 7 + // test [esp], eax 3 + // cmp esp, eax 2 + // jge loop 2 + // lea rsp, [rbp + frameSize] + // + // For AMD64 using RAX + // lea rax, [rsp - frameSize] + // loop: + // lea rsp, [rsp - pageSize] 8 + // test [rsp], rax 4 + // cmp rsp, rax 3 + // jge loop 2 + // lea rsp, [rax + frameSize] + // + // For AMD64 using RBP + // lea rbp, [rsp - frameSize] + // loop: + // lea rsp, [rsp - pageSize] 8 + // test [rsp], rbp 4 + // cmp rsp, rbp 3 + // jge loop 2 + // lea rsp, [rbp + frameSize] + + int sPageSize = (int)pageSize; + + getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, initReg, REG_SPBASE, -((ssize_t)frameSize)); // get frame border + + getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -sPageSize); + getEmitter()->emitIns_R_AR(INS_TEST, EA_PTRSIZE, initReg, REG_SPBASE, 0); + inst_RV_RV(INS_cmp, REG_SPBASE, initReg); + + int bytesForBackwardJump; +#ifdef _TARGET_AMD64_ + assert((initReg == REG_EAX) || (initReg == REG_EBP)); // We use RBP as initReg for EH funclets. + bytesForBackwardJump = -17; +#else // !_TARGET_AMD64_ + assert(initReg == REG_EAX); + bytesForBackwardJump = -14; +#endif // !_TARGET_AMD64_ + + inst_IV(INS_jge, bytesForBackwardJump); // Branch backwards to start of loop + + getEmitter()->emitIns_R_AR(INS_lea, EA_PTRSIZE, REG_SPBASE, initReg, frameSize); // restore stack pointer +#endif // _TARGET_UNIX_ #endif // !CPU_LOAD_STORE_ARCH -- 2.7.4