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 --expose-gc 29 30// This is a regression test for overlapping key and value registers. 31function f(a) { 32 a[0] = 0; 33 a[1] = 0; 34} 35 36var a = new Int32Array(2); 37for (var i = 0; i < 5; i++) { 38 f(a); 39} 40%OptimizeFunctionOnNextCall(f); 41f(a); 42 43assertEquals(0, a[0]); 44assertEquals(0, a[1]); 45 46// No-parameter constructor should fail right now. 47function abfunc1() { 48 return new ArrayBuffer(); 49} 50assertThrows(abfunc1); 51 52// Test derivation from an ArrayBuffer 53var ab = new ArrayBuffer(12); 54var derived_uint8 = new Uint8Array(ab); 55assertEquals(12, derived_uint8.length); 56var derived_uint32 = new Uint32Array(ab); 57assertEquals(3, derived_uint32.length); 58var derived_uint32_2 = new Uint32Array(ab,4); 59assertEquals(2, derived_uint32_2.length); 60var derived_uint32_3 = new Uint32Array(ab,4,1); 61assertEquals(1, derived_uint32_3.length); 62 63// If a given byteOffset and length references an area beyond the end of the 64// ArrayBuffer an exception is raised. 65function abfunc3() { 66 new Uint32Array(ab,4,3); 67} 68assertThrows(abfunc3); 69function abfunc4() { 70 new Uint32Array(ab,16); 71} 72assertThrows(abfunc4); 73 74// The given byteOffset must be a multiple of the element size of the specific 75// type, otherwise an exception is raised. 76function abfunc5() { 77 new Uint32Array(ab,5); 78} 79assertThrows(abfunc5); 80 81// If length is not explicitly specified, the length of the ArrayBuffer minus 82// the byteOffset must be a multiple of the element size of the specific type, 83// or an exception is raised. 84var ab2 = new ArrayBuffer(13); 85function abfunc6() { 86 new Uint32Array(ab2,4); 87} 88assertThrows(abfunc6); 89 90// Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is 91// "constant", but not read-only). 92a = new Int32Array(2); 93assertEquals(4, a.BYTES_PER_ELEMENT); 94a.BYTES_PER_ELEMENT = 42; 95assertEquals(42, a.BYTES_PER_ELEMENT); 96a = new Uint8Array(2); 97assertEquals(1, a.BYTES_PER_ELEMENT); 98a = new Int16Array(2); 99assertEquals(2, a.BYTES_PER_ELEMENT); 100 101// Test Float64Arrays. 102function get(a, index) { 103 return a[index]; 104} 105function set(a, index, value) { 106 a[index] = value; 107} 108function temp() { 109var array = new Float64Array(2); 110for (var i = 0; i < 5; i++) { 111 set(array, 0, 2.5); 112 assertEquals(2.5, array[0]); 113} 114%OptimizeFunctionOnNextCall(set); 115set(array, 0, 2.5); 116assertEquals(2.5, array[0]); 117set(array, 1, 3.5); 118assertEquals(3.5, array[1]); 119for (var i = 0; i < 5; i++) { 120 assertEquals(2.5, get(array, 0)); 121 assertEquals(3.5, array[1]); 122} 123%OptimizeFunctionOnNextCall(get); 124assertEquals(2.5, get(array, 0)); 125assertEquals(3.5, get(array, 1)); 126} 127 128// Test non-number parameters. 129var array_with_length_from_non_number = new Int32Array("2"); 130assertEquals(2, array_with_length_from_non_number.length); 131array_with_length_from_non_number = new Int32Array(undefined); 132assertEquals(0, array_with_length_from_non_number.length); 133var foo = { valueOf: function() { return 3; } }; 134array_with_length_from_non_number = new Int32Array(foo); 135assertEquals(3, array_with_length_from_non_number.length); 136foo = { toString: function() { return "4"; } }; 137array_with_length_from_non_number = new Int32Array(foo); 138assertEquals(4, array_with_length_from_non_number.length); 139 140 141// Test loads and stores. 142types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, 143 Uint32Array, PixelArray, Float32Array, Float64Array]; 144 145test_result_nan = [NaN, 0, 0, 0, 0, 0, 0, 0, NaN, NaN]; 146test_result_low_int = [-1, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1, -1]; 147test_result_low_double = [-1.25, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1.25, -1.25]; 148test_result_middle = [253.75, -3, 253, 253, 253, 253, 253, 254, 253.75, 253.75]; 149test_result_high_int = [256, 0, 0, 256, 256, 256, 256, 255, 256, 256]; 150test_result_high_double = [256.25, 0, 0, 256, 256, 256, 256, 255, 256.25, 256.25]; 151 152const kElementCount = 40; 153 154function test_load(array, sum) { 155 for (var i = 0; i < kElementCount; i++) { 156 sum += array[i]; 157 } 158 return sum; 159} 160 161function test_load_const_key(array, sum) { 162 sum += array[0]; 163 sum += array[1]; 164 sum += array[2]; 165 return sum; 166} 167 168function test_store(array, sum) { 169 for (var i = 0; i < kElementCount; i++) { 170 sum += array[i] = i+1; 171 } 172 return sum; 173} 174 175function test_store_const_key(array, sum) { 176 sum += array[0] = 1; 177 sum += array[1] = 2; 178 sum += array[2] = 3; 179 return sum; 180} 181 182function zero() { 183 return 0.0; 184} 185 186function test_store_middle_tagged(array, sum) { 187 array[0] = 253.75; 188 return array[0]; 189} 190 191function test_store_high_tagged(array, sum) { 192 array[0] = 256.25; 193 return array[0]; 194} 195 196function test_store_middle_double(array, sum) { 197 array[0] = 253.75 + zero(); // + forces double type feedback 198 return array[0]; 199} 200 201function test_store_high_double(array, sum) { 202 array[0] = 256.25 + zero(); // + forces double type feedback 203 return array[0]; 204} 205 206function test_store_high_double(array, sum) { 207 array[0] = 256.25; 208 return array[0]; 209} 210 211function test_store_low_int(array, sum) { 212 array[0] = -1; 213 return array[0]; 214} 215 216function test_store_low_tagged(array, sum) { 217 array[0] = -1.25; 218 return array[0]; 219} 220 221function test_store_low_double(array, sum) { 222 array[0] = -1.25 + zero(); // + forces double type feedback 223 return array[0]; 224} 225 226function test_store_high_int(array, sum) { 227 array[0] = 256; 228 return array[0]; 229} 230 231function test_store_nan(array, sum) { 232 array[0] = NaN; 233 return array[0]; 234} 235 236const kRuns = 10; 237 238function run_test(test_func, array, expected_result) { 239 for (var i = 0; i < 5; i++) test_func(array, 0); 240 %OptimizeFunctionOnNextCall(test_func); 241 var sum = 0; 242 for (var i = 0; i < kRuns; i++) { 243 sum = test_func(array, sum); 244 } 245 assertEquals(expected_result, sum); 246 %DeoptimizeFunction(test_func); 247 gc(); // Makes V8 forget about type information for test_func. 248} 249 250function run_bounds_test(test_func, array, expected_result) { 251 assertEquals(undefined, a[kElementCount]); 252 a[kElementCount] = 456; 253 assertEquals(undefined, a[kElementCount]); 254 assertEquals(undefined, a[kElementCount+1]); 255 a[kElementCount+1] = 456; 256 assertEquals(undefined, a[kElementCount+1]); 257} 258 259for (var t = 0; t < types.length; t++) { 260 var type = types[t]; 261 var a = new type(kElementCount); 262 263 for (var i = 0; i < kElementCount; i++) { 264 a[i] = i; 265 } 266 267 // Run test functions defined above. 268 run_test(test_load, a, 780 * kRuns); 269 run_test(test_load_const_key, a, 3 * kRuns); 270 run_test(test_store, a, 820 * kRuns); 271 run_test(test_store_const_key, a, 6 * kRuns); 272 run_test(test_store_low_int, a, test_result_low_int[t]); 273 run_test(test_store_low_double, a, test_result_low_double[t]); 274 run_test(test_store_low_tagged, a, test_result_low_double[t]); 275 run_test(test_store_high_int, a, test_result_high_int[t]); 276 run_test(test_store_nan, a, test_result_nan[t]); 277 run_test(test_store_middle_double, a, test_result_middle[t]); 278 run_test(test_store_middle_tagged, a, test_result_middle[t]); 279 run_test(test_store_high_double, a, test_result_high_double[t]); 280 run_test(test_store_high_tagged, a, test_result_high_double[t]); 281 282 // Test the correct behavior of the |length| property (which is read-only). 283 if (t != 0) { 284 assertEquals(kElementCount, a.length); 285 a.length = 2; 286 assertEquals(kElementCount, a.length); 287 assertTrue(delete a.length); 288 a.length = 2; 289 assertEquals(2, a.length); 290 291 // Make sure bounds checks are handled correctly for external arrays. 292 run_bounds_test(a); 293 run_bounds_test(a); 294 run_bounds_test(a); 295 %OptimizeFunctionOnNextCall(run_bounds_test); 296 run_bounds_test(a); 297 %DeoptimizeFunction(run_bounds_test); 298 gc(); // Makes V8 forget about type information for test_func. 299 300 } 301 302 function array_load_set_smi_check(a) { 303 return a[0] = a[0] = 1; 304 } 305 306 array_load_set_smi_check(a); 307 array_load_set_smi_check(0); 308 309 function array_load_set_smi_check2(a) { 310 return a[0] = a[0] = 1; 311 } 312 313 array_load_set_smi_check2(a); 314 %OptimizeFunctionOnNextCall(array_load_set_smi_check2); 315 array_load_set_smi_check2(a); 316 array_load_set_smi_check2(0); 317 %DeoptimizeFunction(array_load_set_smi_check2); 318 gc(); // Makes V8 forget about type information for array_load_set_smi_check. 319} 320 321// Check handling of undefined in 32- and 64-bit external float arrays. 322 323function store_float32_undefined(ext_array) { 324 ext_array[0] = undefined; 325} 326 327var float32_array = new Float32Array(1); 328// Make sure runtime does it right 329store_float32_undefined(float32_array); 330assertTrue(isNaN(float32_array[0])); 331// Make sure the ICs do it right 332store_float32_undefined(float32_array); 333assertTrue(isNaN(float32_array[0])); 334// Make sure that Cranskshft does it right. 335%OptimizeFunctionOnNextCall(store_float32_undefined); 336store_float32_undefined(float32_array); 337assertTrue(isNaN(float32_array[0])); 338 339function store_float64_undefined(ext_array) { 340 ext_array[0] = undefined; 341} 342 343var float64_array = new Float64Array(1); 344// Make sure runtime does it right 345store_float64_undefined(float64_array); 346assertTrue(isNaN(float64_array[0])); 347// Make sure the ICs do it right 348store_float64_undefined(float64_array); 349assertTrue(isNaN(float64_array[0])); 350// Make sure that Cranskshft does it right. 351%OptimizeFunctionOnNextCall(store_float64_undefined); 352store_float64_undefined(float64_array); 353assertTrue(isNaN(float64_array[0])); 354