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