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 35function array_store_1(a,b,c) { 36 return (a[b] = c); 37} 38 39// Check handling of the empty array. 40var a = []; 41array_store_1(a, 0, 1); 42a = []; 43array_store_1(a, 0, 1); 44assertEquals(1, a[0]); 45assertEquals(1, array_store_1([], 0, 1)); 46 47a = []; 48for (x=0;x<100000;++x) { 49 assertEquals(x, array_store_1(a, x, x)); 50} 51 52for (x=0;x<100000;++x) { 53 assertEquals(x, array_store_1([], 0, x)); 54} 55 56function array_store_2(a,b,c) { 57 return (a[b] = c); 58} 59 60a = []; 61array_store_2(a, 0, 0.5); 62a = []; 63array_store_2(a, 0, 0.5); 64assertEquals(0.5, a[0]); 65assertEquals(0.5, array_store_2([], 0, 0.5)); 66 67function array_store_3(a,b,c) { 68 return (a[b] = c); 69} 70 71x = new Object(); 72a = []; 73array_store_3(a, 0, x); 74a = []; 75array_store_3(a, 0, x); 76assertEquals(x, a[0]); 77assertEquals(x, array_store_3([], 0, x)); 78 79// Check the handling of COW arrays 80function makeCOW() { 81 return [1]; 82} 83 84function array_store_4(a,b,c) { 85 return (a[b] = c); 86} 87 88a = makeCOW(); 89array_store_4(a, 1, 1); 90a = makeCOW(); 91array_store_4(a, 1, 1); 92assertEquals(1, a[1]); 93assertEquals(1, array_store_4([], 1, 1)); 94 95function array_store_5(a,b,c) { 96 return (a[b] = c); 97} 98 99a = makeCOW(); 100array_store_5(a, 1, 0.5); 101a = makeCOW(); 102array_store_5(a, 1, 0.5); 103assertEquals(0.5, a[1]); 104a = []; 105assertEquals(0.5, array_store_5(a, 1, 0.5)); 106assertEquals(undefined, a[0]); 107assertEquals(0.5, a[1]); 108 109function array_store_6(a,b,c) { 110 return (a[b] = c); 111} 112 113a = makeCOW(); 114array_store_6(a, 1, x); 115a = makeCOW(); 116array_store_6(a, 1, x); 117assertEquals(x, a[1]); 118assertEquals(x, array_store_6([], 1, x)); 119 120// Check the handling of mutable arrays. 121a = new Array(1,2,3); 122array_store_4(a, 3, 1); 123a = new Array(1,2,3); 124array_store_4(a, 3, 1); 125assertEquals(1, a[3]); 126assertEquals(1, array_store_4([], 3, 1)); 127 128function array_store_5(a,b,c) { 129 return (a[b] = c); 130} 131 132a = new Array(1,2,3); 133array_store_5(a, 3, 0.5); 134a = new Array(1,2,3); 135array_store_5(a, 3, 0.5); 136assertEquals(0.5, a[3]); 137assertEquals(0.5, array_store_5([], 3, 0.5)); 138 139function array_store_6(a,b,c) { 140 return (a[b] = c); 141} 142 143a = new Array(1,2,3); 144array_store_6(a, 3, x); 145a = new Array(1,2,3); 146array_store_6(a, 3, x); 147assertEquals(x, a[3]); 148assertEquals(x, array_store_6([], 3, x)); 149 150function array_store_7(a,b,c) { 151 return (a[b] = c); 152} 153 154// Check the handling of mutable arrays of doubles 155var a = new Array(0.5, 1.5); 156array_store_7(a, 2, .5); 157a = new Array(0.5, 1.5); 158array_store_7(a, 2, .5); 159assertEquals(0.5, a[2]); 160a = new Array(0.5, 1.5); 161assertEquals(0.5, array_store_7(a, 2, 0.5)); 162 163for (x=0;x<100000;++x) { 164 a = new Array(0.5, 1.5); 165 assertEquals(x, array_store_7(a, 2, x)); 166} 167 168function array_store_8(a,b,c) { 169 return (a[b] = c); 170} 171 172var a = new Array(0.5, 1.5); 173array_store_8(a, 2, .5); 174a = new Array(0.5, 1.5); 175array_store_8(a, 10, .5); 176assertEquals(0.5, a[10]); 177 178// Grow the empty array with a double store. 179function array_store_9(a,b,c) { 180 return (a[b] = c); 181} 182 183var a = []; 184array_store_9(a, 0, 0.5); 185a = []; 186array_store_1(a, 0, 0.5); 187assertEquals(0.5, a[0]); 188assertEquals(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