Skip to content

Commit

Permalink
[wasm][eh] Update delegate behavior
Browse files Browse the repository at this point in the history
Update the behavior of 'delegate' according to:
WebAssembly/exception-handling#176

Summary: delegate can target any block, which just rethrows to the next
outer try/catch.

[email protected]

Bug: v8:8091
Change-Id: I967db9ab1cbb1a15b2c5e0a1a20f64fa19a3f769
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3140603
Commit-Queue: Thibaud Michaud <[email protected]>
Reviewed-by: Clemens Backes <[email protected]>
Cr-Commit-Position: refs/heads/main@{#76677}
  • Loading branch information
thibaudmichaud authored and V8 LUCI CQ committed Sep 6, 2021
1 parent f7d65d5 commit 7c67bc1
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 22 deletions.
18 changes: 7 additions & 11 deletions src/wasm/function-body-decoder-impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2635,19 +2635,15 @@ class WasmFullDecoder : public WasmDecoder<validate, decoding_mode> {
return 0;
}
// +1 because the current try block is not included in the count.
Control* target = control_at(imm.depth + 1);
if (imm.depth + 1 < control_depth() - 1 && !target->is_try()) {
this->DecodeError(
"delegate target must be a try block or the function block");
return 0;
}
if (target->is_try_catch() || target->is_try_catchall()) {
this->DecodeError(
"cannot delegate inside the catch handler of the target");
return 0;
uint32_t target_depth = imm.depth + 1;
while (target_depth < control_depth() - 1 &&
(!control_at(target_depth)->is_try() ||
control_at(target_depth)->is_try_catch() ||
control_at(target_depth)->is_try_catchall())) {
target_depth++;
}
FallThrough();
CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(Delegate, imm.depth + 1, c);
CALL_INTERFACE_IF_OK_AND_PARENT_REACHABLE(Delegate, target_depth, c);
current_catch_ = c->previous_catch;
EndControl();
PopControl();
Expand Down
38 changes: 38 additions & 0 deletions test/mjsunit/wasm/exceptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1073,3 +1073,41 @@ d8.file.execute("test/mjsunit/wasm/exceptions-utils.js");
assertDoesNotThrow(() => instance.exports.catchless_try(0));
assertWasmThrows(instance, except, [], () => instance.exports.catchless_try(1));
})();

// Delegate to a regular block inside a try block.
(function TestDelegateToBlock() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addTag(kSig_v_v);
builder.addFunction('test', kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprBlock, kWasmI32,
kExprTry, kWasmI32,
kExprThrow, except,
kExprDelegate, 0,
kExprEnd,
kExprCatch, except,
kExprI32Const, 2,
kExprEnd,
]).exportFunc();
instance = builder.instantiate();
assertEquals(2, instance.exports.test());
})();

// Delegate to a regular block with no outer try (delegate to caller).
(function TestDelegateToCallerWithBlock() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addTag(kSig_v_v);
builder.addFunction('test', kSig_v_v)
.addBody([
kExprBlock, kWasmVoid,
kExprTry, kWasmVoid,
kExprThrow, except,
kExprDelegate, 0,
kExprEnd
]).exportFunc();
instance = builder.instantiate();
assertThrows(() => instance.exports.test(), WebAssembly.Exception);
})();
20 changes: 9 additions & 11 deletions test/unittests/wasm/function-body-decoder-unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2990,18 +2990,16 @@ TEST_F(FunctionBodyDecoderTest, TryDelegate) {
sigs.v_v(),
{WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 2),
kExprCatch, ex, kExprEnd)});
ExpectValidates(sigs.v_v(),
{WASM_TRY_OP, kExprCatch, ex,
WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0), kExprEnd},
kAppendEnd);
ExpectValidates(sigs.v_v(),
{WASM_TRY_OP,
WASM_BLOCK(WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0)),
kExprCatch, ex, kExprEnd},
kAppendEnd);

ExpectFailure(sigs.v_v(),
{WASM_TRY_OP,
WASM_BLOCK(WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0)),
kExprCatch, ex, kExprEnd},
kAppendEnd,
"delegate target must be a try block or the function block");
ExpectFailure(sigs.v_v(),
{WASM_TRY_OP, kExprCatch, ex,
WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 0), kExprEnd},
kAppendEnd,
"cannot delegate inside the catch handler of the target");
ExpectFailure(
sigs.v_v(),
{WASM_BLOCK(WASM_TRY_OP, WASM_TRY_DELEGATE(WASM_STMTS(kExprThrow, ex), 3),
Expand Down

0 comments on commit 7c67bc1

Please sign in to comment.