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