Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(816)

Side by Side Diff: test/mjsunit/wasm/exceptions.js

Issue 2275293002: [WASM] Implements catch for the wasm low level exception mechanism. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Test changes Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 function always() {
14 .addBody([ 15 throw 50;
15 kExprGetLocal, 0, 16 }
16 kExprI32Const, 0, 17
17 kExprI32Ne, 18 var sig_index = builder.addType(kSig_v_v);
18 kExprIf, 19 builder.addImport("_0", sig_index);
19 kExprGetLocal, 0, 20
20 kExprThrow, 21 builder.addFunction("throw_param_if_not_zero", kSig_i_i)
21 kExprEnd, 22 .addBody([
22 kExprI32Const, 1 23 kExprGetLocal, 0,
23 ]) 24 kExprI32Const, 0,
24 .exportFunc() 25 kExprI32Ne,
25 26 kExprIf,
26 builder.addFunction("throw_20", kSig_v_v) 27 kExprGetLocal, 0,
27 .addBody([ 28 kExprThrow,
28 kExprI32Const, 20, 29 kExprEnd,
29 kExprThrow 30 kExprI32Const, 1
30 ]) 31 ])
31 .exportFunc() 32 .exportFunc()
32 33
33 builder.addFunction("throw_expr_with_params", kSig_v_ddi) 34 builder.addFunction("throw_20", kSig_i_v)
34 .addBody([ 35 .addBody([
35 // p2 * (p0 + min(p0, p1))|0 - 20 36 kExprI32Const, 20,
36 kExprGetLocal, 2, 37 kExprThrow,
37 kExprGetLocal, 0, 38 kExprI32Const, 0
38 kExprGetLocal, 0, 39 ])
39 kExprGetLocal, 1, 40 .exportFunc()
40 kExprF64Min, 41
41 kExprF64Add, 42 builder.addFunction("throw_expr_with_params", kSig_v_ddi)
42 kExprI32SConvertF64, 43 .addBody([
43 kExprI32Mul, 44 // p2 * (p0 + min(p0, p1))|0 - 20
44 kExprI32Const, 20, 45 kExprGetLocal, 2,
45 kExprI32Sub, 46 kExprGetLocal, 0,
46 kExprThrow 47 kExprGetLocal, 0,
47 ]) 48 kExprGetLocal, 1,
48 .exportFunc() 49 kExprF64Min,
49 50 kExprF64Add,
50 return builder.instantiate(); 51 kExprI32SConvertF64,
52 kExprI32Mul,
53 kExprI32Const, 20,
54 kExprI32Sub,
55 kExprThrow
56 ])
57 .exportFunc()
58
59 return builder.instantiate({_0: always});
51 })(); 60 })();
52 61
53 // Check the module exists. 62 // Check the test_throw exists.
54 assertFalse(module === undefined); 63 assertFalse(test_throw === undefined);
55 assertFalse(module === null); 64 assertFalse(test_throw === null);
56 assertFalse(module === 0); 65 assertFalse(test_throw === 0);
57 assertEquals("object", typeof module.exports); 66 assertEquals("object", typeof test_throw.exports);
58 assertEquals("function", typeof module.exports.throw_param_if_not_zero); 67 assertEquals("function", typeof test_throw.exports.throw_param_if_not_zero);
59 68 assertEquals("function", typeof test_throw.exports.throw_20);
60 assertEquals(1, module.exports.throw_param_if_not_zero(0)); 69 assertEquals("function", typeof test_throw.exports.throw_expr_with_params);
61 assertWasmThrows(10, function() { module.exports.throw_param_if_not_zero(10) }); 70
62 assertWasmThrows(-1, function() { module.exports.throw_param_if_not_zero(-1) }); 71 assertEquals(1, test_throw.exports.throw_param_if_not_zero(0));
63 assertWasmThrows(20, module.exports.throw_20); 72 assertWasmThrows(10, function() { test_throw.exports.throw_param_if_not_zero(10) });
73 assertWasmThrows(-1, function() { test_throw.exports.throw_param_if_not_zero(-1) });
74 assertWasmThrows(20, test_throw.exports.throw_20);
64 assertWasmThrows( 75 assertWasmThrows(
65 -8, function() { module.exports.throw_expr_with_params(1.5, 2.5, 4); }); 76 -8, function() { test_throw.exports.throw_expr_with_params(1.5, 2.5, 4); });
66 assertWasmThrows( 77 assertWasmThrows(
67 12, function() { module.exports.throw_expr_with_params(5.7, 2.5, 4); }); 78 12, function() { test_throw.exports.throw_expr_with_params(5.7, 2.5, 4); });
79
80
81 // Now that we know throwing works, we test catching the exceptions we raise.
82 var test_catch = (function () {
83 var builder = new WasmModuleBuilder();
84
85 function LEB128(value, size) {
86 let bytes = [];
87
88 let more = 1;
89 let negative = (value < 0);
90 while(more) {
91 b = value & 0x7f; // low order 7 bits of value;
92 value >>= 7;
93
94 /* sign bit of byte is second high order bit (0x40) */
95 if (((value == 0) && ((b & 0x40) == 0)) ||
96 ((value == -1) && ((b & 0x40) != 0)))
97 more = 0;
98 else
99 b |= 0x80;
100 bytes = bytes.concat([b]);
101 }
102
103 return bytes;
104 }
105
106 function varint32(value) {
107 let kBitsInI32 = 32;
108 return LEB128(value, kBitsInI32);
109 }
110
111 // Helper function for throwing from Wasm.
112 var kWasmThrowFunction =
113 builder.addFunction("throw", kSig_v_i)
114 .addBody([
115 kExprGetLocal, 0,
116 kExprThrow
117 ])
118 .index;
119
120 // Helper function for throwing from js. It is imported by the Wasm module
121 // as throw_i.
122 function throw_value(value) {
123 throw value;
124 }
125 var sig_index = builder.addType(kSig_v_i);
126 var kJSThrowI = builder.addImport("throw_i", sig_index);
127
128 // Helper function that throws a string. Wasm should not catch it.
129 function throw_string() {
130 throw "use wasm;";
131 }
132 sig_index = builder.addType(kSig_v_v);
133 var kJSThrowString = builder.addImport("throw_string", sig_index);
134
135 // Helper function that throws undefined. Wasm should not catch it.
136 function throw_undefined() {
137 throw undefined;
138 }
139 var kJSThrowUndefined = builder.addImport("throw_undefined", sig_index);
140
141 // Helper function that throws an fp. Wasm should not catch it.
142 function throw_fp() {
143 throw 10.5;
144 }
145 var kJSThrowFP = builder.addImport("throw_fp", sig_index);
146
147 // Helper function that throws a large number. Wasm should not catch it.
148 function throw_large() {
149 throw 1e+28;
150 }
151 var kJSThrowLarge = builder.addImport("throw_large", sig_index);
152
153 // Scenario 1: Throw and catch appear on the same function. This should
154 // happen in case of inlining, for example.
155 builder.addFunction("same_scope", kSig_i_i)
156 .addBody([
157 kExprTry,
158 kExprGetLocal, 0,
159 kExprI32Const, 0,
160 kExprI32Ne,
161 kExprIf,
162 kExprGetLocal, 0,
163 kExprThrow,
164 kExprEnd,
165 kExprI32Const, 63,
166 kExprCatch, 1,
167 kExprGetLocal, 1,
168 kExprEnd
169 ])
170 .addLocals({i32_count: 1})
171 .exportFunc()
172 .index;
173
174 builder.addFunction("same_scope_ignore", kSig_i_i)
175 .addBody([
176 kExprTry,
177 kExprGetLocal, 0,
178 kExprThrow,
179 kExprUnreachable,
180 kExprCatch, 1,
181 kExprGetLocal, 0,
182 kExprEnd,
183 ])
184 .addLocals({i32_count: 1})
185 .exportFunc();
186
187 builder.addFunction("same_scope_multiple", kSig_i_i)
188 // path = 0;
189 //
190 // try {
191 // try {
192 // try {
193 // if (p == 1)
194 // throw 1;
195 // path |= 2
196 // } catch (v) {
197 // path |= v | 4;
198 // throw path;
199 // }
200 // if (p == 2)
201 // throw path|8;
202 // path |= 16;
203 // } catch (v) {
204 // path |= v | 32;
205 // throw path;
206 // }
207 // if (p == 3)
208 // throw path|64;
209 // path |= 128
210 // } catch (v) {
211 // path |= v | 256;
212 // }
213 //
214 // return path;
215 //
216 // p == 1 -> path == 293
217 // p == 2 -> path == 298
218 // p == 3 -> path == 338
219 // else -> path == 146
220 .addBody([
221 kExprTry,
bradnelson 2016/09/27 04:25:56 Shame how verbose these are. We've been chatting a
John 2016/09/28 13:37:18 Acknowledged.
222 kExprTry,
223 kExprTry,
224 kExprGetLocal, 0,
225 kExprI32Const, 1,
226 kExprI32Eq,
227 kExprIf,
228 kExprI32Const, 1,
229 kExprThrow,
230 kExprUnreachable,
231 kExprElse,
232 kExprI32Const, 2,
233 kExprEnd,
234 kExprCatch, 1,
235 kExprGetLocal, 1,
236 kExprI32Const, 4,
237 kExprI32Ior,
238 kExprThrow,
239 kExprUnreachable,
240 kExprEnd,
241 kExprSetLocal, 2,
242 kExprGetLocal, 0,
243 kExprI32Const, 2,
244 kExprI32Eq,
245 kExprIf,
246 kExprGetLocal, 2,
247 kExprI32Const, 8,
248 kExprI32Ior,
249 kExprThrow,
250 kExprUnreachable,
251 kExprElse,
252 kExprI32Const, 16,
253 kExprEnd,
254 kExprI32Ior,
255 kExprCatch, 1,
256 kExprGetLocal, 1,
257 kExprI32Const, 32,
258 kExprI32Ior,
259 kExprThrow,
260 kExprUnreachable,
261 kExprEnd,
262 kExprSetLocal, 2,
263 kExprGetLocal, 0,
264 kExprI32Const, 3,
265 kExprI32Eq,
266 kExprIf,
267 kExprGetLocal, 2,
268 kExprI32Const].concat(varint32(64)).concat([
269 kExprI32Ior,
270 kExprThrow,
271 kExprUnreachable,
272 kExprElse,
273 kExprI32Const]).concat(varint32(128)).concat([
274 kExprEnd,
275 kExprI32Ior,
276 kExprCatch, 1,
277 kExprGetLocal, 1,
278 kExprI32Const]).concat(varint32(256)).concat([
279 kExprI32Ior,
280 kExprEnd,
281 ]))
282 .addLocals({i32_count: 2})
283 .exportFunc();
284
285 // Scenario 2: Catches an exception raised from the direct callee.
286 var kFromDirectCallee =
287 builder.addFunction("from_direct_callee", kSig_i_i)
288 .addBody([
289 kExprTry,
290 kExprGetLocal, 0,
291 kExprCallFunction, kArity1, kWasmThrowFunction,
292 kExprI32Const].concat(varint32(-1)).concat([
293 kExprCatch, 1,
294 kExprGetLocal, 1,
295 kExprEnd
296 ]))
297 .addLocals({i32_count: 1})
298 .exportFunc()
299 .index;
300
301 // Scenario 3: Catches an exception raised from an indirect callee.
302 var kFromIndirectCalleeHelper = kFromDirectCallee + 1;
303 builder.addFunction("from_indirect_callee_helper", kSig_v_ii)
304 .addBody([
305 kExprGetLocal, 0,
306 kExprI32Const, 0,
307 kExprI32GtS,
308 kExprIf,
309 kExprGetLocal, 0,
310 kExprI32Const, 1,
311 kExprI32Sub,
312 kExprGetLocal, 1,
313 kExprI32Const, 1,
314 kExprI32Sub,
315 kExprCallFunction, kArity2, kFromIndirectCalleeHelper,
316 kExprEnd,
317 kExprGetLocal, 1,
318 kExprCallFunction, kArity1, kWasmThrowFunction
319 ]);
320
321 builder.addFunction("from_indirect_callee", kSig_i_i)
322 .addBody([
323 kExprTry,
324 kExprGetLocal, 0,
325 kExprI32Const, 0,
326 kExprCallFunction, kArity2, kFromIndirectCalleeHelper,
327 kExprI32Const].concat(varint32(-1)).concat([
titzer 2016/09/28 12:53:31 The concats here are a little messy. Maybe just al
John 2016/09/28 13:37:18 Done.
328 kExprCatch, 1,
329 kExprGetLocal, 1,
330 kExprEnd
331 ]))
332 .addLocals({i32_count: 1})
333 .exportFunc();
334
335 // Scenario 4: Catches an exception raised in JS.
336 builder.addFunction("from_js", kSig_i_i)
337 .addBody([
338 kExprTry,
339 kExprGetLocal, 0,
340 kExprCallImport, kArity1, kJSThrowI,
341 kExprI32Const].concat(varint32(-1)).concat([
342 kExprCatch, 1,
343 kExprGetLocal, 1,
344 kExprEnd,
345 ]))
346 .addLocals({i32_count: 1})
347 .exportFunc();
348
349 // Scenario 5: Does not catch an exception raised in JS if it is not a
350 // number.
351 builder.addFunction("string_from_js", kSig_v_v)
352 .addBody([
353 kExprCallImport, kArity0, kJSThrowString,
354 ])
355 .exportFunc();
356
357 builder.addFunction("fp_from_js", kSig_v_v)
358 .addBody([
359 kExprCallImport, kArity0, kJSThrowFP,
360 ])
361 .exportFunc();
362
363 builder.addFunction("large_from_js", kSig_v_v)
364 .addBody([
365 kExprCallImport, kArity0, kJSThrowLarge,
366 ])
367 .exportFunc();
368
369 builder.addFunction("undefined_from_js", kSig_v_v)
370 .addBody([
371 kExprCallImport, kArity0, kJSThrowUndefined,
372 ])
373 .exportFunc();
374
375 return builder.instantiate({
376 throw_i: throw_value,
377 throw_string: throw_string,
378 throw_fp: throw_fp,
379 throw_large, throw_large,
380 throw_undefined: throw_undefined
381 });
382 })();
383
384 // Check the test_catch exists.
385 assertFalse(test_catch === undefined);
386 assertFalse(test_catch === null);
387 assertFalse(test_catch === 0);
388 assertEquals("object", typeof test_catch.exports);
389 assertEquals("function", typeof test_catch.exports.same_scope);
390 assertEquals("function", typeof test_catch.exports.same_scope_ignore);
391 assertEquals("function", typeof test_catch.exports.same_scope_multiple);
392 assertEquals("function", typeof test_catch.exports.from_direct_callee);
393 assertEquals("function", typeof test_catch.exports.from_indirect_callee);
394 assertEquals("function", typeof test_catch.exports.from_js);
395 assertEquals("function", typeof test_catch.exports.string_from_js);
396
397 assertEquals(63, test_catch.exports.same_scope(0));
398 assertEquals(1024, test_catch.exports.same_scope(1024));
399 assertEquals(-3, test_catch.exports.same_scope(-3));
400 assertEquals(1024, test_catch.exports.same_scope_ignore(1024));
401 assertEquals(0x7FFFFFFF, test_catch.exports.same_scope_ignore(0x7FFFFFFF));
402 assertEquals(-1, test_catch.exports.same_scope_ignore(-1));
403 assertEquals(293, test_catch.exports.same_scope_multiple(1));
404 assertEquals(298, test_catch.exports.same_scope_multiple(2));
405 assertEquals(338, test_catch.exports.same_scope_multiple(3));
406 assertEquals(146, test_catch.exports.same_scope_multiple(0));
407 assertEquals(-10024, test_catch.exports.from_direct_callee(-10024));
408 assertEquals(3334333, test_catch.exports.from_direct_callee(3334333));
409 assertEquals(-1, test_catch.exports.from_direct_callee(0xFFFFFFFF));
410 assertEquals(0x7FFFFFFF, test_catch.exports.from_direct_callee(0x7FFFFFFF));
411 assertEquals(-10, test_catch.exports.from_indirect_callee(10));
412 assertEquals(-77, test_catch.exports.from_indirect_callee(77));
413 assertEquals(10, test_catch.exports.from_js(10));
414 assertEquals(-10, test_catch.exports.from_js(-10));
415
416 assertThrowsEquals(test_catch.exports.string_from_js, "use wasm;");
417 assertThrowsEquals(test_catch.exports.large_from_js, 1e+28);
418 assertThrowsEquals(test_catch.exports.undefined_from_js, undefined);
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698