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. 33var 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 37for (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 49function f1() { } 50 51function f2(x) { } 52 53function f3() { 54 let x; 55} 56 57function f4() { 58 function foo() { 59 } 60} 61 62function f5() { 63 let x = 1; 64} 65 66function f6() { 67 const x = 1; 68} 69 70function f7(x) { 71 return x; 72} 73 74function f8() { 75 let x; 76 return x; 77} 78 79function f9() { 80 function x() { 81 } 82 return x; 83} 84 85function f10(x) { 86 x = 1; 87} 88 89function f11() { 90 let x; 91 x = 1; 92} 93 94function f12() { 95 function x() {}; 96 x = 1; 97} 98 99function f13(x) { 100 (function() { x; }); 101} 102 103function f14() { 104 let x; 105 (function() { x; }); 106} 107 108function f15() { 109 function x() { 110 } 111 (function() { x; }); 112} 113 114function f16() { 115 let x = 1; 116 (function() { x; }); 117} 118 119function f17() { 120 const x = 1; 121 (function() { x; }); 122} 123 124function f18(x) { 125 return x; 126 (function() { x; }); 127} 128 129function f19() { 130 let x; 131 return x; 132 (function() { x; }); 133} 134 135function f20() { 136 function x() { 137 } 138 return x; 139 (function() { x; }); 140} 141 142function f21(x) { 143 x = 1; 144 (function() { x; }); 145} 146 147function f22() { 148 let x; 149 x = 1; 150 (function() { x; }); 151} 152 153function f23() { 154 function x() { } 155 x = 1; 156 (function() { x; }); 157} 158 159function 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 172function 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 186function 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 204function 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 217function 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 227function 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 244function 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 258function 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 272var c = true; 273 274function 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 293function 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 312function 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 336TestThrow(); 337 338// Test that temporal dead zone semantics for function and block scoped 339// let bindings are handled by the optimizing compiler. 340 341function 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 363function 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 389function 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 411function 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 437function TestAll(s) { 438 TestFunctionLocal(s); 439 TestFunctionContext(s); 440 TestBlockLocal(s); 441 TestBlockContext(s); 442} 443 444// Use before initialization in declaration statement. 445TestAll('let x = x + 1'); 446TestAll('let x = x += 1'); 447TestAll('let x = x++'); 448TestAll('let x = ++x'); 449TestAll('const x = x + 1'); 450 451// Use before initialization in prior statement. 452TestAll('x + 1; let x;'); 453TestAll('x = 1; let x;'); 454TestAll('x += 1; let x;'); 455TestAll('++x; let x;'); 456TestAll('x++; let x;'); 457TestAll('let y = x; const x = 1;'); 458 459 460function f(x) { 461 let y = x + 42; 462 return y; 463} 464 465function g(x) { 466 { 467 let y = x + 42; 468 return y; 469 } 470} 471 472for (var i=0; i<10; i++) { 473 f(i); 474 g(i); 475} 476 477%OptimizeFunctionOnNextCall(f); 478%OptimizeFunctionOnNextCall(g); 479 480f(12); 481g(12); 482 483assertTrue(%GetOptimizationStatus(f) != 2); 484assertTrue(%GetOptimizationStatus(g) != 2); 485