Line data Source code
1 : // Copyright 2019 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #include "src/api-inl.h"
6 : #include "test/cctest/wasm/wasm-atomics-utils.h"
7 : #include "test/common/wasm/test-signatures.h"
8 : #include "test/common/wasm/wasm-macro-gen.h"
9 :
10 : namespace v8 {
11 : namespace internal {
12 : namespace wasm {
13 : namespace test_run_wasm_exceptions {
14 :
15 26680 : WASM_EXEC_TEST(TryCatchThrow) {
16 12 : TestSignatures sigs;
17 : EXPERIMENTAL_FLAG_SCOPE(eh);
18 24 : WasmRunner<uint32_t, uint32_t> r(execution_tier);
19 12 : uint32_t except = r.builder().AddException(sigs.v_v());
20 : constexpr uint32_t kResult0 = 23;
21 : constexpr uint32_t kResult1 = 42;
22 :
23 : // Build the main test function.
24 12 : BUILD(r, WASM_TRY_CATCH_T(kWasmI32,
25 : WASM_STMTS(WASM_I32V(kResult1),
26 : WASM_IF(WASM_I32_EQZ(WASM_GET_LOCAL(0)),
27 : WASM_THROW(except))),
28 : WASM_STMTS(WASM_DROP, WASM_I32V(kResult0))));
29 :
30 : // Need to call through JS to allow for creation of stack traces.
31 12 : r.CheckCallViaJS(kResult0, 0);
32 12 : r.CheckCallViaJS(kResult1, 1);
33 12 : }
34 :
35 26680 : WASM_EXEC_TEST(TryCatchCallDirect) {
36 12 : TestSignatures sigs;
37 : EXPERIMENTAL_FLAG_SCOPE(eh);
38 24 : WasmRunner<uint32_t, uint32_t> r(execution_tier);
39 12 : uint32_t except = r.builder().AddException(sigs.v_v());
40 : constexpr uint32_t kResult0 = 23;
41 : constexpr uint32_t kResult1 = 42;
42 :
43 : // Build a throwing helper function.
44 12 : WasmFunctionCompiler& throw_func = r.NewFunction(sigs.i_ii());
45 12 : BUILD(throw_func, WASM_THROW(except));
46 :
47 : // Build the main test function.
48 24 : BUILD(r, WASM_TRY_CATCH_T(
49 : kWasmI32,
50 : WASM_STMTS(WASM_I32V(kResult1),
51 : WASM_IF(WASM_I32_EQZ(WASM_GET_LOCAL(0)),
52 : WASM_STMTS(WASM_CALL_FUNCTION(
53 : throw_func.function_index(),
54 : WASM_I32V(7), WASM_I32V(9)),
55 : WASM_DROP))),
56 : WASM_STMTS(WASM_DROP, WASM_I32V(kResult0))));
57 :
58 : // Need to call through JS to allow for creation of stack traces.
59 12 : r.CheckCallViaJS(kResult0, 0);
60 12 : r.CheckCallViaJS(kResult1, 1);
61 12 : }
62 :
63 26680 : WASM_EXEC_TEST(TryCatchCallIndirect) {
64 12 : TestSignatures sigs;
65 : EXPERIMENTAL_FLAG_SCOPE(eh);
66 24 : WasmRunner<uint32_t, uint32_t> r(execution_tier);
67 12 : uint32_t except = r.builder().AddException(sigs.v_v());
68 : constexpr uint32_t kResult0 = 23;
69 : constexpr uint32_t kResult1 = 42;
70 :
71 : // Build a throwing helper function.
72 12 : WasmFunctionCompiler& throw_func = r.NewFunction(sigs.i_ii());
73 12 : BUILD(throw_func, WASM_THROW(except));
74 12 : r.builder().AddSignature(sigs.i_ii());
75 : throw_func.SetSigIndex(0);
76 :
77 : // Add an indirect function table.
78 : uint16_t indirect_function_table[] = {
79 12 : static_cast<uint16_t>(throw_func.function_index())};
80 : r.builder().AddIndirectFunctionTable(indirect_function_table,
81 12 : arraysize(indirect_function_table));
82 :
83 : // Build the main test function.
84 12 : BUILD(r, WASM_TRY_CATCH_T(
85 : kWasmI32,
86 : WASM_STMTS(WASM_I32V(kResult1),
87 : WASM_IF(WASM_I32_EQZ(WASM_GET_LOCAL(0)),
88 : WASM_STMTS(WASM_CALL_INDIRECT2(
89 : 0, WASM_GET_LOCAL(0),
90 : WASM_I32V(7), WASM_I32V(9)),
91 : WASM_DROP))),
92 : WASM_STMTS(WASM_DROP, WASM_I32V(kResult0))));
93 :
94 : // Need to call through JS to allow for creation of stack traces.
95 12 : r.CheckCallViaJS(kResult0, 0);
96 12 : r.CheckCallViaJS(kResult1, 1);
97 12 : }
98 :
99 26680 : WASM_EXEC_TEST(TryCatchCallExternal) {
100 12 : TestSignatures sigs;
101 : EXPERIMENTAL_FLAG_SCOPE(eh);
102 : HandleScope scope(CcTest::InitIsolateOnce());
103 : const char* source = "(function() { throw 'ball'; })";
104 : Handle<JSFunction> js_function =
105 : Handle<JSFunction>::cast(v8::Utils::OpenHandle(
106 : *v8::Local<v8::Function>::Cast(CompileRun(source))));
107 12 : ManuallyImportedJSFunction import = {sigs.i_ii(), js_function};
108 24 : WasmRunner<uint32_t, uint32_t> r(execution_tier, &import);
109 : constexpr uint32_t kResult0 = 23;
110 : constexpr uint32_t kResult1 = 42;
111 : constexpr uint32_t kJSFunc = 0;
112 :
113 : // Build the main test function.
114 12 : BUILD(r, WASM_TRY_CATCH_T(
115 : kWasmI32,
116 : WASM_STMTS(
117 : WASM_I32V(kResult1),
118 : WASM_IF(WASM_I32_EQZ(WASM_GET_LOCAL(0)),
119 : WASM_STMTS(WASM_CALL_FUNCTION(kJSFunc, WASM_I32V(7),
120 : WASM_I32V(9)),
121 : WASM_DROP))),
122 : WASM_STMTS(WASM_DROP, WASM_I32V(kResult0))));
123 :
124 : // Need to call through JS to allow for creation of stack traces.
125 12 : r.CheckCallViaJS(kResult0, 0);
126 12 : r.CheckCallViaJS(kResult1, 1);
127 12 : }
128 :
129 26680 : WASM_EXEC_TEST(TryCatchTrapTypeError) {
130 12 : TestSignatures sigs;
131 : EXPERIMENTAL_FLAG_SCOPE(eh);
132 : HandleScope scope(CcTest::InitIsolateOnce());
133 : const char* source = "(function() { return 0; })";
134 : Handle<JSFunction> js_function =
135 : Handle<JSFunction>::cast(v8::Utils::OpenHandle(
136 : *v8::Local<v8::Function>::Cast(CompileRun(source))));
137 : // Make sure to use a signature incompatible with JS below.
138 12 : ManuallyImportedJSFunction import = {sigs.i_ll(), js_function};
139 24 : WasmRunner<uint32_t, uint32_t> r(execution_tier, &import);
140 : constexpr uint32_t kResult0 = 23;
141 : constexpr uint32_t kResult1 = 42;
142 : constexpr uint32_t kJSFunc = 0;
143 :
144 : // Build the main test function.
145 12 : BUILD(r, WASM_TRY_CATCH_T(
146 : kWasmI32,
147 : WASM_STMTS(
148 : WASM_I32V(kResult1),
149 : WASM_IF(WASM_I32_EQZ(WASM_GET_LOCAL(0)),
150 : WASM_STMTS(WASM_CALL_FUNCTION(kJSFunc, WASM_I64V(7),
151 : WASM_I64V(9)),
152 : WASM_DROP))),
153 : WASM_STMTS(WASM_DROP, WASM_I32V(kResult0))));
154 :
155 : // Need to call through JS to allow for creation of stack traces.
156 12 : r.CheckCallViaJS(kResult0, 0);
157 12 : r.CheckCallViaJS(kResult1, 1);
158 12 : }
159 :
160 : namespace {
161 :
162 : // TODO(8729): The semantics of this are not yet specified and might change,
163 : // this test aims at keeping semantics of various execution tiers consistent.
164 48 : void TestTryCatchTrap(byte* code, size_t code_size,
165 : ExecutionTier execution_tier) {
166 48 : TestSignatures sigs;
167 : EXPERIMENTAL_FLAG_SCOPE(eh);
168 : WasmRunner<uint32_t, uint32_t> r(execution_tier, nullptr, "main",
169 96 : kRuntimeExceptionSupport);
170 48 : r.builder().AddMemory(kWasmPageSize);
171 : constexpr uint32_t kResult0 = 23;
172 : constexpr uint32_t kResult1 = 42;
173 :
174 : // Build a trapping helper function.
175 48 : WasmFunctionCompiler& trap_func = r.NewFunction(sigs.i_ii());
176 48 : trap_func.Build(code, code + code_size);
177 :
178 : // Build the main test function.
179 96 : BUILD(r, WASM_TRY_CATCH_T(
180 : kWasmI32,
181 : WASM_STMTS(WASM_I32V(kResult1),
182 : WASM_IF(WASM_I32_EQZ(WASM_GET_LOCAL(0)),
183 : WASM_STMTS(WASM_CALL_FUNCTION(
184 : trap_func.function_index(),
185 : WASM_I32V(7), WASM_I32V(9)),
186 : WASM_DROP))),
187 : WASM_STMTS(WASM_DROP, WASM_I32V(kResult0))));
188 :
189 : // Need to call through JS to allow for creation of stack traces.
190 48 : r.CheckCallViaJS(kResult0, 0);
191 48 : r.CheckCallViaJS(kResult1, 1);
192 48 : }
193 :
194 : } // namespace
195 :
196 26680 : WASM_EXEC_TEST(TryCatchTrapUnreachable) {
197 12 : byte code[] = {WASM_UNREACHABLE};
198 12 : TestTryCatchTrap(code, arraysize(code), execution_tier);
199 0 : }
200 :
201 26680 : WASM_EXEC_TEST(TryCatchTrapMemOutOfBounds) {
202 12 : byte code[] = {WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(-1))};
203 12 : TestTryCatchTrap(code, arraysize(code), execution_tier);
204 12 : }
205 :
206 26680 : WASM_EXEC_TEST(TryCatchTrapDivByZero) {
207 12 : byte code[] = {WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I32V_1(0))};
208 12 : TestTryCatchTrap(code, arraysize(code), execution_tier);
209 0 : }
210 :
211 26680 : WASM_EXEC_TEST(TryCatchTrapRemByZero) {
212 12 : byte code[] = {WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_I32V_1(0))};
213 12 : TestTryCatchTrap(code, arraysize(code), execution_tier);
214 0 : }
215 :
216 : } // namespace test_run_wasm_exceptions
217 : } // namespace wasm
218 : } // namespace internal
219 79968 : } // namespace v8
|