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(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 352testOneArrayType(make_object_like_array); 353testOneArrayType(Array); 354 355var large_array = new Array(large_array_size); 356force_to_fast_double_array(large_array); 357assertTrue(%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. 361large_array[5] = Infinity; 362large_array[large_array_size+10001] = 50; 363assertTrue(%HasDictionaryElements(large_array)); 364assertEquals(50, large_array[large_array_size+10001]); 365assertEquals(large_array_size+10002, large_array.length); 366assertEquals(Infinity, large_array[5]); 367assertEquals(undefined, large_array[large_array_size-1]); 368assertEquals(undefined, large_array[-1]); 369assertEquals(large_array_size+10002, large_array.length); 370 371// Test dictionary -> double elements -> fast elements. 372var large_array2 = new Array(large_array_size); 373force_to_fast_double_array(large_array2); 374delete large_array2[5]; 375 376// Convert back to fast elements and make sure the contents of the array are 377// unchanged. 378large_array2[25] = new Object(); 379assertTrue(%HasFastElements(large_array2)); 380for (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} 385assertEquals(undefined, large_array2[5]); 386assertEquals(undefined, large_array2[large_array_size-1]); 387assertEquals(undefined, large_array2[-1]); 388assertEquals(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. 392var large_array3 = new Array(large_array_size); 393force_to_fast_double_array(large_array3); 394large_array3.length = 60000; 395assertEquals(60000, large_array3.length); 396assertEquals(undefined, large_array3[60000]); 397assertTrue(%HasFastDoubleElements(large_array3)); 398assertEquals(expected_array_value(5), large_array3[5]); 399assertEquals(expected_array_value(6), large_array3[6]); 400assertEquals(expected_array_value(7), large_array3[7]); 401assertEquals(expected_array_value(large_array3.length-1), 402 large_array3[large_array3.length-1]); 403assertEquals(undefined, large_array3[large_array_size-1]); 404assertEquals(undefined, large_array3[-1]); 405gc(); 406 407for (var i= 0; i < large_array3.length; i += 501 ) { 408 assertEquals(expected_array_value(i), large_array3[i]); 409} 410 411large_array3.length = 25; 412assertEquals(25, large_array3.length); 413assertTrue(%HasFastDoubleElements(large_array3)); 414assertEquals(undefined, large_array3[25]); 415assertEquals(expected_array_value(5), large_array3[5]); 416assertEquals(expected_array_value(6), large_array3[6]); 417assertEquals(expected_array_value(7), large_array3[7]); 418assertEquals(expected_array_value(large_array3.length-1), 419 large_array3[large_array3.length-1]); 420assertEquals(undefined, large_array3[large_array_size-1]); 421assertEquals(undefined, large_array3[-1]); 422gc(); 423 424for (var i= 0; i < large_array3.length; ++i) { 425 assertEquals(expected_array_value(i), large_array3[i]); 426} 427 428large_array3.length = 100; 429assertEquals(100, large_array3.length); 430large_array3[95] = 95; 431assertTrue(%HasFastDoubleElements(large_array3)); 432assertEquals(undefined, large_array3[100]); 433assertEquals(95, large_array3[95]); 434assertEquals(expected_array_value(5), large_array3[5]); 435assertEquals(expected_array_value(6), large_array3[6]); 436assertEquals(expected_array_value(7), large_array3[7]); 437assertEquals(undefined, large_array3[large_array3.length-1]); 438assertEquals(undefined, large_array3[large_array_size-1]); 439assertEquals(undefined, large_array3[-1]); 440gc(); 441 442// Test apply on arrays backed by double elements. 443function 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 452large_array3[1] = NaN; 453large_array3[2] = -NaN; 454large_array3[3] = Infinity; 455large_array3[4] = -Infinity; 456 457function call_apply() { 458 called_by_apply.apply({}, large_array3); 459} 460 461call_apply(); 462call_apply(); 463call_apply(); 464%OptimizeFunctionOnNextCall(call_apply); 465call_apply(); 466call_apply(); 467call_apply(); 468 469function 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 481test_for_in(); 482test_for_in(); 483test_for_in(); 484%OptimizeFunctionOnNextCall(test_for_in); 485test_for_in(); 486test_for_in(); 487test_for_in(); 488 489function 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 496test_get_property_names(); 497test_get_property_names(); 498test_get_property_names(); 499 500// Test elements getters. 501assertEquals(expected_array_value(10), large_array3[10]); 502assertEquals(expected_array_value(-NaN), large_array3[2]); 503large_array3.__defineGetter__("2", function(){ 504 return expected_array_value(10); 505}); 506 507function test_getter() { 508 assertEquals(expected_array_value(10), large_array3[10]); 509 assertEquals(expected_array_value(10), large_array3[2]); 510} 511 512test_getter(); 513test_getter(); 514test_getter(); 515%OptimizeFunctionOnNextCall(test_getter); 516test_getter(); 517test_getter(); 518test_getter(); 519 520// Test element setters. 521large_array4 = new Array(large_array_size); 522force_to_fast_double_array(large_array4); 523 524var setter_called = false; 525 526assertEquals(expected_array_value(10), large_array4[10]); 527assertEquals(expected_array_value(2), large_array4[2]); 528large_array4.__defineSetter__("10", function(value){ 529 setter_called = true; 530 }); 531 532function 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 540test_setter(); 541test_setter(); 542test_setter(); 543%OptimizeFunctionOnNextCall(test_setter); 544test_setter(); 545test_setter(); 546test_setter(); 547