summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEgor Chesakov <Egor.Chesakov@microsoft.com>2018-03-30 20:43:28 -0700
committerGitHub <noreply@github.com>2018-03-30 20:43:28 -0700
commit3628bd308c8ba916945d65509fd20cea2909ebc1 (patch)
tree0e5e6890e9d2497bd467d180eaa7240e2630c278 /src
parent9244d906fc03aee057414adb72cfd8be9e390568 (diff)
downloadcoreclr-3628bd308c8ba916945d65509fd20cea2909ebc1.tar.gz
coreclr-3628bd308c8ba916945d65509fd20cea2909ebc1.tar.bz2
coreclr-3628bd308c8ba916945d65509fd20cea2909ebc1.zip
Fix#16827 Stack probing for Linux (#17360)
* Add stack probing algorithm that moves sp while touching pages under _TARGET_UNIX_ only
Diffstat (limited to 'src')
-rw-r--r--src/jit/codegencommon.cpp57
1 files changed, 57 insertions, 0 deletions
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index 72a91d9a0e..c1bcff0eeb 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