Skip to content

Commit e33c13c

Browse files
thibaudmichaudCommit Bot
authored andcommitted
[wasm][eh] Revert to catch with tag immediate
First step towards the new exception handling proposal: WebAssembly/exception-handling#125 This is essentially a revert of: "[wasm] Switch to new 'catch' and 'br_on_exn' proposal." The changes are: - "catch" instruction takes a tag immediate, - "rethrow" instruction takes a label immediate, - Add "catch_all" instruction, - Remove "br_on_exn" instruction, - Do not push exceptions on the stack, only the encoded values [email protected] CC=​[email protected] Bug: v8:8091 Change-Id: Iea4d8d5a5d3ad50693f645e93c13e8de117aa884 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2484514 Commit-Queue: Thibaud Michaud <[email protected]> Reviewed-by: Clemens Backes <[email protected]> Cr-Commit-Position: refs/heads/master@{#71602}
1 parent 1096cbf commit e33c13c

26 files changed

+296
-712
lines changed

src/builtins/base.tq

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,6 @@ extern enum MessageTemplate {
332332
kWasmTrapDataSegmentDropped,
333333
kWasmTrapElemSegmentDropped,
334334
kWasmTrapTableOutOfBounds,
335-
kWasmTrapBrOnExnNull,
336335
kWasmTrapRethrowNull,
337336
kWasmTrapNullDereference,
338337
kWasmTrapIllegalCast,

src/builtins/wasm.tq

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -392,10 +392,6 @@ builtin ThrowWasmTrapTableOutOfBounds(): JSAny {
392392
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapTableOutOfBounds));
393393
}
394394

395-
builtin ThrowWasmTrapBrOnExnNull(): JSAny {
396-
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapBrOnExnNull));
397-
}
398-
399395
builtin ThrowWasmTrapRethrowNull(): JSAny {
400396
tail WasmTrap(SmiConstant(MessageTemplate::kWasmTrapRethrowNull));
401397
}

