[wasm] Fix throwing and catching exceptions

This reimplements functionality that was present before the decoder
refactoring. It's implemented a bit differently though by generating
the code for re-throwing an uncaught exception earlier (when generating
code for the catch).

R=titzer@chromium.org, kschimpf@chromium.org

Bug: v8:6600
Change-Id: Ie2f11837851c0602ab31506fa63475fc2d0b5047
Reviewed-on: https://chromium-review.googlesource.com/641550
Commit-Queue: Brad Nelson <bradnelson@chromium.org>
Reviewed-by: Brad Nelson <bradnelson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47687}
This commit is contained in:
Clemens Hammacher 2017-08-29 18:07:48 +02:00 committed by Commit Bot
parent 693e8ac59f
commit 9ee7e4ec98
3 changed files with 16 additions and 16 deletions

View File

@ -1243,7 +1243,7 @@ class WasmFullDecoder : public WasmDecoder<validate> {
break;
}
if (c->is_try_catch()) {
if (CHECK_ERROR(c->is_try_catch())) {
OPCODE_ERROR(opcode, "multiple catch blocks not implemented");
break;
}

View File

@ -176,18 +176,10 @@ class WasmGraphBuildingInterface
SetEnv(c->interface_data.end_env);
}
void PopControl(Decoder* decoder, const Control& block) {
void PopControl(Decoder* decoder, Control& block) {
if (block.is_onearmed_if()) {
Goto(decoder, block.interface_data.false_env,
block.interface_data.end_env);
} else if (block.is_try_catch()) {
SsaEnv* fallthru_ssa_env = ssa_env_;
DCHECK_NOT_NULL(block.interface_data.try_info->catch_env);
SetEnv(block.interface_data.try_info->catch_env);
BUILD(Rethrow);
// TODO(clemensh): Make this work again.
// FallThruTo(decoder, &block);
SetEnv(fallthru_ssa_env);
}
}
@ -400,8 +392,10 @@ class WasmGraphBuildingInterface
void Catch(Decoder* decoder, const ExceptionIndexOperand<true>& operand,
Control* block) {
DCHECK_NOT_NULL(block->interface_data.try_info);
DCHECK(block->is_try_catch());
current_catch_ = block->interface_data.previous_catch;
SsaEnv* catch_env = block->interface_data.try_info->catch_env;
SetEnv(catch_env);
// Get the exception and see if wanted exception.
TFNode* exception_as_i32 = BUILD(
@ -412,12 +406,18 @@ class WasmGraphBuildingInterface
TFNode* if_true = nullptr;
TFNode* if_false = nullptr;
BUILD(BranchNoHint, compare_i32, &if_true, &if_false);
SsaEnv* end_env = ssa_env_;
SsaEnv* false_env = Split(decoder, end_env);
SsaEnv* false_env = Split(decoder, catch_env);
false_env->control = if_false;
SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
SsaEnv* true_env = Steal(decoder->zone(), catch_env);
true_env->control = if_true;
block->interface_data.try_info->catch_env = false_env;
// Generate code to re-throw the exception.
DCHECK_NOT_NULL(block->interface_data.try_info->catch_env);
SetEnv(false_env);
BUILD(Rethrow);
FallThruTo(decoder, block);
SetEnv(true_env);
// TODO(kschimpf): Add code to pop caught exception from isolate.
}

View File

@ -34,8 +34,6 @@ assertFalse(test_throw === 0);
assertEquals("object", typeof test_throw.exports);
assertEquals("function", typeof test_throw.exports.throw_if_param_not_zero);
/* TODO(kschimpf) Convert these tests to work for the proposed exceptions.
// Test expected behavior of throws
assertEquals(1, test_throw.exports.throw_if_param_not_zero(0));
assertWasmThrows([], function() { test_throw.exports.throw_if_param_not_zero(10) });
@ -74,6 +72,8 @@ assertEquals("function", typeof test_catch.exports.simple_throw_catch_to_0_1);
assertEquals(0, test_catch.exports.simple_throw_catch_to_0_1(0));
assertEquals(1, test_catch.exports.simple_throw_catch_to_0_1(1));
/* TODO(kschimpf) Convert these tests to work for the proposed exceptions.
// The following methods do not attempt to catch the exception they raise.
var test_throw = (function () {
var builder = new WasmModuleBuilder();