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 --smi-only-arrays --expose-gc 29 30 // Ensure that ElementsKind transitions in various situations are hoisted (or 31 // not hoisted) correctly, don't change the semantics programs and don't trigger 32 // deopt through hoisting in important situations. 33 34 support_smi_only_arrays = %HasFastSmiOnlyElements(new Array(1,2,3,4,5,6)); 35 36 if (support_smi_only_arrays) { 37 print("Tests include smi-only arrays."); 38 } else { 39 print("Tests do NOT include smi-only arrays."); 40 } 41 42 // Force existing ICs from previous stress runs to be flushed, otherwise the 43 // assumptions in this test about when deoptimizations get triggered are not 44 // valid. 45 gc(); 46 47 if (support_smi_only_arrays) { 48 // Make sure that a simple elements array transitions inside a loop before 49 // stores to an array gets hoisted in a way that doesn't generate a deopt in 50 // simple cases.} 51 function testDoubleConversion4(a) { 52 var object = new Object(); 53 a[0] = 0; 54 var count = 3; 55 do { 56 a[0] = object; 57 } while (--count > 0); 58 } 59 60 testDoubleConversion4(new Array(5)); 61 %OptimizeFunctionOnNextCall(testDoubleConversion4); 62 testDoubleConversion4(new Array(5)); 63 testDoubleConversion4(new Array(5)); 64 assertTrue(2 != %GetOptimizationStatus(testDoubleConversion4)); 65 66 // Make sure that non-element related map checks that are not preceded by 67 // transitions in a loop still get hoisted in a way that doesn't generate a 68 // deopt in simple cases. 69 function testExactMapHoisting(a) { 70 var object = new Object(); 71 a.foo = 0; 72 a[0] = 0; 73 a[1] = 1; 74 var count = 3; 75 do { 76 a.foo = object; // This map check should be hoistable 77 a[1] = object; 78 result = a.foo == object && a[1] == object; 79 } while (--count > 0); 80 } 81 82 testExactMapHoisting(new Array(5)); 83 %OptimizeFunctionOnNextCall(testExactMapHoisting); 84 testExactMapHoisting(new Array(5)); 85 testExactMapHoisting(new Array(5)); 86 assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting)); 87 88 // Make sure that non-element related map checks do NOT get hoisted if they 89 // depend on an elements transition before them and it's not possible to hoist 90 // that transition. 91 function testExactMapHoisting2(a) { 92 var object = new Object(); 93 a.foo = 0; 94 a[0] = 0; 95 a[1] = 1; 96 var count = 3; 97 do { 98 if (a.bar === undefined) { 99 a[1] = 2.5; 100 } 101 a.foo = object; // This map check should NOT be hoistable because it 102 // includes a check for the FAST_ELEMENTS map as well as 103 // the FAST_DOUBLE_ELEMENTS map, which depends on the 104 // double transition above in the if, which cannot be 105 // hoisted. 106 } while (--count > 0); 107 } 108 109 testExactMapHoisting2(new Array(5)); 110 %OptimizeFunctionOnNextCall(testExactMapHoisting2); 111 testExactMapHoisting2(new Array(5)); 112 testExactMapHoisting2(new Array(5)); 113 assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting2)); 114 115 // Make sure that non-element related map checks do get hoisted if they use 116 // the transitioned map for the check and all transitions that they depend 117 // upon can hoisted, too. 118 function testExactMapHoisting3(a) { 119 var object = new Object(); 120 a.foo = 0; 121 a[0] = 0; 122 a[1] = 1; 123 var count = 3; 124 do { 125 a[1] = 2.5; 126 a.foo = object; // This map check should be hoistable because all elements 127 // transitions in the loop can also be hoisted. 128 } while (--count > 0); 129 } 130 131 var add_transition = new Array(5); 132 add_transition.foo = 0; 133 add_transition[0] = new Object(); // For FAST_ELEMENT transition to be created 134 testExactMapHoisting3(new Array(5)); 135 %OptimizeFunctionOnNextCall(testExactMapHoisting3); 136 testExactMapHoisting3(new Array(5)); 137 testExactMapHoisting3(new Array(5)); 138 assertTrue(2 != %GetOptimizationStatus(testExactMapHoisting3)); 139 140 function testDominatingTransitionHoisting1(a) { 141 var object = new Object(); 142 a[0] = 0; 143 var count = 3; 144 do { 145 if (a.baz != true) { 146 a[1] = 2.5; 147 } 148 a[0] = object; 149 } while (--count > 3); 150 } 151 152 testDominatingTransitionHoisting1(new Array(5)); 153 %OptimizeFunctionOnNextCall(testDominatingTransitionHoisting1); 154 testDominatingTransitionHoisting1(new Array(5)); 155 testDominatingTransitionHoisting1(new Array(5)); 156 assertTrue(2 != %GetOptimizationStatus(testDominatingTransitionHoisting1)); 157 158 function testHoistingWithSideEffect(a) { 159 var object = new Object(); 160 a[0] = 0; 161 var count = 3; 162 do { 163 assertTrue(true); 164 a[0] = object; 165 } while (--count > 3); 166 } 167 168 testHoistingWithSideEffect(new Array(5)); 169 %OptimizeFunctionOnNextCall(testHoistingWithSideEffect); 170 testHoistingWithSideEffect(new Array(5)); 171 testHoistingWithSideEffect(new Array(5)); 172 assertTrue(2 != %GetOptimizationStatus(testHoistingWithSideEffect)); 173 174 function testStraightLineDupeElinination(a,b,c,d,e,f) { 175 var count = 3; 176 do { 177 assertTrue(true); 178 a[0] = b; 179 a[1] = c; 180 a[2] = d; 181 assertTrue(true); 182 a[3] = e; // TransitionElementsKind should be eliminated despite call. 183 a[4] = f; 184 } while (--count > 3); 185 } 186 187 testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,0,.5); 188 testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,0,.5,0); 189 testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,0,.5,0,0); 190 testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),0,.5,0,0,0); 191 testStraightLineDupeElinination(new Array(0, 0, 0, 0, 0),.5,0,0,0,0); 192 testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,0,.5); 193 testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,0,.5,0); 194 testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,0,.5,0,0); 195 testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),0,.5,0,0,0); 196 testStraightLineDupeElinination(new Array(.1,.1,.1,.1,.1),.5,0,0,0,0); 197 testStraightLineDupeElinination(new Array(5),.5,0,0,0,0); 198 testStraightLineDupeElinination(new Array(5),0,.5,0,0,0); 199 testStraightLineDupeElinination(new Array(5),0,0,.5,0,0); 200 testStraightLineDupeElinination(new Array(5),0,0,0,.5,0); 201 testStraightLineDupeElinination(new Array(5),0,0,0,0,.5); 202 testStraightLineDupeElinination(new Array(5),.5,0,0,0,0); 203 testStraightLineDupeElinination(new Array(5),0,.5,0,0,0); 204 testStraightLineDupeElinination(new Array(5),0,0,.5,0,0); 205 testStraightLineDupeElinination(new Array(5),0,0,0,.5,0); 206 testStraightLineDupeElinination(new Array(5),0,0,0,0,.5); 207 %OptimizeFunctionOnNextCall(testStraightLineDupeElinination); 208 testStraightLineDupeElinination(new Array(5)); 209 testStraightLineDupeElinination(new Array(5)); 210 assertTrue(2 != %GetOptimizationStatus(testStraightLineDupeElinination)); 211 } 212