Commit 2064c1f9 authored by Andreas Haas's avatar Andreas Haas Committed by Commit Bot

[wasm][ia32] Add an additional stack check for functions with big frames

This is the ia32 implementation of the CL
https://codereview.chromium.org/2763593002

Original message:

[wasm][arm] Add an additional stack check for functions with big frames.

Stack overflow checks are typically implemented as part of the TurboFan
graph of a function. This means that the stack check code is executed
after frame construction. When a frame is too big, though, there may not
be enough space on the stack anymore to throw the stack overflow
exception after frame construction. With this CL we do an additional
stack check before frame construction for functions with big frames.

As discussed offline with mstarzinger, I do this change currently only
for WebAssembly.

This CL contains only the changes for arm. I will do the other platforms
in separate CLs.

Bug:v8:6318

R=neis@chromium.org, titzer@chromium.org

Change-Id: Ibeedc5c4c4571cffd3a9c58016ddc44b64e2bf02
Reviewed-on: https://chromium-review.googlesource.com/568305
Commit-Queue: Andreas Haas <ahaas@chromium.org>
Reviewed-by: 's avatarGeorg Neis <neis@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#46711}
parent 4c50af93
......@@ -2240,9 +2240,7 @@ void CodeGenerator::AssembleArchTrap(Instruction* instr,
new (gen_->zone()) ReferenceMap(gen_->zone());
gen_->RecordSafepoint(reference_map, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
if (FLAG_debug_code) {
__ ud2();
}
__ AssertUnreachable(kUnexpectedReturnFromWasmTrap);
}
}
......@@ -2522,6 +2520,40 @@ void CodeGenerator::AssembleConstructFrame() {
const RegList saves = descriptor->CalleeSavedRegisters();
if (shrink_slots > 0) {
if (info()->IsWasm() && shrink_slots > 128) {
// For WebAssembly functions with big frames we have to do the stack
// overflow check before we construct the frame. Otherwise we may not
// have enough space on the stack to call the runtime for the stack
// overflow.
Label done;
// If the frame is bigger than the stack, we throw the stack overflow
// exception unconditionally. Thereby we can avoid the integer overflow
// check in the condition code.
if (shrink_slots * kPointerSize < FLAG_stack_size * 1024) {
Register scratch = esi;
__ push(scratch);
__ mov(scratch,
Immediate(ExternalReference::address_of_real_stack_limit(
__ isolate())));
__ mov(scratch, Operand(scratch, 0));
__ add(scratch, Immediate(shrink_slots * kPointerSize));
__ cmp(esp, scratch);
__ pop(scratch);
__ j(above_equal, &done);
}
if (!frame_access_state()->has_frame()) {
__ set_has_frame(true);
__ EnterFrame(StackFrame::WASM_COMPILED);
}
__ Move(esi, Smi::kZero);
__ CallRuntimeDelayed(zone(), Runtime::kThrowWasmStackOverflow);
ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
RecordSafepoint(reference_map, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
__ AssertUnreachable(kUnexpectedReturnFromWasmTrap);
__ bind(&done);
}
__ sub(esp, Immediate(shrink_slots * kPointerSize));
}
......
......@@ -1545,6 +1545,17 @@ void MacroAssembler::CallRuntime(const Runtime::Function* f,
CallStub(&ces);
}
void TurboAssembler::CallRuntimeDelayed(Zone* zone, Runtime::FunctionId fid,
SaveFPRegsMode save_doubles) {
const Runtime::Function* f = Runtime::FunctionForId(fid);
// TODO(1236192): Most runtime routines don't need the number of
// arguments passed in because it is constant. At some point we
// should remove this need and make the runtime routine entry code
// smarter.
Move(eax, Immediate(f->nargs));
mov(ebx, Immediate(ExternalReference(f, isolate())));
CallStubDelayed(new (zone) CEntryStub(nullptr, 1, save_doubles));
}
void MacroAssembler::CallExternalReference(ExternalReference ref,
int num_arguments) {
......@@ -2297,6 +2308,10 @@ void TurboAssembler::Assert(Condition cc, BailoutReason reason) {
if (emit_debug_code()) Check(cc, reason);
}
void TurboAssembler::AssertUnreachable(BailoutReason reason) {
if (emit_debug_code()) Abort(reason);
}
void TurboAssembler::Check(Condition cc, BailoutReason reason) {
Label L;
j(cc, &L);
......
......@@ -91,6 +91,10 @@ class TurboAssembler : public Assembler {
// Use --debug_code to enable.
void Assert(Condition cc, BailoutReason reason);
// Like Assert(), but without condition.
// Use --debug_code to enable.
void AssertUnreachable(BailoutReason reason);
// Like Assert(), but always enabled.
void Check(Condition cc, BailoutReason reason);
......@@ -124,6 +128,9 @@ class TurboAssembler : public Assembler {
inline bool AllowThisStubCall(CodeStub* stub);
void CallStubDelayed(CodeStub* stub);
void CallRuntimeDelayed(Zone* zone, Runtime::FunctionId fid,
SaveFPRegsMode save_doubles = kDontSaveFPRegs);
// Jump the register contains a smi.
inline void JumpIfSmi(Register value, Label* smi_label,
Label::Distance distance = Label::kFar) {
......
......@@ -6,7 +6,7 @@
[ALWAYS, {
#TODO(ahaas): Add additional stack checks on mips.
# Issue 6318: Stack checks for functions with huge stack frames fail on x64 and ia32
'tests/skip-stack-guard-page': [PASS, ['arch == mipsel or arch == mips64el or arch == ia32 or ((arch == ppc or arch == ppc64 or arch == s390 or arch == s390x) and simulator_run)', SKIP]],
'tests/skip-stack-guard-page': [PASS, ['arch == mipsel or arch == mips64el or ((arch == ppc or arch == ppc64 or arch == s390 or arch == s390x) and simulator_run)', SKIP]],
}], # ALWAYS
['arch == mipsel or arch == mips64el or arch == mips or arch == mips64', {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment