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