| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --strong-mode --allow-natives-syntax |
| |
| "use strict"; |
| |
| // Boolean indicates whether an operator can be part of a compound assignment. |
| let strongNumberBinops = [ |
| ["-", true], |
| ["*", true], |
| ["/", true], |
| ["%", true], |
| ["|", true], |
| ["&", true], |
| ["^", true], |
| ["<<", true], |
| [">>", true], |
| [">>>", true] |
| ]; |
| |
| let strongStringOrNumberBinops = [ |
| ["+", true], |
| ["<", false], |
| [">", false], |
| ["<=", false], |
| [">=", false] |
| ]; |
| |
| let strongBinops = strongNumberBinops.concat(strongStringOrNumberBinops); |
| |
| let strongUnops = [ |
| "~", |
| "+", |
| "-" |
| ]; |
| |
| let nonStringOrNumberValues = [ |
| "null", |
| "undefined", |
| "{}", |
| "false", |
| "(function(){})", |
| "[]", |
| "(class Foo {})" |
| ]; |
| |
| let stringValues = [ |
| "''", |
| "' '", |
| "'foo'", |
| "'f\\u006F\\u006F'", |
| "'0'", |
| "'NaN'" |
| ]; |
| |
| let nonNumberValues = nonStringOrNumberValues.concat(stringValues); |
| |
| let numberValues = [ |
| "0", |
| "(-0)", |
| "1", |
| "(-4294967295)", |
| "(-4294967296)", |
| "9999999999999", |
| "(-9999999999999)", |
| "NaN", |
| "Infinity", |
| "(-Infinity)" |
| ]; |
| |
| //****************************************************************************** |
| // Relational comparison function declarations |
| function add_strong(x, y) { |
| "use strong"; |
| return x + y; |
| } |
| |
| function add_num_strong(x, y) { |
| "use strong"; |
| return x + y; |
| } |
| |
| function sub_strong(x, y) { |
| "use strong"; |
| return x - y; |
| } |
| |
| function mul_strong(x, y) { |
| "use strong"; |
| return x * y; |
| } |
| |
| function div_strong(x, y) { |
| "use strong"; |
| return x / y; |
| } |
| |
| function mod_strong(x, y) { |
| "use strong"; |
| return x % y; |
| } |
| |
| function or_strong(x, y) { |
| "use strong"; |
| return x | y; |
| } |
| |
| function and_strong(x, y) { |
| "use strong"; |
| return x & y; |
| } |
| |
| function xor_strong(x, y) { |
| "use strong"; |
| return x ^ y; |
| } |
| |
| function shl_strong(x, y) { |
| "use strong"; |
| return x << y; |
| } |
| |
| function shr_strong(x, y) { |
| "use strong"; |
| return x >> y; |
| } |
| |
| function sar_strong(x, y) { |
| "use strong"; |
| return x >>> y; |
| } |
| |
| function less_strong(x, y) { |
| "use strong"; |
| return x < y; |
| } |
| |
| function less_num_strong(x, y) { |
| "use strong"; |
| return x < y; |
| } |
| |
| function greater_strong(x, y) { |
| "use strong"; |
| return x > y; |
| } |
| |
| function greater_num_strong(x, y) { |
| "use strong"; |
| return x > y; |
| } |
| |
| function less_equal_strong(x, y) { |
| "use strong"; |
| return x <= y; |
| } |
| |
| function less_equal_num_strong(x, y) { |
| "use strong"; |
| return x <= y; |
| } |
| |
| function greater_equal_strong(x, y) { |
| "use strong"; |
| return x >= y; |
| } |
| |
| function greater_equal_num_strong(x, y) { |
| "use strong"; |
| return x >= y; |
| } |
| |
| function typed_add_strong(x, y) { |
| "use strong"; |
| return (+x) + (+y); |
| } |
| |
| function typed_sub_strong(x, y) { |
| "use strong"; |
| return (+x) - (+y); |
| } |
| |
| function typed_mul_strong(x, y) { |
| "use strong"; |
| return (+x) * (+y); |
| } |
| |
| function typed_div_strong(x, y) { |
| "use strong"; |
| return (+x) / (+y); |
| } |
| |
| function typed_mod_strong(x, y) { |
| "use strong"; |
| return (+x) % (+y); |
| } |
| |
| function typed_or_strong(x, y) { |
| "use strong"; |
| return (+x) | (+y); |
| } |
| |
| function typed_and_strong(x, y) { |
| "use strong"; |
| return (+x) & (+y); |
| } |
| |
| function typed_xor_strong(x, y) { |
| "use strong"; |
| return (+x) ^ (+y); |
| } |
| |
| function typed_shl_strong(x, y) { |
| "use strong"; |
| return (+x) << (+y); |
| } |
| |
| function typed_shr_strong(x, y) { |
| "use strong"; |
| return (+x) >> (+y); |
| } |
| |
| function typed_sar_strong(x, y) { |
| "use strong"; |
| return (+x) >>> (+y); |
| } |
| |
| function typed_less_strong(x, y) { |
| "use strong"; |
| return (+x) < (+y); |
| } |
| |
| function typed_greater_strong(x, y) { |
| "use strong"; |
| return (+x) > (+y); |
| } |
| |
| function typed_less_equal_strong(x, y) { |
| "use strong"; |
| return (+x) <= (+y); |
| } |
| |
| function typed_greater_equal_strong(x, y) { |
| "use strong"; |
| return (+x) >= (+y); |
| } |
| |
| //****************************************************************************** |
| // (in)equality function declarations |
| function str_equal_strong(x, y) { |
| "use strong"; |
| return x === y; |
| } |
| |
| function str_ineq_strong(x, y) { |
| "use strong"; |
| return x !== y; |
| } |
| |
| let strongNumberFuncs = [add_num_strong, sub_strong, mul_strong, div_strong, |
| mod_strong, or_strong, and_strong, xor_strong, |
| shl_strong, shr_strong, sar_strong, less_num_strong, |
| greater_num_strong, less_equal_num_strong, |
| greater_equal_num_strong, typed_add_strong, |
| typed_sub_strong, typed_mul_strong, typed_div_strong, |
| typed_mod_strong, typed_or_strong, typed_and_strong, |
| typed_xor_strong, typed_shl_strong, typed_shr_strong, |
| typed_sar_strong, typed_less_strong, |
| typed_greater_strong, typed_less_equal_strong, |
| typed_greater_equal_strong]; |
| |
| let strongStringOrNumberFuncs = [add_strong, less_strong, greater_strong, |
| less_equal_strong, greater_equal_strong]; |
| |
| let strongFuncs = strongNumberFuncs.concat(strongStringOrNumberFuncs); |
| |
| function assertStrongNonThrowBehaviour(expr) { |
| assertEquals(eval(expr), eval("'use strong';" + expr)); |
| assertDoesNotThrow("'use strong'; " + expr + ";"); |
| assertDoesNotThrow("'use strong'; let v = " + expr + ";"); |
| } |
| |
| function assertStrongThrowBehaviour(expr) { |
| assertDoesNotThrow("'use strict'; " + expr + ";"); |
| assertDoesNotThrow("'use strict'; let v = " + expr + ";"); |
| assertThrows("'use strong'; " + expr + ";", TypeError); |
| assertThrows("'use strong'; let v = " + expr + ";", TypeError); |
| } |
| |
| function checkArgumentCombinations(op, leftList, rightList, willThrow) { |
| for (let v1 of leftList) { |
| let assignExpr = "foo " + op[0] + "= " + v1 + ";"; |
| for (let v2 of rightList) { |
| let compoundAssignment = "'use strong'; let foo = " + v2 + "; " + |
| assignExpr; |
| if (willThrow) { |
| if (op[1]) { |
| assertThrows(compoundAssignment, TypeError); |
| } |
| assertStrongThrowBehaviour("(" + v1 + op[0] + v2 + ")"); |
| } else { |
| if (op[1]) { |
| assertDoesNotThrow(compoundAssignment); |
| } |
| assertStrongNonThrowBehaviour("(" + v1 + op[0] + v2 + ")"); |
| } |
| } |
| } |
| } |
| |
| for (let op of strongBinops) { |
| checkArgumentCombinations(op, numberValues, numberValues, false); |
| checkArgumentCombinations(op, numberValues, nonNumberValues, true); |
| } |
| |
| for (let op of strongNumberBinops) { |
| checkArgumentCombinations(op, nonNumberValues, |
| numberValues.concat(nonNumberValues), true); |
| } |
| |
| for (let op of strongStringOrNumberBinops) { |
| checkArgumentCombinations(op, nonNumberValues, |
| numberValues.concat(nonStringOrNumberValues), true); |
| checkArgumentCombinations(op, nonStringOrNumberValues, stringValues, true); |
| checkArgumentCombinations(op, stringValues, stringValues, false); |
| } |
| |
| for (let op of strongUnops) { |
| for (let value of numberValues) { |
| assertStrongNonThrowBehaviour("(" + op + value + ")"); |
| } |
| for (let value of nonNumberValues) { |
| assertStrongThrowBehaviour("(" + op + value + ")"); |
| } |
| } |
| |
| for (let func of strongNumberFuncs) { |
| // Check IC None*None->None throws |
| for (let v of nonNumberValues) { |
| let value = eval(v); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %OptimizeFunctionOnNextCall(func); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %DeoptimizeFunction(func); |
| } |
| func(4, 5); |
| func(4, 5); |
| // Check IC Smi*Smi->Smi throws |
| for (let v of nonNumberValues) { |
| let value = eval(v); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %OptimizeFunctionOnNextCall(func); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %DeoptimizeFunction(func); |
| } |
| func(NaN, NaN); |
| func(NaN, NaN); |
| // Check IC Number*Number->Number throws |
| for (let v of nonNumberValues) { |
| let value = eval(v); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %OptimizeFunctionOnNextCall(func); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %DeoptimizeFunction(func); |
| } |
| } |
| |
| for (let func of strongStringOrNumberFuncs) { |
| // Check IC None*None->None throws |
| for (let v of nonNumberValues) { |
| let value = eval(v); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %OptimizeFunctionOnNextCall(func); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %DeoptimizeFunction(func); |
| } |
| func("foo", "bar"); |
| func("foo", "bar"); |
| // Check IC String*String->String throws |
| for (let v of nonNumberValues) { |
| let value = eval(v); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %OptimizeFunctionOnNextCall(func); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %DeoptimizeFunction(func); |
| } |
| func(NaN, NaN); |
| func(NaN, NaN); |
| // Check IC Generic*Generic->Generic throws |
| for (let v of nonNumberValues) { |
| let value = eval(v); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %OptimizeFunctionOnNextCall(func); |
| assertThrows(function(){func(2, value);}, TypeError); |
| %DeoptimizeFunction(func); |
| } |
| } |
| |
| for (let func of [str_equal_strong, str_ineq_strong]) { |
| assertDoesNotThrow(function(){func(2, undefined)}); |
| assertDoesNotThrow(function(){func(2, undefined)}); |
| %OptimizeFunctionOnNextCall(func); |
| assertDoesNotThrow(function(){func(2, undefined)}); |
| %DeoptimizeFunction(func); |
| assertDoesNotThrow(function(){func(true, {})}); |
| assertDoesNotThrow(function(){func(true, {})}); |
| %OptimizeFunctionOnNextCall(func); |
| assertDoesNotThrow(function(){func(true, {})}); |
| %DeoptimizeFunction(func); |
| } |