Skip to content

Commit

Permalink
For x86/x64, call a stack probe helper for all frame sizes equal or o…
Browse files Browse the repository at this point in the history
…ver one page (#44664)
  • Loading branch information
echesakov authored Nov 19, 2020
1 parent 0cb3cfd commit 999785e
Showing 1 changed file with 14 additions and 35 deletions.
49 changes: 14 additions & 35 deletions src/coreclr/src/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1970,43 +1970,32 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
return;
}

const target_size_t pageSize = compiler->eeGetPageSize();
target_size_t lastTouchDelta = 0; // What offset from the final SP was the last probe?
const target_size_t pageSize = compiler->eeGetPageSize();

if (frameSize == REGSIZE_BYTES)
{
// Frame size is the same as register size.
inst_RV(INS_push, REG_EAX, TYP_I_IMPL);
GetEmitter()->emitIns_R(INS_push, EA_PTRSIZE, REG_EAX);
compiler->unwindAllocStack(frameSize);
}
else if (frameSize < pageSize)
{
// Frame size is (0x0008..0x1000)
inst_RV_IV(INS_sub, REG_SPBASE, frameSize, EA_PTRSIZE);
lastTouchDelta = frameSize;
}
else if (frameSize < compiler->getVeryLargeFrameSize())
{
lastTouchDelta = frameSize;

// Frame size is (0x1000..0x3000)
GetEmitter()->emitIns_R_I(INS_sub, EA_PTRSIZE, REG_SPBASE, frameSize);
compiler->unwindAllocStack(frameSize);

GetEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, -(int)pageSize);
lastTouchDelta -= pageSize;
const unsigned lastProbedLocToFinalSp = frameSize;

if (frameSize >= 0x2000)
if (lastProbedLocToFinalSp + STACK_PROBE_BOUNDARY_THRESHOLD_BYTES > pageSize)
{
GetEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, -2 * (int)pageSize);
lastTouchDelta -= pageSize;
// We haven't probed almost a complete page. If the next action on the stack might subtract from SP
// first, before touching the current SP, then we need to probe at the very bottom. This can
// happen on x86, for example, when we copy an argument to the stack using a "SUB ESP; REP MOV"
// strategy.
GetEmitter()->emitIns_R_AR(INS_test, EA_4BYTE, REG_EAX, REG_SPBASE, 0);
}

inst_RV_IV(INS_sub, REG_SPBASE, frameSize, EA_PTRSIZE);
assert(lastTouchDelta == frameSize % pageSize);
}
else
{
// Frame size >= 0x3000
assert(frameSize >= compiler->getVeryLargeFrameSize());

#ifdef TARGET_X86
int spOffset = -(int)frameSize;

Expand Down Expand Up @@ -2053,24 +2042,14 @@ void CodeGen::genAllocLclFrame(unsigned frameSize, regNumber initReg, bool* pIni
GetEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, REG_SPBASE, REG_STACK_PROBE_HELPER_ARG);
#endif // !TARGET_X86

compiler->unwindAllocStack(frameSize);

if (initReg == REG_STACK_PROBE_HELPER_ARG)
{
*pInitRegZeroed = false;
}
}

if (lastTouchDelta + STACK_PROBE_BOUNDARY_THRESHOLD_BYTES > pageSize)
{
// We haven't probed almost a complete page. If the next action on the stack might subtract from SP
// first, before touching the current SP, then we do one more probe at the very bottom. This can
// happen on x86, for example, when we copy an argument to the stack using a "SUB ESP; REP MOV"
// strategy.

GetEmitter()->emitIns_AR_R(INS_test, EA_PTRSIZE, REG_EAX, REG_SPBASE, 0);
}

compiler->unwindAllocStack(frameSize);

#ifdef USING_SCOPE_INFO
if (!doubleAlignOrFramePointerUsed())
{
Expand Down

0 comments on commit 999785e

Please sign in to comment.