Commit f035b2f0 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

[wasm][interpreter] Fix max stack height for implicit rethrow

Take into account that the implicit rethrow at the end of a try block
might unpack the exception values, and reserve enough stack space for
them.
This is normally done for all throwing opcodes before the switch, but
'end' is not considered a throwing opcode, which is why it needs special
handling.

Also clean up by factorizing the rethrow logic.

R=ahaas@chromium.org

Bug: chromium:1186795
Change-Id: I6fde1b88085db95a9cab32c2c8e0ed1d28b64a32
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2783024Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73627}
parent ee138d10
......@@ -610,6 +610,25 @@ TEST(Regress1190291) {
r.CallInterpreter();
}
TEST(Regress1186795) {
TestSignatures sigs;
EXPERIMENTAL_FLAG_SCOPE(eh);
WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter);
uint32_t except = r.builder().AddException(sigs.v_i());
BUILD(r, WASM_TRY_CATCH_T(
kWasmI32,
WASM_STMTS(
WASM_I32V(0), WASM_I32V(0), WASM_I32V(0), WASM_I32V(0),
WASM_I32V(0), WASM_I32V(0), WASM_I32V(0),
WASM_TRY_UNWIND_T(
kWasmI32, WASM_STMTS(WASM_I32V(0), WASM_THROW(except)),
WASM_I32V(0)),
WASM_DROP, WASM_DROP, WASM_DROP, WASM_DROP, WASM_DROP,
WASM_DROP, WASM_DROP),
WASM_NOP, except));
CHECK_EQ(0, r.CallInterpreter());
}
} // namespace test_run_wasm_exceptions
} // namespace wasm
} // namespace internal
......
......@@ -946,6 +946,7 @@ class SideTable : public ZoneObject {
TRACE("control @%u: End\n", i.pc_offset());
// Only loops have bound labels.
DCHECK_IMPLIES(c->end_label->target, *c->pc == kExprLoop);
bool rethrow = false;
if (!c->end_label->target) {
if (c->else_label) {
if (*c->pc == kExprIf) {
......@@ -954,30 +955,34 @@ class SideTable : public ZoneObject {
} else if (!exception_stack.empty()) {
// No catch_all block, prepare for implicit rethrow.
DCHECK_EQ(*c->pc, kExprTry);
Control* next_try_block =
&control_stack[exception_stack.back()];
constexpr int kUnusedControlIndex = -1;
c->else_label->Bind(i.pc(), kRethrowOrDelegateExceptionIndex,
kUnusedControlIndex);
if (!unreachable) {
next_try_block->else_label->Ref(
i.pc(), c->else_label->target_stack_height);
}
DCHECK_IMPLIES(
!unreachable,
stack_height >= c->else_label->target_stack_height);
stack_height = c->else_label->target_stack_height;
rethrow = !unreachable;
}
} else if (c->unwind) {
DCHECK_EQ(*c->pc, kExprTry);
rethrow_map_.emplace(i.pc() - i.start(),
static_cast<int>(control_stack.size()) - 1);
if (!exception_stack.empty()) {
Control* next_try_block =
&control_stack[exception_stack.back()];
if (!unreachable) {
next_try_block->else_label->Ref(i.pc(), stack_height);
}
rethrow = !unreachable;
}
}
c->end_label->Bind(i.pc() + 1);
}
if (rethrow) {
Control* next_try_block = &control_stack[exception_stack.back()];
next_try_block->else_label->Ref(i.pc(), stack_height);
// We normally update the max stack height before the switch.
// However 'end' is not in the list of throwing opcodes so we don't
// take into account that it may unpack an exception.
max_stack_height_ =
std::max(max_stack_height_, stack_height + max_exception_arity);
}
c->Finish(&map_, code->start);
DCHECK_IMPLIES(!unreachable,
......
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