Commit ff2cf7da authored by Thibaud Michaud's avatar Thibaud Michaud Committed by V8 LUCI CQ

[wasm][eh] Remove unwind instruction

Relevant links:
https://github.com/WebAssembly/exception-handling/issues/153
https://github.com/WebAssembly/exception-handling/pull/156

R=clemensb@chromium.org

Bug: v8:8091
Change-Id: I0deeb9665c6648e643d0aa4f310b7676e1c2fa32
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2959624
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75135}
parent 659424f8
...@@ -1226,8 +1226,7 @@ class LiftoffCompiler { ...@@ -1226,8 +1226,7 @@ class LiftoffCompiler {
} }
void CatchAll(FullDecoder* decoder, Control* block) { void CatchAll(FullDecoder* decoder, Control* block) {
DCHECK(block->is_try_catchall() || block->is_try_catch() || DCHECK(block->is_try_catchall() || block->is_try_catch());
block->is_try_unwind());
DCHECK_EQ(decoder->control_at(0), block); DCHECK_EQ(decoder->control_at(0), block);
// The catch block is unreachable if no possible throws in the try block // The catch block is unreachable if no possible throws in the try block
...@@ -1333,7 +1332,7 @@ class LiftoffCompiler { ...@@ -1333,7 +1332,7 @@ class LiftoffCompiler {
} }
void FinishTry(FullDecoder* decoder, Control* c) { void FinishTry(FullDecoder* decoder, Control* c) {
DCHECK(c->is_try_catch() || c->is_try_catchall() || c->is_try_unwind()); DCHECK(c->is_try_catch() || c->is_try_catchall());
if (!c->end_merge.reached) { if (!c->end_merge.reached) {
if (c->try_info->catch_reached) { if (c->try_info->catch_reached) {
// Drop the implicit exception ref. // Drop the implicit exception ref.
...@@ -1357,8 +1356,7 @@ class LiftoffCompiler { ...@@ -1357,8 +1356,7 @@ class LiftoffCompiler {
if (c->is_onearmed_if()) { if (c->is_onearmed_if()) {
// Special handling for one-armed ifs. // Special handling for one-armed ifs.
FinishOneArmedIf(decoder, c); FinishOneArmedIf(decoder, c);
} else if (c->is_try_catch() || c->is_try_catchall() || } else if (c->is_try_catch() || c->is_try_catchall()) {
c->is_try_unwind()) {
FinishTry(decoder, c); FinishTry(decoder, c);
} else if (c->end_merge.reached) { } else if (c->end_merge.reached) {
// There is a merge already. Merge our state into that, then continue with // There is a merge already. Merge our state into that, then continue with
...@@ -3128,8 +3126,7 @@ class LiftoffCompiler { ...@@ -3128,8 +3126,7 @@ class LiftoffCompiler {
? next_control->stack_depth + __ num_locals() + ? next_control->stack_depth + __ num_locals() +
next_control->num_exceptions next_control->num_exceptions
: __ cache_state()->stack_height(); : __ cache_state()->stack_height();
bool exception = control->is_try_catch() || control->is_try_catchall() || bool exception = control->is_try_catch() || control->is_try_catchall();
control->is_try_unwind();
for (; index < end_index; ++index) { for (; index < end_index; ++index) {
auto& slot = stack_state[index]; auto& slot = stack_state[index];
auto& value = values[index]; auto& value = values[index];
......
...@@ -843,7 +843,6 @@ enum ControlKind : uint8_t { ...@@ -843,7 +843,6 @@ enum ControlKind : uint8_t {
kControlTry, kControlTry,
kControlTryCatch, kControlTryCatch,
kControlTryCatchAll, kControlTryCatchAll,
kControlTryUnwind
}; };
enum Reachability : uint8_t { enum Reachability : uint8_t {
...@@ -905,10 +904,8 @@ struct ControlBase : public PcForErrors<validate> { ...@@ -905,10 +904,8 @@ struct ControlBase : public PcForErrors<validate> {
bool is_incomplete_try() const { return kind == kControlTry; } bool is_incomplete_try() const { return kind == kControlTry; }
bool is_try_catch() const { return kind == kControlTryCatch; } bool is_try_catch() const { return kind == kControlTryCatch; }
bool is_try_catchall() const { return kind == kControlTryCatchAll; } bool is_try_catchall() const { return kind == kControlTryCatchAll; }
bool is_try_unwind() const { return kind == kControlTryUnwind; }
bool is_try() const { bool is_try() const {
return is_incomplete_try() || is_try_catch() || is_try_catchall() || return is_incomplete_try() || is_try_catch() || is_try_catchall();
is_try_unwind();
} }
Merge<Value>* br_merge() { Merge<Value>* br_merge() {
...@@ -1629,7 +1626,6 @@ class WasmDecoder : public Decoder { ...@@ -1629,7 +1626,6 @@ class WasmDecoder : public Decoder {
case kExprDrop: case kExprDrop:
case kExprSelect: case kExprSelect:
case kExprCatchAll: case kExprCatchAll:
case kExprUnwind:
return 1; return 1;
case kExprSelectWithType: { case kExprSelectWithType: {
SelectTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1, SelectTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
...@@ -1972,7 +1968,6 @@ class WasmDecoder : public Decoder { ...@@ -1972,7 +1968,6 @@ class WasmDecoder : public Decoder {
case kExprCatch: case kExprCatch:
case kExprCatchAll: case kExprCatchAll:
case kExprDelegate: case kExprDelegate:
case kExprUnwind:
case kExprRethrow: case kExprRethrow:
case kExprNop: case kExprNop:
case kExprNopForTestingUnsupportedInLiftoff: case kExprNopForTestingUnsupportedInLiftoff:
...@@ -2328,7 +2323,6 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2328,7 +2323,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
case kControlIfElse: case kControlIfElse:
case kControlTryCatch: case kControlTryCatch:
case kControlTryCatchAll: case kControlTryCatchAll:
case kControlTryUnwind:
case kControlLet: // TODO(7748): Implement case kControlLet: // TODO(7748): Implement
break; break;
} }
...@@ -2452,10 +2446,6 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2452,10 +2446,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
this->DecodeError("catch after catch-all for try"); this->DecodeError("catch after catch-all for try");
return 0; return 0;
} }
if (!VALIDATE(!c->is_try_unwind())) {
this->DecodeError("catch after unwind for try");
return 0;
}
FallThrough(); FallThrough();
c->kind = kControlTryCatch; c->kind = kControlTryCatch;
// TODO(jkummerow): Consider moving the stack manipulation after the // TODO(jkummerow): Consider moving the stack manipulation after the
...@@ -2492,8 +2482,7 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2492,8 +2482,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
"delegate target must be a try block or the function block"); "delegate target must be a try block or the function block");
return 0; return 0;
} }
if (target->is_try_catch() || target->is_try_catchall() || if (target->is_try_catch() || target->is_try_catchall()) {
target->is_try_unwind()) {
this->DecodeError( this->DecodeError(
"cannot delegate inside the catch handler of the target"); "cannot delegate inside the catch handler of the target");
return 0; return 0;
...@@ -2518,10 +2507,6 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2518,10 +2507,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
this->error("catch-all already present for try"); this->error("catch-all already present for try");
return 0; return 0;
} }
if (!VALIDATE(!c->is_try_unwind())) {
this->error("cannot have catch-all after unwind");
return 0;
}
FallThrough(); FallThrough();
c->kind = kControlTryCatchAll; c->kind = kControlTryCatchAll;
c->reachability = control_at(1)->innerReachability(); c->reachability = control_at(1)->innerReachability();
...@@ -2532,29 +2517,6 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2532,29 +2517,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
return 1; return 1;
} }
DECODE(Unwind) {
CHECK_PROTOTYPE_OPCODE(eh);
DCHECK(!control_.empty());
Control* c = &control_.back();
if (!VALIDATE(c->is_try())) {
this->DecodeError("unwind does not match a try");
return 0;
}
if (!VALIDATE(!c->is_try_catch() && !c->is_try_catchall() &&
!c->is_try_unwind())) {
this->error("catch, catch-all or unwind already present for try");
return 0;
}
FallThrough();
c->kind = kControlTryUnwind;
c->reachability = control_at(1)->innerReachability();
current_catch_ = c->previous_catch; // Pop try scope.
CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(CatchAll, c);
stack_end_ = stack_ + c->stack_depth;
current_code_reachable_and_ok_ = this->ok() && c->reachable();
return 1;
}
DECODE(BrOnNull) { DECODE(BrOnNull) {
CHECK_PROTOTYPE_OPCODE(typed_funcref); CHECK_PROTOTYPE_OPCODE(typed_funcref);
BranchDepthImmediate<validate> imm(this, this->pc_ + 1); BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
...@@ -2738,11 +2700,6 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -2738,11 +2700,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
if (c->is_onearmed_if()) { if (c->is_onearmed_if()) {
if (!VALIDATE(TypeCheckOneArmedIf(c))) return 0; if (!VALIDATE(TypeCheckOneArmedIf(c))) return 0;
} }
if (c->is_try_unwind()) {
// Unwind implicitly rethrows at the end.
CALL_INTERFACE_IF_OK_AND_REACHABLE(Rethrow, c);
EndControl();
}
if (c->is_let()) { if (c->is_let()) {
CALL_INTERFACE_IF_OK_AND_REACHABLE(DeallocateLocals, c->locals_count); CALL_INTERFACE_IF_OK_AND_REACHABLE(DeallocateLocals, c->locals_count);
...@@ -3344,7 +3301,6 @@ class WasmFullDecoder : public WasmDecoder<validate> { ...@@ -3344,7 +3301,6 @@ class WasmFullDecoder : public WasmDecoder<validate> {
DECODE_IMPL(Catch); DECODE_IMPL(Catch);
DECODE_IMPL(Delegate); DECODE_IMPL(Delegate);
DECODE_IMPL(CatchAll); DECODE_IMPL(CatchAll);
DECODE_IMPL(Unwind);
DECODE_IMPL(BrOnNull); DECODE_IMPL(BrOnNull);
DECODE_IMPL(BrOnNonNull); DECODE_IMPL(BrOnNonNull);
DECODE_IMPL(Let); DECODE_IMPL(Let);
......
...@@ -191,7 +191,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body, ...@@ -191,7 +191,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
} }
if (line_numbers) line_numbers->push_back(i.position()); if (line_numbers) line_numbers->push_back(i.position());
if (opcode == kExprElse || opcode == kExprCatch || if (opcode == kExprElse || opcode == kExprCatch ||
opcode == kExprCatchAll || opcode == kExprUnwind) { opcode == kExprCatchAll) {
control_depth--; control_depth--;
} }
...@@ -241,7 +241,6 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body, ...@@ -241,7 +241,6 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
case kExprElse: case kExprElse:
case kExprCatch: case kExprCatch:
case kExprCatchAll: case kExprCatchAll:
case kExprUnwind:
os << " @" << i.pc_offset(); os << " @" << i.pc_offset();
control_depth++; control_depth++;
break; break;
......
...@@ -721,8 +721,7 @@ class WasmGraphBuildingInterface { ...@@ -721,8 +721,7 @@ class WasmGraphBuildingInterface {
} }
void Rethrow(FullDecoder* decoder, Control* block) { void Rethrow(FullDecoder* decoder, Control* block) {
DCHECK(block->is_try_catchall() || block->is_try_catch() || DCHECK(block->is_try_catchall() || block->is_try_catch());
block->is_try_unwind());
TFNode* exception = block->try_info->exception; TFNode* exception = block->try_info->exception;
DCHECK_NOT_NULL(exception); DCHECK_NOT_NULL(exception);
CheckForException(decoder, builder_->Rethrow(exception)); CheckForException(decoder, builder_->Rethrow(exception));
...@@ -808,8 +807,7 @@ class WasmGraphBuildingInterface { ...@@ -808,8 +807,7 @@ class WasmGraphBuildingInterface {
} }
void CatchAll(FullDecoder* decoder, Control* block) { void CatchAll(FullDecoder* decoder, Control* block) {
DCHECK(block->is_try_catchall() || block->is_try_catch() || DCHECK(block->is_try_catchall() || block->is_try_catch());
block->is_try_unwind());
DCHECK_EQ(decoder->control_at(0), block); DCHECK_EQ(decoder->control_at(0), block);
// The catch block is unreachable if no possible throws in the try block // The catch block is unreachable if no possible throws in the try block
......
...@@ -197,7 +197,6 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) { ...@@ -197,7 +197,6 @@ constexpr const char* WasmOpcodes::OpcodeName(WasmOpcode opcode) {
CASE_OP(Throw, "throw") CASE_OP(Throw, "throw")
CASE_OP(Rethrow, "rethrow") CASE_OP(Rethrow, "rethrow")
CASE_OP(CatchAll, "catch-all") CASE_OP(CatchAll, "catch-all")
CASE_OP(Unwind, "unwind")
// asm.js-only opcodes. // asm.js-only opcodes.
CASE_F64_OP(Acos, "acos") CASE_F64_OP(Acos, "acos")
......
...@@ -42,7 +42,6 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig, ...@@ -42,7 +42,6 @@ bool V8_EXPORT_PRIVATE IsJSCompatibleSignature(const FunctionSig* sig,
V(Catch, 0x07, _ /* eh_prototype */) \ V(Catch, 0x07, _ /* eh_prototype */) \
V(Throw, 0x08, _ /* eh_prototype */) \ V(Throw, 0x08, _ /* eh_prototype */) \
V(Rethrow, 0x09, _ /* eh_prototype */) \ V(Rethrow, 0x09, _ /* eh_prototype */) \
V(Unwind, 0x0a, _ /* eh_prototype */) \
V(End, 0x0b, _) \ V(End, 0x0b, _) \
V(Br, 0x0c, _) \ V(Br, 0x0c, _) \
V(BrIf, 0x0d, _) \ V(BrIf, 0x0d, _) \
......
...@@ -211,43 +211,11 @@ WASM_EXEC_TEST(TryDelegate) { ...@@ -211,43 +211,11 @@ WASM_EXEC_TEST(TryDelegate) {
} }
} }
WASM_EXEC_TEST(TryUnwind) {
TestSignatures sigs;
EXPERIMENTAL_FLAG_SCOPE(eh);
WasmRunner<uint32_t, uint32_t> r(execution_tier);
byte except = r.builder().AddException(sigs.v_v());
constexpr uint32_t kResult0 = 23;
constexpr uint32_t kResult1 = 42;
// Build the main test function.
BUILD(r, WASM_TRY_CATCH_T(
kWasmI32,
WASM_TRY_UNWIND_T(
kWasmI32,
WASM_TRY_DELEGATE_T(
kWasmI32,
WASM_STMTS(WASM_I32V(kResult1),
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
WASM_THROW(except))),
0),
kExprNop),
WASM_I32V(kResult0), except));
if (execution_tier != TestExecutionTier::kInterpreter) {
// Need to call through JS to allow for creation of stack traces.
r.CheckCallViaJS(kResult0, 0);
r.CheckCallViaJS(kResult1, 1);
} else {
CHECK_EQ(kResult0, r.CallInterpreter(0));
CHECK_EQ(kResult1, r.CallInterpreter(1));
}
}
WASM_EXEC_TEST(TestCatchlessTry) { WASM_EXEC_TEST(TestCatchlessTry) {
TestSignatures sigs; TestSignatures sigs;
EXPERIMENTAL_FLAG_SCOPE(eh); EXPERIMENTAL_FLAG_SCOPE(eh);
WasmRunner<uint32_t> r(execution_tier); WasmRunner<uint32_t> r(execution_tier);
uint32_t except = r.builder().AddException(sigs.v_i()); byte except = r.builder().AddException(sigs.v_i());
BUILD(r, BUILD(r,
WASM_TRY_CATCH_T( WASM_TRY_CATCH_T(
kWasmI32, kWasmI32,
...@@ -706,17 +674,16 @@ TEST(Regress1186795) { ...@@ -706,17 +674,16 @@ TEST(Regress1186795) {
EXPERIMENTAL_FLAG_SCOPE(eh); EXPERIMENTAL_FLAG_SCOPE(eh);
WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter); WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter);
byte except = r.builder().AddException(sigs.v_i()); byte except = r.builder().AddException(sigs.v_i());
BUILD(r, WASM_TRY_CATCH_T( BUILD(r,
kWasmI32, WASM_TRY_CATCH_T(
WASM_STMTS( kWasmI32,
WASM_I32V(0), WASM_I32V(0), WASM_I32V(0), WASM_I32V(0), WASM_STMTS(WASM_I32V(0), WASM_I32V(0), WASM_I32V(0), 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( WASM_TRY_T(kWasmI32,
kWasmI32, WASM_STMTS(WASM_I32V(0), WASM_THROW(except)), 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_DROP, WASM_DROP, WASM_DROP, WASM_DROP, WASM_DROP),
WASM_DROP, WASM_DROP), WASM_NOP, except));
WASM_NOP, except));
CHECK_EQ(0, r.CallInterpreter()); CHECK_EQ(0, r.CallInterpreter());
} }
......
...@@ -690,9 +690,6 @@ class SideTable : public ZoneObject { ...@@ -690,9 +690,6 @@ class SideTable : public ZoneObject {
// Track whether this block was already left, i.e. all further // Track whether this block was already left, i.e. all further
// instructions are unreachable. // instructions are unreachable.
bool unreachable = false; bool unreachable = false;
// Whether this is a try...unwind...end block. Needed to handle the
// implicit rethrow when we reach the end of the block.
bool unwind = false;
Control(const byte* pc, CLabel* end_label, CLabel* else_label, Control(const byte* pc, CLabel* end_label, CLabel* else_label,
uint32_t exit_arity) uint32_t exit_arity)
...@@ -865,27 +862,6 @@ class SideTable : public ZoneObject { ...@@ -865,27 +862,6 @@ class SideTable : public ZoneObject {
stack_height = c->end_label->target_stack_height; stack_height = c->end_label->target_stack_height;
break; 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();
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;
c->else_label->Bind(i.pc() + 1, kCatchAllExceptionIndex,
control_index);
c->else_label->Finish(&map_, code->start);
c->else_label = nullptr;
c->unwind = true;
DCHECK_IMPLIES(!unreachable,
stack_height >= c->end_label->target_stack_height);
stack_height = c->end_label->target_stack_height;
break;
}
case kExprTry: { case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidation> imm( BlockTypeImmediate<Decoder::kNoValidation> imm(
WasmFeatures::All(), &i, i.pc() + 1, module); WasmFeatures::All(), &i, i.pc() + 1, module);
...@@ -968,13 +944,6 @@ class SideTable : public ZoneObject { ...@@ -968,13 +944,6 @@ class SideTable : public ZoneObject {
stack_height = c->else_label->target_stack_height; stack_height = c->else_label->target_stack_height;
rethrow = !unreachable; 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()) {
rethrow = !unreachable;
}
} }
c->end_label->Bind(i.pc() + 1); c->end_label->Bind(i.pc() + 1);
} }
...@@ -3415,7 +3384,6 @@ class WasmInterpreterInternals { ...@@ -3415,7 +3384,6 @@ class WasmInterpreterInternals {
break; break;
} }
case kExprElse: case kExprElse:
case kExprUnwind:
case kExprCatch: case kExprCatch:
case kExprCatchAll: { case kExprCatchAll: {
len = LookupTargetDelta(code, pc); len = LookupTargetDelta(code, pc);
...@@ -3512,19 +3480,6 @@ class WasmInterpreterInternals { ...@@ -3512,19 +3480,6 @@ class WasmInterpreterInternals {
break; break;
} }
case kExprEnd: { case kExprEnd: {
if (code->side_table->rethrow_map_.count(pc)) {
// Implicit rethrow after unwind.
HandleScope scope(isolate_);
DCHECK(!frames_.back().caught_exception_stack.is_null());
int index = code->side_table->rethrow_map_[pc];
Handle<Object> exception = handle(
frames_.back().caught_exception_stack->get(index), isolate_);
DCHECK(!exception->IsTheHole());
CommitPc(pc); // Needed for local unwinding.
if (!DoRethrowException(exception)) return;
ReloadFromFrameOnException(&decoder, &code, &pc, &limit);
continue; // Do not bump pc.
}
break; break;
} }
case kExprI32Const: { case kExprI32Const: {
......
...@@ -199,9 +199,6 @@ ...@@ -199,9 +199,6 @@
#define WASM_TRY_DELEGATE_T(t, trystmt, depth) \ #define WASM_TRY_DELEGATE_T(t, trystmt, depth) \
kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprDelegate, \ kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprDelegate, \
depth depth
#define WASM_TRY_UNWIND_T(t, trystmt, unwindstmt) \
kExprTry, static_cast<byte>((t).value_type_code()), trystmt, kExprUnwind, \
unwindstmt, kExprEnd
#define WASM_SELECT(tval, fval, cond) tval, fval, cond, kExprSelect #define WASM_SELECT(tval, fval, cond) tval, fval, cond, kExprSelect
#define WASM_SELECT_I(tval, fval, cond) \ #define WASM_SELECT_I(tval, fval, cond) \
......
...@@ -215,7 +215,6 @@ class WasmGenerator { ...@@ -215,7 +215,6 @@ class WasmGenerator {
// Allow one more target than there are enclosing try blocks, for delegating // Allow one more target than there are enclosing try blocks, for delegating
// to the caller. // to the caller.
uint8_t delegate_target = data->get<uint8_t>() % (try_blocks_.size() + 1); uint8_t delegate_target = data->get<uint8_t>() % (try_blocks_.size() + 1);
bool is_unwind = num_catch == 0 && !has_catch_all && !is_delegate;
Vector<const ValueType> return_type_vec = return_type.kind() == kVoid Vector<const ValueType> return_type_vec = return_type.kind() == kVoid
? Vector<ValueType>{} ? Vector<ValueType>{}
...@@ -249,10 +248,6 @@ class WasmGenerator { ...@@ -249,10 +248,6 @@ class WasmGenerator {
builder_->EmitWithU32V(kExprDelegate, delegate_depth); builder_->EmitWithU32V(kExprDelegate, delegate_depth);
} }
catch_blocks_.pop_back(); catch_blocks_.pop_back();
if (is_unwind) {
builder_->Emit(kExprUnwind);
Generate(return_type, data);
}
} }
template <ValueKind T> template <ValueKind T>
......
...@@ -79,17 +79,9 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -79,17 +79,9 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
kExprCatchAll, kExprCatchAll,
kExprEnd kExprEnd
]).exportFunc(); ]).exportFunc();
builder.addFunction('unreachable_in_try_unwind', kSig_v_v)
.addBody([
kExprTry, kWasmVoid,
kExprUnreachable,
kExprUnwind,
kExprEnd
]).exportFunc();
let instance = builder.instantiate(); let instance = builder.instantiate();
assertTraps(kTrapUnreachable, () => instance.exports.unreachable_in_try()); assertTraps(kTrapUnreachable, () => instance.exports.unreachable_in_try());
assertTraps(kTrapUnreachable, () => instance.exports.unreachable_in_try_unwind());
})(); })();
(function TestTrapInCalleeNotCaught() { (function TestTrapInCalleeNotCaught() {
...@@ -110,21 +102,10 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -110,21 +102,10 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
kExprI32Const, 11, kExprI32Const, 11,
kExprEnd kExprEnd
]).exportFunc(); ]).exportFunc();
builder.addFunction('trap_in_callee_unwind', kSig_i_ii)
.addBody([
kExprTry, kWasmI32,
kExprLocalGet, 0,
kExprLocalGet, 1,
kExprCallFunction, func_div.index,
kExprUnwind,
kExprI32Const, 11,
kExprEnd
]).exportFunc();
let instance = builder.instantiate(); let instance = builder.instantiate();
assertEquals(3, instance.exports.trap_in_callee(7, 2)); assertEquals(3, instance.exports.trap_in_callee(7, 2));
assertTraps(kTrapDivByZero, () => instance.exports.trap_in_callee(1, 0)); assertTraps(kTrapDivByZero, () => instance.exports.trap_in_callee(1, 0));
assertTraps(kTrapDivByZero, () => instance.exports.trap_in_callee_unwind(1, 0));
})(); })();
(function TestTrapViaJSNotCaught() { (function TestTrapViaJSNotCaught() {
...@@ -145,14 +126,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -145,14 +126,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
kExprI32Const, 11, kExprI32Const, 11,
kExprEnd kExprEnd
]).exportFunc(); ]).exportFunc();
builder.addFunction('call_import_unwind', kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprCallFunction, imp,
kExprUnwind,
kExprI32Const, 11,
kExprEnd
]).exportFunc();
let exception = undefined; let exception = undefined;
let instance; let instance;
function js_import() { function js_import() {
...@@ -175,18 +148,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -175,18 +148,6 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
assertSame(exception, caught); assertSame(exception, caught);
assertInstanceof(exception, WebAssembly.RuntimeError); assertInstanceof(exception, WebAssembly.RuntimeError);
assertEquals(exception.message, kTrapMsgs[kTrapDivByZero]); assertEquals(exception.message, kTrapMsgs[kTrapDivByZero]);
// Same test with unwind instead of catch_all.
caught = undefined;
try {
let res = instance.exports.call_import_unwind();
assertUnreachable('call_import_unwind should trap, but returned with ' + res);
} catch (e) {
caught = e;
}
assertSame(exception, caught);
assertInstanceof(exception, WebAssembly.RuntimeError);
assertEquals(exception.message, kTrapMsgs[kTrapDivByZero]);
})(); })();
(function TestManuallyThrownRuntimeErrorCaught() { (function TestManuallyThrownRuntimeErrorCaught() {
...@@ -201,21 +162,12 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -201,21 +162,12 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
kExprI32Const, 11, kExprI32Const, 11,
kExprEnd kExprEnd
]).exportFunc(); ]).exportFunc();
builder.addFunction('call_import_unwind', kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprCallFunction, imp,
kExprUnwind,
kExprI32Const, 11,
kExprEnd
]).exportFunc();
function throw_exc() { function throw_exc() {
throw new WebAssembly.RuntimeError('My user text'); throw new WebAssembly.RuntimeError('My user text');
} }
let instance = builder.instantiate({imp: {ort: throw_exc}}); let instance = builder.instantiate({imp: {ort: throw_exc}});
assertEquals(11, instance.exports.call_import()); assertEquals(11, instance.exports.call_import());
assertThrows(instance.exports.call_import_unwind, WebAssembly.RuntimeError, "My user text");
})(); })();
(function TestExnWithWasmProtoNotCaught() { (function TestExnWithWasmProtoNotCaught() {
...@@ -1041,18 +993,8 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -1041,18 +993,8 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
kExprCatchAll, kExprCatchAll,
kExprEnd kExprEnd
]).exportFunc(); ]).exportFunc();
builder.addFunction('test_unwind', kSig_v_v)
.addBody([
kExprTry, kWasmVoid,
kExprTry, kWasmVoid,
kExprThrow, except,
kExprDelegate, 1,
kExprUnwind,
kExprEnd
]).exportFunc();
instance = builder.instantiate(); instance = builder.instantiate();
assertTraps(WebAssembly.RuntimeError, () => instance.exports.test()); assertTraps(WebAssembly.RuntimeError, () => instance.exports.test());
assertTraps(WebAssembly.RuntimeError, () => instance.exports.test_unwind());
})(); })();
(function TestThrowBeforeUnreachable() { (function TestThrowBeforeUnreachable() {
......
...@@ -228,7 +228,6 @@ const kWasmOpcodes = { ...@@ -228,7 +228,6 @@ const kWasmOpcodes = {
'Throw': 0x08, 'Throw': 0x08,
'Rethrow': 0x09, 'Rethrow': 0x09,
'CatchAll': 0x19, 'CatchAll': 0x19,
'Unwind': 0x0a,
'End': 0x0b, 'End': 0x0b,
'Br': 0x0c, 'Br': 0x0c,
'BrIf': 0x0d, 'BrIf': 0x0d,
......
...@@ -2967,21 +2967,6 @@ TEST_F(FunctionBodyDecoderTest, TryCatch) { ...@@ -2967,21 +2967,6 @@ TEST_F(FunctionBodyDecoderTest, TryCatch) {
"catch does not match a try"); "catch does not match a try");
} }
TEST_F(FunctionBodyDecoderTest, TryUnwind) {
WASM_FEATURE_SCOPE(eh);
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},
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) { TEST_F(FunctionBodyDecoderTest, Rethrow) {
WASM_FEATURE_SCOPE(eh); WASM_FEATURE_SCOPE(eh);
ExpectValidates(sigs.v_v(), ExpectValidates(sigs.v_v(),
...@@ -2993,9 +2978,6 @@ TEST_F(FunctionBodyDecoderTest, Rethrow) { ...@@ -2993,9 +2978,6 @@ TEST_F(FunctionBodyDecoderTest, Rethrow) {
"rethrow not targeting catch or catch-all"); "rethrow not targeting catch or catch-all");
ExpectFailure(sigs.v_v(), {kExprRethrow, 0}, kAppendEnd, ExpectFailure(sigs.v_v(), {kExprRethrow, 0}, kAppendEnd,
"rethrow not targeting catch or catch-all"); "rethrow not targeting catch or catch-all");
ExpectFailure(sigs.v_v(),
{WASM_TRY_OP, kExprUnwind, kExprRethrow, 0, kExprEnd},
kAppendEnd, "rethrow not targeting catch or catch-all");
} }
TEST_F(FunctionBodyDecoderTest, TryDelegate) { TEST_F(FunctionBodyDecoderTest, TryDelegate) {
...@@ -3021,11 +3003,6 @@ TEST_F(FunctionBodyDecoderTest, TryDelegate) { ...@@ -3021,11 +3003,6 @@ TEST_F(FunctionBodyDecoderTest, TryDelegate) {
WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0), kExprEnd}, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0), kExprEnd},
kAppendEnd, kAppendEnd,
"cannot delegate inside the catch handler of the target"); "cannot delegate inside the catch handler of the target");
ExpectFailure(sigs.v_v(),
{WASM_TRY_OP, kExprUnwind,
WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0), kExprEnd},
kAppendEnd,
"cannot delegate inside the catch handler of the target");
ExpectFailure( ExpectFailure(
sigs.v_v(), sigs.v_v(),
{WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 3), {WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 3),
......
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