[wasm][eh] Update catch_all encoding
'catch_all' and 'else' use distinct opcodes now. R=clemensb@chromium.org Bug: v8:8091 Change-Id: If07e46b9ea23068953db1765d10c7e3746d21d99 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2699258 Commit-Queue: Thibaud Michaud <thibaudm@chromium.org> Reviewed-by: Clemens Backes <clemensb@chromium.org> Cr-Commit-Position: refs/heads/master@{#72810}
This commit is contained in:
parent
54ef2044a2
commit
5d618f1f81
@ -1747,6 +1747,7 @@ class WasmDecoder : public Decoder {
|
||||
case kExprReturnCallRef:
|
||||
case kExprDrop:
|
||||
case kExprSelect:
|
||||
case kExprCatchAll:
|
||||
case kExprUnwind:
|
||||
return 1;
|
||||
case kExprSelectWithType: {
|
||||
@ -2073,6 +2074,7 @@ class WasmDecoder : public Decoder {
|
||||
case kExprElse:
|
||||
case kExprTry:
|
||||
case kExprCatch:
|
||||
case kExprCatchAll:
|
||||
case kExprDelegate:
|
||||
case kExprUnwind:
|
||||
case kExprRethrow:
|
||||
@ -2575,6 +2577,31 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
||||
return 1 + imm.length;
|
||||
}
|
||||
|
||||
DECODE(CatchAll) {
|
||||
CHECK_PROTOTYPE_OPCODE(eh);
|
||||
DCHECK(!control_.empty());
|
||||
Control* c = &control_.back();
|
||||
if (!VALIDATE(c->is_try())) {
|
||||
this->DecodeError("catch-all does not match a try");
|
||||
return 0;
|
||||
}
|
||||
if (!VALIDATE(!c->is_try_catchall())) {
|
||||
this->error("catch-all already present for try");
|
||||
return 0;
|
||||
}
|
||||
if (!VALIDATE(!c->is_try_unwind())) {
|
||||
this->error("cannot have catch-all after unwind");
|
||||
return 0;
|
||||
}
|
||||
FallThruTo(c);
|
||||
c->kind = kControlTryCatchAll;
|
||||
stack_end_ = stack_ + c->stack_depth;
|
||||
c->reachability = control_at(1)->innerReachability();
|
||||
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchAll, c);
|
||||
current_code_reachable_ = this->ok() && c->reachable();
|
||||
return 1;
|
||||
}
|
||||
|
||||
DECODE(Unwind) {
|
||||
CHECK_PROTOTYPE_OPCODE(eh);
|
||||
DCHECK(!control_.empty());
|
||||
@ -2692,15 +2719,13 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
||||
return 1 + imm.length;
|
||||
}
|
||||
|
||||
// Alias for "catch_all" if the current block is a try.
|
||||
DECODE(Else) {
|
||||
DCHECK(!control_.empty());
|
||||
Control* c = &control_.back();
|
||||
if (!VALIDATE(c->is_if() || c->is_try())) {
|
||||
this->DecodeError("else/catch_all does not match an if/try");
|
||||
if (!VALIDATE(c->is_if())) {
|
||||
this->DecodeError("else does not match an if");
|
||||
return 0;
|
||||
}
|
||||
if (c->is_if()) {
|
||||
if (!VALIDATE(c->is_onearmed_if())) {
|
||||
this->DecodeError("else already present for if");
|
||||
return 0;
|
||||
@ -2711,23 +2736,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
||||
if (c->reachable()) c->end_merge.reached = true;
|
||||
PushMergeValues(c, &c->start_merge);
|
||||
c->reachability = control_at(1)->innerReachability();
|
||||
} else {
|
||||
CHECK_PROTOTYPE_OPCODE(eh);
|
||||
DCHECK(c->is_try());
|
||||
if (!VALIDATE(!c->is_try_catchall())) {
|
||||
this->error("catch-all already present for try");
|
||||
return 0;
|
||||
}
|
||||
if (!VALIDATE(!c->is_try_unwind())) {
|
||||
this->error("cannot have a catch-all after unwind");
|
||||
return 0;
|
||||
}
|
||||
c->kind = kControlTryCatchAll;
|
||||
FallThruTo(c);
|
||||
stack_end_ = stack_ + c->stack_depth;
|
||||
c->reachability = control_at(1)->innerReachability();
|
||||
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchAll, c);
|
||||
}
|
||||
current_code_reachable_ = this->ok() && c->reachable();
|
||||
return 1;
|
||||
}
|
||||
@ -3329,6 +3337,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
|
||||
DECODE_IMPL(Try);
|
||||
DECODE_IMPL(Catch);
|
||||
DECODE_IMPL(Delegate);
|
||||
DECODE_IMPL(CatchAll);
|
||||
DECODE_IMPL(Unwind);
|
||||
DECODE_IMPL(BrOnNull);
|
||||
DECODE_IMPL(Let);
|
||||
|
@ -190,7 +190,8 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
|
||||
offset = 2;
|
||||
}
|
||||
if (line_numbers) line_numbers->push_back(i.position());
|
||||
if (opcode == kExprElse || opcode == kExprCatch || opcode == kExprUnwind) {
|
||||
if (opcode == kExprElse || opcode == kExprCatch ||
|
||||
opcode == kExprCatchAll || opcode == kExprUnwind) {
|
||||
control_depth--;
|
||||
}
|
||||
|
||||
@ -240,6 +241,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
|
||||
switch (opcode) {
|
||||
case kExprElse:
|
||||
case kExprCatch:
|
||||
case kExprCatchAll:
|
||||
case kExprUnwind:
|
||||
os << " @" << i.pc_offset();
|
||||
control_depth++;
|
||||
|
@ -188,6 +188,7 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
|
||||
CASE_OP(Delegate, "delegate")
|
||||
CASE_OP(Throw, "throw")
|
||||
CASE_OP(Rethrow, "rethrow")
|
||||
CASE_OP(CatchAll, "catch-all")
|
||||
CASE_OP(Unwind, "unwind")
|
||||
|
||||
// asm.js-only opcodes.
|
||||
|
@ -46,8 +46,9 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
|
||||
V(Return, 0x0f, _) \
|
||||
V(Let, 0x17, _ /* typed_funcref prototype */) \
|
||||
V(Delegate, 0x18, _ /* eh_prototype */) \
|
||||
V(CatchAll, 0x19, _ /* eh_prototype */) \
|
||||
V(BrOnNull, 0xd4, _ /* gc prototype */) \
|
||||
V(NopForTestingUnsupportedInLiftoff, 0x19, _)
|
||||
V(NopForTestingUnsupportedInLiftoff, 0x16, _)
|
||||
|
||||
// Constants, locals, globals, and calls.
|
||||
#define FOREACH_MISC_OPCODE(V) \
|
||||
|
@ -112,7 +112,7 @@ WASM_EXEC_TEST(TryCatchAllThrow) {
|
||||
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), WASM_THROW(except1)),
|
||||
WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(0), WASM_I32V(1)),
|
||||
WASM_THROW(except2))),
|
||||
kExprCatch, except1, WASM_STMTS(WASM_I32V(kResult0)), kExprElse,
|
||||
kExprCatch, except1, WASM_STMTS(WASM_I32V(kResult0)), kExprCatchAll,
|
||||
WASM_STMTS(WASM_I32V(kResult1)), kExprEnd);
|
||||
|
||||
if (execution_tier != TestExecutionTier::kInterpreter) {
|
||||
|
@ -825,11 +825,10 @@ class SideTable : public ZoneObject {
|
||||
break;
|
||||
}
|
||||
case kExprElse: {
|
||||
// Alias for catch_all if the current block is a try.
|
||||
Control* c = &control_stack.back();
|
||||
if (*c->pc == kExprIf) {
|
||||
copy_unreachable();
|
||||
TRACE("control @%u: Else\n", i.pc_offset());
|
||||
Control* c = &control_stack.back();
|
||||
DCHECK_EQ(*c->pc, kExprIf);
|
||||
copy_unreachable();
|
||||
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
|
||||
DCHECK_NOT_NULL(c->else_label);
|
||||
c->else_label->Bind(i.pc() + 1);
|
||||
@ -838,7 +837,11 @@ class SideTable : public ZoneObject {
|
||||
c->else_label = nullptr;
|
||||
DCHECK_IMPLIES(!unreachable,
|
||||
stack_height >= c->end_label->target_stack_height);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
case kExprCatchAll: {
|
||||
TRACE("control @%u: CatchAll\n", i.pc_offset());
|
||||
Control* c = &control_stack.back();
|
||||
DCHECK_EQ(*c->pc, kExprTry);
|
||||
if (!exception_stack.empty() &&
|
||||
exception_stack.back() == control_stack.size() - 1) {
|
||||
@ -846,7 +849,6 @@ class SideTable : public ZoneObject {
|
||||
exception_stack.pop_back();
|
||||
}
|
||||
copy_unreachable();
|
||||
TRACE("control @%u: CatchAll\n", i.pc_offset());
|
||||
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
|
||||
DCHECK_NOT_NULL(c->else_label);
|
||||
int control_index = static_cast<int>(control_stack.size()) - 1;
|
||||
@ -857,17 +859,16 @@ class SideTable : public ZoneObject {
|
||||
DCHECK_IMPLIES(!unreachable,
|
||||
stack_height >= c->end_label->target_stack_height);
|
||||
stack_height = c->end_label->target_stack_height;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kExprUnwind: {
|
||||
TRACE("control @%u: Unwind\n", i.pc_offset());
|
||||
Control* c = &control_stack.back();
|
||||
DCHECK_EQ(*c->pc, kExprTry);
|
||||
DCHECK(!exception_stack.empty());
|
||||
DCHECK_EQ(exception_stack.back(), control_stack.size() - 1);
|
||||
exception_stack.pop_back();
|
||||
copy_unreachable();
|
||||
TRACE("control @%u: Unwind\n", i.pc_offset());
|
||||
if (!unreachable) c->end_label->Ref(i.pc(), stack_height);
|
||||
DCHECK_NOT_NULL(c->else_label);
|
||||
int control_index = static_cast<int>(control_stack.size()) - 1;
|
||||
@ -3472,7 +3473,8 @@ class WasmInterpreterInternals {
|
||||
}
|
||||
case kExprElse:
|
||||
case kExprUnwind:
|
||||
case kExprCatch: {
|
||||
case kExprCatch:
|
||||
case kExprCatchAll: {
|
||||
len = LookupTargetDelta(code, pc);
|
||||
TRACE(" end => @%zu\n", pc + len);
|
||||
break;
|
||||
|
@ -190,7 +190,7 @@
|
||||
#define WASM_TRY_CATCH_R(t, trystmt, catchstmt) \
|
||||
kExprTry, WASM_REF_TYPE(t), trystmt, kExprCatch, catchstmt, kExprEnd
|
||||
#define WASM_TRY_CATCH_ALL_T(t, trystmt, catchstmt) \
|
||||
kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprElse, \
|
||||
kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprCatchAll, \
|
||||
catchstmt, kExprEnd
|
||||
#define WASM_TRY_DELEGATE(trystmt, depth) \
|
||||
kExprTry, kVoidCode, trystmt, kExprDelegate, depth
|
||||
|
@ -11,7 +11,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
|
||||
|
||||
// Create a simple Wasm module.
|
||||
function create_builder(i) {
|
||||
const kExprNopForTestingUnsupportedInLiftoff = 0x19;
|
||||
const kExprNopForTestingUnsupportedInLiftoff = 0x16;
|
||||
const builder = new WasmModuleBuilder();
|
||||
builder.addFunction('main', kSig_i_i)
|
||||
.addBody([
|
||||
|
@ -21,7 +21,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
|
||||
kExprCallFunction, f.index,
|
||||
kExprCallFunction, f.index,
|
||||
kExprLocalSet, 0,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprLocalGet, 0,
|
||||
kExprCallFunction, f.index,
|
||||
kExprLocalSet, 0,
|
||||
|
@ -49,7 +49,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
.addBody([
|
||||
kExprTry, kWasmStmt,
|
||||
kExprThrow, except,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprRethrow, 0,
|
||||
kExprEnd,
|
||||
]).exportFunc();
|
||||
@ -57,7 +57,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
.addBody([
|
||||
kExprTry, kWasmI32,
|
||||
kExprThrow, except,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprLocalGet, 0,
|
||||
kExprI32Eqz,
|
||||
kExprIf, kWasmStmt,
|
||||
|
@ -76,7 +76,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
.addBody([
|
||||
kExprTry, kWasmStmt,
|
||||
kExprUnreachable,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprEnd
|
||||
]).exportFunc();
|
||||
builder.addFunction('unreachable_in_try_unwind', kSig_v_v)
|
||||
@ -106,7 +106,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
kExprLocalGet, 0,
|
||||
kExprLocalGet, 1,
|
||||
kExprCallFunction, func_div.index,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprI32Const, 11,
|
||||
kExprEnd
|
||||
]).exportFunc();
|
||||
@ -141,7 +141,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
.addBody([
|
||||
kExprTry, kWasmI32,
|
||||
kExprCallFunction, imp,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprI32Const, 11,
|
||||
kExprEnd
|
||||
]).exportFunc();
|
||||
@ -197,7 +197,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
.addBody([
|
||||
kExprTry, kWasmI32,
|
||||
kExprCallFunction, imp,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprI32Const, 11,
|
||||
kExprEnd
|
||||
]).exportFunc();
|
||||
@ -1016,7 +1016,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
|
||||
kExprTry, kWasmStmt,
|
||||
kExprThrow, except,
|
||||
kExprDelegate, 1,
|
||||
kExprElse,
|
||||
kExprCatchAll,
|
||||
kExprEnd
|
||||
]).exportFunc();
|
||||
builder.addFunction('test_unwind', kSig_v_v)
|
||||
|
@ -216,6 +216,7 @@ const kWasmOpcodes = {
|
||||
'Catch': 0x07,
|
||||
'Throw': 0x08,
|
||||
'Rethrow': 0x09,
|
||||
'CatchAll': 0x19,
|
||||
'Unwind': 0x0a,
|
||||
'End': 0x0b,
|
||||
'Br': 0x0c,
|
||||
|
@ -2872,12 +2872,17 @@ TEST_F(FunctionBodyDecoderTest, TryCatch) {
|
||||
byte ex = builder.AddException(sigs.v_v());
|
||||
ExpectValidates(sigs.v_v(), {WASM_TRY_OP, kExprCatch, ex, kExprEnd});
|
||||
ExpectValidates(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprCatch, ex, kExprElse, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprElse, kExprCatch, ex, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprElse, kExprElse, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprEnd}); // Missing catch.
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprCatch, ex}); // Missing end.
|
||||
ExpectFailure(sigs.v_v(), {kExprCatch, kExprEnd}); // Missing try.
|
||||
{WASM_TRY_OP, kExprCatch, ex, kExprCatchAll, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprCatchAll, kExprCatch, ex, kExprEnd},
|
||||
kAppendEnd, "catch after catch-all for try");
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprCatchAll, kExprCatchAll, kExprEnd},
|
||||
kAppendEnd, "catch-all already present for try");
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprEnd}, kAppendEnd,
|
||||
"missing catch or catch-all in try");
|
||||
ExpectFailure(sigs.v_v(), {kExprCatch, ex, kExprEnd}, kAppendEnd,
|
||||
"catch does not match a try");
|
||||
}
|
||||
|
||||
TEST_F(FunctionBodyDecoderTest, TryUnwind) {
|
||||
@ -2885,16 +2890,20 @@ TEST_F(FunctionBodyDecoderTest, TryUnwind) {
|
||||
byte ex = builder.AddException(sigs.v_v());
|
||||
ExpectValidates(sigs.v_v(), {WASM_TRY_OP, kExprUnwind, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprUnwind, kExprCatch, ex, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprElse, kExprUnwind, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprCatch, ex, kExprUnwind, kExprEnd});
|
||||
{WASM_TRY_OP, kExprUnwind, kExprCatch, ex, kExprEnd},
|
||||
kAppendEnd, "catch after unwind for try");
|
||||
ExpectFailure(sigs.v_v(), {WASM_TRY_OP, kExprCatchAll, kExprUnwind, kExprEnd},
|
||||
kAppendEnd,
|
||||
"catch, catch-all or unwind already present for try");
|
||||
ExpectFailure(
|
||||
sigs.v_v(), {WASM_TRY_OP, kExprCatch, ex, kExprUnwind, kExprEnd},
|
||||
kAppendEnd, "catch, catch-all or unwind already present for try");
|
||||
}
|
||||
|
||||
TEST_F(FunctionBodyDecoderTest, Rethrow) {
|
||||
WASM_FEATURE_SCOPE(eh);
|
||||
ExpectValidates(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprElse, kExprRethrow, 0, kExprEnd});
|
||||
{WASM_TRY_OP, kExprCatchAll, kExprRethrow, 0, kExprEnd});
|
||||
ExpectFailure(sigs.v_v(),
|
||||
{WASM_TRY_OP, kExprRethrow, 0, kExprCatch, kExprEnd},
|
||||
kAppendEnd, "rethrow not targeting catch or catch-all");
|
||||
@ -2941,7 +2950,7 @@ TEST_F(FunctionBodyDecoderTest, TryDelegate) {
|
||||
kAppendEnd, "delegate does not match a try");
|
||||
ExpectFailure(
|
||||
sigs.v_v(),
|
||||
{WASM_TRY_OP, WASM_TRY_OP, kExprElse, kExprDelegate, 1, kExprEnd},
|
||||
{WASM_TRY_OP, WASM_TRY_OP, kExprCatchAll, kExprDelegate, 1, kExprEnd},
|
||||
kAppendEnd, "delegate does not match a try");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user