Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Flags: --strong-mode --allow-natives-syntax | 5 // Flags: --strong-mode --allow-natives-syntax |
| 6 | 6 |
| 7 "use strict"; | 7 "use strict"; |
| 8 | 8 |
| 9 // TODO(conradw): Implement other strong operators | 9 // TODO(conradw): Implement other strong operators |
| 10 let strongBinops = [ | 10 let strongNumberBinops = [ |
| 11 "-", | 11 "-", |
| 12 "*", | 12 "*", |
| 13 "/", | 13 "/", |
| 14 "%", | 14 "%", |
| 15 "|", | 15 "|", |
| 16 "&", | 16 "&", |
| 17 "^", | 17 "^", |
| 18 "<<", | 18 "<<", |
| 19 ">>", | 19 ">>", |
| 20 ">>>", | 20 ">>>", |
| 21 ]; | 21 ]; |
| 22 | 22 |
| 23 let strongStringOrNumberBinops = [ | |
| 24 "+" | |
| 25 ]; | |
| 26 | |
| 27 let strongBinops = strongNumberBinops.concat(strongStringOrNumberBinops); | |
| 28 | |
| 23 let strongUnops = [ | 29 let strongUnops = [ |
| 24 "~", | 30 "~", |
| 25 "+", | 31 "+", |
| 26 "-" | 32 "-" |
| 27 ]; | 33 ]; |
| 28 | 34 |
| 29 let nonNumberValues = [ | 35 let nonStringOrNumberValues = [ |
| 30 "{}", | 36 "{}", |
| 31 "'foo'", | 37 "false", |
| 32 "(function(){})", | 38 "(function(){})", |
| 33 "[]", | 39 "[]", |
| 34 "'0'", | |
| 35 "'NaN'", | |
| 36 "(class Foo {})" | 40 "(class Foo {})" |
| 37 ]; | 41 ]; |
| 38 | 42 |
| 43 let stringValues = [ | |
| 44 "''", | |
| 45 "' '", | |
| 46 "'foo'", | |
| 47 "'f\\u006F\\u006F'", | |
| 48 "'0'", | |
| 49 "'NaN'" | |
| 50 ]; | |
| 51 | |
| 52 let nonNumberValues = nonStringOrNumberValues.concat(stringValues); | |
| 53 | |
| 39 let numberValues = [ | 54 let numberValues = [ |
| 40 "0", | 55 "0", |
| 41 "(-0)", | 56 "(-0)", |
| 42 "1", | 57 "1", |
| 43 "0.79", | 58 "0.79", |
| 44 "(-0.79)", | 59 "(-0.79)", |
| 45 "4294967295", | 60 "4294967295", |
| 46 "4294967296", | 61 "4294967296", |
| 47 "(-4294967295)", | 62 "(-4294967295)", |
| 48 "(-4294967296)", | 63 "(-4294967296)", |
| 49 "9999999999999", | 64 "9999999999999", |
| 50 "(-9999999999999)", | 65 "(-9999999999999)", |
| 51 "1.5e10", | 66 "1.5e10", |
| 52 "(-1.5e10)", | 67 "(-1.5e10)", |
| 53 "0xFFF", | 68 "0xFFF", |
| 54 "(-0xFFF)", | 69 "(-0xFFF)", |
| 55 "NaN", | 70 "NaN", |
| 56 "Infinity", | 71 "Infinity", |
| 57 "(-Infinity)" | 72 "(-Infinity)" |
| 58 ]; | 73 ]; |
| 59 | 74 |
| 75 function add_strong(x, y) { | |
| 76 "use strong"; | |
| 77 return x + y; | |
| 78 } | |
| 79 | |
| 80 function add_num_strong(x, y) { | |
|
arv (Not doing code reviews)
2015/04/30 16:07:32
Any reason for this over add_strong?
conradw
2015/05/04 09:28:22
It's a kind of unfortunate way to make sure that t
| |
| 81 "use strong"; | |
| 82 return x + y; | |
| 83 } | |
| 84 | |
| 60 function sub_strong(x, y) { | 85 function sub_strong(x, y) { |
| 61 "use strong"; | 86 "use strong"; |
| 62 return x - y; | 87 return x - y; |
| 63 } | 88 } |
| 64 | 89 |
| 65 function mul_strong(x, y) { | 90 function mul_strong(x, y) { |
| 66 "use strong"; | 91 "use strong"; |
| 67 return x * y; | 92 return x * y; |
| 68 } | 93 } |
| 69 | 94 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 100 function shr_strong(x, y) { | 125 function shr_strong(x, y) { |
| 101 "use strong"; | 126 "use strong"; |
| 102 return x >> y; | 127 return x >> y; |
| 103 } | 128 } |
| 104 | 129 |
| 105 function sar_strong(x, y) { | 130 function sar_strong(x, y) { |
| 106 "use strong"; | 131 "use strong"; |
| 107 return x >>> y; | 132 return x >>> y; |
| 108 } | 133 } |
| 109 | 134 |
| 135 function typed_add_strong(x, y) { | |
| 136 "use strong"; | |
| 137 return (+x) + (+y); | |
| 138 } | |
| 139 | |
| 110 function typed_sub_strong(x, y) { | 140 function typed_sub_strong(x, y) { |
| 111 "use strong"; | 141 "use strong"; |
| 112 return (+x) - (+y); | 142 return (+x) - (+y); |
| 113 } | 143 } |
| 114 | 144 |
| 115 function typed_mul_strong(x, y) { | 145 function typed_mul_strong(x, y) { |
| 116 "use strong"; | 146 "use strong"; |
| 117 return (+x) * (+y); | 147 return (+x) * (+y); |
| 118 } | 148 } |
| 119 | 149 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 150 function typed_shr_strong(x, y) { | 180 function typed_shr_strong(x, y) { |
| 151 "use strong"; | 181 "use strong"; |
| 152 return (+x) >> (+y); | 182 return (+x) >> (+y); |
| 153 } | 183 } |
| 154 | 184 |
| 155 function typed_sar_strong(x, y) { | 185 function typed_sar_strong(x, y) { |
| 156 "use strong"; | 186 "use strong"; |
| 157 return (+x) >>> (+y); | 187 return (+x) >>> (+y); |
| 158 } | 188 } |
| 159 | 189 |
| 160 let strongFuncs = [sub_strong, mul_strong, div_strong, mod_strong, or_strong, | 190 let strongNumberFuncs = [add_num_strong, sub_strong, mul_strong, div_strong, |
| 161 and_strong, xor_strong, shl_strong, shr_strong, sar_strong, | 191 mod_strong, or_strong, and_strong, xor_strong, |
| 162 typed_sub_strong, typed_mul_strong, typed_div_strong, | 192 shl_strong, shr_strong, sar_strong, typed_add_strong, |
| 163 typed_mod_strong, typed_or_strong, typed_and_strong, | 193 typed_sub_strong, typed_mul_strong, typed_div_strong, |
| 164 typed_xor_strong, typed_shl_strong, typed_shr_strong, | 194 typed_mod_strong, typed_or_strong, typed_and_strong, |
| 165 typed_sar_strong]; | 195 typed_xor_strong, typed_shl_strong, typed_shr_strong, |
| 196 typed_sar_strong]; | |
| 197 | |
| 198 let strongStringOrNumberFuncs = [add_strong]; | |
| 199 | |
| 200 let strongFuncs = strongNumberFuncs.concat(strongStringOrNumberFuncs); | |
| 166 | 201 |
| 167 function inline_sub_strong(x, y) { | 202 function inline_sub_strong(x, y) { |
| 168 "use strong"; | 203 "use strong"; |
| 169 let v = x - y; | 204 let v = x - y; |
| 170 return v; | 205 return v; |
| 171 } | 206 } |
| 172 | 207 |
| 173 function inline_outer(x, y) { | 208 function inline_outer(x, y) { |
| 174 return inline_sub_strong(x, y); | 209 return inline_sub_strong(x, y); |
| 175 } | 210 } |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 190 assertDoesNotThrow("'use strong'; let v = " + expr + ";"); | 225 assertDoesNotThrow("'use strong'; let v = " + expr + ";"); |
| 191 } | 226 } |
| 192 | 227 |
| 193 function assertStrongThrowBehaviour(expr) { | 228 function assertStrongThrowBehaviour(expr) { |
| 194 assertDoesNotThrow("'use strict'; " + expr + ";"); | 229 assertDoesNotThrow("'use strict'; " + expr + ";"); |
| 195 assertDoesNotThrow("'use strict'; let v = " + expr + ";"); | 230 assertDoesNotThrow("'use strict'; let v = " + expr + ";"); |
| 196 assertThrows("'use strong'; " + expr + ";", TypeError); | 231 assertThrows("'use strong'; " + expr + ";", TypeError); |
| 197 assertThrows("'use strong'; let v = " + expr + ";", TypeError); | 232 assertThrows("'use strong'; let v = " + expr + ";", TypeError); |
| 198 } | 233 } |
| 199 | 234 |
| 200 for (let op of strongBinops) { | 235 function checkArgumentCombinations(op, leftList, rightList, willThrow) { |
| 201 for (let v1 of numberValues) { | 236 for (let v1 of leftList) { |
| 202 let assignExpr = "foo " + op + "= " + v1 + ";"; | 237 let assignExpr = "foo " + op + "= " + v1 + ";"; |
| 203 for (let v2 of numberValues) { | 238 for (let v2 of rightList) { |
| 204 assertDoesNotThrow("'use strong'; let foo = " + v2 + "; " + assignExpr); | 239 let compoundAssignment = "'use strong'; let foo = " + v2 + "; " + |
| 205 assertStrongNonThrowBehaviour("(" + v1 + op + v2 + ")"); | 240 assignExpr; |
| 206 } | 241 if(willThrow) { |
| 207 for (let v2 of nonNumberValues) { | 242 assertThrows(compoundAssignment, TypeError); |
| 208 assertThrows("'use strong'; let foo = " + v2 + "; " + assignExpr, | 243 assertStrongThrowBehaviour("(" + v1 + op + v2 + ")"); |
| 209 TypeError); | 244 } else { |
| 210 assertStrongThrowBehaviour("(" + v1 + op + v2 + ")"); | 245 assertDoesNotThrow(compoundAssignment); |
| 246 assertStrongNonThrowBehaviour("(" + v1 + op + v2 + ")"); | |
| 247 } | |
| 211 } | 248 } |
| 212 } | 249 } |
| 213 for (let v1 of nonNumberValues) { | 250 } |
| 214 let assignExpr = "foo " + op + "= " + v1 + ";"; | 251 |
| 215 for (let v2 of numberValues.concat(nonNumberValues)) { | 252 for (let op of strongBinops) { |
| 216 assertThrows("'use strong'; let foo = " + v2 + "; " + assignExpr, | 253 checkArgumentCombinations(op, numberValues, numberValues, false); |
| 217 TypeError); | 254 checkArgumentCombinations(op, numberValues, nonNumberValues, true); |
| 218 assertStrongThrowBehaviour("(" + v1 + op + v2 + ")"); | 255 } |
| 219 } | 256 |
| 220 } | 257 for (let op of strongNumberBinops) { |
| 258 checkArgumentCombinations(op, nonNumberValues, | |
| 259 numberValues.concat(nonNumberValues), true); | |
| 260 } | |
| 261 | |
| 262 for (let op of strongStringOrNumberBinops) { | |
| 263 checkArgumentCombinations(op, nonNumberValues, | |
| 264 numberValues.concat(nonStringOrNumberValues), true); | |
| 265 checkArgumentCombinations(op, nonStringOrNumberValues, stringValues, true); | |
| 266 checkArgumentCombinations(op, stringValues, stringValues, false); | |
| 221 } | 267 } |
| 222 | 268 |
| 223 for (let op of strongUnops) { | 269 for (let op of strongUnops) { |
| 224 for (let value of numberValues) { | 270 for (let value of numberValues) { |
| 225 assertStrongNonThrowBehaviour("(" + op + value + ")"); | 271 assertStrongNonThrowBehaviour("(" + op + value + ")"); |
| 226 } | 272 } |
| 227 for (let value of nonNumberValues) { | 273 for (let value of nonNumberValues) { |
| 228 assertStrongThrowBehaviour("(" + op + value + ")"); | 274 assertStrongThrowBehaviour("(" + op + value + ")"); |
| 229 } | 275 } |
| 230 } | 276 } |
| 231 | 277 |
| 232 for (let func of strongFuncs) { | 278 for (let func of strongNumberFuncs) { |
| 233 let a = func(4, 5); | 279 // Check IC None*None->None throws |
| 234 let b = func(4, 5); | 280 assertThrows(function(){func(2, "foo");}, TypeError); |
| 235 assertTrue(a === b); | |
| 236 %OptimizeFunctionOnNextCall(func); | 281 %OptimizeFunctionOnNextCall(func); |
| 237 let c = func(4, 5); | 282 assertThrows(function(){func(2, "foo");}, TypeError); |
| 238 assertOptimized(func); | |
| 239 assertTrue(b === c); | |
| 240 %DeoptimizeFunction(func); | 283 %DeoptimizeFunction(func); |
| 241 let d = func(4, 5); | 284 func(4, 5); |
| 242 assertTrue(c === d); | 285 func(4, 5); |
| 286 // Check IC Smi*Smi->Smi throws | |
| 287 assertThrows(function(){func(2, "foo");}, TypeError); | |
| 288 %OptimizeFunctionOnNextCall(func); | |
| 289 assertThrows(function(){func(2, "foo");}, TypeError); | |
| 243 %DeoptimizeFunction(func); | 290 %DeoptimizeFunction(func); |
| 244 %ClearFunctionTypeFeedback(func); | 291 func(NaN, NaN); |
| 292 func(NaN, NaN); | |
| 293 // Check IC Number*Number->Number throws | |
| 294 assertThrows(function(){func(2, "foo");}, TypeError); | |
|
arv (Not doing code reviews)
2015/04/30 16:07:32
Shouldn't this use a non smi?
conradw
2015/05/04 09:28:22
I'm not particularly worried in this case, because
| |
| 295 %OptimizeFunctionOnNextCall(func); | |
| 296 assertThrows(function(){func(2, "foo");}, TypeError); | |
| 297 %DeoptimizeFunction(func); | |
| 245 } | 298 } |
| 246 | 299 |
| 247 for (let func of strongFuncs) { | 300 for (let func of strongStringOrNumberFuncs) { |
| 248 try { | 301 // Check IC None*None->None throws |
| 249 let a = func(2, 3); | 302 assertThrows(function(){func(2, "foo");}, TypeError); |
| 250 let b = func(2, 3); | 303 %OptimizeFunctionOnNextCall(func); |
| 251 assertTrue(a === b); | 304 assertThrows(function(){func(2, "foo");}, TypeError); |
| 252 %OptimizeFunctionOnNextCall(func); | 305 %DeoptimizeFunction(func); |
| 253 let c = func(2, "foo"); | 306 func("foo", "bar"); |
| 254 assertUnreachable(); | 307 func("foo", "bar"); |
| 255 } catch (e) { | 308 // Check IC String*String->String throws |
| 256 assertInstanceof(e, TypeError); | 309 assertThrows(function(){func(2, "foo");}, TypeError); |
| 257 assertUnoptimized(func); | 310 %OptimizeFunctionOnNextCall(func); |
| 258 assertThrows(function(){func(2, "foo");}, TypeError); | 311 assertThrows(function(){func(2, "foo");}, TypeError); |
| 259 assertDoesNotThrow(function(){func(2, 3);}); | 312 %DeoptimizeFunction(func); |
| 260 } | 313 func(NaN, NaN); |
| 314 func(NaN, NaN); | |
| 315 // Check IC Generic*Generic->Generic throws | |
| 316 assertThrows(function(){func(2, "foo");}, TypeError); | |
| 317 %OptimizeFunctionOnNextCall(func); | |
| 318 assertThrows(function(){func(2, "foo");}, TypeError); | |
| 319 %DeoptimizeFunction(func); | |
| 261 } | 320 } |
| 262 | 321 |
| 263 assertThrows(function(){inline_outer(1, {})}, TypeError); | 322 assertThrows(function(){inline_outer(1, {})}, TypeError); |
| 264 for (var i = 0; i < 100; i++) { | 323 for (var i = 0; i < 100; i++) { |
| 265 inline_outer(1, 2); | 324 inline_outer(1, 2); |
| 266 } | 325 } |
| 267 assertThrows(function(){inline_outer(1, {})}, TypeError); | 326 assertThrows(function(){inline_outer(1, {})}, TypeError); |
| 268 | 327 |
| 269 assertDoesNotThrow(function(){inline_outer_strong(1, {})}); | 328 assertDoesNotThrow(function(){inline_outer_strong(1, {})}); |
| 270 for (var i = 0; i < 100; i++) { | 329 for (var i = 0; i < 100; i++) { |
| 271 inline_outer_strong(1, 2); | 330 inline_outer_strong(1, 2); |
| 272 } | 331 } |
| 273 assertDoesNotThrow(function(){inline_outer_strong(1, {})}); | 332 assertDoesNotThrow(function(){inline_outer_strong(1, {})}); |
| OLD | NEW |