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 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); 485