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