Home | History | Annotate | Download | only in harmony
      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.
     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