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