external-array.js revision 85b71799222b55eb5dd74ea26efe0c64ab655c8c
1// Copyright 2011 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// Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is 47// "constant", but not read-only). 48a = new Int32Array(2); 49assertEquals(4, a.BYTES_PER_ELEMENT); 50a.BYTES_PER_ELEMENT = 42; 51assertEquals(42, a.BYTES_PER_ELEMENT); 52a = new Uint8Array(2); 53assertEquals(1, a.BYTES_PER_ELEMENT); 54a = new Int16Array(2); 55assertEquals(2, a.BYTES_PER_ELEMENT); 56 57// Test Float64Arrays. 58function get(a, index) { 59 return a[index]; 60} 61function set(a, index, value) { 62 a[index] = value; 63} 64function temp() { 65var array = new Float64Array(2); 66for (var i = 0; i < 5; i++) { 67 set(array, 0, 2.5); 68 assertEquals(2.5, array[0]); 69} 70%OptimizeFunctionOnNextCall(set); 71set(array, 0, 2.5); 72assertEquals(2.5, array[0]); 73set(array, 1, 3.5); 74assertEquals(3.5, array[1]); 75for (var i = 0; i < 5; i++) { 76 assertEquals(2.5, get(array, 0)); 77 assertEquals(3.5, array[1]); 78} 79%OptimizeFunctionOnNextCall(get); 80assertEquals(2.5, get(array, 0)); 81assertEquals(3.5, get(array, 1)); 82} 83 84// Test non-number parameters. 85var array_with_length_from_non_number = new Int32Array("2"); 86assertEquals(2, array_with_length_from_non_number.length); 87array_with_length_from_non_number = new Int32Array(undefined); 88assertEquals(0, array_with_length_from_non_number.length); 89var foo = { valueOf: function() { return 3; } }; 90array_with_length_from_non_number = new Int32Array(foo); 91assertEquals(3, array_with_length_from_non_number.length); 92foo = { toString: function() { return "4"; } }; 93array_with_length_from_non_number = new Int32Array(foo); 94assertEquals(4, array_with_length_from_non_number.length); 95 96 97// Test loads and stores. 98types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, 99 Uint32Array, PixelArray, Float32Array, Float64Array]; 100 101test_result_nan = [NaN, 0, 0, 0, 0, 0, 0, 0, NaN, NaN]; 102test_result_low_int = [-1, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1, -1]; 103test_result_low_double = [-1.25, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1.25, -1.25]; 104test_result_middle = [253.75, -3, 253, 253, 253, 253, 253, 254, 253.75, 253.75]; 105test_result_high_int = [256, 0, 0, 256, 256, 256, 256, 255, 256, 256]; 106test_result_high_double = [256.25, 0, 0, 256, 256, 256, 256, 255, 256.25, 256.25]; 107 108const kElementCount = 40; 109 110function test_load(array, sum) { 111 for (var i = 0; i < kElementCount; i++) { 112 sum += array[i]; 113 } 114 return sum; 115} 116 117function test_load_const_key(array, sum) { 118 sum += array[0]; 119 sum += array[1]; 120 sum += array[2]; 121 return sum; 122} 123 124function test_store(array, sum) { 125 for (var i = 0; i < kElementCount; i++) { 126 sum += array[i] = i+1; 127 } 128 return sum; 129} 130 131function test_store_const_key(array, sum) { 132 sum += array[0] = 1; 133 sum += array[1] = 2; 134 sum += array[2] = 3; 135 return sum; 136} 137 138function zero() { 139 return 0.0; 140} 141 142function test_store_middle_tagged(array, sum) { 143 array[0] = 253.75; 144 return array[0]; 145} 146 147function test_store_high_tagged(array, sum) { 148 array[0] = 256.25; 149 return array[0]; 150} 151 152function test_store_middle_double(array, sum) { 153 array[0] = 253.75 + zero(); // + forces double type feedback 154 return array[0]; 155} 156 157function test_store_high_double(array, sum) { 158 array[0] = 256.25 + zero(); // + forces double type feedback 159 return array[0]; 160} 161 162function test_store_high_double(array, sum) { 163 array[0] = 256.25; 164 return array[0]; 165} 166 167function test_store_low_int(array, sum) { 168 array[0] = -1; 169 return array[0]; 170} 171 172function test_store_low_tagged(array, sum) { 173 array[0] = -1.25; 174 return array[0]; 175} 176 177function test_store_low_double(array, sum) { 178 array[0] = -1.25 + zero(); // + forces double type feedback 179 return array[0]; 180} 181 182function test_store_high_int(array, sum) { 183 array[0] = 256; 184 return array[0]; 185} 186 187function test_store_nan(array, sum) { 188 array[0] = NaN; 189 return array[0]; 190} 191 192const kRuns = 10; 193 194function run_test(test_func, array, expected_result) { 195 for (var i = 0; i < 5; i++) test_func(array, 0); 196 %OptimizeFunctionOnNextCall(test_func); 197 var sum = 0; 198 for (var i = 0; i < kRuns; i++) { 199 sum = test_func(array, sum); 200 } 201 assertEquals(expected_result, sum); 202 %DeoptimizeFunction(test_func); 203 gc(); // Makes V8 forget about type information for test_func. 204} 205 206function run_bounds_test(test_func, array, expected_result) { 207 assertEquals(undefined, a[kElementCount]); 208 a[kElementCount] = 456; 209 assertEquals(undefined, a[kElementCount]); 210 assertEquals(undefined, a[kElementCount+1]); 211 a[kElementCount+1] = 456; 212 assertEquals(undefined, a[kElementCount+1]); 213} 214 215for (var t = 0; t < types.length; t++) { 216 var type = types[t]; 217 var a = new type(kElementCount); 218 219 for (var i = 0; i < kElementCount; i++) { 220 a[i] = i; 221 } 222 223 // Run test functions defined above. 224 run_test(test_load, a, 780 * kRuns); 225 run_test(test_load_const_key, a, 3 * kRuns); 226 run_test(test_store, a, 820 * kRuns); 227 run_test(test_store_const_key, a, 6 * kRuns); 228 run_test(test_store_low_int, a, test_result_low_int[t]); 229 run_test(test_store_low_double, a, test_result_low_double[t]); 230 run_test(test_store_low_tagged, a, test_result_low_double[t]); 231 run_test(test_store_high_int, a, test_result_high_int[t]); 232 run_test(test_store_nan, a, test_result_nan[t]); 233 run_test(test_store_middle_double, a, test_result_middle[t]); 234 run_test(test_store_middle_tagged, a, test_result_middle[t]); 235 run_test(test_store_high_double, a, test_result_high_double[t]); 236 run_test(test_store_high_tagged, a, test_result_high_double[t]); 237 238 // Test the correct behavior of the |length| property (which is read-only). 239 if (t != 0) { 240 assertEquals(kElementCount, a.length); 241 a.length = 2; 242 assertEquals(kElementCount, a.length); 243 assertTrue(delete a.length); 244 a.length = 2; 245 assertEquals(2, a.length); 246 247 // Make sure bounds checks are handled correctly for external arrays. 248 run_bounds_test(a); 249 run_bounds_test(a); 250 run_bounds_test(a); 251 %OptimizeFunctionOnNextCall(run_bounds_test); 252 run_bounds_test(a); 253 %DeoptimizeFunction(run_bounds_test); 254 gc(); // Makes V8 forget about type information for test_func. 255 256 } 257 258 function array_load_set_smi_check(a) { 259 return a[0] = a[0] = 1; 260 } 261 262 array_load_set_smi_check(a); 263 array_load_set_smi_check(0); 264 265 function array_load_set_smi_check2(a) { 266 return a[0] = a[0] = 1; 267 } 268 269 array_load_set_smi_check2(a); 270 %OptimizeFunctionOnNextCall(array_load_set_smi_check2); 271 array_load_set_smi_check2(a); 272 array_load_set_smi_check2(0); 273 %DeoptimizeFunction(array_load_set_smi_check2); 274 gc(); // Makes V8 forget about type information for array_load_set_smi_check. 275} 276