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 30 // Verifies that the KeyedStoreIC correctly handles out-of-bounds stores 31 // to an array that grow it by a single element. Test functions are 32 // called twice to make sure that the IC is used, first call is handled 33 // by the runtime in the miss stub. 34 35 function array_store_1(a,b,c) { 36 return (a[b] = c); 37 } 38 39 // Check handling of the empty array. 40 var a = []; 41 array_store_1(a, 0, 1); 42 a = []; 43 array_store_1(a, 0, 1); 44 assertEquals(1, a[0]); 45 assertEquals(1, array_store_1([], 0, 1)); 46 47 a = []; 48 for (x=0;x<100000;++x) { 49 assertEquals(x, array_store_1(a, x, x)); 50 } 51 52 for (x=0;x<100000;++x) { 53 assertEquals(x, array_store_1([], 0, x)); 54 } 55 56 function array_store_2(a,b,c) { 57 return (a[b] = c); 58 } 59 60 a = []; 61 array_store_2(a, 0, 0.5); 62 a = []; 63 array_store_2(a, 0, 0.5); 64 assertEquals(0.5, a[0]); 65 assertEquals(0.5, array_store_2([], 0, 0.5)); 66 67 function array_store_3(a,b,c) { 68 return (a[b] = c); 69 } 70 71 x = new Object(); 72 a = []; 73 array_store_3(a, 0, x); 74 a = []; 75 array_store_3(a, 0, x); 76 assertEquals(x, a[0]); 77 assertEquals(x, array_store_3([], 0, x)); 78 79 // Check the handling of COW arrays 80 function makeCOW() { 81 return [1]; 82 } 83 84 function array_store_4(a,b,c) { 85 return (a[b] = c); 86 } 87 88 a = makeCOW(); 89 array_store_4(a, 1, 1); 90 a = makeCOW(); 91 array_store_4(a, 1, 1); 92 assertEquals(1, a[1]); 93 assertEquals(1, array_store_4([], 1, 1)); 94 95 function array_store_5(a,b,c) { 96 return (a[b] = c); 97 } 98 99 a = makeCOW(); 100 array_store_5(a, 1, 0.5); 101 a = makeCOW(); 102 array_store_5(a, 1, 0.5); 103 assertEquals(0.5, a[1]); 104 a = []; 105 assertEquals(0.5, array_store_5(a, 1, 0.5)); 106 assertEquals(undefined, a[0]); 107 assertEquals(0.5, a[1]); 108 109 function array_store_6(a,b,c) { 110 return (a[b] = c); 111 } 112 113 a = makeCOW(); 114 array_store_6(a, 1, x); 115 a = makeCOW(); 116 array_store_6(a, 1, x); 117 assertEquals(x, a[1]); 118 assertEquals(x, array_store_6([], 1, x)); 119 120 // Check the handling of mutable arrays. 121 a = new Array(1,2,3); 122 array_store_4(a, 3, 1); 123 a = new Array(1,2,3); 124 array_store_4(a, 3, 1); 125 assertEquals(1, a[3]); 126 assertEquals(1, array_store_4([], 3, 1)); 127 128 function array_store_5(a,b,c) { 129 return (a[b] = c); 130 } 131 132 a = new Array(1,2,3); 133 array_store_5(a, 3, 0.5); 134 a = new Array(1,2,3); 135 array_store_5(a, 3, 0.5); 136 assertEquals(0.5, a[3]); 137 assertEquals(0.5, array_store_5([], 3, 0.5)); 138 139 function array_store_6(a,b,c) { 140 return (a[b] = c); 141 } 142 143 a = new Array(1,2,3); 144 array_store_6(a, 3, x); 145 a = new Array(1,2,3); 146 array_store_6(a, 3, x); 147 assertEquals(x, a[3]); 148 assertEquals(x, array_store_6([], 3, x)); 149 150 function array_store_7(a,b,c) { 151 return (a[b] = c); 152 } 153 154 // Check the handling of mutable arrays of doubles 155 var a = new Array(0.5, 1.5); 156 array_store_7(a, 2, .5); 157 a = new Array(0.5, 1.5); 158 array_store_7(a, 2, .5); 159 assertEquals(0.5, a[2]); 160 a = new Array(0.5, 1.5); 161 assertEquals(0.5, array_store_7(a, 2, 0.5)); 162 163 for (x=0;x<100000;++x) { 164 a = new Array(0.5, 1.5); 165 assertEquals(x, array_store_7(a, 2, x)); 166 } 167 168 function array_store_8(a,b,c) { 169 return (a[b] = c); 170 } 171 172 var a = new Array(0.5, 1.5); 173 array_store_8(a, 2, .5); 174 a = new Array(0.5, 1.5); 175 array_store_8(a, 10, .5); 176 assertEquals(0.5, a[10]); 177 178 // Grow the empty array with a double store. 179 function array_store_9(a,b,c) { 180 return (a[b] = c); 181 } 182 183 var a = []; 184 array_store_9(a, 0, 0.5); 185 a = []; 186 array_store_1(a, 0, 0.5); 187 assertEquals(0.5, a[0]); 188 assertEquals(0.5, array_store_1([], 0, 0.5)); 189 190 191 // Verify that a grow store will deoptimize if the max gap (difference between 192 // the end of an array capacity and a new index) is passed. The wrapper is to 193 // make sure array_store_10 isn't inlined. 194 195 (function() { 196 function grow_store(a,b,c) { 197 a[b] = c; 198 } 199 200 a = new Array(1); 201 grow_store(a,1,1); 202 grow_store(a,2,1); 203 %OptimizeFunctionOnNextCall(grow_store); 204 grow_store(a,10,1); 205 assertOptimized(grow_store); 206 grow_store(a,2048,1); 207 assertUnoptimized(grow_store); 208 %ClearFunctionTypeFeedback(grow_store); 209 })(); 210 211 212 // Verify that a polymorphic store and grow IC when crankshafted is still 213 // a grow IC (earlier it would revert to a standard store in the polymorphic 214 // case). 215 (function() { 216 function f(o, k, v) { 217 o[k] = v; 218 } 219 220 a = [3.5]; 221 f(a, 1, "hi"); // DOUBLE packed array -> tagged packed grow 222 a = {}; 223 a.p = "property"; 224 a[0] = 1; 225 f(a, 0, 5.4); 226 227 %OptimizeFunctionOnNextCall(f); 228 // Should be a polymorphic grow stub. If not a grow stub it will deopt. 229 f(new Array("hi"), 1, 3); 230 assertOptimized(f); 231 %ClearFunctionTypeFeedback(f); 232 })(); 233 234 235 // Now verify that a polymorphic store (non-growing) IC when crankshafted WILL 236 // deopt if you pass an element out of bounds. 237 (function() { 238 function f(o, k, v) { 239 o[k] = v; 240 } 241 242 a = [3.5]; 243 f(a, 0, "hi"); // DOUBLE packed array -> tagged packed grow 244 a = {}; 245 a.p = "property"; 246 a[0] = 1; 247 f(a, 0, 5.4); 248 249 %OptimizeFunctionOnNextCall(f); 250 f(new Array("hi"), 0, 3); 251 assertOptimized(f); 252 // An attempt to grow should cause deopt 253 f(new Array("hi"), 1, 3); 254 assertUnoptimized(f); 255 %ClearFunctionTypeFeedback(f); 256 })(); 257