Home | History | Annotate | Download | only in mjsunit
      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