OLD | NEW |
| (Empty) |
1 // Copyright 2011 the V8 project authors. All rights reserved. | |
2 // Redistribution and use in source and binary forms, with or without | |
3 // modification, are permitted provided that the following conditions are | |
4 // met: | |
5 // | |
6 // * Redistributions of source code must retain the above copyright | |
7 // notice, this list of conditions and the following disclaimer. | |
8 // * Redistributions in binary form must reproduce the above | |
9 // copyright notice, this list of conditions and the following | |
10 // disclaimer in the documentation and/or other materials provided | |
11 // with the distribution. | |
12 // * Neither the name of Google Inc. nor the names of its | |
13 // contributors may be used to endorse or promote products derived | |
14 // from this software without specific prior written permission. | |
15 // | |
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
27 | |
28 // Flags: --harmony-scoping --allow-natives-syntax | |
29 | |
30 "use strict"; | |
31 | |
32 // Check that the following functions are optimizable. | |
33 var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, | |
34 f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26, | |
35 f27, f28, f29, f30, f31, f32, f33]; | |
36 | |
37 for (var i = 0; i < functions.length; ++i) { | |
38 var func = functions[i]; | |
39 print("Testing:"); | |
40 print(func); | |
41 for (var j = 0; j < 10; ++j) { | |
42 func(12); | |
43 } | |
44 %OptimizeFunctionOnNextCall(func); | |
45 func(12); | |
46 assertOptimized(func); | |
47 } | |
48 | |
49 function f1() { } | |
50 | |
51 function f2(x) { } | |
52 | |
53 function f3() { | |
54 let x; | |
55 } | |
56 | |
57 function f4() { | |
58 function foo() { | |
59 } | |
60 } | |
61 | |
62 function f5() { | |
63 let x = 1; | |
64 } | |
65 | |
66 function f6() { | |
67 const x = 1; | |
68 } | |
69 | |
70 function f7(x) { | |
71 return x; | |
72 } | |
73 | |
74 function f8() { | |
75 let x; | |
76 return x; | |
77 } | |
78 | |
79 function f9() { | |
80 function x() { | |
81 } | |
82 return x; | |
83 } | |
84 | |
85 function f10(x) { | |
86 x = 1; | |
87 } | |
88 | |
89 function f11() { | |
90 let x; | |
91 x = 1; | |
92 } | |
93 | |
94 function f12() { | |
95 function x() {}; | |
96 x = 1; | |
97 } | |
98 | |
99 function f13(x) { | |
100 (function() { x; }); | |
101 } | |
102 | |
103 function f14() { | |
104 let x; | |
105 (function() { x; }); | |
106 } | |
107 | |
108 function f15() { | |
109 function x() { | |
110 } | |
111 (function() { x; }); | |
112 } | |
113 | |
114 function f16() { | |
115 let x = 1; | |
116 (function() { x; }); | |
117 } | |
118 | |
119 function f17() { | |
120 const x = 1; | |
121 (function() { x; }); | |
122 } | |
123 | |
124 function f18(x) { | |
125 return x; | |
126 (function() { x; }); | |
127 } | |
128 | |
129 function f19() { | |
130 let x; | |
131 return x; | |
132 (function() { x; }); | |
133 } | |
134 | |
135 function f20() { | |
136 function x() { | |
137 } | |
138 return x; | |
139 (function() { x; }); | |
140 } | |
141 | |
142 function f21(x) { | |
143 x = 1; | |
144 (function() { x; }); | |
145 } | |
146 | |
147 function f22() { | |
148 let x; | |
149 x = 1; | |
150 (function() { x; }); | |
151 } | |
152 | |
153 function f23() { | |
154 function x() { } | |
155 x = 1; | |
156 (function() { x; }); | |
157 } | |
158 | |
159 function f24() { | |
160 let x = 1; | |
161 { | |
162 let x = 2; | |
163 { | |
164 let x = 3; | |
165 assertEquals(3, x); | |
166 } | |
167 assertEquals(2, x); | |
168 } | |
169 assertEquals(1, x); | |
170 } | |
171 | |
172 function f25() { | |
173 { | |
174 let x = 2; | |
175 L: { | |
176 let x = 3; | |
177 assertEquals(3, x); | |
178 break L; | |
179 assertTrue(false); | |
180 } | |
181 assertEquals(2, x); | |
182 } | |
183 assertTrue(true); | |
184 } | |
185 | |
186 function f26() { | |
187 { | |
188 let x = 1; | |
189 L: { | |
190 let x = 2; | |
191 { | |
192 let x = 3; | |
193 assertEquals(3, x); | |
194 break L; | |
195 assertTrue(false); | |
196 } | |
197 assertTrue(false); | |
198 } | |
199 assertEquals(1, x); | |
200 } | |
201 } | |
202 | |
203 | |
204 function f27() { | |
205 do { | |
206 let x = 4; | |
207 assertEquals(4,x); | |
208 { | |
209 let x = 5; | |
210 assertEquals(5, x); | |
211 continue; | |
212 assertTrue(false); | |
213 } | |
214 } while (false); | |
215 } | |
216 | |
217 function f28() { | |
218 label: for (var i = 0; i < 10; ++i) { | |
219 let x = 'middle' + i; | |
220 for (var j = 0; j < 10; ++j) { | |
221 let x = 'inner' + j; | |
222 continue label; | |
223 } | |
224 } | |
225 } | |
226 | |
227 function f29() { | |
228 // Verify that the context is correctly set in the stack frame after exiting | |
229 // from with. | |
230 | |
231 let x = 'outer'; | |
232 label: { | |
233 let x = 'inner'; | |
234 break label; | |
235 } | |
236 f(); // The context could be restored from the stack after the call. | |
237 assertEquals('outer', x); | |
238 | |
239 function f() { | |
240 assertEquals('outer', x); | |
241 }; | |
242 } | |
243 | |
244 function f30() { | |
245 let x = 'outer'; | |
246 for (var i = 0; i < 10; ++i) { | |
247 let x = 'inner'; | |
248 continue; | |
249 } | |
250 f(); | |
251 assertEquals('outer', x); | |
252 | |
253 function f() { | |
254 assertEquals('outer', x); | |
255 }; | |
256 } | |
257 | |
258 function f31() { | |
259 { | |
260 let x = 'outer'; | |
261 label: for (var i = 0; assertEquals('outer', x), i < 10; ++i) { | |
262 let x = 'middle' + i; | |
263 { | |
264 let x = 'inner' + j; | |
265 continue label; | |
266 } | |
267 } | |
268 assertEquals('outer', x); | |
269 } | |
270 } | |
271 | |
272 var c = true; | |
273 | |
274 function f32() { | |
275 { | |
276 let x = 'outer'; | |
277 L: { | |
278 { | |
279 let x = 'inner'; | |
280 if (c) { | |
281 break L; | |
282 } | |
283 } | |
284 foo(); | |
285 } | |
286 } | |
287 | |
288 function foo() { | |
289 return 'bar'; | |
290 } | |
291 } | |
292 | |
293 function f33() { | |
294 { | |
295 let x = 'outer'; | |
296 L: { | |
297 { | |
298 let x = 'inner'; | |
299 if (c) { | |
300 break L; | |
301 } | |
302 foo(); | |
303 } | |
304 } | |
305 } | |
306 | |
307 function foo() { | |
308 return 'bar'; | |
309 } | |
310 } | |
311 | |
312 function TestThrow() { | |
313 function f() { | |
314 let x = 'outer'; | |
315 { | |
316 let x = 'inner'; | |
317 throw x; | |
318 } | |
319 } | |
320 for (var i = 0; i < 5; i++) { | |
321 try { | |
322 f(); | |
323 } catch (e) { | |
324 assertEquals('inner', e); | |
325 } | |
326 } | |
327 %OptimizeFunctionOnNextCall(f); | |
328 try { | |
329 f(); | |
330 } catch (e) { | |
331 assertEquals('inner', e); | |
332 } | |
333 assertOptimized(f); | |
334 } | |
335 | |
336 TestThrow(); | |
337 | |
338 // Test that temporal dead zone semantics for function and block scoped | |
339 // let bindings are handled by the optimizing compiler. | |
340 | |
341 function TestFunctionLocal(s) { | |
342 'use strict'; | |
343 var func = eval("(function baz(){" + s + "; })"); | |
344 print("Testing:"); | |
345 print(func); | |
346 for (var i = 0; i < 5; ++i) { | |
347 try { | |
348 func(); | |
349 assertUnreachable(); | |
350 } catch (e) { | |
351 assertInstanceof(e, ReferenceError); | |
352 } | |
353 } | |
354 %OptimizeFunctionOnNextCall(func); | |
355 try { | |
356 func(); | |
357 assertUnreachable(); | |
358 } catch (e) { | |
359 assertInstanceof(e, ReferenceError); | |
360 } | |
361 } | |
362 | |
363 function TestFunctionContext(s) { | |
364 'use strict'; | |
365 var func = eval("(function baz(){ " + s + "; (function() { x; }); })"); | |
366 print("Testing:"); | |
367 print(func); | |
368 for (var i = 0; i < 5; ++i) { | |
369 print(i); | |
370 try { | |
371 func(); | |
372 assertUnreachable(); | |
373 } catch (e) { | |
374 assertInstanceof(e, ReferenceError); | |
375 } | |
376 } | |
377 print("optimize"); | |
378 %OptimizeFunctionOnNextCall(func); | |
379 try { | |
380 print("call"); | |
381 func(); | |
382 assertUnreachable(); | |
383 } catch (e) { | |
384 print("catch"); | |
385 assertInstanceof(e, ReferenceError); | |
386 } | |
387 } | |
388 | |
389 function TestBlockLocal(s) { | |
390 'use strict'; | |
391 var func = eval("(function baz(){ { " + s + "; } })"); | |
392 print("Testing:"); | |
393 print(func); | |
394 for (var i = 0; i < 5; ++i) { | |
395 try { | |
396 func(); | |
397 assertUnreachable(); | |
398 } catch (e) { | |
399 assertInstanceof(e, ReferenceError); | |
400 } | |
401 } | |
402 %OptimizeFunctionOnNextCall(func); | |
403 try { | |
404 func(); | |
405 assertUnreachable(); | |
406 } catch (e) { | |
407 assertInstanceof(e, ReferenceError); | |
408 } | |
409 } | |
410 | |
411 function TestBlockContext(s) { | |
412 'use strict'; | |
413 var func = eval("(function baz(){ { " + s + "; (function() { x; }); } })"); | |
414 print("Testing:"); | |
415 print(func); | |
416 for (var i = 0; i < 5; ++i) { | |
417 print(i); | |
418 try { | |
419 func(); | |
420 assertUnreachable(); | |
421 } catch (e) { | |
422 assertInstanceof(e, ReferenceError); | |
423 } | |
424 } | |
425 print("optimize"); | |
426 %OptimizeFunctionOnNextCall(func); | |
427 try { | |
428 print("call"); | |
429 func(); | |
430 assertUnreachable(); | |
431 } catch (e) { | |
432 print("catch"); | |
433 assertInstanceof(e, ReferenceError); | |
434 } | |
435 } | |
436 | |
437 function TestAll(s) { | |
438 TestFunctionLocal(s); | |
439 TestFunctionContext(s); | |
440 TestBlockLocal(s); | |
441 TestBlockContext(s); | |
442 } | |
443 | |
444 // Use before initialization in declaration statement. | |
445 TestAll('let x = x + 1'); | |
446 TestAll('let x = x += 1'); | |
447 TestAll('let x = x++'); | |
448 TestAll('let x = ++x'); | |
449 TestAll('const x = x + 1'); | |
450 | |
451 // Use before initialization in prior statement. | |
452 TestAll('x + 1; let x;'); | |
453 TestAll('x = 1; let x;'); | |
454 TestAll('x += 1; let x;'); | |
455 TestAll('++x; let x;'); | |
456 TestAll('x++; let x;'); | |
457 TestAll('let y = x; const x = 1;'); | |
458 | |
459 | |
460 function f(x) { | |
461 let y = x + 42; | |
462 return y; | |
463 } | |
464 | |
465 function g(x) { | |
466 { | |
467 let y = x + 42; | |
468 return y; | |
469 } | |
470 } | |
471 | |
472 for (var i=0; i<10; i++) { | |
473 f(i); | |
474 g(i); | |
475 } | |
476 | |
477 %OptimizeFunctionOnNextCall(f); | |
478 %OptimizeFunctionOnNextCall(g); | |
479 | |
480 f(12); | |
481 g(12); | |
482 | |
483 assertTrue(%GetOptimizationStatus(f) != 2); | |
484 assertTrue(%GetOptimizationStatus(g) != 2); | |
OLD | NEW |