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 --smi-only-arrays --expose-gc
     29 // Flags: --noalways-opt
     30 
     31 // Test element kind of objects.
     32 // Since --smi-only-arrays affects builtins, its default setting at compile
     33 // time sticks if built with snapshot.  If --smi-only-arrays is deactivated
     34 // by default, only a no-snapshot build actually has smi-only arrays enabled
     35 // in this test case.  Depending on whether smi-only arrays are actually
     36 // enabled, this test takes the appropriate code path to check smi-only arrays.
     37 
     38 // support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
     39 support_smi_only_arrays = true;
     40 
     41 if (support_smi_only_arrays) {
     42   print("Tests include smi-only arrays.");
     43 } else {
     44   print("Tests do NOT include smi-only arrays.");
     45 }
     46 
     47 var elements_kind = {
     48   fast_smi_only            :  'fast smi only elements',
     49   fast                     :  'fast elements',
     50   fast_double              :  'fast double elements',
     51   dictionary               :  'dictionary elements',
     52   external_byte            :  'external byte elements',
     53   external_unsigned_byte   :  'external unsigned byte elements',
     54   external_short           :  'external short elements',
     55   external_unsigned_short  :  'external unsigned short elements',
     56   external_int             :  'external int elements',
     57   external_unsigned_int    :  'external unsigned int elements',
     58   external_float           :  'external float elements',
     59   external_double          :  'external double elements',
     60   external_pixel           :  'external pixel elements'
     61 }
     62 
     63 function getKind(obj) {
     64   if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
     65   if (%HasFastObjectElements(obj)) return elements_kind.fast;
     66   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
     67   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
     68 }
     69 
     70 function isHoley(obj) {
     71   if (%HasFastHoleyElements(obj)) return true;
     72   return false;
     73 }
     74 
     75 function assertKind(expected, obj, name_opt) {
     76   if (!support_smi_only_arrays &&
     77       expected == elements_kind.fast_smi_only) {
     78     expected = elements_kind.fast;
     79   }
     80   assertEquals(expected, getKind(obj), name_opt);
     81 }
     82 
     83 if (support_smi_only_arrays) {
     84 
     85   // Verify that basic elements kind feedback works for non-constructor
     86   // array calls (as long as the call is made through an IC, and not
     87   // a CallStub).
     88   (function (){
     89     function create0() {
     90       return Array();
     91     }
     92 
     93     // Calls through ICs need warm up through uninitialized, then
     94     // premonomorphic first.
     95     create0();
     96     a = create0();
     97     assertKind(elements_kind.fast_smi_only, a);
     98     a[0] = 3.5;
     99     b = create0();
    100     assertKind(elements_kind.fast_double, b);
    101 
    102     function create1(arg) {
    103       return Array(arg);
    104     }
    105 
    106     create1(0);
    107     create1(0);
    108     a = create1(0);
    109     assertFalse(isHoley(a));
    110     assertKind(elements_kind.fast_smi_only, a);
    111     a[0] = "hello";
    112     b = create1(10);
    113     assertTrue(isHoley(b));
    114     assertKind(elements_kind.fast, b);
    115 
    116     a = create1(100000);
    117     assertKind(elements_kind.dictionary, a);
    118 
    119     function create3(arg1, arg2, arg3) {
    120       return Array(arg1, arg2, arg3);
    121     }
    122 
    123     create3(1,2,3);
    124     create3(1,2,3);
    125     a = create3(1,2,3);
    126     a[0] = 3.035;
    127     assertKind(elements_kind.fast_double, a);
    128     b = create3(1,2,3);
    129     assertKind(elements_kind.fast_double, b);
    130     assertFalse(isHoley(b));
    131   })();
    132 
    133 
    134   // Verify that keyed calls work
    135   (function (){
    136     function create0(name) {
    137       return this[name]();
    138     }
    139 
    140     name = "Array";
    141     create0(name);
    142     create0(name);
    143     a = create0(name);
    144     a[0] = 3.5;
    145     b = create0(name);
    146     assertKind(elements_kind.fast_double, b);
    147   })();
    148 
    149 
    150   // Verify that feedback is turned off if the call site goes megamorphic.
    151   (function (){
    152     function foo(arg) { return arg(); }
    153     foo(Array);
    154     foo(function() {});
    155     foo(Array);
    156 
    157     gc();
    158 
    159     a = foo(Array);
    160     a[0] = 3.5;
    161     b = foo(Array);
    162     // b doesn't benefit from elements kind feedback at a megamorphic site.
    163     assertKind(elements_kind.fast_smi_only, b);
    164   })();
    165 
    166 
    167   // Verify that crankshaft consumes type feedback.
    168   (function (){
    169     function create0() {
    170       return Array();
    171     }
    172 
    173     create0();
    174     create0();
    175     a = create0();
    176     a[0] = 3.5;
    177     %OptimizeFunctionOnNextCall(create0);
    178     create0();
    179     create0();
    180     b = create0();
    181     assertKind(elements_kind.fast_double, b);
    182     assertOptimized(create0);
    183 
    184     function create1(arg) {
    185       return Array(arg);
    186     }
    187 
    188     create1(8);
    189     create1(8);
    190     a = create1(8);
    191     a[0] = 3.5;
    192     %OptimizeFunctionOnNextCall(create1);
    193     b = create1(8);
    194     assertKind(elements_kind.fast_double, b);
    195     assertOptimized(create1);
    196 
    197     function createN(arg1, arg2, arg3) {
    198       return Array(arg1, arg2, arg3);
    199     }
    200 
    201     createN(1, 2, 3);
    202     createN(1, 2, 3);
    203     a = createN(1, 2, 3);
    204     a[0] = 3.5;
    205     %OptimizeFunctionOnNextCall(createN);
    206     b = createN(1, 2, 3);
    207     assertKind(elements_kind.fast_double, b);
    208     assertOptimized(createN);
    209   })();
    210 
    211   // Verify that cross context calls work
    212   (function (){
    213     var realmA = Realm.current();
    214     var realmB = Realm.create();
    215     assertEquals(0, realmA);
    216     assertEquals(1, realmB);
    217 
    218     function instanceof_check(type) {
    219       assertTrue(type() instanceof type);
    220       assertTrue(type(5) instanceof type);
    221       assertTrue(type(1,2,3) instanceof type);
    222     }
    223 
    224     var realmBArray = Realm.eval(realmB, "Array");
    225     instanceof_check(Array);
    226     instanceof_check(Array);
    227     instanceof_check(Array);
    228     instanceof_check(realmBArray);
    229     instanceof_check(realmBArray);
    230     instanceof_check(realmBArray);
    231   })();
    232 }
    233