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: --track-allocation-sites --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 // Reset the GC stress mode to be off. Needed because AllocationMementos only
     39 // live for one gc, so a gc that happens in certain fragile areas of the test
     40 // can break assumptions.
     41 %SetFlags("--gc-interval=-1")
     42 
     43 // support_smi_only_arrays = %HasFastSmiElements(new Array(1,2,3,4,5,6,7,8));
     44 support_smi_only_arrays = true;
     45 
     46 if (support_smi_only_arrays) {
     47   print("Tests include smi-only arrays.");
     48 } else {
     49   print("Tests do NOT include smi-only arrays.");
     50 }
     51 
     52 var elements_kind = {
     53   fast_smi_only            :  'fast smi only elements',
     54   fast                     :  'fast elements',
     55   fast_double              :  'fast double elements',
     56   dictionary               :  'dictionary elements',
     57   external_byte            :  'external byte elements',
     58   external_unsigned_byte   :  'external unsigned byte elements',
     59   external_short           :  'external short elements',
     60   external_unsigned_short  :  'external unsigned short elements',
     61   external_int             :  'external int elements',
     62   external_unsigned_int    :  'external unsigned int elements',
     63   external_float           :  'external float elements',
     64   external_double          :  'external double elements',
     65   external_pixel           :  'external pixel elements'
     66 }
     67 
     68 function getKind(obj) {
     69   if (%HasFastSmiElements(obj)) return elements_kind.fast_smi_only;
     70   if (%HasFastObjectElements(obj)) return elements_kind.fast;
     71   if (%HasFastDoubleElements(obj)) return elements_kind.fast_double;
     72   if (%HasDictionaryElements(obj)) return elements_kind.dictionary;
     73 }
     74 
     75 function isHoley(obj) {
     76   if (%HasFastHoleyElements(obj)) return true;
     77   return false;
     78 }
     79 
     80 function assertKind(expected, obj, name_opt) {
     81   if (!support_smi_only_arrays &&
     82       expected == elements_kind.fast_smi_only) {
     83     expected = elements_kind.fast;
     84   }
     85   assertEquals(expected, getKind(obj), name_opt);
     86 }
     87 
     88 if (support_smi_only_arrays) {
     89 
     90   // Verify that basic elements kind feedback works for non-constructor
     91   // array calls (as long as the call is made through an IC, and not
     92   // a CallStub).
     93   (function (){
     94     function create0() {
     95       return Array();
     96     }
     97 
     98     // Calls through ICs need warm up through uninitialized, then
     99     // premonomorphic first.
    100     create0();
    101     create0();
    102     a = create0();
    103     assertKind(elements_kind.fast_smi_only, a);
    104     a[0] = 3.5;
    105     b = create0();
    106     assertKind(elements_kind.fast_double, b);
    107 
    108     function create1(arg) {
    109       return Array(arg);
    110     }
    111 
    112     create1(0);
    113     create1(0);
    114     a = create1(0);
    115     assertFalse(isHoley(a));
    116     assertKind(elements_kind.fast_smi_only, a);
    117     a[0] = "hello";
    118     b = create1(10);
    119     assertTrue(isHoley(b));
    120     assertKind(elements_kind.fast, b);
    121 
    122     a = create1(100000);
    123     assertKind(elements_kind.dictionary, a);
    124 
    125     function create3(arg1, arg2, arg3) {
    126       return Array(arg1, arg2, arg3);
    127     }
    128 
    129     create3();
    130     create3();
    131     a = create3(1,2,3);
    132     a[0] = 3.5;
    133     b = create3(1,2,3);
    134     assertKind(elements_kind.fast_double, b);
    135     assertFalse(isHoley(b));
    136   })();
    137 
    138 
    139   // Verify that keyed calls work
    140   (function (){
    141     function create0(name) {
    142       return this[name]();
    143     }
    144 
    145     name = "Array";
    146     create0(name);
    147     create0(name);
    148     a = create0(name);
    149     a[0] = 3.5;
    150     b = create0(name);
    151     assertKind(elements_kind.fast_double, b);
    152   })();
    153 
    154 
    155   // Verify that the IC can't be spoofed by patching
    156   (function (){
    157     function create0() {
    158       return Array();
    159     }
    160 
    161     create0();
    162     create0();
    163     a = create0();
    164     assertKind(elements_kind.fast_smi_only, a);
    165     var oldArray = this.Array;
    166     this.Array = function() { return ["hi"]; };
    167     b = create0();
    168     assertEquals(["hi"], b);
    169     this.Array = oldArray;
    170   })();
    171 
    172   // Verify that calls are still made through an IC after crankshaft,
    173   // though the type information is reset.
    174   // TODO(mvstanton): instead, consume the type feedback gathered up
    175   // until crankshaft time.
    176   (function (){
    177     function create0() {
    178       return Array();
    179     }
    180 
    181     create0();
    182     create0();
    183     a = create0();
    184     a[0] = 3.5;
    185     %OptimizeFunctionOnNextCall(create0);
    186     create0();
    187     // This test only makes sense if crankshaft is allowed
    188     if (4 != %GetOptimizationStatus(create0)) {
    189       create0();
    190       b = create0();
    191       assertKind(elements_kind.fast_smi_only, b);
    192       b[0] = 3.5;
    193       c = create0();
    194       assertKind(elements_kind.fast_double, c);
    195       assertOptimized(create0);
    196     }
    197   })();
    198 
    199 
    200   // Verify that cross context calls work
    201   (function (){
    202     var realmA = Realm.current();
    203     var realmB = Realm.create();
    204     assertEquals(0, realmA);
    205     assertEquals(1, realmB);
    206 
    207     function instanceof_check(type) {
    208       assertTrue(type() instanceof type);
    209       assertTrue(type(5) instanceof type);
    210       assertTrue(type(1,2,3) instanceof type);
    211     }
    212 
    213     var realmBArray = Realm.eval(realmB, "Array");
    214     instanceof_check(Array);
    215     instanceof_check(Array);
    216     instanceof_check(Array);
    217     instanceof_check(realmBArray);
    218     instanceof_check(realmBArray);
    219     instanceof_check(realmBArray);
    220   })();
    221 }
    222