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