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 // Flags: --allow-natives-syntax --expose-gc
     29 
     30 // This is a regression test for overlapping key and value registers.
     31 function f(a) {
     32   a[0] = 0;
     33   a[1] = 0;
     34 }
     35 
     36 var a = new Int32Array(2);
     37 for (var i = 0; i < 5; i++) {
     38   f(a);
     39 }
     40 %OptimizeFunctionOnNextCall(f);
     41 f(a);
     42 
     43 assertEquals(0, a[0]);
     44 assertEquals(0, a[1]);
     45 
     46 // No-parameter constructor should fail right now.
     47 function abfunc1() {
     48   return new ArrayBuffer();
     49 }
     50 assertThrows(abfunc1);
     51 
     52 // Test derivation from an ArrayBuffer
     53 var ab = new ArrayBuffer(12);
     54 var derived_uint8 = new Uint8Array(ab);
     55 assertEquals(12, derived_uint8.length);
     56 var derived_uint32 = new Uint32Array(ab);
     57 assertEquals(3, derived_uint32.length);
     58 var derived_uint32_2 = new Uint32Array(ab,4);
     59 assertEquals(2, derived_uint32_2.length);
     60 var derived_uint32_3 = new Uint32Array(ab,4,1);
     61 assertEquals(1, derived_uint32_3.length);
     62 
     63 // If a given byteOffset and length references an area beyond the end of the
     64 // ArrayBuffer an exception is raised.
     65 function abfunc3() {
     66   new Uint32Array(ab,4,3);
     67 }
     68 assertThrows(abfunc3);
     69 function abfunc4() {
     70   new Uint32Array(ab,16);
     71 }
     72 assertThrows(abfunc4);
     73 
     74 // The given byteOffset must be a multiple of the element size of the specific
     75 // type, otherwise an exception is raised.
     76 function abfunc5() {
     77   new Uint32Array(ab,5);
     78 }
     79 assertThrows(abfunc5);
     80 
     81 // If length is not explicitly specified, the length of the ArrayBuffer minus
     82 // the byteOffset must be a multiple of the element size of the specific type,
     83 // or an exception is raised.
     84 var ab2 = new ArrayBuffer(13);
     85 function abfunc6() {
     86   new Uint32Array(ab2,4);
     87 }
     88 assertThrows(abfunc6);
     89 
     90 // Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is
     91 // "constant", but not read-only).
     92 a = new Int32Array(2);
     93 assertEquals(4, a.BYTES_PER_ELEMENT);
     94 a.BYTES_PER_ELEMENT = 42;
     95 assertEquals(42, a.BYTES_PER_ELEMENT);
     96 a = new Uint8Array(2);
     97 assertEquals(1, a.BYTES_PER_ELEMENT);
     98 a = new Int16Array(2);
     99 assertEquals(2, a.BYTES_PER_ELEMENT);
    100 
    101 // Test Float64Arrays.
    102 function get(a, index) {
    103   return a[index];
    104 }
    105 function set(a, index, value) {
    106   a[index] = value;
    107 }
    108 function temp() {
    109 var array = new Float64Array(2);
    110 for (var i = 0; i < 5; i++) {
    111   set(array, 0, 2.5);
    112   assertEquals(2.5, array[0]);
    113 }
    114 %OptimizeFunctionOnNextCall(set);
    115 set(array, 0, 2.5);
    116 assertEquals(2.5, array[0]);
    117 set(array, 1, 3.5);
    118 assertEquals(3.5, array[1]);
    119 for (var i = 0; i < 5; i++) {
    120   assertEquals(2.5, get(array, 0));
    121   assertEquals(3.5, array[1]);
    122 }
    123 %OptimizeFunctionOnNextCall(get);
    124 assertEquals(2.5, get(array, 0));
    125 assertEquals(3.5, get(array, 1));
    126 }
    127 
    128 // Test non-number parameters.
    129 var array_with_length_from_non_number = new Int32Array("2");
    130 assertEquals(2, array_with_length_from_non_number.length);
    131 array_with_length_from_non_number = new Int32Array(undefined);
    132 assertEquals(0, array_with_length_from_non_number.length);
    133 var foo = { valueOf: function() { return 3; } };
    134 array_with_length_from_non_number = new Int32Array(foo);
    135 assertEquals(3, array_with_length_from_non_number.length);
    136 foo = { toString: function() { return "4"; } };
    137 array_with_length_from_non_number = new Int32Array(foo);
    138 assertEquals(4, array_with_length_from_non_number.length);
    139 
    140 
    141 // Test loads and stores.
    142 types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array,
    143          Uint32Array, PixelArray, Float32Array, Float64Array];
    144 
    145 test_result_nan = [NaN, 0, 0, 0, 0, 0, 0, 0, NaN, NaN];
    146 test_result_low_int = [-1, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1, -1];
    147 test_result_low_double = [-1.25, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1.25, -1.25];
    148 test_result_middle = [253.75, -3, 253, 253, 253, 253, 253, 254, 253.75, 253.75];
    149 test_result_high_int = [256, 0, 0, 256, 256, 256, 256, 255, 256, 256];
    150 test_result_high_double = [256.25, 0, 0, 256, 256, 256, 256, 255, 256.25, 256.25];
    151 
    152 const kElementCount = 40;
    153 
    154 function test_load(array, sum) {
    155   for (var i = 0; i < kElementCount; i++) {
    156     sum += array[i];
    157   }
    158   return sum;
    159 }
    160 
    161 function test_load_const_key(array, sum) {
    162   sum += array[0];
    163   sum += array[1];
    164   sum += array[2];
    165   return sum;
    166 }
    167 
    168 function test_store(array, sum) {
    169   for (var i = 0; i < kElementCount; i++) {
    170     sum += array[i] = i+1;
    171   }
    172   return sum;
    173 }
    174 
    175 function test_store_const_key(array, sum) {
    176   sum += array[0] = 1;
    177   sum += array[1] = 2;
    178   sum += array[2] = 3;
    179   return sum;
    180 }
    181 
    182 function zero() {
    183   return 0.0;
    184 }
    185 
    186 function test_store_middle_tagged(array, sum) {
    187   array[0] = 253.75;
    188   return array[0];
    189 }
    190 
    191 function test_store_high_tagged(array, sum) {
    192   array[0] = 256.25;
    193   return array[0];
    194 }
    195 
    196 function test_store_middle_double(array, sum) {
    197   array[0] = 253.75 + zero(); // + forces double type feedback
    198   return array[0];
    199 }
    200 
    201 function test_store_high_double(array, sum) {
    202   array[0] = 256.25 + zero(); // + forces double type feedback
    203   return array[0];
    204 }
    205 
    206 function test_store_high_double(array, sum) {
    207   array[0] = 256.25;
    208   return array[0];
    209 }
    210 
    211 function test_store_low_int(array, sum) {
    212   array[0] = -1;
    213   return array[0];
    214 }
    215 
    216 function test_store_low_tagged(array, sum) {
    217   array[0] = -1.25;
    218   return array[0];
    219 }
    220 
    221 function test_store_low_double(array, sum) {
    222   array[0] = -1.25 + zero(); // + forces double type feedback
    223   return array[0];
    224 }
    225 
    226 function test_store_high_int(array, sum) {
    227   array[0] = 256;
    228   return array[0];
    229 }
    230 
    231 function test_store_nan(array, sum) {
    232   array[0] = NaN;
    233   return array[0];
    234 }
    235 
    236 const kRuns = 10;
    237 
    238 function run_test(test_func, array, expected_result) {
    239   for (var i = 0; i < 5; i++) test_func(array, 0);
    240   %OptimizeFunctionOnNextCall(test_func);
    241   var sum = 0;
    242   for (var i = 0; i < kRuns; i++) {
    243     sum = test_func(array, sum);
    244   }
    245   assertEquals(expected_result, sum);
    246   %DeoptimizeFunction(test_func);
    247   gc();  // Makes V8 forget about type information for test_func.
    248 }
    249 
    250 function run_bounds_test(test_func, array, expected_result) {
    251   assertEquals(undefined, a[kElementCount]);
    252   a[kElementCount] = 456;
    253   assertEquals(undefined, a[kElementCount]);
    254   assertEquals(undefined, a[kElementCount+1]);
    255   a[kElementCount+1] = 456;
    256   assertEquals(undefined, a[kElementCount+1]);
    257 }
    258 
    259 for (var t = 0; t < types.length; t++) {
    260   var type = types[t];
    261   var a = new type(kElementCount);
    262 
    263   for (var i = 0; i < kElementCount; i++) {
    264     a[i] = i;
    265   }
    266 
    267   // Run test functions defined above.
    268   run_test(test_load, a, 780 * kRuns);
    269   run_test(test_load_const_key, a, 3 * kRuns);
    270   run_test(test_store, a, 820 * kRuns);
    271   run_test(test_store_const_key, a, 6 * kRuns);
    272   run_test(test_store_low_int, a, test_result_low_int[t]);
    273   run_test(test_store_low_double, a, test_result_low_double[t]);
    274   run_test(test_store_low_tagged, a, test_result_low_double[t]);
    275   run_test(test_store_high_int, a, test_result_high_int[t]);
    276   run_test(test_store_nan, a, test_result_nan[t]);
    277   run_test(test_store_middle_double, a, test_result_middle[t]);
    278   run_test(test_store_middle_tagged, a, test_result_middle[t]);
    279   run_test(test_store_high_double, a, test_result_high_double[t]);
    280   run_test(test_store_high_tagged, a, test_result_high_double[t]);
    281 
    282   // Test the correct behavior of the |length| property (which is read-only).
    283   if (t != 0) {
    284     assertEquals(kElementCount, a.length);
    285     a.length = 2;
    286     assertEquals(kElementCount, a.length);
    287     assertTrue(delete a.length);
    288     a.length = 2;
    289     assertEquals(2, a.length);
    290 
    291     // Make sure bounds checks are handled correctly for external arrays.
    292     run_bounds_test(a);
    293     run_bounds_test(a);
    294     run_bounds_test(a);
    295     %OptimizeFunctionOnNextCall(run_bounds_test);
    296     run_bounds_test(a);
    297     %DeoptimizeFunction(run_bounds_test);
    298     gc();  // Makes V8 forget about type information for test_func.
    299 
    300   }
    301 
    302   function array_load_set_smi_check(a) {
    303     return a[0] = a[0] = 1;
    304   }
    305 
    306   array_load_set_smi_check(a);
    307   array_load_set_smi_check(0);
    308 
    309   function array_load_set_smi_check2(a) {
    310     return a[0] = a[0] = 1;
    311   }
    312 
    313   array_load_set_smi_check2(a);
    314   %OptimizeFunctionOnNextCall(array_load_set_smi_check2);
    315   array_load_set_smi_check2(a);
    316   array_load_set_smi_check2(0);
    317   %DeoptimizeFunction(array_load_set_smi_check2);
    318   gc();  // Makes V8 forget about type information for array_load_set_smi_check.
    319 }
    320 
    321 // Check handling of undefined in 32- and 64-bit external float arrays.
    322 
    323 function store_float32_undefined(ext_array) {
    324   ext_array[0] = undefined;
    325 }
    326 
    327 var float32_array = new Float32Array(1);
    328 // Make sure runtime does it right
    329 store_float32_undefined(float32_array);
    330 assertTrue(isNaN(float32_array[0]));
    331 // Make sure the ICs do it right
    332 store_float32_undefined(float32_array);
    333 assertTrue(isNaN(float32_array[0]));
    334 // Make sure that Cranskshft does it right.
    335 %OptimizeFunctionOnNextCall(store_float32_undefined);
    336 store_float32_undefined(float32_array);
    337 assertTrue(isNaN(float32_array[0]));
    338 
    339 function store_float64_undefined(ext_array) {
    340   ext_array[0] = undefined;
    341 }
    342 
    343 var float64_array = new Float64Array(1);
    344 // Make sure runtime does it right
    345 store_float64_undefined(float64_array);
    346 assertTrue(isNaN(float64_array[0]));
    347 // Make sure the ICs do it right
    348 store_float64_undefined(float64_array);
    349 assertTrue(isNaN(float64_array[0]));
    350 // Make sure that Cranskshft does it right.
    351 %OptimizeFunctionOnNextCall(store_float64_undefined);
    352 store_float64_undefined(float64_array);
    353 assertTrue(isNaN(float64_array[0]));
    354