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 37support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6)); 38 39if (support_smi_only_arrays) { 40 print("Tests include smi-only arrays."); 41} else { 42 print("Tests do NOT include smi-only arrays."); 43} 44 45if (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