1771e4aaa3
Since the reftypes proposal has shipped, we remove the respective flag and the code that handled its absence. We maintain a WasmFeature for reftypes for feature detection purposes. We remove the flag declaration from tests, and adapt some tests that make no sense without the flag. Bug: v8:7581 Change-Id: Icf2f8d0feae8f30ec68d5560f1e7ee5959481483 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3329781 Reviewed-by: Andreas Haas <ahaas@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/main@{#78351}
726 lines
26 KiB
C++
726 lines
26 KiB
C++
// Copyright 2019 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "include/v8-function.h"
|
|
#include "src/api/api-inl.h"
|
|
#include "test/cctest/wasm/wasm-atomics-utils.h"
|
|
#include "test/common/wasm/test-signatures.h"
|
|
#include "test/common/wasm/wasm-macro-gen.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
namespace wasm {
|
|
namespace test_run_wasm_exceptions {
|
|
|
|
WASM_EXEC_TEST(TryCatchThrow) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_T(kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_THROW(except))),
|
|
WASM_STMTS(WASM_I32V(kResult0)), except));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchThrowWithValue) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_i());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_I32V(kResult0), WASM_THROW(except))),
|
|
WASM_STMTS(kExprNop), except));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryMultiCatchThrow) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except1 = r.builder().AddException(sigs.v_v());
|
|
byte except2 = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
constexpr uint32_t kResult2 = 51;
|
|
|
|
// Build the main test function.
|
|
BUILD(
|
|
r, kExprTry, static_cast<byte>((kWasmI32).value_type_code()),
|
|
WASM_STMTS(WASM_I32V(kResult2),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), WASM_THROW(except1)),
|
|
WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(0), WASM_I32V(1)),
|
|
WASM_THROW(except2))),
|
|
kExprCatch, except1, WASM_STMTS(WASM_I32V(kResult0)), kExprCatch, except2,
|
|
WASM_STMTS(WASM_I32V(kResult1)), kExprEnd);
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
r.CheckCallViaJS(kResult2, 2);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
CHECK_EQ(kResult2, r.CallInterpreter(2));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchAllThrow) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build the main test function.
|
|
BUILD(r, kExprTry, static_cast<byte>((kWasmI32).value_type_code()),
|
|
WASM_STMTS(WASM_I32V(kResult1), WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_THROW(except))),
|
|
kExprCatchAll, WASM_I32V(kResult0), kExprEnd);
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchCatchAllThrow) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except1 = r.builder().AddException(sigs.v_v());
|
|
byte except2 = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
constexpr uint32_t kResult2 = 51;
|
|
|
|
// Build the main test function.
|
|
BUILD(
|
|
r, kExprTry, static_cast<byte>((kWasmI32).value_type_code()),
|
|
WASM_STMTS(WASM_I32V(kResult2),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)), WASM_THROW(except1)),
|
|
WASM_IF(WASM_I32_EQ(WASM_LOCAL_GET(0), WASM_I32V(1)),
|
|
WASM_THROW(except2))),
|
|
kExprCatch, except1, WASM_I32V(kResult0), kExprCatchAll,
|
|
WASM_I32V(kResult1), kExprEnd);
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
r.CheckCallViaJS(kResult2, 2);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
CHECK_EQ(kResult2, r.CallInterpreter(2));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryImplicitRethrow) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except1 = r.builder().AddException(sigs.v_v());
|
|
byte except2 = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
constexpr uint32_t kResult2 = 51;
|
|
|
|
// Build the main test function.
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_T(
|
|
kWasmI32,
|
|
WASM_TRY_CATCH_T(kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_THROW(except2))),
|
|
WASM_STMTS(WASM_I32V(kResult2)), except1),
|
|
WASM_I32V(kResult0), except2));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryDelegate) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build the main test function.
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_T(kWasmI32,
|
|
WASM_TRY_DELEGATE_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_THROW(except))),
|
|
0),
|
|
WASM_I32V(kResult0), except));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TestCatchlessTry) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_i());
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_T(
|
|
kWasmI32,
|
|
WASM_TRY_T(kWasmI32, WASM_STMTS(WASM_I32V(0), WASM_THROW(except))),
|
|
WASM_NOP, except));
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
r.CheckCallViaJS(0);
|
|
} else {
|
|
CHECK_EQ(0, r.CallInterpreter());
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchRethrow) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except1 = r.builder().AddException(sigs.v_v());
|
|
byte except2 = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
constexpr uint32_t kUnreachable = 51;
|
|
|
|
// Build the main test function.
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_CATCH_T(
|
|
kWasmI32,
|
|
WASM_TRY_CATCH_T(
|
|
kWasmI32, WASM_THROW(except2),
|
|
WASM_TRY_CATCH_T(
|
|
kWasmI32, WASM_THROW(except1),
|
|
WASM_STMTS(WASM_I32V(kUnreachable),
|
|
WASM_IF_ELSE(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_RETHROW(1), WASM_RETHROW(2))),
|
|
except1),
|
|
except2),
|
|
except1, WASM_I32V(kResult0), except2, WASM_I32V(kResult1)));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryDelegateToCaller) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build the main test function.
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_T(kWasmI32,
|
|
WASM_TRY_DELEGATE_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_THROW(except))),
|
|
1),
|
|
WASM_I32V(kResult0), except));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
constexpr int64_t trap = 0xDEADBEEF;
|
|
r.CheckCallViaJS(trap, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
constexpr int stopped = 0;
|
|
CHECK_EQ(stopped, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchCallDirect) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build a throwing helper function.
|
|
WasmFunctionCompiler& throw_func = r.NewFunction(sigs.i_ii());
|
|
BUILD(throw_func, WASM_THROW(except));
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_STMTS(WASM_CALL_FUNCTION(
|
|
throw_func.function_index(),
|
|
WASM_I32V(7), WASM_I32V(9)),
|
|
WASM_DROP))),
|
|
WASM_STMTS(WASM_I32V(kResult0)), except));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchAllCallDirect) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build a throwing helper function.
|
|
WasmFunctionCompiler& throw_func = r.NewFunction(sigs.i_ii());
|
|
BUILD(throw_func, WASM_THROW(except));
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_STMTS(WASM_CALL_FUNCTION(
|
|
throw_func.function_index(),
|
|
WASM_I32V(7), WASM_I32V(9)),
|
|
WASM_DROP))),
|
|
WASM_STMTS(WASM_I32V(kResult0))));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchCallIndirect) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build a throwing helper function.
|
|
WasmFunctionCompiler& throw_func = r.NewFunction(sigs.i_ii());
|
|
BUILD(throw_func, WASM_THROW(except));
|
|
byte sig_index = r.builder().AddSignature(sigs.i_ii());
|
|
throw_func.SetSigIndex(0);
|
|
|
|
// Add an indirect function table.
|
|
uint16_t indirect_function_table[] = {
|
|
static_cast<uint16_t>(throw_func.function_index())};
|
|
r.builder().AddIndirectFunctionTable(indirect_function_table,
|
|
arraysize(indirect_function_table));
|
|
|
|
// Build the main test function.
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_STMTS(WASM_CALL_INDIRECT(
|
|
sig_index, WASM_I32V(7),
|
|
WASM_I32V(9), WASM_LOCAL_GET(0)),
|
|
WASM_DROP))),
|
|
WASM_I32V(kResult0), except));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchAllCallIndirect) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
|
|
// Build a throwing helper function.
|
|
WasmFunctionCompiler& throw_func = r.NewFunction(sigs.i_ii());
|
|
BUILD(throw_func, WASM_THROW(except));
|
|
byte sig_index = r.builder().AddSignature(sigs.i_ii());
|
|
throw_func.SetSigIndex(0);
|
|
|
|
// Add an indirect function table.
|
|
uint16_t indirect_function_table[] = {
|
|
static_cast<uint16_t>(throw_func.function_index())};
|
|
r.builder().AddIndirectFunctionTable(indirect_function_table,
|
|
arraysize(indirect_function_table));
|
|
|
|
// Build the main test function.
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_STMTS(WASM_CALL_INDIRECT(
|
|
sig_index, WASM_I32V(7),
|
|
WASM_I32V(9), WASM_LOCAL_GET(0)),
|
|
WASM_DROP))),
|
|
WASM_I32V(kResult0)));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
} else {
|
|
CHECK_EQ(kResult0, r.CallInterpreter(0));
|
|
CHECK_EQ(kResult1, r.CallInterpreter(1));
|
|
}
|
|
}
|
|
|
|
WASM_COMPILED_EXEC_TEST(TryCatchCallExternal) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
HandleScope scope(CcTest::InitIsolateOnce());
|
|
const char* source = "(function() { throw 'ball'; })";
|
|
Handle<JSFunction> js_function =
|
|
Handle<JSFunction>::cast(v8::Utils::OpenHandle(
|
|
*v8::Local<v8::Function>::Cast(CompileRun(source))));
|
|
ManuallyImportedJSFunction import = {sigs.i_ii(), js_function};
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier, &import);
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
constexpr uint32_t kJSFunc = 0;
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_STMTS(
|
|
WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_STMTS(WASM_CALL_FUNCTION(kJSFunc, WASM_I32V(7),
|
|
WASM_I32V(9)),
|
|
WASM_DROP))),
|
|
WASM_I32V(kResult0)));
|
|
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
}
|
|
|
|
WASM_COMPILED_EXEC_TEST(TryCatchAllCallExternal) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
HandleScope scope(CcTest::InitIsolateOnce());
|
|
const char* source = "(function() { throw 'ball'; })";
|
|
Handle<JSFunction> js_function =
|
|
Handle<JSFunction>::cast(v8::Utils::OpenHandle(
|
|
*v8::Local<v8::Function>::Cast(CompileRun(source))));
|
|
ManuallyImportedJSFunction import = {sigs.i_ii(), js_function};
|
|
WasmRunner<uint32_t, uint32_t> r(execution_tier, &import);
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kResult1 = 42;
|
|
constexpr uint32_t kJSFunc = 0;
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_STMTS(
|
|
WASM_I32V(kResult1),
|
|
WASM_IF(WASM_I32_EQZ(WASM_LOCAL_GET(0)),
|
|
WASM_STMTS(WASM_CALL_FUNCTION(kJSFunc, WASM_I32V(7),
|
|
WASM_I32V(9)),
|
|
WASM_DROP))),
|
|
WASM_I32V(kResult0)));
|
|
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJS(kResult0, 0);
|
|
r.CheckCallViaJS(kResult1, 1);
|
|
}
|
|
|
|
namespace {
|
|
|
|
void TestTrapNotCaught(byte* code, size_t code_size,
|
|
TestExecutionTier execution_tier) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t> r(execution_tier, nullptr, "main",
|
|
kRuntimeExceptionSupport);
|
|
r.builder().AddMemory(kWasmPageSize);
|
|
constexpr uint32_t kResultSuccess = 23;
|
|
constexpr uint32_t kResultCaught = 47;
|
|
|
|
// Add an indirect function table.
|
|
const int kTableSize = 2;
|
|
r.builder().AddIndirectFunctionTable(nullptr, kTableSize);
|
|
|
|
// Build a trapping helper function.
|
|
WasmFunctionCompiler& trap_func = r.NewFunction(sigs.i_ii());
|
|
trap_func.Build(code, code + code_size);
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(kResultSuccess),
|
|
WASM_CALL_FUNCTION(trap_func.function_index(),
|
|
WASM_I32V(7), WASM_I32V(9)),
|
|
WASM_DROP),
|
|
WASM_STMTS(WASM_I32V(kResultCaught))));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJSTraps();
|
|
} else {
|
|
r.CallInterpreter();
|
|
}
|
|
}
|
|
|
|
} // namespace
|
|
|
|
WASM_EXEC_TEST(TryCatchTrapUnreachable) {
|
|
byte code[] = {WASM_UNREACHABLE};
|
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchTrapMemOutOfBounds) {
|
|
byte code[] = {WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(-1))};
|
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchTrapDivByZero) {
|
|
byte code[] = {WASM_I32_DIVS(WASM_LOCAL_GET(0), WASM_I32V_1(0))};
|
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchTrapRemByZero) {
|
|
byte code[] = {WASM_I32_REMS(WASM_LOCAL_GET(0), WASM_I32V_1(0))};
|
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
|
}
|
|
|
|
WASM_EXEC_TEST(TryCatchTrapTableFill) {
|
|
int table_index = 0;
|
|
int length = 10; // OOB.
|
|
int start = 10; // OOB.
|
|
byte code[] = {WASM_TABLE_FILL(table_index, WASM_I32V(length),
|
|
WASM_REF_NULL(kFuncRefCode), WASM_I32V(start)),
|
|
WASM_I32V_1(42)};
|
|
TestTrapNotCaught(code, arraysize(code), execution_tier);
|
|
}
|
|
|
|
namespace {
|
|
// TODO(cleanup): Define in cctest.h and re-use where appropriate.
|
|
class IsolateScope {
|
|
public:
|
|
IsolateScope() {
|
|
v8::Isolate::CreateParams create_params;
|
|
create_params.array_buffer_allocator = CcTest::array_buffer_allocator();
|
|
isolate_ = v8::Isolate::New(create_params);
|
|
isolate_->Enter();
|
|
}
|
|
|
|
~IsolateScope() {
|
|
isolate_->Exit();
|
|
isolate_->Dispose();
|
|
}
|
|
|
|
v8::Isolate* isolate() { return isolate_; }
|
|
Isolate* i_isolate() { return reinterpret_cast<Isolate*>(isolate_); }
|
|
|
|
private:
|
|
v8::Isolate* isolate_;
|
|
};
|
|
} // namespace
|
|
|
|
UNINITIALIZED_WASM_EXEC_TEST(TestStackOverflowNotCaught) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
// FLAG_stack_size must be set before isolate initialization.
|
|
FlagScope<int32_t> stack_size(&v8::internal::FLAG_stack_size, 8);
|
|
|
|
IsolateScope isolate_scope;
|
|
LocalContext context(isolate_scope.isolate());
|
|
|
|
WasmRunner<uint32_t> r(execution_tier, nullptr, "main",
|
|
kRuntimeExceptionSupport, kMemory32,
|
|
isolate_scope.i_isolate());
|
|
|
|
// Build a function that calls itself until stack overflow.
|
|
WasmFunctionCompiler& stack_overflow = r.NewFunction(sigs.v_v());
|
|
byte stack_overflow_code[] = {
|
|
kExprCallFunction, static_cast<byte>(stack_overflow.function_index())};
|
|
stack_overflow.Build(stack_overflow_code,
|
|
stack_overflow_code + arraysize(stack_overflow_code));
|
|
|
|
// Build the main test function.
|
|
BUILD(r, WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(1), kExprCallFunction,
|
|
static_cast<byte>(stack_overflow.function_index())),
|
|
WASM_STMTS(WASM_I32V(1))));
|
|
|
|
if (execution_tier != TestExecutionTier::kInterpreter) {
|
|
// Need to call through JS to allow for creation of stack traces.
|
|
r.CheckCallViaJSTraps();
|
|
} else {
|
|
constexpr int stopped = 0;
|
|
CHECK_EQ(stopped, r.CallInterpreter());
|
|
}
|
|
}
|
|
|
|
TEST(Regress1180457) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter);
|
|
constexpr uint32_t kResult0 = 23;
|
|
constexpr uint32_t kUnreachable = 42;
|
|
BUILD(r, WASM_TRY_CATCH_ALL_T(
|
|
kWasmI32,
|
|
WASM_TRY_DELEGATE_T(
|
|
kWasmI32, WASM_STMTS(WASM_I32V(kResult0), WASM_BR(0)), 0),
|
|
WASM_I32V(kUnreachable)));
|
|
|
|
CHECK_EQ(kResult0, r.CallInterpreter());
|
|
}
|
|
|
|
TEST(Regress1187896) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter);
|
|
byte try_sig = r.builder().AddSignature(sigs.v_i());
|
|
constexpr uint32_t kResult = 23;
|
|
BUILD(r, kExprI32Const, 0, kExprTry, try_sig, kExprDrop, kExprCatchAll,
|
|
kExprNop, kExprEnd, kExprI32Const, kResult);
|
|
CHECK_EQ(kResult, r.CallInterpreter());
|
|
}
|
|
|
|
TEST(Regress1190291) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter);
|
|
byte try_sig = r.builder().AddSignature(sigs.v_i());
|
|
BUILD(r, kExprUnreachable, kExprTry, try_sig, kExprCatchAll, kExprEnd,
|
|
kExprI32Const, 0);
|
|
r.CallInterpreter();
|
|
}
|
|
|
|
TEST(Regress1186795) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<uint32_t> r(TestExecutionTier::kInterpreter);
|
|
byte except = r.builder().AddException(sigs.v_i());
|
|
BUILD(r,
|
|
WASM_TRY_CATCH_T(
|
|
kWasmI32,
|
|
WASM_STMTS(WASM_I32V(0), WASM_I32V(0), WASM_I32V(0), WASM_I32V(0),
|
|
WASM_I32V(0), WASM_I32V(0), WASM_I32V(0),
|
|
WASM_TRY_T(kWasmI32,
|
|
WASM_STMTS(WASM_I32V(0), WASM_THROW(except))),
|
|
WASM_DROP, WASM_DROP, WASM_DROP, WASM_DROP, WASM_DROP,
|
|
WASM_DROP, WASM_DROP),
|
|
WASM_NOP, except));
|
|
CHECK_EQ(0, r.CallInterpreter());
|
|
}
|
|
|
|
TEST(Regress1197408) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<int32_t, int32_t, int32_t, int32_t> r(
|
|
TestExecutionTier::kInterpreter);
|
|
byte sig_id = r.builder().AddSignature(sigs.i_iii());
|
|
BUILD(r, WASM_STMTS(WASM_I32V(0), WASM_I32V(0), WASM_I32V(0), kExprTry,
|
|
sig_id, kExprTry, sig_id, kExprCallFunction, 0,
|
|
kExprDelegate, 0, kExprDelegate, 0));
|
|
CHECK_EQ(0, r.CallInterpreter(0, 0, 0));
|
|
}
|
|
|
|
TEST(Regress1212396) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<int32_t> r(TestExecutionTier::kInterpreter);
|
|
byte except = r.builder().AddException(sigs.v_v());
|
|
BUILD(r, kExprTry, kVoidCode, kExprTry, kVoidCode, kExprI32Const, 0,
|
|
kExprThrow, except, kExprDelegate, 0, kExprCatch, except, kExprEnd,
|
|
kExprI32Const, 42);
|
|
CHECK_EQ(42, r.CallInterpreter());
|
|
}
|
|
|
|
TEST(Regress1219746) {
|
|
TestSignatures sigs;
|
|
EXPERIMENTAL_FLAG_SCOPE(eh);
|
|
WasmRunner<int32_t> r(TestExecutionTier::kInterpreter);
|
|
BUILD(r, kExprTry, kVoidCode, kExprI32Const, 0, kExprEnd);
|
|
CHECK_EQ(0, r.CallInterpreter());
|
|
}
|
|
|
|
} // namespace test_run_wasm_exceptions
|
|
} // namespace wasm
|
|
} // namespace internal
|
|
} // namespace v8
|