src/common/globals.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1644,7 +1644,6 @@ enum class LoadSensitivity {
16441644
V(TrapDataSegmentDropped) \
16451645
V(TrapElemSegmentDropped) \
16461646
V(TrapTableOutOfBounds) \
1647-
V(TrapBrOnExnNull) \
16481647
V(TrapRethrowNull) \
16491648
V(TrapNullDereference) \
16501649
V(TrapIllegalCast) \

src/common/message-template.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,6 @@ namespace internal {
564564
T(WasmTrapJSTypeError, "type incompatibility when transforming from/to JS") \
565565
T(WasmTrapDataSegmentDropped, "data segment has been dropped") \
566566
T(WasmTrapElemSegmentDropped, "element segment has been dropped") \
567-
T(WasmTrapBrOnExnNull, "br_on_exn on null value") \
568567
T(WasmTrapRethrowNull, "rethrowing null value") \
569568
T(WasmTrapNullDereference, "dereferencing a null pointer") \
570569
T(WasmTrapIllegalCast, "illegal cast") \

src/compiler/wasm-compiler.cc

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,10 +2394,7 @@ Node* WasmGraphBuilder::LoadExceptionTagFromTable(uint32_t exception_index) {
23942394
return tag;
23952395
}
23962396

2397-
Node* WasmGraphBuilder::GetExceptionTag(Node* except_obj,
2398-
wasm::WasmCodePosition position) {
2399-
TrapIfTrue(wasm::kTrapBrOnExnNull, gasm_->WordEqual(RefNull(), except_obj),
2400-
position);
2397+
Node* WasmGraphBuilder::GetExceptionTag(Node* except_obj) {
24012398
return CALL_BUILTIN(
24022399
WasmGetOwnProperty, except_obj,
24032400
LOAD_FULL_POINTER(

src/compiler/wasm-compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ class WasmGraphBuilder {
221221
Node* Rethrow(Node* except_obj);
222222
Node* ExceptionTagEqual(Node* caught_tag, Node* expected_tag);
223223
Node* LoadExceptionTagFromTable(uint32_t exception_index);
224-
Node* GetExceptionTag(Node* except_obj, wasm::WasmCodePosition);
224+
Node* GetExceptionTag(Node* except_obj);
225225
Node* GetExceptionValues(Node* except_obj,
226226
const wasm::WasmException* exception,
227227
Vector<Node*> values_out);

src/wasm/baseline/liftoff-compiler.cc

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -935,10 +935,20 @@ class LiftoffCompiler {
935935
unsupported(decoder, kExceptionHandling, "try");
936936
}
937937

938-
void Catch(FullDecoder* decoder, Control* block, Value* exception) {
938+
void CatchException(FullDecoder* decoder,
939+
const ExceptionIndexImmediate<validate>& imm,
940+
Control* block, Vector<Value> values) {
939941
unsupported(decoder, kExceptionHandling, "catch");
940942
}
941943

944+
void Rethrow(FullDecoder* decoder, Control* block) {
945+
unsupported(decoder, kExceptionHandling, "rethrow");
946+
}
947+
948+
void CatchAll(FullDecoder* decoder, Control* block) {
949+
unsupported(decoder, kExceptionHandling, "catch-all");
950+
}
951+
942952
void If(FullDecoder* decoder, const Value& cond, Control* if_block) {
943953
DCHECK_EQ(if_block, decoder->control_at(0));
944954
DCHECK(if_block->is_if());
@@ -3142,12 +3152,6 @@ class LiftoffCompiler {
31423152
void Rethrow(FullDecoder* decoder, const Value& exception) {
31433153
unsupported(decoder, kExceptionHandling, "rethrow");
31443154
}
3145-
void BrOnException(FullDecoder* decoder, const Value& exception,
3146-
const ExceptionIndexImmediate<validate>& imm,
3147-
uint32_t depth, Vector<Value> values) {
3148-
unsupported(decoder, kExceptionHandling, "br_on_exn");
3149-
}
3150-
31513155
void AtomicStoreMem(FullDecoder* decoder, StoreType type,
31523156
const MemoryAccessImmediate<validate>& imm) {
31533157
LiftoffRegList pinned;

src/wasm/function-body-decoder-impl.h

Lines changed: 67 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -894,7 +894,8 @@ enum ControlKind : uint8_t {
894894
kControlLoop,
895895
kControlLet,
896896
kControlTry,
897-
kControlTryCatch
897+
kControlTryCatch,
898+
kControlTryCatchAll
898899
};
899900

900901
enum Reachability : uint8_t {
@@ -953,7 +954,10 @@ struct ControlBase : public PcForErrors<validate> {
953954
bool is_loop() const { return kind == kControlLoop; }
954955
bool is_incomplete_try() const { return kind == kControlTry; }
955956
bool is_try_catch() const { return kind == kControlTryCatch; }
956-
bool is_try() const { return is_incomplete_try() || is_try_catch(); }
957+
bool is_try_catchall() const { return kind == kControlTryCatchAll; }
958+
bool is_try() const {
959+
return is_incomplete_try() || is_try_catch() || is_try_catchall();
960+
}
957961

958962
inline Merge<Value>* br_merge() {
959963
return is_loop() ? &this->start_merge : &this->end_merge;
@@ -974,7 +978,6 @@ struct ControlBase : public PcForErrors<validate> {
974978
F(Block, Control* block) \
975979
F(Loop, Control* block) \
976980
F(Try, Control* block) \
977-
F(Catch, Control* block, Value* exception) \
978981
F(If, const Value& cond, Control* if_block) \
979982
F(FallThruTo, Control* c) \
980983
F(PopControl, Control* block) \
@@ -1049,10 +1052,10 @@ struct ControlBase : public PcForErrors<validate> {
10491052
const Value& input0, const Value& input1, Value* result) \
10501053
F(Throw, const ExceptionIndexImmediate<validate>& imm, \
10511054
const Vector<Value>& args) \
1052-
F(Rethrow, const Value& exception) \
1053-
F(BrOnException, const Value& exception, \
1054-
const ExceptionIndexImmediate<validate>& imm, uint32_t depth, \
1055-
Vector<Value> values) \
1055+
F(Rethrow, Control* block) \
1056+
F(CatchException, const ExceptionIndexImmediate<validate>& imm, \
1057+
Control* block, Vector<Value> caught_values) \
1058+
F(CatchAll, Control* block) \
10561059
F(AtomicOp, WasmOpcode opcode, Vector<Value> args, \
10571060
const MemoryAccessImmediate<validate>& imm, Value* result) \
10581061
F(AtomicFence) \
@@ -1631,6 +1634,7 @@ class WasmDecoder : public Decoder {
16311634
nullptr);
16321635
return 1 + imm.length;
16331636
}
1637+
case kExprRethrow:
16341638
case kExprBr:
16351639
case kExprBrIf:
16361640
case kExprBrOnNull: {
@@ -1642,17 +1646,11 @@ class WasmDecoder : public Decoder {
16421646
BranchTableIterator<validate> iterator(decoder, imm);
16431647
return 1 + iterator.length();
16441648
}
1645-
case kExprThrow: {
1649+
case kExprThrow:
1650+
case kExprCatch: {
16461651
ExceptionIndexImmediate<validate> imm(decoder, pc + 1);
16471652
return 1 + imm.length;
16481653
}
1649-
case kExprCatch:
1650-
case kExprRethrow:
1651-
return 1;
1652-
case kExprBrOnExn: {
1653-
BranchOnExceptionImmediate<validate> imm(decoder, pc + 1);
1654-
return 1 + imm.length;
1655-
}
16561654
case kExprLet: {
16571655
BlockTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
16581656
nullptr);
@@ -1678,12 +1676,14 @@ class WasmDecoder : public Decoder {
16781676
case kExprReturnCallRef:
16791677
case kExprDrop:
16801678
case kExprSelect:
1679+
case kExprCatchAll:
16811680
return 1;
16821681
case kExprSelectWithType: {
16831682
SelectTypeImmediate<validate> imm(WasmFeatures::All(), decoder, pc + 1,
16841683
nullptr);
16851684
return 1 + imm.length;
16861685
}
1686+
16871687
case kExprLocalGet:
16881688
case kExprLocalSet:
16891689
case kExprLocalTee: {
@@ -2016,7 +2016,6 @@ class WasmDecoder : public Decoder {
20162016
case kExprElse:
20172017
case kExprTry:
20182018
case kExprCatch:
2019-
case kExprBrOnExn:
20202019
case kExprNop:
20212020
case kExprReturn:
20222021
case kExprReturnCall:
@@ -2344,6 +2343,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
23442343
break;
23452344
case kControlIfElse:
23462345
case kControlTryCatch:
2346+
case kControlTryCatchAll:
23472347
case kControlLet: // TODO(7748): Implement
23482348
break;
23492349
}
@@ -2404,10 +2404,16 @@ class WasmFullDecoder : public WasmDecoder<validate> {
24042404

24052405
DECODE(Rethrow) {
24062406
CHECK_PROTOTYPE_OPCODE(eh);
2407-
Value exception = Pop(0, kWasmExnRef);
2408-
CALL_INTERFACE_IF_REACHABLE(Rethrow, exception);
2407+
BranchDepthImmediate<validate> imm(this, this->pc_ + 1);
2408+
if (!this->Validate(this->pc_ + 1, imm, control_.size())) return 0;
2409+
Control* c = control_at(imm.depth);
2410+
if (!VALIDATE(c->is_try_catchall() || c->is_try_catch())) {
2411+
this->error("rethrow not targeting catch or catch-all");
2412+
return 0;
2413+
}
2414+
CALL_INTERFACE_IF_REACHABLE(Rethrow, c);
24092415
EndControl();
2410-
return 1;
2416+
return 1 + imm.length;
24112417
}
24122418

24132419
DECODE(Throw) {
@@ -2435,6 +2441,8 @@ class WasmFullDecoder : public WasmDecoder<validate> {
24352441

24362442
DECODE(Catch) {
24372443
CHECK_PROTOTYPE_OPCODE(eh);
2444+
ExceptionIndexImmediate<validate> imm(this, this->pc_ + 1);
2445+
if (!this->Validate(this->pc_ + 1, imm)) return 0;
24382446
if (!VALIDATE(!control_.empty())) {
24392447
this->DecodeError("catch does not match any try");
24402448
return 0;
@@ -2444,46 +2452,46 @@ class WasmFullDecoder : public WasmDecoder<validate> {
24442452
this->DecodeError("catch does not match any try");
24452453
return 0;
24462454
}
2447-
if (!VALIDATE(c->is_incomplete_try())) {
2448-
this->DecodeError("catch already present for try");
2455+
if (!VALIDATE(!c->is_try_catchall())) {
2456+
this->DecodeError("catch after catch-all for try");
24492457
return 0;
24502458
}
24512459
c->kind = kControlTryCatch;
24522460
FallThruTo(c);
24532461
DCHECK_LE(stack_ + c->stack_depth, stack_end_);
24542462
stack_end_ = stack_ + c->stack_depth;
24552463
c->reachability = control_at(1)->innerReachability();
2464+
const WasmExceptionSig* sig = imm.exception->sig;
2465+
for (size_t i = 0, e = sig->parameter_count(); i < e; ++i) {
2466+
Push(sig->GetParam(i));
2467+
}
2468+
Vector<Value> values(stack_ + c->stack_depth, sig->parameter_count());
2469+
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchException, imm, c, values);
24562470
current_code_reachable_ = this->ok() && c->reachable();
2457-
Value* exception = Push(kWasmExnRef);
2458-
CALL_INTERFACE_IF_PARENT_REACHABLE(Catch, c, exception);
2459-
return 1;
2471+
return 1 + imm.length;
24602472
}
24612473

2462-
DECODE(BrOnExn) {
2463-
CHECK_PROTOTYPE_OPCODE(eh);
2464-
BranchOnExceptionImmediate<validate> imm(this, this->pc_ + 1);
2465-
if (!this->Validate(this->pc() + 1, imm, control_.size())) return 0;
2466-
Control* c = control_at(imm.depth.depth);
2467-
Value exception = Pop(0, kWasmExnRef);
2468-
const WasmExceptionSig* sig = imm.index.exception->sig;
2469-
int value_count = static_cast<int>(sig->parameter_count());
2470-
// TODO(wasm): This operand stack mutation is an ugly hack to make
2471-
// both type checking here as well as environment merging in the
2472-
// graph builder interface work out of the box. We should introduce
2473-
// special handling for both and do minimal/no stack mutation here.
2474-
EnsureStackSpace(value_count);
2475-
for (int i = 0; i < value_count; ++i) Push(sig->GetParam(i));
2476-
Vector<Value> values(stack_ + c->stack_depth, value_count);
2477-
TypeCheckBranchResult check_result = TypeCheckBranch(c, true);
2478-
if (V8_LIKELY(check_result == kReachableBranch)) {
2479-
CALL_INTERFACE_IF_REACHABLE(BrOnException, exception, imm.index,
2480-
imm.depth.depth, values);
2481-
c->br_merge()->reached = true;
2474+
DECODE(CatchAll) {
2475+
if (!VALIDATE(!control_.empty())) {
2476+
this->error("catch-all does not match any try");
2477+
return 0;
24822478
}
2483-
for (int i = value_count - 1; i >= 0; i--) Pop(i);
2484-
Value* pexception = Push(kWasmExnRef);
2485-
*pexception = exception;
2486-
return 1 + imm.length;
2479+
Control* c = &control_.back();
2480+
if (!VALIDATE(c->is_try())) {
2481+
this->error("catch-all does not match any try");
2482+
return 0;
2483+
}
2484+
if (!VALIDATE(!c->is_try_catchall())) {
2485+
this->error("catch-all already present for try");
2486+
return 0;
2487+
}
2488+
c->kind = kControlTryCatchAll;
2489+
FallThruTo(c);
2490+
stack_end_ = stack_ + c->stack_depth;
2491+
c->reachability = control_at(1)->innerReachability();
2492+
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchAll, c);
2493+
current_code_reachable_ = this->ok() && c->reachable();
2494+
return 1;
24872495
}
24882496

24892497
DECODE(BrOnNull) {
@@ -2623,6 +2631,16 @@ class WasmFullDecoder : public WasmDecoder<validate> {
26232631
}
26242632
if (!TypeCheckOneArmedIf(c)) return 0;
26252633
}
2634+
if (c->is_try_catch()) {
2635+
// Emulate catch-all + re-throw.
2636+
FallThruTo(c);
2637+
c->reachability = control_at(1)->innerReachability();
2638+
CALL_INTERFACE_IF_PARENT_REACHABLE(CatchAll, c);
2639+
current_code_reachable_ = this->ok() && control_.back().reachable();
2640+
CALL_INTERFACE_IF_REACHABLE(Rethrow, c);
2641+
EndControl();
2642+
}
2643+
26262644
if (c->is_let()) {
26272645
this->local_types_.erase(this->local_types_.begin(),
26282646
this->local_types_.begin() + c->locals_count);
@@ -3197,7 +3215,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
31973215
DECODE_IMPL(Throw);
31983216
DECODE_IMPL(Try);
31993217
DECODE_IMPL(Catch);
3200-
DECODE_IMPL(BrOnExn);
3218+
DECODE_IMPL(CatchAll);
32013219
DECODE_IMPL(BrOnNull);
32023220
DECODE_IMPL(Let);
32033221
DECODE_IMPL(Loop);

src/wasm/function-body-decoder.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
187187
offset = 2;
188188
}
189189
if (line_numbers) line_numbers->push_back(i.position());
190-
if (opcode == kExprElse || opcode == kExprCatch) {
190+
if (opcode == kExprElse || opcode == kExprCatch ||
191+
opcode == kExprCatchAll) {
191192
control_depth--;
192193
}
193194

@@ -237,6 +238,7 @@ bool PrintRawWasmCode(AccountingAllocator* allocator, const FunctionBody& body,
237238
switch (opcode) {
238239
case kExprElse:
239240
case kExprCatch:
241+
case kExprCatchAll:
240242
os << " @" << i.pc_offset();
241243
control_depth++;
242244
break;

0 commit comments

Comments
 (0)