Home | History | Annotate | Download | only in strong
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Flags: --strong-mode --allow-natives-syntax
      6 
      7 "use strict";
      8 
      9 // Boolean indicates whether an operator can be part of a compound assignment.
     10 let strongNumberBinops = [
     11   ["-", true],
     12   ["*", true],
     13   ["/", true],
     14   ["%", true],
     15   ["|", true],
     16   ["&", true],
     17   ["^", true],
     18   ["<<", true],
     19   [">>", true],
     20   [">>>", true]
     21 ];
     22 
     23 let strongStringOrNumberBinops = [
     24   ["+", true],
     25   ["<", false],
     26   [">", false],
     27   ["<=", false],
     28   [">=", false]
     29 ];
     30 
     31 let strongBinops = strongNumberBinops.concat(strongStringOrNumberBinops);
     32 
     33 let strongUnops = [
     34   "~",
     35   "+",
     36   "-"
     37 ];
     38 
     39 let nonStringOrNumberValues = [
     40   "null",
     41   "undefined",
     42   "{}",
     43   "false",
     44   "(function(){})",
     45   "[]",
     46   "(class Foo {})"
     47 ];
     48 
     49 let stringValues = [
     50   "''",
     51   "'               '",
     52   "'foo'",
     53   "'f\\u006F\\u006F'",
     54   "'0'",
     55   "'NaN'"
     56 ];
     57 
     58 let nonNumberValues = nonStringOrNumberValues.concat(stringValues);
     59 
     60 let numberValues = [
     61   "0",
     62   "(-0)",
     63   "1",
     64   "(-4294967295)",
     65   "(-4294967296)",
     66   "9999999999999",
     67   "(-9999999999999)",
     68   "NaN",
     69   "Infinity",
     70   "(-Infinity)"
     71 ];
     72 
     73 //******************************************************************************
     74 // Relational comparison function declarations
     75 function add_strong(x, y) {
     76   "use strong";
     77   return x + y;
     78 }
     79 
     80 function add_num_strong(x, y) {
     81   "use strong";
     82   return x + y;
     83 }
     84 
     85 function sub_strong(x, y) {
     86   "use strong";
     87   return x - y;
     88 }
     89 
     90 function mul_strong(x, y) {
     91   "use strong";
     92   return x * y;
     93 }
     94 
     95 function div_strong(x, y) {
     96   "use strong";
     97   return x / y;
     98 }
     99 
    100 function mod_strong(x, y) {
    101   "use strong";
    102   return x % y;
    103 }
    104 
    105 function or_strong(x, y) {
    106   "use strong";
    107   return x | y;
    108 }
    109 
    110 function and_strong(x, y) {
    111   "use strong";
    112   return x & y;
    113 }
    114 
    115 function xor_strong(x, y) {
    116   "use strong";
    117   return x ^ y;
    118 }
    119 
    120 function shl_strong(x, y) {
    121   "use strong";
    122   return x << y;
    123 }
    124 
    125 function shr_strong(x, y) {
    126   "use strong";
    127   return x >> y;
    128 }
    129 
    130 function sar_strong(x, y) {
    131   "use strong";
    132   return x >>> y;
    133 }
    134 
    135 function less_strong(x, y) {
    136   "use strong";
    137   return x < y;
    138 }
    139 
    140 function less_num_strong(x, y) {
    141   "use strong";
    142   return x < y;
    143 }
    144 
    145 function greater_strong(x, y) {
    146   "use strong";
    147   return x > y;
    148 }
    149 
    150 function greater_num_strong(x, y) {
    151   "use strong";
    152   return x > y;
    153 }
    154 
    155 function less_equal_strong(x, y) {
    156   "use strong";
    157   return x <= y;
    158 }
    159 
    160 function less_equal_num_strong(x, y) {
    161   "use strong";
    162   return x <= y;
    163 }
    164 
    165 function greater_equal_strong(x, y) {
    166   "use strong";
    167   return x >= y;
    168 }
    169 
    170 function greater_equal_num_strong(x, y) {
    171   "use strong";
    172   return x >= y;
    173 }
    174 
    175 function typed_add_strong(x, y) {
    176   "use strong";
    177   return (+x) + (+y);
    178 }
    179 
    180 function typed_sub_strong(x, y) {
    181   "use strong";
    182   return (+x) - (+y);
    183 }
    184 
    185 function typed_mul_strong(x, y) {
    186   "use strong";
    187   return (+x) * (+y);
    188 }
    189 
    190 function typed_div_strong(x, y) {
    191   "use strong";
    192   return (+x) / (+y);
    193 }
    194 
    195 function typed_mod_strong(x, y) {
    196   "use strong";
    197   return (+x) % (+y);
    198 }
    199 
    200 function typed_or_strong(x, y) {
    201   "use strong";
    202   return (+x) | (+y);
    203 }
    204 
    205 function typed_and_strong(x, y) {
    206   "use strong";
    207   return (+x) & (+y);
    208 }
    209 
    210 function typed_xor_strong(x, y) {
    211   "use strong";
    212   return (+x) ^ (+y);
    213 }
    214 
    215 function typed_shl_strong(x, y) {
    216   "use strong";
    217   return (+x) << (+y);
    218 }
    219 
    220 function typed_shr_strong(x, y) {
    221   "use strong";
    222   return (+x) >> (+y);
    223 }
    224 
    225 function typed_sar_strong(x, y) {
    226   "use strong";
    227   return (+x) >>> (+y);
    228 }
    229 
    230 function typed_less_strong(x, y) {
    231   "use strong";
    232   return (+x) < (+y);
    233 }
    234 
    235 function typed_greater_strong(x, y) {
    236   "use strong";
    237   return (+x) > (+y);
    238 }
    239 
    240 function typed_less_equal_strong(x, y) {
    241   "use strong";
    242   return (+x) <= (+y);
    243 }
    244 
    245 function typed_greater_equal_strong(x, y) {
    246   "use strong";
    247   return (+x) >= (+y);
    248 }
    249 
    250 //******************************************************************************
    251 // (in)equality function declarations
    252 function str_equal_strong(x, y) {
    253   "use strong";
    254   return x === y;
    255 }
    256 
    257 function str_ineq_strong(x, y) {
    258   "use strong";
    259   return x !== y;
    260 }
    261 
    262 let strongNumberFuncs = [add_num_strong, sub_strong, mul_strong, div_strong,
    263                          mod_strong, or_strong, and_strong, xor_strong,
    264                          shl_strong, shr_strong, sar_strong, less_num_strong,
    265                          greater_num_strong, less_equal_num_strong,
    266                          greater_equal_num_strong, typed_add_strong,
    267                          typed_sub_strong, typed_mul_strong, typed_div_strong,
    268                          typed_mod_strong, typed_or_strong,  typed_and_strong,
    269                          typed_xor_strong, typed_shl_strong, typed_shr_strong,
    270                          typed_sar_strong, typed_less_strong,
    271                          typed_greater_strong, typed_less_equal_strong,
    272                          typed_greater_equal_strong];
    273 
    274 let strongStringOrNumberFuncs = [add_strong, less_strong, greater_strong,
    275                                  less_equal_strong, greater_equal_strong];
    276 
    277 let strongFuncs = strongNumberFuncs.concat(strongStringOrNumberFuncs);
    278 
    279 function assertStrongNonThrowBehaviour(expr) {
    280   assertEquals(eval(expr), eval("'use strong';" + expr));
    281   assertDoesNotThrow("'use strong'; " + expr + ";");
    282   assertDoesNotThrow("'use strong'; let v = " + expr + ";");
    283 }
    284 
    285 function assertStrongThrowBehaviour(expr) {
    286   assertDoesNotThrow("'use strict'; " + expr + ";");
    287   assertDoesNotThrow("'use strict'; let v = " + expr + ";");
    288   assertThrows("'use strong'; " + expr + ";", TypeError);
    289   assertThrows("'use strong'; let v = " + expr + ";", TypeError);
    290 }
    291 
    292 function checkArgumentCombinations(op, leftList, rightList, willThrow) {
    293   for (let v1 of leftList) {
    294     let assignExpr = "foo " + op[0] + "= " + v1 + ";";
    295     for (let v2 of rightList) {
    296       let compoundAssignment = "'use strong'; let foo = " + v2 + "; " +
    297                                assignExpr;
    298       if (willThrow) {
    299         if (op[1]) {
    300           assertThrows(compoundAssignment, TypeError);
    301         }
    302         assertStrongThrowBehaviour("(" + v1 + op[0] + v2 + ")");
    303       } else {
    304         if (op[1]) {
    305           assertDoesNotThrow(compoundAssignment);
    306         }
    307         assertStrongNonThrowBehaviour("(" + v1 + op[0] + v2 + ")");
    308       }
    309     }
    310   }
    311 }
    312 
    313 for (let op of strongBinops) {
    314   checkArgumentCombinations(op, numberValues, numberValues, false);
    315   checkArgumentCombinations(op, numberValues, nonNumberValues, true);
    316 }
    317 
    318 for (let op of strongNumberBinops) {
    319   checkArgumentCombinations(op, nonNumberValues,
    320                             numberValues.concat(nonNumberValues), true);
    321 }
    322 
    323 for (let op of strongStringOrNumberBinops) {
    324   checkArgumentCombinations(op, nonNumberValues,
    325                             numberValues.concat(nonStringOrNumberValues), true);
    326   checkArgumentCombinations(op, nonStringOrNumberValues, stringValues, true);
    327   checkArgumentCombinations(op, stringValues, stringValues, false);
    328 }
    329 
    330 for (let op of strongUnops) {
    331   for (let value of numberValues) {
    332     assertStrongNonThrowBehaviour("(" + op + value + ")");
    333   }
    334   for (let value of nonNumberValues) {
    335     assertStrongThrowBehaviour("(" + op + value + ")");
    336   }
    337 }
    338 
    339 for (let func of strongNumberFuncs) {
    340   // Check IC None*None->None throws
    341   for (let v of nonNumberValues) {
    342     let value = eval(v);
    343     assertThrows(function(){func(2, value);}, TypeError);
    344     %OptimizeFunctionOnNextCall(func);
    345     assertThrows(function(){func(2, value);}, TypeError);
    346     %DeoptimizeFunction(func);
    347   }
    348   func(4, 5);
    349   func(4, 5);
    350   // Check IC Smi*Smi->Smi throws
    351   for (let v of nonNumberValues) {
    352     let value = eval(v);
    353     assertThrows(function(){func(2, value);}, TypeError);
    354     %OptimizeFunctionOnNextCall(func);
    355     assertThrows(function(){func(2, value);}, TypeError);
    356     %DeoptimizeFunction(func);
    357   }
    358   func(NaN, NaN);
    359   func(NaN, NaN);
    360   // Check IC Number*Number->Number throws
    361   for (let v of nonNumberValues) {
    362     let value = eval(v);
    363     assertThrows(function(){func(2, value);}, TypeError);
    364     %OptimizeFunctionOnNextCall(func);
    365     assertThrows(function(){func(2, value);}, TypeError);
    366     %DeoptimizeFunction(func);
    367   }
    368 }
    369 
    370 for (let func of strongStringOrNumberFuncs) {
    371   // Check IC None*None->None throws
    372   for (let v of nonNumberValues) {
    373     let value = eval(v);
    374     assertThrows(function(){func(2, value);}, TypeError);
    375     %OptimizeFunctionOnNextCall(func);
    376     assertThrows(function(){func(2, value);}, TypeError);
    377     %DeoptimizeFunction(func);
    378   }
    379   func("foo", "bar");
    380   func("foo", "bar");
    381   // Check IC String*String->String throws
    382   for (let v of nonNumberValues) {
    383     let value = eval(v);
    384     assertThrows(function(){func(2, value);}, TypeError);
    385     %OptimizeFunctionOnNextCall(func);
    386     assertThrows(function(){func(2, value);}, TypeError);
    387     %DeoptimizeFunction(func);
    388   }
    389   func(NaN, NaN);
    390   func(NaN, NaN);
    391   // Check IC Generic*Generic->Generic throws
    392   for (let v of nonNumberValues) {
    393     let value = eval(v);
    394     assertThrows(function(){func(2, value);}, TypeError);
    395     %OptimizeFunctionOnNextCall(func);
    396     assertThrows(function(){func(2, value);}, TypeError);
    397     %DeoptimizeFunction(func);
    398   }
    399 }
    400 
    401 for (let func of [str_equal_strong, str_ineq_strong]) {
    402   assertDoesNotThrow(function(){func(2, undefined)});
    403   assertDoesNotThrow(function(){func(2, undefined)});
    404   %OptimizeFunctionOnNextCall(func);
    405   assertDoesNotThrow(function(){func(2, undefined)});
    406   %DeoptimizeFunction(func);
    407   assertDoesNotThrow(function(){func(true, {})});
    408   assertDoesNotThrow(function(){func(true, {})});
    409   %OptimizeFunctionOnNextCall(func);
    410   assertDoesNotThrow(function(){func(true, {})});
    411   %DeoptimizeFunction(func);
    412 }
    413