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. 31 function f(a) { 32 a[0] = 0; 33 a[1] = 0; 34 } 35 36 var a = new Int32Array(2); 37 for (var i = 0; i < 5; i++) { 38 f(a); 39 } 40 %OptimizeFunctionOnNextCall(f); 41 f(a); 42 43 assertEquals(0, a[0]); 44 assertEquals(0, a[1]); 45 46 // No-parameter constructor should fail right now. 47 function abfunc1() { 48 return new ArrayBuffer(); 49 } 50 assertThrows(abfunc1); 51 52 // Test derivation from an ArrayBuffer 53 var ab = new ArrayBuffer(12); 54 var derived_uint8 = new Uint8Array(ab); 55 assertEquals(12, derived_uint8.length); 56 var derived_uint32 = new Uint32Array(ab); 57 assertEquals(3, derived_uint32.length); 58 var derived_uint32_2 = new Uint32Array(ab,4); 59 assertEquals(2, derived_uint32_2.length); 60 var derived_uint32_3 = new Uint32Array(ab,4,1); 61 assertEquals(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. 65 function abfunc3() { 66 new Uint32Array(ab,4,3); 67 } 68 assertThrows(abfunc3); 69 function abfunc4() { 70 new Uint32Array(ab,16); 71 } 72 assertThrows(abfunc4); 73 74 // The given byteOffset must be a multiple of the element size of the specific 75 // type, otherwise an exception is raised. 76 function abfunc5() { 77 new Uint32Array(ab,5); 78 } 79 assertThrows(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. 84 var ab2 = new ArrayBuffer(13); 85 function abfunc6() { 86 new Uint32Array(ab2,4); 87 } 88 assertThrows(abfunc6); 89 90 // Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is 91 // "constant", but not read-only). 92 a = new Int32Array(2); 93 assertEquals(4, a.BYTES_PER_ELEMENT); 94 a.BYTES_PER_ELEMENT = 42; 95 assertEquals(42, a.BYTES_PER_ELEMENT); 96 a = new Uint8Array(2); 97 assertEquals(1, a.BYTES_PER_ELEMENT); 98 a = new Int16Array(2); 99 assertEquals(2, a.BYTES_PER_ELEMENT); 100 101 // Test Float64Arrays. 102 function get(a, index) { 103 return a[index]; 104 } 105 function set(a, index, value) { 106 a[index] = value; 107 } 108 function temp() { 109 var array = new Float64Array(2); 110 for (var i = 0; i < 5; i++) { 111 set(array, 0, 2.5); 112 assertEquals(2.5, array[0]); 113 } 114 %OptimizeFunctionOnNextCall(set); 115 set(array, 0, 2.5); 116 assertEquals(2.5, array[0]); 117 set(array, 1, 3.5); 118 assertEquals(3.5, array[1]); 119 for (var i = 0; i < 5; i++) { 120 assertEquals(2.5, get(array, 0)); 121 assertEquals(3.5, array[1]); 122 } 123 %OptimizeFunctionOnNextCall(get); 124 assertEquals(2.5, get(array, 0)); 125 assertEquals(3.5, get(array, 1)); 126 } 127 128 // Test non-number parameters. 129 var array_with_length_from_non_number = new Int32Array("2"); 130 assertEquals(2, array_with_length_from_non_number.length); 131 array_with_length_from_non_number = new Int32Array(undefined); 132 assertEquals(0, array_with_length_from_non_number.length); 133 var foo = { valueOf: function() { return 3; } }; 134 array_with_length_from_non_number = new Int32Array(foo); 135 assertEquals(3, array_with_length_from_non_number.length); 136 foo = { toString: function() { return "4"; } }; 137 array_with_length_from_non_number = new Int32Array(foo); 138 assertEquals(4, array_with_length_from_non_number.length); 139 140 141 // Test loads and stores. 142 types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, 143 Uint32Array, PixelArray, Float32Array, Float64Array]; 144 145 test_result_nan = [NaN, 0, 0, 0, 0, 0, 0, 0, NaN, NaN]; 146 test_result_low_int = [-1, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1, -1]; 147 test_result_low_double = [-1.25, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1.25, -1.25]; 148 test_result_middle = [253.75, -3, 253, 253, 253, 253, 253, 254, 253.75, 253.75]; 149 test_result_high_int = [256, 0, 0, 256, 256, 256, 256, 255, 256, 256]; 150 test_result_high_double = [256.25, 0, 0, 256, 256, 256, 256, 255, 256.25, 256.25]; 151 152 const kElementCount = 40; 153 154 function test_load(array, sum) { 155 for (var i = 0; i < kElementCount; i++) { 156 sum += array[i]; 157 } 158 return sum; 159 } 160 161 function test_load_const_key(array, sum) { 162 sum += array[0]; 163 sum += array[1]; 164 sum += array[2]; 165 return sum; 166 } 167 168 function test_store(array, sum) { 169 for (var i = 0; i < kElementCount; i++) { 170 sum += array[i] = i+1; 171 } 172 return sum; 173 } 174 175 function 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 182 function zero() { 183 return 0.0; 184 } 185 186 function test_store_middle_tagged(array, sum) { 187 array[0] = 253.75; 188 return array[0]; 189 } 190 191 function test_store_high_tagged(array, sum) { 192 array[0] = 256.25; 193 return array[0]; 194 } 195 196 function test_store_middle_double(array, sum) { 197 array[0] = 253.75 + zero(); // + forces double type feedback 198 return array[0]; 199 } 200 201 function test_store_high_double(array, sum) { 202 array[0] = 256.25 + zero(); // + forces double type feedback 203 return array[0]; 204 } 205 206 function test_store_high_double(array, sum) { 207 array[0] = 256.25; 208 return array[0]; 209 } 210 211 function test_store_low_int(array, sum) { 212 array[0] = -1; 213 return array[0]; 214 } 215 216 function test_store_low_tagged(array, sum) { 217 array[0] = -1.25; 218 return array[0]; 219 } 220 221 function test_store_low_double(array, sum) { 222 array[0] = -1.25 + zero(); // + forces double type feedback 223 return array[0]; 224 } 225 226 function test_store_high_int(array, sum) { 227 array[0] = 256; 228 return array[0]; 229 } 230 231 function test_store_nan(array, sum) { 232 array[0] = NaN; 233 return array[0]; 234 } 235 236 const kRuns = 10; 237 238 function 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 250 function 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 259 for (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 323 function store_float32_undefined(ext_array) { 324 ext_array[0] = undefined; 325 } 326 327 var float32_array = new Float32Array(1); 328 // Make sure runtime does it right 329 store_float32_undefined(float32_array); 330 assertTrue(isNaN(float32_array[0])); 331 // Make sure the ICs do it right 332 store_float32_undefined(float32_array); 333 assertTrue(isNaN(float32_array[0])); 334 // Make sure that Cranskshft does it right. 335 %OptimizeFunctionOnNextCall(store_float32_undefined); 336 store_float32_undefined(float32_array); 337 assertTrue(isNaN(float32_array[0])); 338 339 function store_float64_undefined(ext_array) { 340 ext_array[0] = undefined; 341 } 342 343 var float64_array = new Float64Array(1); 344 // Make sure runtime does it right 345 store_float64_undefined(float64_array); 346 assertTrue(isNaN(float64_array[0])); 347 // Make sure the ICs do it right 348 store_float64_undefined(float64_array); 349 assertTrue(isNaN(float64_array[0])); 350 // Make sure that Cranskshft does it right. 351 %OptimizeFunctionOnNextCall(store_float64_undefined); 352 store_float64_undefined(float64_array); 353 assertTrue(isNaN(float64_array[0])); 354