From 9ee7e4ec98ce55934e5465aa2f31d0732473a99f Mon Sep 17 00:00:00 2001 From: Clemens Hammacher Date: Tue, 29 Aug 2017 18:07:48 +0200 Subject: [PATCH] [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 Reviewed-by: Brad Nelson Cr-Commit-Position: refs/heads/master@{#47687} --- src/wasm/function-body-decoder-impl.h | 2 +- src/wasm/function-body-decoder.cc | 26 +++++++++++++------------- test/mjsunit/wasm/exceptions.js | 4 ++-- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/wasm/function-body-decoder-impl.h b/src/wasm/function-body-decoder-impl.h index 1364476b8c..1a7278c78e 100644 --- a/src/wasm/function-body-decoder-impl.h +++ b/src/wasm/function-body-decoder-impl.h @@ -1243,7 +1243,7 @@ class WasmFullDecoder : public WasmDecoder { break; } - if (c->is_try_catch()) { + if (CHECK_ERROR(c->is_try_catch())) { OPCODE_ERROR(opcode, "multiple catch blocks not implemented"); break; } diff --git a/src/wasm/function-body-decoder.cc b/src/wasm/function-body-decoder.cc index 38b6312839..db6a8dbdb9 100644 --- a/src/wasm/function-body-decoder.cc +++ b/src/wasm/function-body-decoder.cc @@ -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& 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. } diff --git a/test/mjsunit/wasm/exceptions.js b/test/mjsunit/wasm/exceptions.js index 72f98ff8cd..8fcfd15ff4 100644 --- a/test/mjsunit/wasm/exceptions.js +++ b/test/mjsunit/wasm/exceptions.js @@ -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();