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. 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); 484