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