• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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