OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Flags: --expose-wasm --wasm-eh-prototype | 5 // Flags: --expose-wasm --wasm-eh-prototype |
6 | 6 |
7 load("test/mjsunit/wasm/wasm-constants.js"); | 7 load("test/mjsunit/wasm/wasm-constants.js"); |
8 load("test/mjsunit/wasm/wasm-module-builder.js"); | 8 load("test/mjsunit/wasm/wasm-module-builder.js"); |
9 | 9 |
10 var module = (function () { | 10 // The following methods do not attempt to catch the exception they raise. |
11 var test_throw = (function () { | |
11 var builder = new WasmModuleBuilder(); | 12 var builder = new WasmModuleBuilder(); |
12 | 13 |
13 builder.addFunction("throw_param_if_not_zero", kSig_i_i) | 14 builder.addFunction("throw_param_if_not_zero", kSig_i_i) |
14 .addBody([ | 15 .addBody([ |
15 kExprGetLocal, 0, | 16 kExprGetLocal, 0, |
16 kExprI32Const, 0, | 17 kExprI32Const, 0, |
17 kExprI32Ne, | 18 kExprI32Ne, |
18 kExprIf, kAstStmt, | 19 kExprIf, kAstStmt, |
19 kExprGetLocal, 0, | 20 kExprGetLocal, 0, |
20 kExprThrow, kAstStmt, | 21 kExprThrow, |
21 kExprEnd, | 22 kExprEnd, |
22 kExprI32Const, 1 | 23 kExprI32Const, 1 |
23 ]) | 24 ]) |
24 .exportFunc() | 25 .exportFunc() |
25 | 26 |
26 builder.addFunction("throw_20", kSig_v_v) | 27 builder.addFunction("throw_20", kSig_v_v) |
27 .addBody([ | 28 .addBody([ |
28 kExprI32Const, 20, | 29 kExprI32Const, 20, |
29 kExprThrow, kAstStmt | 30 kExprThrow, |
30 ]) | 31 ]) |
31 .exportFunc() | 32 .exportFunc() |
32 | 33 |
33 builder.addFunction("throw_expr_with_params", kSig_v_ddi) | 34 builder.addFunction("throw_expr_with_params", kSig_v_ddi) |
34 .addBody([ | 35 .addBody([ |
35 // p2 * (p0 + min(p0, p1))|0 - 20 | 36 // p2 * (p0 + min(p0, p1))|0 - 20 |
36 kExprGetLocal, 2, | 37 kExprGetLocal, 2, |
37 kExprGetLocal, 0, | 38 kExprGetLocal, 0, |
38 kExprGetLocal, 0, | 39 kExprGetLocal, 0, |
39 kExprGetLocal, 1, | 40 kExprGetLocal, 1, |
40 kExprF64Min, | 41 kExprF64Min, |
41 kExprF64Add, | 42 kExprF64Add, |
42 kExprI32SConvertF64, | 43 kExprI32SConvertF64, |
43 kExprI32Mul, | 44 kExprI32Mul, |
44 kExprI32Const, 20, | 45 kExprI32Const, 20, |
45 kExprI32Sub, | 46 kExprI32Sub, |
46 kExprThrow, kAstStmt | 47 kExprThrow, |
47 ]) | 48 ]) |
48 .exportFunc() | 49 .exportFunc() |
49 | 50 |
50 return builder.instantiate(); | 51 return builder.instantiate(); |
51 })(); | 52 })(); |
52 | 53 |
53 // Check the module exists. | 54 // Check the test_throw exists. |
54 assertFalse(module === undefined); | 55 assertFalse(test_throw === undefined); |
55 assertFalse(module === null); | 56 assertFalse(test_throw === null); |
56 assertFalse(module === 0); | 57 assertFalse(test_throw === 0); |
57 assertEquals("object", typeof module.exports); | 58 assertEquals("object", typeof test_throw.exports); |
58 assertEquals("function", typeof module.exports.throw_param_if_not_zero); | 59 assertEquals("function", typeof test_throw.exports.throw_param_if_not_zero); |
59 | 60 assertEquals("function", typeof test_throw.exports.throw_20); |
60 assertEquals(1, module.exports.throw_param_if_not_zero(0)); | 61 assertEquals("function", typeof test_throw.exports.throw_expr_with_params); |
61 assertWasmThrows(10, function() { module.exports.throw_param_if_not_zero(10) }); | 62 |
62 assertWasmThrows(-1, function() { module.exports.throw_param_if_not_zero(-1) }); | 63 assertEquals(1, test_throw.exports.throw_param_if_not_zero(0)); |
63 assertWasmThrows(20, module.exports.throw_20); | 64 assertWasmThrows(10, function() { test_throw.exports.throw_param_if_not_zero(10) }); |
65 assertWasmThrows(-1, function() { test_throw.exports.throw_param_if_not_zero(-1) }); | |
66 assertWasmThrows(20, test_throw.exports.throw_20); | |
64 assertWasmThrows( | 67 assertWasmThrows( |
65 -8, function() { module.exports.throw_expr_with_params(1.5, 2.5, 4); }); | 68 -8, function() { test_throw.exports.throw_expr_with_params(1.5, 2.5, 4); }); |
66 assertWasmThrows( | 69 assertWasmThrows( |
67 12, function() { module.exports.throw_expr_with_params(5.7, 2.5, 4); }); | 70 12, function() { test_throw.exports.throw_expr_with_params(5.7, 2.5, 4); }); |
71 | |
72 // Now that we know throwing works, we test catching the exceptions we raise. | |
73 var test_catch = (function () { | |
74 var builder = new WasmModuleBuilder(); | |
75 | |
76 // Helper function for throwing from js. It is imported by the Wasm module | |
77 // as throw_i. | |
78 function throw_value(value) { | |
79 throw value; | |
80 } | |
81 var sig_index = builder.addType(kSig_v_i); | |
82 var kJSThrowI = builder.addImport("throw_i", sig_index); | |
83 | |
84 // Helper function that throws a string. Wasm should not catch it. | |
85 function throw_string() { | |
86 throw "use wasm;"; | |
87 } | |
88 sig_index = builder.addType(kSig_v_v); | |
89 var kJSThrowString = builder.addImport("throw_string", sig_index); | |
90 | |
91 // Helper function that throws undefined. Wasm should not catch it. | |
92 function throw_undefined() { | |
93 throw undefined; | |
94 } | |
95 var kJSThrowUndefined = builder.addImport("throw_undefined", sig_index); | |
96 | |
97 // Helper function that throws an fp. Wasm should not catch it. | |
98 function throw_fp() { | |
99 throw 10.5; | |
100 } | |
101 var kJSThrowFP = builder.addImport("throw_fp", sig_index); | |
102 | |
103 // Helper function that throws a large number. Wasm should not catch it. | |
104 function throw_large() { | |
105 throw 1e+28; | |
106 } | |
107 var kJSThrowLarge = builder.addImport("throw_large", sig_index); | |
108 | |
109 // Helper function for throwing from Wasm. | |
110 var kWasmThrowFunction = | |
111 builder.addFunction("throw", kSig_v_i) | |
112 .addBody([ | |
113 kExprGetLocal, 0, | |
114 kExprThrow | |
115 ]) | |
116 .index; | |
117 | |
118 // Scenario 1: Throw and catch appear on the same function. This should | |
119 // happen in case of inlining, for example. | |
120 builder.addFunction("same_scope", kSig_i_i) | |
121 .addBody([ | |
122 kExprTry, kAstI32, | |
123 kExprGetLocal, 0, | |
124 kExprI32Const, 0, | |
125 kExprI32Ne, | |
126 kExprIf, kAstStmt, | |
127 kExprGetLocal, 0, | |
128 kExprThrow, | |
129 kExprUnreachable, | |
130 kExprEnd, | |
131 kExprI32Const, 63, | |
132 kExprCatch, 1, | |
133 kExprGetLocal, 1, | |
134 kExprEnd | |
135 ]) | |
136 .addLocals({i32_count: 1}) | |
137 .exportFunc() | |
138 .index; | |
139 | |
140 builder.addFunction("same_scope_ignore", kSig_i_i) | |
141 .addBody([ | |
142 kExprTry, kAstI32, | |
143 kExprGetLocal, 0, | |
144 kExprThrow, | |
145 kExprUnreachable, | |
146 kExprCatch, 1, | |
147 kExprGetLocal, 0, | |
148 kExprEnd, | |
149 ]) | |
150 .addLocals({i32_count: 1}) | |
151 .exportFunc(); | |
152 | |
153 builder.addFunction("same_scope_multiple", kSig_i_i) | |
154 // path = 0; | |
155 // | |
Mircea Trofin
2016/09/30 16:00:44
why is this commented? could you please delete it,
John
2016/09/30 16:07:17
This documents what the test does -- it is pretty
| |
156 // try { | |
157 // try { | |
158 // try { | |
159 // if (p == 1) | |
160 // throw 1; | |
161 // path |= 2 | |
162 // } catch (v) { | |
163 // path |= v | 4; | |
164 // throw path; | |
165 // } | |
166 // if (p == 2) | |
167 // throw path|8; | |
168 // path |= 16; | |
169 // } catch (v) { | |
170 // path |= v | 32; | |
171 // throw path; | |
172 // } | |
173 // if (p == 3) | |
174 // throw path|64; | |
175 // path |= 128 | |
176 // } catch (v) { | |
177 // path |= v | 256; | |
178 // } | |
179 // | |
180 // return path; | |
181 // | |
182 // p == 1 -> path == 293 | |
183 // p == 2 -> path == 298 | |
184 // p == 3 -> path == 338 | |
185 // else -> path == 146 | |
186 .addBody([ | |
187 kExprTry, kAstI32, | |
188 kExprTry, kAstI32, | |
189 kExprTry, kAstI32, | |
190 kExprGetLocal, 0, | |
191 kExprI32Const, 1, | |
192 kExprI32Eq, | |
193 kExprIf, kAstStmt, | |
194 kExprI32Const, 1, | |
195 kExprThrow, | |
196 kExprUnreachable, | |
197 kExprEnd, | |
198 kExprI32Const, 2, | |
199 kExprCatch, 1, | |
200 kExprGetLocal, 1, | |
201 kExprI32Const, 4, | |
202 kExprI32Ior, | |
203 kExprThrow, | |
204 kExprUnreachable, | |
205 kExprEnd, | |
206 kExprTeeLocal, 2, | |
207 kExprGetLocal, 0, | |
208 kExprI32Const, 2, | |
209 kExprI32Eq, | |
210 kExprIf, kAstStmt, | |
211 kExprGetLocal, 2, | |
212 kExprI32Const, 8, | |
213 kExprI32Ior, | |
214 kExprThrow, | |
215 kExprUnreachable, | |
216 kExprEnd, | |
217 kExprI32Const, 16, | |
218 kExprI32Ior, | |
219 kExprCatch, 1, | |
220 kExprGetLocal, 1, | |
221 kExprI32Const, 32, | |
222 kExprI32Ior, | |
223 kExprThrow, | |
224 kExprUnreachable, | |
225 kExprEnd, | |
226 kExprTeeLocal, 2, | |
227 kExprGetLocal, 0, | |
228 kExprI32Const, 3, | |
229 kExprI32Eq, | |
230 kExprIf, kAstStmt, | |
231 kExprGetLocal, 2, | |
232 kExprI32Const, /*64=*/ 192, 0, | |
233 kExprI32Ior, | |
234 kExprThrow, | |
235 kExprUnreachable, | |
236 kExprEnd, | |
237 kExprI32Const, /*128=*/ 128, 1, | |
238 kExprI32Ior, | |
239 kExprCatch, 1, | |
240 kExprGetLocal, 1, | |
241 kExprI32Const, /*256=*/ 128, 2, | |
242 kExprI32Ior, | |
243 kExprEnd, | |
244 ]) | |
245 .addLocals({i32_count: 2}) | |
246 .exportFunc(); | |
247 | |
248 // Scenario 2: Catches an exception raised from the direct callee. | |
249 var kFromDirectCallee = | |
250 builder.addFunction("from_direct_callee", kSig_i_i) | |
251 .addBody([ | |
252 kExprTry, kAstI32, | |
253 kExprGetLocal, 0, | |
254 kExprCallFunction, kWasmThrowFunction, | |
255 kExprI32Const, /*-1=*/ 127, | |
256 kExprCatch, 1, | |
257 kExprGetLocal, 1, | |
258 kExprEnd | |
259 ]) | |
260 .addLocals({i32_count: 1}) | |
261 .exportFunc() | |
262 .index; | |
263 | |
264 // Scenario 3: Catches an exception raised from an indirect callee. | |
265 var kFromIndirectCalleeHelper = kFromDirectCallee + 1; | |
266 builder.addFunction("from_indirect_callee_helper", kSig_v_ii) | |
267 .addBody([ | |
268 kExprGetLocal, 0, | |
269 kExprI32Const, 0, | |
270 kExprI32GtS, | |
271 kExprIf, kAstStmt, | |
272 kExprGetLocal, 0, | |
273 kExprI32Const, 1, | |
274 kExprI32Sub, | |
275 kExprGetLocal, 1, | |
276 kExprI32Const, 1, | |
277 kExprI32Sub, | |
278 kExprCallFunction, kFromIndirectCalleeHelper, | |
279 kExprEnd, | |
280 kExprGetLocal, 1, | |
281 kExprCallFunction, kWasmThrowFunction, | |
282 ]); | |
283 | |
284 builder.addFunction("from_indirect_callee", kSig_i_i) | |
285 .addBody([ | |
286 kExprTry, kAstI32, | |
287 kExprGetLocal, 0, | |
288 kExprI32Const, 0, | |
289 kExprCallFunction, kFromIndirectCalleeHelper, | |
290 kExprI32Const, /*-1=*/ 127, | |
291 kExprCatch, 1, | |
292 kExprGetLocal, 1, | |
293 kExprEnd | |
294 ]) | |
295 .addLocals({i32_count: 1}) | |
296 .exportFunc(); | |
297 | |
298 // Scenario 4: Catches an exception raised in JS. | |
299 builder.addFunction("from_js", kSig_i_i) | |
300 .addBody([ | |
301 kExprTry, kAstI32, | |
302 kExprGetLocal, 0, | |
303 kExprCallFunction, kJSThrowI, | |
304 kExprI32Const, /*-1=*/ 127, | |
305 kExprCatch, 1, | |
306 kExprGetLocal, 1, | |
307 kExprEnd, | |
308 ]) | |
309 .addLocals({i32_count: 1}) | |
310 .exportFunc(); | |
311 | |
312 // Scenario 5: Does not catch an exception raised in JS if it is not a | |
313 // number. | |
314 builder.addFunction("string_from_js", kSig_v_v) | |
315 .addBody([ | |
316 kExprCallFunction, kJSThrowString | |
317 ]) | |
318 .exportFunc(); | |
319 | |
320 builder.addFunction("fp_from_js", kSig_v_v) | |
321 .addBody([ | |
322 kExprCallFunction, kJSThrowFP | |
323 ]) | |
324 .exportFunc(); | |
325 | |
326 builder.addFunction("large_from_js", kSig_v_v) | |
327 .addBody([ | |
328 kExprCallFunction, kJSThrowLarge | |
329 ]) | |
330 .exportFunc(); | |
331 | |
332 builder.addFunction("undefined_from_js", kSig_v_v) | |
333 .addBody([ | |
334 kExprCallFunction, kJSThrowUndefined | |
335 ]) | |
336 .exportFunc(); | |
337 | |
338 return builder.instantiate({ | |
339 throw_i: throw_value, | |
340 throw_string: throw_string, | |
341 throw_fp: throw_fp, | |
342 throw_large, throw_large, | |
343 throw_undefined: throw_undefined | |
344 }); | |
345 })(); | |
346 | |
347 // Check the test_catch exists. | |
348 assertFalse(test_catch === undefined); | |
349 assertFalse(test_catch === null); | |
350 assertFalse(test_catch === 0); | |
351 assertEquals("object", typeof test_catch.exports); | |
352 assertEquals("function", typeof test_catch.exports.same_scope); | |
353 assertEquals("function", typeof test_catch.exports.same_scope_ignore); | |
354 assertEquals("function", typeof test_catch.exports.same_scope_multiple); | |
355 assertEquals("function", typeof test_catch.exports.from_direct_callee); | |
356 assertEquals("function", typeof test_catch.exports.from_indirect_callee); | |
357 assertEquals("function", typeof test_catch.exports.from_js); | |
358 assertEquals("function", typeof test_catch.exports.string_from_js); | |
359 | |
360 assertEquals(63, test_catch.exports.same_scope(0)); | |
361 assertEquals(1024, test_catch.exports.same_scope(1024)); | |
362 assertEquals(-3, test_catch.exports.same_scope(-3)); | |
363 assertEquals(-1, test_catch.exports.same_scope_ignore(-1)); | |
364 assertEquals(1, test_catch.exports.same_scope_ignore(1)); | |
365 assertEquals(0x7FFFFFFF, test_catch.exports.same_scope_ignore(0x7FFFFFFF)); | |
366 assertEquals(1024, test_catch.exports.same_scope_ignore(1024)); | |
367 assertEquals(-1, test_catch.exports.same_scope_ignore(-1)); | |
368 assertEquals(293, test_catch.exports.same_scope_multiple(1)); | |
369 assertEquals(298, test_catch.exports.same_scope_multiple(2)); | |
370 assertEquals(338, test_catch.exports.same_scope_multiple(3)); | |
371 assertEquals(146, test_catch.exports.same_scope_multiple(0)); | |
372 assertEquals(-10024, test_catch.exports.from_direct_callee(-10024)); | |
373 assertEquals(3334333, test_catch.exports.from_direct_callee(3334333)); | |
374 assertEquals(-1, test_catch.exports.from_direct_callee(0xFFFFFFFF)); | |
375 assertEquals(0x7FFFFFFF, test_catch.exports.from_direct_callee(0x7FFFFFFF)); | |
376 assertEquals(-10, test_catch.exports.from_indirect_callee(10)); | |
377 assertEquals(-77, test_catch.exports.from_indirect_callee(77)); | |
378 assertEquals(10, test_catch.exports.from_js(10)); | |
379 assertEquals(-10, test_catch.exports.from_js(-10)); | |
380 | |
381 assertThrowsEquals(test_catch.exports.string_from_js, "use wasm;"); | |
382 assertThrowsEquals(test_catch.exports.large_from_js, 1e+28); | |
383 assertThrowsEquals(test_catch.exports.undefined_from_js, undefined); | |
OLD | NEW |