Commit 1003fcc4 authored by Michael Starzinger's avatar Michael Starzinger Committed by Commit Bot

[wasm] Fix exception handling with empty try blocks.

R=clemensh@chromium.org
TEST=mjsunit/wasm/exceptions
BUG=v8:8091

Change-Id: I866430e1f3d3e7b93001a4375a869f19de75e65e
Reviewed-on: https://chromium-review.googlesource.com/1203954Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Michael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#55605}
parent 1c2aa605
...@@ -433,48 +433,37 @@ class WasmGraphBuildingInterface { ...@@ -433,48 +433,37 @@ class WasmGraphBuildingInterface {
SsaEnv* catch_env = block->try_info->catch_env; SsaEnv* catch_env = block->try_info->catch_env;
SetEnv(catch_env); SetEnv(catch_env);
TFNode* compare_i32 = nullptr; // The catch block is unreachable if no possible throws in the try block
if (exception == nullptr) { // exist. We only build a landing pad if some node in the try block can
// Catch not applicable, no possible throws in the try // (possibly) throw. Otherwise the below catch environments remain empty.
// block. Create dummy code so that body of catch still DCHECK_EQ(exception != nullptr, ssa_env_->go());
// compiles. Note: This only happens because the current
// implementation only builds a landing pad if some node in the TFNode* if_catch = nullptr;
// try block can (possibly) throw. TFNode* if_no_catch = nullptr;
// if (exception != nullptr) {
// TODO(kschimpf): Always generate a landing pad for a try block.
compare_i32 = BUILD(Int32Constant, 0);
} else {
// Get the exception and see if wanted exception. // Get the exception and see if wanted exception.
TFNode* caught_tag = BUILD(GetExceptionRuntimeId, exception); TFNode* caught_tag = BUILD(GetExceptionRuntimeId, exception);
TFNode* exception_tag = BUILD(ConvertExceptionTagToRuntimeId, imm.index); TFNode* exception_tag = BUILD(ConvertExceptionTagToRuntimeId, imm.index);
compare_i32 = BUILD(Binop, kExprI32Eq, caught_tag, exception_tag); TFNode* compare_i32 = BUILD(Binop, kExprI32Eq, caught_tag, exception_tag);
BUILD(BranchNoHint, compare_i32, &if_catch, &if_no_catch);
} }
TFNode* if_catch = nullptr;
TFNode* if_no_catch = nullptr;
BUILD(BranchNoHint, compare_i32, &if_catch, &if_no_catch);
SsaEnv* if_no_catch_env = Split(decoder, ssa_env_); SsaEnv* if_no_catch_env = Split(decoder, ssa_env_);
if_no_catch_env->control = if_no_catch; if_no_catch_env->control = if_no_catch;
SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_); SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_);
if_catch_env->control = if_catch; if_catch_env->control = if_catch;
// TODO(kschimpf): Generalize to allow more catches. Will force
// moving no_catch code to END opcode.
SetEnv(if_no_catch_env); SetEnv(if_no_catch_env);
BUILD(Rethrow, exception); if (exception != nullptr) {
Unreachable(decoder); // TODO(kschimpf): Generalize to allow more catches. Will force
EndControl(decoder, block); // moving no_catch code to END opcode.
BUILD(Rethrow, exception);
Unreachable(decoder);
EndControl(decoder, block);
}
SetEnv(if_catch_env); SetEnv(if_catch_env);
if (exception != nullptr) {
if (exception == nullptr) {
// No caught value, make up filler nodes so that catch block still
// compiles.
for (Value& value : values) {
value.node = DefaultValue(value.type);
}
} else {
// TODO(kschimpf): Can't use BUILD() here, GetExceptionValues() returns // TODO(kschimpf): Can't use BUILD() here, GetExceptionValues() returns
// TFNode** rather than TFNode*. Fix to add landing pads. // TFNode** rather than TFNode*. Fix to add landing pads.
TFNode** caught_values = TFNode** caught_values =
......
...@@ -61,6 +61,21 @@ function assertWasmThrows(runtime_id, values, code) { ...@@ -61,6 +61,21 @@ function assertWasmThrows(runtime_id, values, code) {
assertWasmThrows(except, [], () => instance.exports.throw_if_param_not_zero(-1)); assertWasmThrows(except, [], () => instance.exports.throw_if_param_not_zero(-1));
})(); })();
// Test that empty try/catch blocks work.
(function TestCatchEmptyBlocks() {
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_v);
builder.addFunction("catch_empty_try", kSig_v_v)
.addBody([
kExprTry, kWasmStmt,
kExprCatch, except,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
assertDoesNotThrow(instance.exports.catch_empty_try);
})();
// Now that we know throwing works, we test catching the exceptions we raise. // Now that we know throwing works, we test catching the exceptions we raise.
(function TestCatchSimple() { (function TestCatchSimple() {
let builder = new WasmModuleBuilder(); let builder = new WasmModuleBuilder();
......
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