Home | History | Annotate | Download | only in compiler
      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: --optimize-for-in --allow-natives-syntax
     29 // Flags: --no-concurrent-osr
     30 
     31 // Test for-in support in Crankshaft.  For simplicity this tests assumes certain
     32 // fixed iteration order for properties and will have to be adjusted if V8
     33 // stops following insertion order.
     34 
     35 
     36 function a(t) {
     37   var result = [];
     38   for (var i in t) {
     39     result.push(i + t[i]);
     40   }
     41   return result.join('');
     42 }
     43 
     44 // Check that we correctly deoptimize on map check.
     45 function b(t) {
     46   var result = [];
     47   for (var i in t) {
     48     result.push(i + t[i]);
     49     delete t[i];
     50   }
     51   return result.join('');
     52 }
     53 
     54 // Check that we correctly deoptimize during preparation step.
     55 function c(t) {
     56   var result = [];
     57   for (var i in t) {
     58     result.push(i + t[i]);
     59   }
     60   return result.join('');
     61 }
     62 
     63 // Check that we deoptimize to the place after side effect in the right state.
     64 function d(t) {
     65   var result = [];
     66   var o;
     67   for (var i in (o = t())) {
     68     result.push(i + o[i]);
     69   }
     70   return result.join('');
     71 }
     72 
     73 // Check that we correctly deoptimize on map check inserted for fused load.
     74 function e(t) {
     75   var result = [];
     76   for (var i in t) {
     77     delete t[i];
     78     t[i] = i;
     79     result.push(i + t[i]);
     80   }
     81   return result.join('');
     82 }
     83 
     84 // Nested for-in loops.
     85 function f(t) {
     86   var result = [];
     87   for (var i in t) {
     88     for (var j in t) {
     89       result.push(i + j + t[i] + t[j]);
     90     }
     91   }
     92   return result.join('');
     93 }
     94 
     95 // Deoptimization from the inner for-in loop.
     96 function g(t) {
     97   var result = [];
     98   for (var i in t) {
     99     for (var j in t) {
    100       result.push(i + j + t[i] + t[j]);
    101       var v = t[i];
    102       delete t[i];
    103       t[i] = v;
    104     }
    105   }
    106   return result.join('');
    107 }
    108 
    109 
    110 // Break from the inner for-in loop.
    111 function h(t, deopt) {
    112   var result = [];
    113   for (var i in t) {
    114     for (var j in t) {
    115       result.push(i + j + t[i] + t[j]);
    116       break;
    117     }
    118   }
    119   deopt.deopt;
    120   return result.join('');
    121 }
    122 
    123 // Continue in the inner loop.
    124 function j(t, deopt) {
    125   var result = [];
    126   for (var i in t) {
    127     for (var j in t) {
    128       result.push(i + j + t[i] + t[j]);
    129       continue;
    130     }
    131   }
    132   deopt.deopt;
    133   return result.join('');
    134 }
    135 
    136 // Continue of the outer loop.
    137 function k(t, deopt) {
    138   var result = [];
    139   outer: for (var i in t) {
    140     for (var j in t) {
    141       result.push(i + j + t[i] + t[j]);
    142       continue outer;
    143     }
    144   }
    145   deopt.deopt;
    146   return result.join('');
    147 }
    148 
    149 // Break of the outer loop.
    150 function l(t, deopt) {
    151   var result = [];
    152   outer: for (var i in t) {
    153     for (var j in t) {
    154       result.push(i + j + t[i] + t[j]);
    155       break outer;
    156     }
    157   }
    158   deopt.deopt;
    159   return result.join('');
    160 }
    161 
    162 // Test deoptimization from inlined frame (currently it is not inlined).
    163 function m0(t, deopt) {
    164   for (var i in t) {
    165     for (var j in t) {
    166       deopt.deopt;
    167       return i + j + t[i] + t[j];
    168     }
    169   }
    170 }
    171 
    172 function m(t, deopt) {
    173   return m0(t, deopt);
    174 }
    175 
    176 
    177 function tryFunction(s, mkT, f) {
    178   var d = {deopt: false};
    179   assertEquals(s, f(mkT(), d));
    180   assertEquals(s, f(mkT(), d));
    181   assertEquals(s, f(mkT(), d));
    182   %OptimizeFunctionOnNextCall(f);
    183   assertEquals(s, f(mkT(), d));
    184   assertEquals(s, f(mkT(), {}));
    185 }
    186 
    187 var s = "a1b2c3d4";
    188 function mkTable() { return { a: "1", b: "2", c: "3", d: "4" }; }
    189 
    190 
    191 tryFunction(s, mkTable, a);
    192 tryFunction(s, mkTable, b);
    193 tryFunction("0a1b2c3d", function () { return "abcd"; }, c);
    194 tryFunction("0a1b2c3d", function () {
    195   var cnt = false;
    196   return function () {
    197     cnt = true;
    198     return "abcd";
    199   }
    200 }, d);
    201 tryFunction("aabbccdd", mkTable, e);
    202 
    203 function mkSmallTable() { return { a: "1", b: "2" }; }
    204 
    205 tryFunction("aa11ab12ba21bb22", mkSmallTable, f);
    206 tryFunction("aa11ab12bb22ba21", mkSmallTable, g);
    207 tryFunction("aa11ba21", mkSmallTable, h);
    208 tryFunction("aa11ab12ba21bb22", mkSmallTable, j);
    209 tryFunction("aa11ba21", mkSmallTable, h);
    210 tryFunction("aa11ba21", mkSmallTable, k);
    211 tryFunction("aa11", mkSmallTable, l);
    212 tryFunction("aa11", mkSmallTable, m);
    213 
    214 // Test handling of null.
    215 tryFunction("", function () {
    216   return function () { return null; }
    217 }, function (t) {
    218   for (var i in t()) { return i; }
    219   return "";
    220 });
    221 
    222 // Test smis.
    223 tryFunction("", function () {
    224   return function () { return 11; }
    225 }, function (t) {
    226   for (var i in t()) { return i; }
    227   return "";
    228 });
    229 
    230 // Test LoadFieldByIndex for out of object properties.
    231 function O() { this.a = 1; }
    232 for (var i = 0; i < 10; i++) new O();
    233 tryFunction("a1b2c3d4e5f6", function () {
    234   var o = new O();
    235   o.b = 2;
    236   o.c = 3;
    237   o.d = 4;
    238   o.e = 5;
    239   o.f = 6;
    240   return o;
    241 }, function (t) {
    242   var r = [];
    243   for (var i in t) r.push(i + t[i]);
    244   return r.join('');
    245 });
    246 
    247 // Test OSR inside for-in.
    248 function osr_inner(t, limit) {
    249   var r = 1;
    250   for (var x in t) {
    251     if (t.hasOwnProperty(x)) {
    252       for (var i = 0; i < t[x].length; i++) {
    253         r += t[x][i];
    254         if (i === limit) {
    255           %OptimizeFunctionOnNextCall(osr_inner, "osr");
    256         }
    257       }
    258       r += x;
    259     }
    260   }
    261   return r;
    262 }
    263 
    264 function osr_outer(t, osr_after) {
    265   var r = 1;
    266   for (var x in t) {
    267     for (var i = 0; i < t[x].length; i++) {
    268       r += t[x][i];
    269     }
    270     if (x === osr_after) {
    271       %OptimizeFunctionOnNextCall(osr_outer, "osr");
    272     }
    273     r += x;
    274   }
    275   return r;
    276 }
    277 
    278 function osr_outer_and_deopt(t, osr_after) {
    279   var r = 1;
    280   for (var x in t) {
    281     r += x;
    282     if (x == osr_after) {
    283       %OptimizeFunctionOnNextCall(osr_outer_and_deopt, "osr");
    284     }
    285   }
    286   return r;
    287 }
    288 
    289 function test_osr() {
    290   with ({}) {}  // Disable optimizations of this function.
    291   var arr = new Array(20);
    292   for (var i = 0; i < arr.length; i++) {
    293     arr[i] = i + 1;
    294   }
    295   arr.push(":");  // Force deopt at the end of the loop.
    296   assertEquals("211:x1234567891011121314151617181920:y", osr_inner({x: arr, y: arr}, (arr.length / 2) | 0));
    297   assertEquals("7x456y", osr_outer({x: [1,2,3], y: [4,5,6]}, "x"));
    298   assertEquals("101234567", osr_outer_and_deopt([1,2,3,4,5,6,7,8], "5"));
    299 }
    300 
    301 test_osr();
    302