Commit 9f01d5c1 authored by ahaas's avatar ahaas Committed by Commit bot

[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.

R=mstarzinger@chromium.org, v8-arm-ports@googlegroups.com

Review-Url: https://codereview.chromium.org/2763593002
Cr-Commit-Position: refs/heads/master@{#44065}
parent 03179ab3
...@@ -2409,6 +2409,47 @@ void CodeGenerator::AssembleConstructFrame() { ...@@ -2409,6 +2409,47 @@ void CodeGenerator::AssembleConstructFrame() {
const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); const RegList saves_fp = descriptor->CalleeSavedFPRegisters();
if (shrink_slots > 0) { if (shrink_slots > 0) {
if (info()->IsWasm()) {
if (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) {
__ Move(kScratchReg,
Operand(ExternalReference::address_of_real_stack_limit(
isolate())));
__ ldr(kScratchReg, MemOperand(kScratchReg));
__ add(kScratchReg, kScratchReg,
Operand(shrink_slots * kPointerSize));
__ cmp(sp, kScratchReg);
__ b(cs, &done);
}
if (!frame_access_state()->has_frame()) {
__ set_has_frame(true);
// There is no need to leave the frame, we will not return from the
// runtime call.
__ EnterFrame(StackFrame::WASM_COMPILED);
}
__ Move(cp, Smi::kZero);
__ CallRuntime(Runtime::kThrowWasmStackOverflow);
// We come from WebAssembly, there are no references for the GC.
ReferenceMap* reference_map = new (zone()) ReferenceMap(zone());
RecordSafepoint(reference_map, Safepoint::kSimple, 0,
Safepoint::kNoLazyDeopt);
if (FLAG_debug_code) {
__ stop(GetBailoutReason(kUnexpectedReturnFromThrow));
}
__ bind(&done);
}
}
__ sub(sp, sp, Operand(shrink_slots * kPointerSize)); __ sub(sp, sp, Operand(shrink_slots * kPointerSize));
} }
......
...@@ -136,6 +136,14 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) { ...@@ -136,6 +136,14 @@ RUNTIME_FUNCTION(Runtime_ThrowWasmError) {
return ThrowRuntimeError(isolate, message_id, byte_offset, true); return ThrowRuntimeError(isolate, message_id, byte_offset, true);
} }
RUNTIME_FUNCTION(Runtime_ThrowWasmStackOverflow) {
SealHandleScope shs(isolate);
DCHECK_LE(0, args.length());
DCHECK_NULL(isolate->context());
isolate->set_context(GetWasmContextOnStackTop(isolate));
return isolate->StackOverflow();
}
RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) { RUNTIME_FUNCTION(Runtime_WasmThrowTypeError) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(0, args.length()); DCHECK_EQ(0, args.length());
......
...@@ -636,6 +636,7 @@ namespace internal { ...@@ -636,6 +636,7 @@ namespace internal {
F(WasmMemorySize, 0, 1) \ F(WasmMemorySize, 0, 1) \
F(ThrowWasmError, 2, 1) \ F(ThrowWasmError, 2, 1) \
F(ThrowWasmErrorFromTrapIf, 1, 1) \ F(ThrowWasmErrorFromTrapIf, 1, 1) \
F(ThrowWasmStackOverflow, 0, 1) \
F(WasmThrowTypeError, 0, 1) \ F(WasmThrowTypeError, 0, 1) \
F(WasmThrow, 2, 1) \ F(WasmThrow, 2, 1) \
F(WasmGetCaughtExceptionValue, 1, 1) \ F(WasmGetCaughtExceptionValue, 1, 1) \
......
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