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 |