blob: cd8acf70857bf31050a07ff5d5fd24615c449d57 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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}