Commit 6e812955 authored by Thibaud Michaud's avatar Thibaud Michaud Committed by Commit Bot

[wasm][liftoff][eh] Implement rethrow

Push the caught exception on the value stack, so that we can access it
from an inner catch block and rethrow it.

R=clemensb@chromium.org

Bug: v8:11453
Change-Id: Ibc5e653a07c3e4436e252c001b53bc2d3402abc9
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2739974Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73295}
parent 4c3db4fd
...@@ -627,6 +627,15 @@ void LiftoffAssembler::DropValues(int count) { ...@@ -627,6 +627,15 @@ void LiftoffAssembler::DropValues(int count) {
} }
} }
void LiftoffAssembler::DropValue(int depth) {
auto* dropped = cache_state_.stack_state.begin() + depth;
if (dropped->is_reg()) {
cache_state_.dec_used(dropped->reg());
}
std::copy(dropped + 1, cache_state_.stack_state.end(), dropped);
cache_state_.stack_state.pop_back();
}
void LiftoffAssembler::PrepareLoopArgs(int num) { void LiftoffAssembler::PrepareLoopArgs(int num) {
for (int i = 0; i < num; ++i) { for (int i = 0; i < num; ++i) {
VarState& slot = cache_state_.stack_state.end()[-1 - i]; VarState& slot = cache_state_.stack_state.end()[-1 - i];
......
...@@ -410,6 +410,8 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -410,6 +410,8 @@ class LiftoffAssembler : public TurboAssembler {
void DropValues(int count); void DropValues(int count);
void DropValue(int depth);
// Ensure that the loop inputs are either in a register or spilled to the // Ensure that the loop inputs are either in a register or spilled to the
// stack, so that we can merge different values on the back-edge. // stack, so that we can merge different values on the back-edge.
void PrepareLoopArgs(int num); void PrepareLoopArgs(int num);
...@@ -434,6 +436,16 @@ class LiftoffAssembler : public TurboAssembler { ...@@ -434,6 +436,16 @@ class LiftoffAssembler : public TurboAssembler {
cache_state_.stack_state.emplace_back(kind, reg, NextSpillOffset(kind)); cache_state_.stack_state.emplace_back(kind, reg, NextSpillOffset(kind));
} }
// Assumes that the exception is in {kReturnRegister0}. This is where the
// exception is stored by the unwinder after a throwing call.
void PushException() {
LiftoffRegister reg{kReturnRegister0};
// This is used after a call, so {kReturnRegister0} is not used yet.
DCHECK(cache_state_.is_free(reg));
cache_state_.inc_used(reg);
cache_state_.stack_state.emplace_back(kRef, reg, NextSpillOffset(kRef));
}
void PushConstant(ValueKind kind, int32_t i32_const) { void PushConstant(ValueKind kind, int32_t i32_const) {
DCHECK(kind == kI32 || kind == kI64); DCHECK(kind == kI32 || kind == kI64);
cache_state_.stack_state.emplace_back(kind, i32_const, cache_state_.stack_state.emplace_back(kind, i32_const,
......
This diff is collapsed.
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "src/wasm/wasm-debug.h" #include "src/wasm/wasm-debug.h"
#include "test/cctest/cctest.h" #include "test/cctest/cctest.h"
#include "test/cctest/wasm/wasm-run-utils.h" #include "test/cctest/wasm/wasm-run-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h" #include "test/common/wasm/wasm-macro-gen.h"
namespace v8 { namespace v8 {
...@@ -89,6 +90,8 @@ class LiftoffCompileEnvironment { ...@@ -89,6 +90,8 @@ class LiftoffCompileEnvironment {
return debug_side_table_via_compilation; return debug_side_table_via_compilation;
} }
TestingModuleBuilder* builder() { return &wasm_runner_.builder(); }
private: private:
static void CheckTableEquals(const DebugSideTable& a, static void CheckTableEquals(const DebugSideTable& a,
const DebugSideTable& b) { const DebugSideTable& b) {
...@@ -423,6 +426,31 @@ TEST(Liftoff_breakpoint_simple) { ...@@ -423,6 +426,31 @@ TEST(Liftoff_breakpoint_simple) {
debug_side_table.get()); debug_side_table.get());
} }
TEST(Liftoff_debug_side_table_catch_all) {
EXPERIMENTAL_FLAG_SCOPE(eh);
LiftoffCompileEnvironment env;
TestSignatures sigs;
int ex = env.builder()->AddException(sigs.v_v());
ValueType exception_type = ValueType::Ref(HeapType::kExtern, kNonNullable);
auto debug_side_table = env.GenerateDebugSideTable(
{}, {},
{WASM_TRY_CATCH_ALL_T(kWasmI32, WASM_STMTS(WASM_I32V(0), WASM_THROW(ex)),
WASM_I32V(1)),
WASM_DROP},
{
18 // Break at the end of the try block.
});
CheckDebugSideTable(
{
// function entry.
{0, {}},
// breakpoint.
{2, {Register(0, exception_type), Constant(1, kWasmI32, 1)}},
{0, {}},
},
debug_side_table.get());
}
} // namespace wasm } // namespace wasm
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -1032,3 +1032,38 @@ load("test/mjsunit/wasm/exceptions-utils.js"); ...@@ -1032,3 +1032,38 @@ load("test/mjsunit/wasm/exceptions-utils.js");
assertTraps(WebAssembly.RuntimeError, () => instance.exports.test()); assertTraps(WebAssembly.RuntimeError, () => instance.exports.test());
assertTraps(WebAssembly.RuntimeError, () => instance.exports.test_unwind()); assertTraps(WebAssembly.RuntimeError, () => instance.exports.test_unwind());
})(); })();
(function TestThrowBeforeUnreachable() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_v);
builder.addFunction('throw_before_unreachable', kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprThrow, except,
kExprUnreachable,
kExprCatchAll,
kExprI32Const, 42,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
assertEquals(42, instance.exports.throw_before_unreachable());
})();
(function TestUnreachableInCatchAll() {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_v);
builder.addFunction('throw_before_unreachable', kSig_i_v)
.addBody([
kExprTry, kWasmI32,
kExprThrow, except,
kExprCatchAll,
kExprUnreachable,
kExprI32Const, 42,
kExprEnd,
]).exportFunc();
let instance = builder.instantiate();
})();
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