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. 10let strongNumberBinops = [ 11 ["-", true], 12 ["*", true], 13 ["/", true], 14 ["%", true], 15 ["|", true], 16 ["&", true], 17 ["^", true], 18 ["<<", true], 19 [">>", true], 20 [">>>", true] 21]; 22 23let strongStringOrNumberBinops = [ 24 ["+", true], 25 ["<", false], 26 [">", false], 27 ["<=", false], 28 [">=", false] 29]; 30 31let strongBinops = strongNumberBinops.concat(strongStringOrNumberBinops); 32 33let strongUnops = [ 34 "~", 35 "+", 36 "-" 37]; 38 39let nonStringOrNumberValues = [ 40 "null", 41 "undefined", 42 "{}", 43 "false", 44 "(function(){})", 45 "[]", 46 "(class Foo {})" 47]; 48 49let stringValues = [ 50 "''", 51 "' '", 52 "'foo'", 53 "'f\\u006F\\u006F'", 54 "'0'", 55 "'NaN'" 56]; 57 58let nonNumberValues = nonStringOrNumberValues.concat(stringValues); 59 60let 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 75function add_strong(x, y) { 76 "use strong"; 77 return x + y; 78} 79 80function add_num_strong(x, y) { 81 "use strong"; 82 return x + y; 83} 84 85function sub_strong(x, y) { 86 "use strong"; 87 return x - y; 88} 89 90function mul_strong(x, y) { 91 "use strong"; 92 return x * y; 93} 94 95function div_strong(x, y) { 96 "use strong"; 97 return x / y; 98} 99 100function mod_strong(x, y) { 101 "use strong"; 102 return x % y; 103} 104 105function or_strong(x, y) { 106 "use strong"; 107 return x | y; 108} 109 110function and_strong(x, y) { 111 "use strong"; 112 return x & y; 113} 114 115function xor_strong(x, y) { 116 "use strong"; 117 return x ^ y; 118} 119 120function shl_strong(x, y) { 121 "use strong"; 122 return x << y; 123} 124 125function shr_strong(x, y) { 126 "use strong"; 127 return x >> y; 128} 129 130function sar_strong(x, y) { 131 "use strong"; 132 return x >>> y; 133} 134 135function less_strong(x, y) { 136 "use strong"; 137 return x < y; 138} 139 140function less_num_strong(x, y) { 141 "use strong"; 142 return x < y; 143} 144 145function greater_strong(x, y) { 146 "use strong"; 147 return x > y; 148} 149 150function greater_num_strong(x, y) { 151 "use strong"; 152 return x > y; 153} 154 155function less_equal_strong(x, y) { 156 "use strong"; 157 return x <= y; 158} 159 160function less_equal_num_strong(x, y) { 161 "use strong"; 162 return x <= y; 163} 164 165function greater_equal_strong(x, y) { 166 "use strong"; 167 return x >= y; 168} 169 170function greater_equal_num_strong(x, y) { 171 "use strong"; 172 return x >= y; 173} 174 175function typed_add_strong(x, y) { 176 "use strong"; 177 return (+x) + (+y); 178} 179 180function typed_sub_strong(x, y) { 181 "use strong"; 182 return (+x) - (+y); 183} 184 185function typed_mul_strong(x, y) { 186 "use strong"; 187 return (+x) * (+y); 188} 189 190function typed_div_strong(x, y) { 191 "use strong"; 192 return (+x) / (+y); 193} 194 195function typed_mod_strong(x, y) { 196 "use strong"; 197 return (+x) % (+y); 198} 199 200function typed_or_strong(x, y) { 201 "use strong"; 202 return (+x) | (+y); 203} 204 205function typed_and_strong(x, y) { 206 "use strong"; 207 return (+x) & (+y); 208} 209 210function typed_xor_strong(x, y) { 211 "use strong"; 212 return (+x) ^ (+y); 213} 214 215function typed_shl_strong(x, y) { 216 "use strong"; 217 return (+x) << (+y); 218} 219 220function typed_shr_strong(x, y) { 221 "use strong"; 222 return (+x) >> (+y); 223} 224 225function typed_sar_strong(x, y) { 226 "use strong"; 227 return (+x) >>> (+y); 228} 229 230function typed_less_strong(x, y) { 231 "use strong"; 232 return (+x) < (+y); 233} 234 235function typed_greater_strong(x, y) { 236 "use strong"; 237 return (+x) > (+y); 238} 239 240function typed_less_equal_strong(x, y) { 241 "use strong"; 242 return (+x) <= (+y); 243} 244 245function typed_greater_equal_strong(x, y) { 246 "use strong"; 247 return (+x) >= (+y); 248} 249 250//****************************************************************************** 251// (in)equality function declarations 252function str_equal_strong(x, y) { 253 "use strong"; 254 return x === y; 255} 256 257function str_ineq_strong(x, y) { 258 "use strong"; 259 return x !== y; 260} 261 262let 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 274let strongStringOrNumberFuncs = [add_strong, less_strong, greater_strong, 275 less_equal_strong, greater_equal_strong]; 276 277let strongFuncs = strongNumberFuncs.concat(strongStringOrNumberFuncs); 278 279function assertStrongNonThrowBehaviour(expr) { 280 assertEquals(eval(expr), eval("'use strong';" + expr)); 281 assertDoesNotThrow("'use strong'; " + expr + ";"); 282 assertDoesNotThrow("'use strong'; let v = " + expr + ";"); 283} 284 285function 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 292function 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 313for (let op of strongBinops) { 314 checkArgumentCombinations(op, numberValues, numberValues, false); 315 checkArgumentCombinations(op, numberValues, nonNumberValues, true); 316} 317 318for (let op of strongNumberBinops) { 319 checkArgumentCombinations(op, nonNumberValues, 320 numberValues.concat(nonNumberValues), true); 321} 322 323for (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 330for (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 339for (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 370for (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 401for (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