[wasm][interpreter] Fix multi-value stack height issue

Unreachable code may consume values from an empty stack as needed, known
as stack polymorphism. After consuming the values, the stack height
should still be 0, which was incorrectly handled by multi-value blocks.

R=ahaas@chromium.org

Bug: chromium:1085507
Change-Id: Ibf5f2d05bec0fbe029cfa66ee2d07540a370934a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2218033
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#68070}
This commit is contained in:
Thibaud Michaud 2020-05-29 10:44:32 +02:00 committed by Commit Bot
parent 69529052ec
commit 67805eab46
2 changed files with 27 additions and 7 deletions

View File

@ -655,9 +655,9 @@ class SideTable : public ZoneObject {
// Represents a control flow label.
class CLabel : public ZoneObject {
explicit CLabel(Zone* zone, int32_t target_stack_height, uint32_t arity)
: target_stack_height(target_stack_height),
arity(arity),
refs(zone) {}
: target_stack_height(target_stack_height), arity(arity), refs(zone) {
DCHECK_LE(0, target_stack_height);
}
public:
struct Ref {
@ -803,8 +803,14 @@ class SideTable : public ZoneObject {
}
TRACE("control @%u: %s, arity %d->%d\n", i.pc_offset(),
is_loop ? "Loop" : "Block", imm.in_arity(), imm.out_arity());
DCHECK_IMPLIES(!unreachable,
stack_height >= static_cast<int32_t>(imm.in_arity()));
int32_t target_stack_height = stack_height - imm.in_arity();
// The stack may underflow in unreachable code. In this case the
// stack height is clamped at 0.
if (V8_UNLIKELY(target_stack_height < 0)) target_stack_height = 0;
CLabel* label =
CLabel::New(&control_transfer_zone, stack_height - imm.in_arity(),
CLabel::New(&control_transfer_zone, target_stack_height,
is_loop ? imm.in_arity() : imm.out_arity());
control_stack.emplace_back(i.pc(), label, imm.out_arity());
copy_unreachable();
@ -819,9 +825,14 @@ class SideTable : public ZoneObject {
}
TRACE("control @%u: If, arity %d->%d\n", i.pc_offset(),
imm.in_arity(), imm.out_arity());
CLabel* end_label =
CLabel::New(&control_transfer_zone, stack_height - imm.in_arity(),
imm.out_arity());
DCHECK_IMPLIES(!unreachable,
stack_height >= static_cast<int32_t>(imm.in_arity()));
int32_t target_stack_height = stack_height - imm.in_arity();
// The stack may underflow in unreachable code. In this case the
// stack height is clamped at 0.
if (V8_UNLIKELY(target_stack_height < 0)) target_stack_height = 0;
CLabel* end_label = CLabel::New(&control_transfer_zone,
target_stack_height, imm.out_arity());
CLabel* else_label =
CLabel::New(&control_transfer_zone, stack_height, 0);
control_stack.emplace_back(i.pc(), end_label, else_label,

View File

@ -3762,6 +3762,15 @@ TEST(Liftoff_tier_up) {
}
}
TEST(Regression_1085507) {
EXPERIMENTAL_FLAG_SCOPE(mv);
WasmRunner<int32_t> r(ExecutionTier::kInterpreter);
TestSignatures sigs;
uint32_t sig_v_i = r.builder().AddSignature(sigs.v_i());
BUILD(r, WASM_I32V_1(0), kExprIf, kLocalVoid, WASM_UNREACHABLE,
WASM_BLOCK_X(sig_v_i, kExprDrop), kExprElse, kExprEnd, WASM_I32V_1(0));
}
#undef B1
#undef B2
#undef RET