blob: 4f29c05693fa5fdf7bebb1d455cea4899d76dc06 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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: --allow-natives-syntax
Ben Murdochda12d292016-06-02 14:46:10 +010029// Flags: --harmony-sloppy --harmony-sloppy-let
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000030
31// Check that the following functions are optimizable.
32var functions = [ f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14,
33 f15, f16, f17, f18, f19, f20, f21, f22, f23, f24, f25, f26,
34 f27, f28, f29, f30, f31, f32, f33];
35
36for (var i = 0; i < functions.length; ++i) {
37 var func = functions[i];
38 print("Testing:");
39 print(func);
40 for (var j = 0; j < 10; ++j) {
41 func(12);
42 }
43 %OptimizeFunctionOnNextCall(func);
44 func(12);
45 assertOptimized(func);
46}
47
48function f1() { }
49
50function f2(x) { }
51
52function f3() {
53 let x;
54}
55
56function f4() {
57 function foo() {
58 }
59}
60
61function f5() {
62 let x = 1;
63}
64
65function f6() {
66 const x = 1;
67}
68
69function f7(x) {
70 return x;
71}
72
73function f8() {
74 let x;
75 return x;
76}
77
78function f9() {
79 function x() {
80 }
81 return x;
82}
83
84function f10(x) {
85 x = 1;
86}
87
88function f11() {
89 let x;
90 x = 1;
91}
92
93function f12() {
94 function x() {};
95 x = 1;
96}
97
98function f13(x) {
99 (function() { x; });
100}
101
102function f14() {
103 let x;
104 (function() { x; });
105}
106
107function f15() {
108 function x() {
109 }
110 (function() { x; });
111}
112
113function f16() {
114 let x = 1;
115 (function() { x; });
116}
117
118function f17() {
119 const x = 1;
120 (function() { x; });
121}
122
123function f18(x) {
124 return x;
125 (function() { x; });
126}
127
128function f19() {
129 let x;
130 return x;
131 (function() { x; });
132}
133
134function f20() {
135 function x() {
136 }
137 return x;
138 (function() { x; });
139}
140
141function f21(x) {
142 x = 1;
143 (function() { x; });
144}
145
146function f22() {
147 let x;
148 x = 1;
149 (function() { x; });
150}
151
152function f23() {
153 function x() { }
154 x = 1;
155 (function() { x; });
156}
157
158function f24() {
159 let x = 1;
160 {
161 let x = 2;
162 {
163 let x = 3;
164 assertEquals(3, x);
165 }
166 assertEquals(2, x);
167 }
168 assertEquals(1, x);
169}
170
171function f25() {
172 {
173 let x = 2;
174 L: {
175 let x = 3;
176 assertEquals(3, x);
177 break L;
178 assertTrue(false);
179 }
180 assertEquals(2, x);
181 }
182 assertTrue(true);
183}
184
185function f26() {
186 {
187 let x = 1;
188 L: {
189 let x = 2;
190 {
191 let x = 3;
192 assertEquals(3, x);
193 break L;
194 assertTrue(false);
195 }
196 assertTrue(false);
197 }
198 assertEquals(1, x);
199 }
200}
201
202
203function f27() {
204 do {
205 let x = 4;
206 assertEquals(4,x);
207 {
208 let x = 5;
209 assertEquals(5, x);
210 continue;
211 assertTrue(false);
212 }
213 } while (false);
214}
215
216function f28() {
217 label: for (var i = 0; i < 10; ++i) {
218 let x = 'middle' + i;
219 for (var j = 0; j < 10; ++j) {
220 let x = 'inner' + j;
221 continue label;
222 }
223 }
224}
225
226function f29() {
227 // Verify that the context is correctly set in the stack frame after exiting
228 // from with.
229
230 let x = 'outer';
231 label: {
232 let x = 'inner';
233 break label;
234 }
235 f(); // The context could be restored from the stack after the call.
236 assertEquals('outer', x);
237
238 function f() {
239 assertEquals('outer', x);
240 };
241}
242
243function f30() {
244 let x = 'outer';
245 for (var i = 0; i < 10; ++i) {
246 let x = 'inner';
247 continue;
248 }
249 f();
250 assertEquals('outer', x);
251
252 function f() {
253 assertEquals('outer', x);
254 };
255}
256
257function f31() {
258 {
259 let x = 'outer';
260 label: for (var i = 0; assertEquals('outer', x), i < 10; ++i) {
261 let x = 'middle' + i;
262 {
263 let x = 'inner' + j;
264 continue label;
265 }
266 }
267 assertEquals('outer', x);
268 }
269}
270
271var c = true;
272
273function f32() {
274 {
275 let x = 'outer';
276 L: {
277 {
278 let x = 'inner';
279 if (c) {
280 break L;
281 }
282 }
283 foo();
284 }
285 }
286
287 function foo() {
288 return 'bar';
289 }
290}
291
292function f33() {
293 {
294 let x = 'outer';
295 L: {
296 {
297 let x = 'inner';
298 if (c) {
299 break L;
300 }
301 foo();
302 }
303 }
304 }
305
306 function foo() {
307 return 'bar';
308 }
309}
310
311function TestThrow() {
312 function f() {
313 let x = 'outer';
314 {
315 let x = 'inner';
316 throw x;
317 }
318 }
319 for (var i = 0; i < 5; i++) {
320 try {
321 f();
322 } catch (e) {
323 assertEquals('inner', e);
324 }
325 }
326 %OptimizeFunctionOnNextCall(f);
327 try {
328 f();
329 } catch (e) {
330 assertEquals('inner', e);
331 }
332 assertOptimized(f);
333}
334
335TestThrow();
336
337// Test that temporal dead zone semantics for function and block scoped
338// let bindings are handled by the optimizing compiler.
339
340function TestFunctionLocal(s) {
341 'use strict';
342 var func = eval("(function baz(){" + s + "; })");
343 print("Testing:");
344 print(func);
345 for (var i = 0; i < 5; ++i) {
346 try {
347 func();
348 assertUnreachable();
349 } catch (e) {
350 assertInstanceof(e, ReferenceError);
351 }
352 }
353 %OptimizeFunctionOnNextCall(func);
354 try {
355 func();
356 assertUnreachable();
357 } catch (e) {
358 assertInstanceof(e, ReferenceError);
359 }
360}
361
362function TestFunctionContext(s) {
363 'use strict';
364 var func = eval("(function baz(){ " + s + "; (function() { x; }); })");
365 print("Testing:");
366 print(func);
367 for (var i = 0; i < 5; ++i) {
368 print(i);
369 try {
370 func();
371 assertUnreachable();
372 } catch (e) {
373 assertInstanceof(e, ReferenceError);
374 }
375 }
376 print("optimize");
377 %OptimizeFunctionOnNextCall(func);
378 try {
379 print("call");
380 func();
381 assertUnreachable();
382 } catch (e) {
383 print("catch");
384 assertInstanceof(e, ReferenceError);
385 }
386}
387
388function TestBlockLocal(s) {
389 'use strict';
390 var func = eval("(function baz(){ { " + s + "; } })");
391 print("Testing:");
392 print(func);
393 for (var i = 0; i < 5; ++i) {
394 try {
395 func();
396 assertUnreachable();
397 } catch (e) {
398 assertInstanceof(e, ReferenceError);
399 }
400 }
401 %OptimizeFunctionOnNextCall(func);
402 try {
403 func();
404 assertUnreachable();
405 } catch (e) {
406 assertInstanceof(e, ReferenceError);
407 }
408}
409
410function TestBlockContext(s) {
411 'use strict';
412 var func = eval("(function baz(){ { " + s + "; (function() { x; }); } })");
413 print("Testing:");
414 print(func);
415 for (var i = 0; i < 5; ++i) {
416 print(i);
417 try {
418 func();
419 assertUnreachable();
420 } catch (e) {
421 assertInstanceof(e, ReferenceError);
422 }
423 }
424 print("optimize");
425 %OptimizeFunctionOnNextCall(func);
426 try {
427 print("call");
428 func();
429 assertUnreachable();
430 } catch (e) {
431 print("catch");
432 assertInstanceof(e, ReferenceError);
433 }
434}
435
436function TestAll(s) {
437 TestFunctionLocal(s);
438 TestFunctionContext(s);
439 TestBlockLocal(s);
440 TestBlockContext(s);
441}
442
443// Use before initialization in declaration statement.
444TestAll('let x = x + 1');
445TestAll('let x = x += 1');
446TestAll('let x = x++');
447TestAll('let x = ++x');
448TestAll('const x = x + 1');
449
450// Use before initialization in prior statement.
451TestAll('x + 1; let x;');
452TestAll('x = 1; let x;');
453TestAll('x += 1; let x;');
454TestAll('++x; let x;');
455TestAll('x++; let x;');
456TestAll('let y = x; const x = 1;');
457
458
459function f(x) {
460 let y = x + 42;
461 return y;
462}
463
464function g(x) {
465 {
466 let y = x + 42;
467 return y;
468 }
469}
470
471for (var i=0; i<10; i++) {
472 f(i);
473 g(i);
474}
475
476%OptimizeFunctionOnNextCall(f);
477%OptimizeFunctionOnNextCall(g);
478
479f(12);
480g(12);
481
482assertTrue(%GetOptimizationStatus(f) != 2);
483assertTrue(%GetOptimizationStatus(g) != 2);