Home | History | Annotate | Download | only in mjsunit
      1 // Copyright 2012 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 --smi-only-arrays --notrack-allocation-sites
     29 
     30 // No tracking of allocation sites because it interfers with the semantics
     31 // the test is trying to ensure.
     32 
     33 // Ensure that ElementsKind transitions in various situations are hoisted (or
     34 // not hoisted) correctly, don't change the semantics programs and don't trigger
     35 // deopt through hoisting in important situations.
     36 
     37 support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6));
     38 
     39 if (support_smi_only_arrays) {
     40   print("Tests include smi-only arrays.");
     41 } else {
     42   print("Tests do NOT include smi-only arrays.");
     43 }
     44 
     45 if (support_smi_only_arrays) {
     46   // Make sure that a simple elements array transitions inside a loop before
     47   // stores to an array gets hoisted in a way that doesn't generate a deopt in
     48   // simple cases.}
     49   function testDoubleConversion4(a) {
     50     var object = new Object();
     51     a[0] = 0;
     52     var count = 3;
     53     do {
     54       a[0] = object;
     55     } while (--count > 0);
     56   }
     57 
     58   testDoubleConversion4(new Array(5));
     59   testDoubleConversion4(new Array(5));  // Call twice to make sure that second
     60                                         // store is a transition and not
     61                                         // optimistically MONOMORPHIC
     62   %OptimizeFunctionOnNextCall(testDoubleConversion4);
     63   testDoubleConversion4(new Array(5));
     64   testDoubleConversion4(new Array(5));
     65   assertOptimized(testDoubleConversion4);
     66   %ClearFunctionTypeFeedback(testDoubleConversion4);
     67 
     68   // Make sure that non-element related map checks that are not preceded by
     69   // transitions in a loop still get hoisted in a way that doesn't generate a
     70   // deopt in simple cases.
     71   function testExactMapHoisting(a) {
     72     var object = new Object();
     73     a.foo = {};
     74     a[0] = 0;
     75     a[1] = 1;
     76     var count = 3;
     77     do {
     78       a.foo = object;  // This map check should be hoistable
     79       a[1] = object;
     80       result = a.foo == object && a[1] == object;
     81     } while (--count > 0);
     82   }
     83 
     84   testExactMapHoisting(new Array(5));
     85   testExactMapHoisting(new Array(5));  // Call twice to make sure that second
     86                                        // store is a transition and not
     87                                        // optimistically MONOMORPHIC
     88   %OptimizeFunctionOnNextCall(testExactMapHoisting);
     89   testExactMapHoisting(new Array(5));
     90   testExactMapHoisting(new Array(5));
     91   assertOptimized(testExactMapHoisting);
     92   %ClearFunctionTypeFeedback(testExactMapHoisting);
     93 
     94   // Make sure that non-element related map checks do NOT get hoisted if they
     95   // depend on an elements transition before them and it's not possible to hoist
     96   // that transition.
     97   function testExactMapHoisting2(a) {
     98     var object = new Object();
     99     a.foo = 0;
    100     a[0] = 0;
    101     a[1] = 1;
    102     var count = 3;
    103     do {
    104       if (a.bar === undefined) {
    105         a[1] = 2.5;
    106       }
    107       a.foo = object;  // This map check should NOT be hoistable because it
    108                        // includes a check for the FAST_ELEMENTS map as well as
    109                        // the FAST_DOUBLE_ELEMENTS map, which depends on the
    110                        // double transition above in the if, which cannot be
    111                        // hoisted.
    112     } while (--count > 0);
    113   }
    114 
    115   testExactMapHoisting2(new Array(5));
    116   testExactMapHoisting2(new Array(5));  // Call twice to make sure that second
    117                                         // store is a transition and not
    118                                         // optimistically MONOMORPHIC
    119   %OptimizeFunctionOnNextCall(testExactMapHoisting2);
    120   testExactMapHoisting2(new Array(5));
    121   testExactMapHoisting2(new Array(5));
    122   // Temporarily disabled - see bug 2176.
    123   // assertOptimized(testExactMapHoisting2);
    124   %ClearFunctionTypeFeedback(testExactMapHoisting2);
    125 
    126   // Make sure that non-element related map checks do get hoisted if they use
    127   // the transitioned map for the check and all transitions that they depend
    128   // upon can hoisted, too.
    129   function testExactMapHoisting3(a) {
    130     var object = new Object();
    131     a.foo = null;
    132     a[0] = 0;
    133     a[1] = 1;
    134     var count = 3;
    135     do {
    136       a[1] = 2.5;
    137       a.foo = object;  // This map check should be hoistable because all elements
    138                        // transitions in the loop can also be hoisted.
    139     } while (--count > 0);
    140   }
    141 
    142   var add_transition = new Array(5);
    143   add_transition.foo = 0;
    144   add_transition[0] = new Object();  // For FAST_ELEMENT transition to be created
    145   testExactMapHoisting3(new Array(5));
    146   testExactMapHoisting3(new Array(5));  // Call twice to make sure that second
    147                                         // store is a transition and not
    148                                         // optimistically MONOMORPHIC
    149   %OptimizeFunctionOnNextCall(testExactMapHoisting3);
    150   testExactMapHoisting3(new Array(5));
    151   testExactMapHoisting3(new Array(5));
    152   assertOptimized(testExactMapHoisting3);
    153   %ClearFunctionTypeFeedback(testExactMapHoisting3);
    154 
    155   function testDominatingTransitionHoisting1(a) {
    156     var object = new Object();
    157     a[0] = 0;
    158     var count = 3;
    159     do {
    160       if (a.baz != true) {
    161         a[1] = 2.5;
    162       }
    163       a[0] = object;
    164     } while (--count > 3);
    165   }
    166 
    167   /*
    168   testDominatingTransitionHoisting1(new Array(5));
    169   testDominatingTransitionHoisting1(new Array(5));  // Call twice to make sure
    170                                                     // that second store is a
    171                                                     // transition and not
    172                                                     // optimistically MONOMORPHIC
    173   %OptimizeFunctionOnNextCall(testDominatingTransitionHoisting1);
    174   testDominatingTransitionHoisting1(new Array(5));
    175   testDominatingTransitionHoisting1(new Array(5));
    176   // TODO(verwaest) With current changes the elements transition gets hoisted
    177   // above the access, causing a deopt. We should update the type of access
    178   // rather than forbid hoisting the transition.
    179   assertOptimized(testDominatingTransitionHoisting1);
    180   %ClearFunctionTypeFeedback(testDominatingTransitionHoisting1);
    181   */
    182 
    183   function testHoistingWithSideEffect(a) {
    184     var object = new Object();
    185     a[0] = 0;
    186     var count = 3;
    187     do {
    188       assertTrue(true);
    189       a[0] = object;
    190     } while (--count > 3);
    191   }
    192 
    193   testHoistingWithSideEffect(new Array(5));
    194   testHoistingWithSideEffect(new Array(5));  // Call twice to make sure that
    195                                              // second store is a transition and
    196                                              // not optimistically MONOMORPHIC
    197   %OptimizeFunctionOnNextCall(testHoistingWithSideEffect);
    198   testHoistingWithSideEffect(new Array(5));
    199   testHoistingWithSideEffect(new Array(5));
    200   assertOptimized(testHoistingWithSideEffect);
    201   %ClearFunctionTypeFeedback(testHoistingWithSideEffect);
    202 
    203   function testStraightLineDupeElinination(a,b,c,d,e,f) {
    204     var count = 3;
    205     do {
    206       assertTrue(true);
    207       a[0] = b;
    208       a[1] = c;
    209       a[2] = d;
    210       assertTrue(true);
    211       a[3] = e;  // TransitionElementsKind should be eliminated despite call.
    212       a[4] = f;
    213     } while (--count > 3);
    214   }
    215 
    216   testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,0,.5);
    217   testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,.5,0);
    218   testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,.5,0,0);
    219   testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,.5,0,0,0);
    220   testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),.5,0,0,0,0);
    221   testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,0,.5);
    222   testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,.5,0);
    223   testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,.5,0,0);
    224   testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,.5,0,0,0);
    225   testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),.5,0,0,0,0);
    226   testStraightLineDupeElinination(new Array(5),.5,0,0,0,0);
    227   testStraightLineDupeElinination(new Array(5),0,.5,0,0,0);
    228   testStraightLineDupeElinination(new Array(5),0,0,.5,0,0);
    229   testStraightLineDupeElinination(new Array(5),0,0,0,.5,0);
    230   testStraightLineDupeElinination(new Array(5),0,0,0,0,.5);
    231   testStraightLineDupeElinination(new Array(5),.5,0,0,0,0);
    232   testStraightLineDupeElinination(new Array(5),0,.5,0,0,0);
    233   testStraightLineDupeElinination(new Array(5),0,0,.5,0,0);
    234   testStraightLineDupeElinination(new Array(5),0,0,0,.5,0);
    235   testStraightLineDupeElinination(new Array(5),0,0,0,0,.5);
    236   %OptimizeFunctionOnNextCall(testStraightLineDupeElinination);
    237   testStraightLineDupeElinination(new Array(5),0,0,0,0,0);
    238   testStraightLineDupeElinination(new Array(5),0,0,0,0,0);
    239   assertOptimized(testStraightLineDupeElinination);
    240   %ClearFunctionTypeFeedback(testStraightLineDupeElinination);
    241 }
    242