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