unbox-double-arrays.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// Test dictionary -> double elements -> dictionary elements round trip 29 30// Flags: --allow-natives-syntax --unbox-double-arrays --expose-gc 31var large_array_size = 100000; 32var approx_dict_to_elements_threshold = 70000; 33 34var name = 0; 35 36function expected_array_value(i) { 37 if ((i % 50) != 0) { 38 return i; 39 } else { 40 return i + 0.5; 41 } 42} 43 44function force_to_fast_double_array(a) { 45 a[large_array_size - 2] = 1; 46 for (var i= 0; i < approx_dict_to_elements_threshold; ++i ) { 47 a[i] = expected_array_value(i); 48 } 49 assertTrue(%HasFastDoubleElements(a)); 50} 51 52function make_object_like_array(size) { 53 obj = new Object(); 54 obj.length = size; 55 return obj; 56} 57 58function testOneArrayType(allocator) { 59 var large_array = new allocator(large_array_size); 60 force_to_fast_double_array(large_array); 61 var six = 6; 62 63 for (var i= 0; i < approx_dict_to_elements_threshold; i += 501 ) { 64 assertEquals(expected_array_value(i), large_array[i]); 65 } 66 67 // This function has a constant and won't get inlined. 68 function computed_6() { 69 return six; 70 } 71 72 // Multiple versions of the test function makes sure that IC/Crankshaft state 73 // doesn't get reused. 74 function test_various_loads(a, value_5, value_6, value_7) { 75 assertTrue(%HasFastDoubleElements(a)); 76 assertEquals(value_5, a[5]); 77 assertEquals(value_6, a[6]); 78 assertEquals(value_6, a[computed_6()]); // Test non-constant key 79 assertEquals(value_7, a[7]); 80 assertEquals(undefined, a[large_array_size-1]); 81 assertEquals(undefined, a[-1]); 82 assertEquals(large_array_size, a.length); 83 assertTrue(%HasFastDoubleElements(a)); 84 } 85 86 function test_various_loads2(a, value_5, value_6, value_7) { 87 assertTrue(%HasFastDoubleElements(a)); 88 assertEquals(value_5, a[5]); 89 assertEquals(value_6, a[6]); 90 assertEquals(value_6, a[computed_6()]); // Test non-constant key 91 assertEquals(value_7, a[7]); 92 assertEquals(undefined, a[large_array_size-1]); 93 assertEquals(undefined, a[-1]); 94 assertEquals(large_array_size, a.length); 95 assertTrue(%HasFastDoubleElements(a)); 96 } 97 98 function test_various_loads3(a, value_5, value_6, value_7) { 99 assertTrue(%HasFastDoubleElements(a)); 100 assertEquals(value_5, a[5]); 101 assertEquals(value_6, a[6]); 102 assertEquals(value_6, a[computed_6()]); // Test non-constant key 103 assertEquals(value_7, a[7]); 104 assertEquals(undefined, a[large_array_size-1]); 105 assertEquals(undefined, a[-1]); 106 assertEquals(large_array_size, a.length); 107 assertTrue(%HasFastDoubleElements(a)); 108 } 109 110 function test_various_loads4(a, value_5, value_6, value_7) { 111 assertTrue(%HasFastDoubleElements(a)); 112 assertEquals(value_5, a[5]); 113 assertEquals(value_6, a[6]); 114 assertEquals(value_6, a[computed_6()]); // Test non-constant key 115 assertEquals(value_7, a[7]); 116 assertEquals(undefined, a[large_array_size-1]); 117 assertEquals(undefined, a[-1]); 118 assertEquals(large_array_size, a.length); 119 assertTrue(%HasFastDoubleElements(a)); 120 } 121 122 function test_various_loads5(a, value_5, value_6, value_7) { 123 assertTrue(%HasFastDoubleElements(a)); 124 assertEquals(value_5, a[5]); 125 assertEquals(value_6, a[6]); 126 assertEquals(value_6, a[computed_6()]); // Test non-constant key 127 assertEquals(value_7, a[7]); 128 assertEquals(undefined, a[large_array_size-1]); 129 assertEquals(undefined, a[-1]); 130 assertEquals(large_array_size, a.length); 131 assertTrue(%HasFastDoubleElements(a)); 132 } 133 134 function test_various_loads6(a, value_5, value_6, value_7) { 135 assertTrue(%HasFastDoubleElements(a)); 136 assertEquals(value_5, a[5]); 137 assertEquals(value_6, a[6]); 138 assertEquals(value_6, a[computed_6()]); // Test non-constant key 139 assertEquals(value_7, a[7]); 140 assertEquals(undefined, a[large_array_size-1]); 141 assertEquals(undefined, a[-1]); 142 assertEquals(large_array_size, a.length); 143 assertTrue(%HasFastDoubleElements(a)); 144 } 145 146 function test_various_stores(a, value_5, value_6, value_7) { 147 assertTrue(%HasFastDoubleElements(a)); 148 a[5] = value_5; 149 a[computed_6()] = value_6; 150 a[7] = value_7; 151 assertTrue(%HasFastDoubleElements(a)); 152 } 153 154 // Test double and integer values 155 test_various_loads(large_array, 156 expected_array_value(5), 157 expected_array_value(6), 158 expected_array_value(7)); 159 test_various_loads(large_array, 160 expected_array_value(5), 161 expected_array_value(6), 162 expected_array_value(7)); 163 test_various_loads(large_array, 164 expected_array_value(5), 165 expected_array_value(6), 166 expected_array_value(7)); 167 %OptimizeFunctionOnNextCall(test_various_loads); 168 test_various_loads(large_array, 169 expected_array_value(5), 170 expected_array_value(6), 171 expected_array_value(7)); 172 173 // Test NaN values 174 test_various_stores(large_array, NaN, -NaN, expected_array_value(7)); 175 176 test_various_loads2(large_array, 177 NaN, 178 -NaN, 179 expected_array_value(7)); 180 test_various_loads2(large_array, 181 NaN, 182 -NaN, 183 expected_array_value(7)); 184 test_various_loads2(large_array, 185 NaN, 186 -NaN, 187 expected_array_value(7)); 188 %OptimizeFunctionOnNextCall(test_various_loads2); 189 test_various_loads2(large_array, 190 NaN, 191 -NaN, 192 expected_array_value(7)); 193 194 // Test Infinity values 195 test_various_stores(large_array, 196 Infinity, 197 -Infinity, 198 expected_array_value(7)); 199 200 test_various_loads3(large_array, 201 Infinity, 202 -Infinity, 203 expected_array_value(7)); 204 test_various_loads3(large_array, 205 Infinity, 206 -Infinity, 207 expected_array_value(7)); 208 test_various_loads3(large_array, 209 Infinity, 210 -Infinity, 211 expected_array_value(7)); 212 %OptimizeFunctionOnNextCall(test_various_loads3); 213 test_various_loads3(large_array, 214 Infinity, 215 -Infinity, 216 expected_array_value(7)); 217 218 // Test the hole for the default runtime implementation. 219 delete large_array[5]; 220 delete large_array[6]; 221 test_various_loads4(large_array, 222 undefined, 223 undefined, 224 expected_array_value(7)); 225 226 // Test the keyed load IC implementation when the value is the hole. 227 test_various_stores(large_array, 228 expected_array_value(5), 229 expected_array_value(6), 230 expected_array_value(7)); 231 test_various_loads5(large_array, 232 expected_array_value(5), 233 expected_array_value(6), 234 expected_array_value(7)); 235 test_various_loads5(large_array, 236 expected_array_value(5), 237 expected_array_value(6), 238 expected_array_value(7)); 239 delete large_array[5]; 240 delete large_array[6]; 241 test_various_loads5(large_array, 242 undefined, 243 undefined, 244 expected_array_value(7)); 245 test_various_loads5(large_array, 246 undefined, 247 undefined, 248 expected_array_value(7)); 249 250 // Make sure Crankshaft code handles the hole correctly (bailout) 251 test_various_stores(large_array, 252 expected_array_value(5), 253 expected_array_value(6), 254 expected_array_value(7)); 255 test_various_loads6(large_array, 256 expected_array_value(5), 257 expected_array_value(6), 258 expected_array_value(7)); 259 test_various_loads6(large_array, 260 expected_array_value(5), 261 expected_array_value(6), 262 expected_array_value(7)); 263 %OptimizeFunctionOnNextCall(test_various_loads6); 264 test_various_loads6(large_array, 265 expected_array_value(5), 266 expected_array_value(6), 267 expected_array_value(7)); 268 269 delete large_array[5]; 270 delete large_array[6]; 271 test_various_loads6(large_array, 272 undefined, 273 undefined, 274 expected_array_value(7)); 275 276 // Test stores for non-NaN. 277 %OptimizeFunctionOnNextCall(test_various_stores); 278 test_various_stores(large_array, 279 expected_array_value(5), 280 expected_array_value(6), 281 expected_array_value(7)); 282 283 test_various_stores(large_array, 284 expected_array_value(5), 285 expected_array_value(6), 286 expected_array_value(7)); 287 288 test_various_loads6(large_array, 289 expected_array_value(5), 290 expected_array_value(6), 291 expected_array_value(7)); 292 293 // Test NaN behavior for stores. 294 test_various_stores(large_array, 295 NaN, 296 -NaN, 297 expected_array_value(7)); 298 299 test_various_stores(large_array, 300 NaN, 301 -NaN, 302 expected_array_value(7)); 303 304 test_various_loads6(large_array, 305 NaN, 306 -NaN, 307 expected_array_value(7)); 308 309 // Test Infinity behavior for stores. 310 test_various_stores(large_array, 311 Infinity, 312 -Infinity, 313 expected_array_value(7)); 314 315 test_various_stores(large_array, 316 Infinity, 317 -Infinity, 318 expected_array_value(7)); 319 320 test_various_loads6(large_array, 321 Infinity, 322 -Infinity, 323 expected_array_value(7)); 324 325 assertTrue(%GetOptimizationStatus(test_various_stores) != 2); 326 327 // Make sure that we haven't converted from fast double. 328 assertTrue(%HasFastDoubleElements(large_array)); 329} 330 331testOneArrayType(make_object_like_array); 332testOneArrayType(Array); 333 334var large_array = new Array(large_array_size); 335force_to_fast_double_array(large_array); 336assertTrue(%HasFastDoubleElements(large_array)); 337 338// Cause the array to grow beyond it's JSArray length. This will double the 339// size of the capacity and force the array into "slow" dictionary case. 340large_array[5] = Infinity; 341large_array[large_array_size+10001] = 50; 342assertTrue(%HasDictionaryElements(large_array)); 343assertEquals(50, large_array[large_array_size+10001]); 344assertEquals(large_array_size+10002, large_array.length); 345assertEquals(Infinity, large_array[5]); 346assertEquals(undefined, large_array[large_array_size-1]); 347assertEquals(undefined, large_array[-1]); 348assertEquals(large_array_size+10002, large_array.length); 349 350// Test dictionary -> double elements -> fast elements. 351var large_array2 = new Array(large_array_size); 352force_to_fast_double_array(large_array2); 353delete large_array2[5]; 354 355// Convert back to fast elements and make sure the contents of the array are 356// unchanged. 357large_array2[25] = new Object(); 358assertTrue(%HasFastElements(large_array2)); 359for (var i= 0; i < approx_dict_to_elements_threshold; i += 500 ) { 360 if (i != 25 && i != 5) { 361 assertEquals(expected_array_value(i), large_array2[i]); 362 } 363} 364assertEquals(undefined, large_array2[5]); 365assertEquals(undefined, large_array2[large_array_size-1]); 366assertEquals(undefined, large_array2[-1]); 367assertEquals(large_array_size, large_array2.length); 368 369// Make sure it's possible to change the array's length and that array is still 370// intact after the resize. 371var large_array3 = new Array(large_array_size); 372force_to_fast_double_array(large_array3); 373large_array3.length = 60000; 374assertEquals(60000, large_array3.length); 375assertEquals(undefined, large_array3[60000]); 376assertTrue(%HasFastDoubleElements(large_array3)); 377assertEquals(expected_array_value(5), large_array3[5]); 378assertEquals(expected_array_value(6), large_array3[6]); 379assertEquals(expected_array_value(7), large_array3[7]); 380assertEquals(expected_array_value(large_array3.length-1), 381 large_array3[large_array3.length-1]); 382assertEquals(undefined, large_array3[large_array_size-1]); 383assertEquals(undefined, large_array3[-1]); 384gc(); 385 386for (var i= 0; i < large_array3.length; i += 501 ) { 387 assertEquals(expected_array_value(i), large_array3[i]); 388} 389 390large_array3.length = 25; 391assertEquals(25, large_array3.length); 392assertTrue(%HasFastDoubleElements(large_array3)); 393assertEquals(undefined, large_array3[25]); 394assertEquals(expected_array_value(5), large_array3[5]); 395assertEquals(expected_array_value(6), large_array3[6]); 396assertEquals(expected_array_value(7), large_array3[7]); 397assertEquals(expected_array_value(large_array3.length-1), 398 large_array3[large_array3.length-1]); 399assertEquals(undefined, large_array3[large_array_size-1]); 400assertEquals(undefined, large_array3[-1]); 401gc(); 402 403for (var i= 0; i < large_array3.length; ++i) { 404 assertEquals(expected_array_value(i), large_array3[i]); 405} 406 407large_array3.length = 100; 408assertEquals(100, large_array3.length); 409large_array3[95] = 95; 410assertTrue(%HasFastDoubleElements(large_array3)); 411assertEquals(undefined, large_array3[100]); 412assertEquals(95, large_array3[95]); 413assertEquals(expected_array_value(5), large_array3[5]); 414assertEquals(expected_array_value(6), large_array3[6]); 415assertEquals(expected_array_value(7), large_array3[7]); 416assertEquals(undefined, large_array3[large_array3.length-1]); 417assertEquals(undefined, large_array3[large_array_size-1]); 418assertEquals(undefined, large_array3[-1]); 419gc(); 420 421// Test apply on arrays backed by double elements. 422function called_by_apply(arg0, arg1, arg2, arg3, arg4, arg5, arg6) { 423 assertEquals(expected_array_value(0), arg0); 424 assertEquals(NaN, arg1); 425 assertEquals(-NaN, arg2); 426 assertEquals(Infinity, arg3); 427 assertEquals(-Infinity, arg4); 428 assertEquals(expected_array_value(5), arg5); 429} 430 431large_array3[1] = NaN; 432large_array3[2] = -NaN; 433large_array3[3] = Infinity; 434large_array3[4] = -Infinity; 435 436function call_apply() { 437 assertTrue(%HasFastDoubleElements(large_array3)); 438 called_by_apply.apply({}, large_array3); 439} 440 441call_apply(); 442call_apply(); 443call_apply(); 444%OptimizeFunctionOnNextCall(call_apply); 445call_apply(); 446call_apply(); 447call_apply(); 448 449function test_for_in() { 450 // Due to previous tests, keys 0..25 and 95 should be present. 451 next_expected = 0; 452 assertTrue(%HasFastDoubleElements(large_array3)); 453 for (x in large_array3) { 454 assertTrue(next_expected++ == x); 455 if (next_expected == 25) { 456 next_expected = 95; 457 } 458 } 459 assertTrue(next_expected == 96); 460} 461 462test_for_in(); 463test_for_in(); 464test_for_in(); 465%OptimizeFunctionOnNextCall(test_for_in); 466test_for_in(); 467test_for_in(); 468test_for_in(); 469 470function test_get_property_names() { 471 names = %GetPropertyNames(large_array3); 472 property_name_count = 0; 473 for (x in names) { property_name_count++; }; 474 assertEquals(26, property_name_count); 475} 476 477test_get_property_names(); 478test_get_property_names(); 479test_get_property_names(); 480 481// Test elements getters. 482assertEquals(expected_array_value(10), large_array3[10]); 483assertEquals(expected_array_value(-NaN), large_array3[2]); 484large_array3.__defineGetter__("2", function(){ 485 return expected_array_value(10); 486}); 487 488function test_getter() { 489 assertEquals(expected_array_value(10), large_array3[10]); 490 assertEquals(expected_array_value(10), large_array3[2]); 491} 492 493test_getter(); 494test_getter(); 495test_getter(); 496%OptimizeFunctionOnNextCall(test_getter); 497test_getter(); 498test_getter(); 499test_getter(); 500 501// Test element setters. 502large_array4 = new Array(large_array_size); 503force_to_fast_double_array(large_array4); 504 505var setter_called = false; 506 507assertEquals(expected_array_value(10), large_array4[10]); 508assertEquals(expected_array_value(2), large_array4[2]); 509large_array4.__defineSetter__("10", function(value){ 510 setter_called = true; 511 }); 512 513function test_setter() { 514 setter_called = false; 515 large_array4[10] = 119; 516 assertTrue(setter_called); 517 assertEquals(undefined, large_array4[10]); 518 assertEquals(expected_array_value(2), large_array4[2]); 519} 520 521test_setter(); 522test_setter(); 523test_setter(); 524%OptimizeFunctionOnNextCall(test_setter); 525test_setter(); 526test_setter(); 527test_setter(); 528