Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For x86/x64, call a stack probe helper for all frame sizes equal or over one page #44664

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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