1// Copyright 2014 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#include "src/v8.h"
6
7#include "test/cctest/compiler/function-tester.h"
8
9using namespace v8::internal;
10using namespace v8::internal::compiler;
11
12TEST(BinopAdd) {
13  FunctionTester T("(function(a,b) { return a + b; })");
14
15  T.CheckCall(3, 1, 2);
16  T.CheckCall(-11, -2, -9);
17  T.CheckCall(-11, -1.5, -9.5);
18  T.CheckCall(T.Val("AB"), T.Val("A"), T.Val("B"));
19  T.CheckCall(T.Val("A11"), T.Val("A"), T.Val(11));
20  T.CheckCall(T.Val("12B"), T.Val(12), T.Val("B"));
21  T.CheckCall(T.Val("38"), T.Val("3"), T.Val("8"));
22  T.CheckCall(T.Val("31"), T.Val("3"), T.NewObject("([1])"));
23  T.CheckCall(T.Val("3[object Object]"), T.Val("3"), T.NewObject("({})"));
24}
25
26
27TEST(BinopSubtract) {
28  FunctionTester T("(function(a,b) { return a - b; })");
29
30  T.CheckCall(3, 4, 1);
31  T.CheckCall(3.0, 4.5, 1.5);
32  T.CheckCall(T.Val(-9), T.Val("0"), T.Val(9));
33  T.CheckCall(T.Val(-9), T.Val(0.0), T.Val("9"));
34  T.CheckCall(T.Val(1), T.Val("3"), T.Val("2"));
35  T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
36  T.CheckCall(T.Val(2), T.Val("3"), T.NewObject("([1])"));
37  T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
38}
39
40
41TEST(BinopMultiply) {
42  FunctionTester T("(function(a,b) { return a * b; })");
43
44  T.CheckCall(6, 3, 2);
45  T.CheckCall(4.5, 2.0, 2.25);
46  T.CheckCall(T.Val(6), T.Val("3"), T.Val(2));
47  T.CheckCall(T.Val(4.5), T.Val(2.0), T.Val("2.25"));
48  T.CheckCall(T.Val(6), T.Val("3"), T.Val("2"));
49  T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
50  T.CheckCall(T.Val(3), T.Val("3"), T.NewObject("([1])"));
51  T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
52}
53
54
55TEST(BinopDivide) {
56  FunctionTester T("(function(a,b) { return a / b; })");
57
58  T.CheckCall(2, 8, 4);
59  T.CheckCall(2.1, 8.4, 4);
60  T.CheckCall(V8_INFINITY, 8, 0);
61  T.CheckCall(-V8_INFINITY, -8, 0);
62  T.CheckCall(T.infinity(), T.Val(8), T.Val("0"));
63  T.CheckCall(T.minus_infinity(), T.Val("-8"), T.Val(0.0));
64  T.CheckCall(T.Val(1.5), T.Val("3"), T.Val("2"));
65  T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
66  T.CheckCall(T.Val(1.5), T.Val("3"), T.NewObject("([2])"));
67  T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
68}
69
70
71TEST(BinopModulus) {
72  FunctionTester T("(function(a,b) { return a % b; })");
73
74  T.CheckCall(3, 8, 5);
75  T.CheckCall(T.Val(3), T.Val("8"), T.Val(5));
76  T.CheckCall(T.Val(3), T.Val(8), T.Val("5"));
77  T.CheckCall(T.Val(1), T.Val("3"), T.Val("2"));
78  T.CheckCall(T.nan(), T.Val("3"), T.Val("B"));
79  T.CheckCall(T.Val(1), T.Val("3"), T.NewObject("([2])"));
80  T.CheckCall(T.nan(), T.Val("3"), T.NewObject("({})"));
81}
82
83
84TEST(BinopShiftLeft) {
85  FunctionTester T("(function(a,b) { return a << b; })");
86
87  T.CheckCall(4, 2, 1);
88  T.CheckCall(T.Val(4), T.Val("2"), T.Val(1));
89  T.CheckCall(T.Val(4), T.Val(2), T.Val("1"));
90}
91
92
93TEST(BinopShiftRight) {
94  FunctionTester T("(function(a,b) { return a >> b; })");
95
96  T.CheckCall(4, 8, 1);
97  T.CheckCall(-4, -8, 1);
98  T.CheckCall(T.Val(4), T.Val("8"), T.Val(1));
99  T.CheckCall(T.Val(4), T.Val(8), T.Val("1"));
100}
101
102
103TEST(BinopShiftRightLogical) {
104  FunctionTester T("(function(a,b) { return a >>> b; })");
105
106  T.CheckCall(4, 8, 1);
107  T.CheckCall(0x7ffffffc, -8, 1);
108  T.CheckCall(T.Val(4), T.Val("8"), T.Val(1));
109  T.CheckCall(T.Val(4), T.Val(8), T.Val("1"));
110}
111
112
113TEST(BinopAnd) {
114  FunctionTester T("(function(a,b) { return a & b; })");
115
116  T.CheckCall(7, 7, 15);
117  T.CheckCall(7, 15, 7);
118  T.CheckCall(T.Val(7), T.Val("15"), T.Val(7));
119  T.CheckCall(T.Val(7), T.Val(15), T.Val("7"));
120}
121
122
123TEST(BinopOr) {
124  FunctionTester T("(function(a,b) { return a | b; })");
125
126  T.CheckCall(6, 4, 2);
127  T.CheckCall(6, 2, 4);
128  T.CheckCall(T.Val(6), T.Val("2"), T.Val(4));
129  T.CheckCall(T.Val(6), T.Val(2), T.Val("4"));
130}
131
132
133TEST(BinopXor) {
134  FunctionTester T("(function(a,b) { return a ^ b; })");
135
136  T.CheckCall(7, 15, 8);
137  T.CheckCall(7, 8, 15);
138  T.CheckCall(T.Val(7), T.Val("8"), T.Val(15));
139  T.CheckCall(T.Val(7), T.Val(8), T.Val("15"));
140}
141
142
143TEST(BinopStrictEqual) {
144  FunctionTester T("(function(a,b) { return a === b; })");
145
146  T.CheckTrue(7, 7);
147  T.CheckFalse(7, 8);
148  T.CheckTrue(7.1, 7.1);
149  T.CheckFalse(7.1, 8.1);
150
151  T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
152  T.CheckFalse(T.Val(7.1), T.Val("7.1"));
153  T.CheckFalse(T.Val(7), T.undefined());
154  T.CheckFalse(T.undefined(), T.Val(7));
155
156  CompileRun("var o = { desc : 'I am a singleton' }");
157  T.CheckFalse(T.NewObject("([1])"), T.NewObject("([1])"));
158  T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
159  T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
160}
161
162
163TEST(BinopEqual) {
164  FunctionTester T("(function(a,b) { return a == b; })");
165
166  T.CheckTrue(7, 7);
167  T.CheckFalse(7, 8);
168  T.CheckTrue(7.1, 7.1);
169  T.CheckFalse(7.1, 8.1);
170
171  T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
172  T.CheckTrue(T.Val(7.1), T.Val("7.1"));
173
174  CompileRun("var o = { desc : 'I am a singleton' }");
175  T.CheckFalse(T.NewObject("([1])"), T.NewObject("([1])"));
176  T.CheckFalse(T.NewObject("({})"), T.NewObject("({})"));
177  T.CheckTrue(T.NewObject("(o)"), T.NewObject("(o)"));
178}
179
180
181TEST(BinopNotEqual) {
182  FunctionTester T("(function(a,b) { return a != b; })");
183
184  T.CheckFalse(7, 7);
185  T.CheckTrue(7, 8);
186  T.CheckFalse(7.1, 7.1);
187  T.CheckTrue(7.1, 8.1);
188
189  T.CheckFalse(T.Val("7.1"), T.Val("7.1"));
190  T.CheckFalse(T.Val(7.1), T.Val("7.1"));
191
192  CompileRun("var o = { desc : 'I am a singleton' }");
193  T.CheckTrue(T.NewObject("([1])"), T.NewObject("([1])"));
194  T.CheckTrue(T.NewObject("({})"), T.NewObject("({})"));
195  T.CheckFalse(T.NewObject("(o)"), T.NewObject("(o)"));
196}
197
198
199TEST(BinopLessThan) {
200  FunctionTester T("(function(a,b) { return a < b; })");
201
202  T.CheckTrue(7, 8);
203  T.CheckFalse(8, 7);
204  T.CheckTrue(-8.1, -8);
205  T.CheckFalse(-8, -8.1);
206  T.CheckFalse(0.111, 0.111);
207
208  T.CheckFalse(T.Val("7.1"), T.Val("7.1"));
209  T.CheckFalse(T.Val(7.1), T.Val("6.1"));
210  T.CheckFalse(T.Val(7.1), T.Val("7.1"));
211  T.CheckTrue(T.Val(7.1), T.Val("8.1"));
212}
213
214
215TEST(BinopLessThanEqual) {
216  FunctionTester T("(function(a,b) { return a <= b; })");
217
218  T.CheckTrue(7, 8);
219  T.CheckFalse(8, 7);
220  T.CheckTrue(-8.1, -8);
221  T.CheckFalse(-8, -8.1);
222  T.CheckTrue(0.111, 0.111);
223
224  T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
225  T.CheckFalse(T.Val(7.1), T.Val("6.1"));
226  T.CheckTrue(T.Val(7.1), T.Val("7.1"));
227  T.CheckTrue(T.Val(7.1), T.Val("8.1"));
228}
229
230
231TEST(BinopGreaterThan) {
232  FunctionTester T("(function(a,b) { return a > b; })");
233
234  T.CheckFalse(7, 8);
235  T.CheckTrue(8, 7);
236  T.CheckFalse(-8.1, -8);
237  T.CheckTrue(-8, -8.1);
238  T.CheckFalse(0.111, 0.111);
239
240  T.CheckFalse(T.Val("7.1"), T.Val("7.1"));
241  T.CheckTrue(T.Val(7.1), T.Val("6.1"));
242  T.CheckFalse(T.Val(7.1), T.Val("7.1"));
243  T.CheckFalse(T.Val(7.1), T.Val("8.1"));
244}
245
246
247TEST(BinopGreaterThanOrEqual) {
248  FunctionTester T("(function(a,b) { return a >= b; })");
249
250  T.CheckFalse(7, 8);
251  T.CheckTrue(8, 7);
252  T.CheckFalse(-8.1, -8);
253  T.CheckTrue(-8, -8.1);
254  T.CheckTrue(0.111, 0.111);
255
256  T.CheckTrue(T.Val("7.1"), T.Val("7.1"));
257  T.CheckTrue(T.Val(7.1), T.Val("6.1"));
258  T.CheckTrue(T.Val(7.1), T.Val("7.1"));
259  T.CheckFalse(T.Val(7.1), T.Val("8.1"));
260}
261
262
263TEST(BinopIn) {
264  FunctionTester T("(function(a,b) { return a in b; })");
265
266  T.CheckTrue(T.Val("x"), T.NewObject("({x:23})"));
267  T.CheckFalse(T.Val("y"), T.NewObject("({x:42})"));
268  T.CheckFalse(T.Val(123), T.NewObject("({x:65})"));
269  T.CheckTrue(T.Val(1), T.NewObject("([1,2,3])"));
270}
271
272
273TEST(BinopInstanceOf) {
274  FunctionTester T("(function(a,b) { return a instanceof b; })");
275
276  T.CheckTrue(T.NewObject("(new Number(23))"), T.NewObject("Number"));
277  T.CheckFalse(T.NewObject("(new Number(23))"), T.NewObject("String"));
278  T.CheckFalse(T.NewObject("(new String('a'))"), T.NewObject("Number"));
279  T.CheckTrue(T.NewObject("(new String('b'))"), T.NewObject("String"));
280  T.CheckFalse(T.Val(1), T.NewObject("Number"));
281  T.CheckFalse(T.Val("abc"), T.NewObject("String"));
282
283  CompileRun("var bound = (function() {}).bind(undefined)");
284  T.CheckTrue(T.NewObject("(new bound())"), T.NewObject("bound"));
285  T.CheckTrue(T.NewObject("(new bound())"), T.NewObject("Object"));
286  T.CheckFalse(T.NewObject("(new bound())"), T.NewObject("Number"));
287}
288
289
290TEST(UnopNot) {
291  FunctionTester T("(function(a) { return !a; })");
292
293  T.CheckCall(T.true_value(), T.false_value(), T.undefined());
294  T.CheckCall(T.false_value(), T.true_value(), T.undefined());
295  T.CheckCall(T.true_value(), T.Val(0.0), T.undefined());
296  T.CheckCall(T.false_value(), T.Val(123), T.undefined());
297  T.CheckCall(T.false_value(), T.Val("x"), T.undefined());
298  T.CheckCall(T.true_value(), T.undefined(), T.undefined());
299  T.CheckCall(T.true_value(), T.nan(), T.undefined());
300}
301
302
303TEST(UnopCountPost) {
304  FunctionTester T("(function(a) { return a++; })");
305
306  T.CheckCall(T.Val(0.0), T.Val(0.0), T.undefined());
307  T.CheckCall(T.Val(2.3), T.Val(2.3), T.undefined());
308  T.CheckCall(T.Val(123), T.Val(123), T.undefined());
309  T.CheckCall(T.Val(7), T.Val("7"), T.undefined());
310  T.CheckCall(T.nan(), T.Val("x"), T.undefined());
311  T.CheckCall(T.nan(), T.undefined(), T.undefined());
312  T.CheckCall(T.Val(1.0), T.true_value(), T.undefined());
313  T.CheckCall(T.Val(0.0), T.false_value(), T.undefined());
314  T.CheckCall(T.nan(), T.nan(), T.undefined());
315}
316
317
318TEST(UnopCountPre) {
319  FunctionTester T("(function(a) { return ++a; })");
320
321  T.CheckCall(T.Val(1.0), T.Val(0.0), T.undefined());
322  T.CheckCall(T.Val(3.3), T.Val(2.3), T.undefined());
323  T.CheckCall(T.Val(124), T.Val(123), T.undefined());
324  T.CheckCall(T.Val(8), T.Val("7"), T.undefined());
325  T.CheckCall(T.nan(), T.Val("x"), T.undefined());
326  T.CheckCall(T.nan(), T.undefined(), T.undefined());
327  T.CheckCall(T.Val(2.0), T.true_value(), T.undefined());
328  T.CheckCall(T.Val(1.0), T.false_value(), T.undefined());
329  T.CheckCall(T.nan(), T.nan(), T.undefined());
330}
331
332
333TEST(PropertyNamedLoad) {
334  FunctionTester T("(function(a,b) { return a.x; })");
335
336  T.CheckCall(T.Val(23), T.NewObject("({x:23})"), T.undefined());
337  T.CheckCall(T.undefined(), T.NewObject("({y:23})"), T.undefined());
338}
339
340
341TEST(PropertyKeyedLoad) {
342  FunctionTester T("(function(a,b) { return a[b]; })");
343
344  T.CheckCall(T.Val(23), T.NewObject("({x:23})"), T.Val("x"));
345  T.CheckCall(T.Val(42), T.NewObject("([23,42,65])"), T.Val(1));
346  T.CheckCall(T.undefined(), T.NewObject("({x:23})"), T.Val("y"));
347  T.CheckCall(T.undefined(), T.NewObject("([23,42,65])"), T.Val(4));
348}
349
350
351TEST(PropertyNamedStore) {
352  FunctionTester T("(function(a) { a.x = 7; return a.x; })");
353
354  T.CheckCall(T.Val(7), T.NewObject("({})"), T.undefined());
355  T.CheckCall(T.Val(7), T.NewObject("({x:23})"), T.undefined());
356}
357
358
359TEST(PropertyKeyedStore) {
360  FunctionTester T("(function(a,b) { a[b] = 7; return a.x; })");
361
362  T.CheckCall(T.Val(7), T.NewObject("({})"), T.Val("x"));
363  T.CheckCall(T.Val(7), T.NewObject("({x:23})"), T.Val("x"));
364  T.CheckCall(T.Val(9), T.NewObject("({x:9})"), T.Val("y"));
365}
366
367
368TEST(PropertyNamedDelete) {
369  FunctionTester T("(function(a) { return delete a.x; })");
370
371  CompileRun("var o = Object.create({}, { x: { value:23 } });");
372  T.CheckTrue(T.NewObject("({x:42})"), T.undefined());
373  T.CheckTrue(T.NewObject("({})"), T.undefined());
374  T.CheckFalse(T.NewObject("(o)"), T.undefined());
375}
376
377
378TEST(PropertyKeyedDelete) {
379  FunctionTester T("(function(a, b) { return delete a[b]; })");
380
381  CompileRun("function getX() { return 'x'; }");
382  CompileRun("var o = Object.create({}, { x: { value:23 } });");
383  T.CheckTrue(T.NewObject("({x:42})"), T.Val("x"));
384  T.CheckFalse(T.NewObject("(o)"), T.Val("x"));
385  T.CheckFalse(T.NewObject("(o)"), T.NewObject("({toString:getX})"));
386}
387
388
389TEST(GlobalLoad) {
390  FunctionTester T("(function() { return g; })");
391
392  T.CheckThrows(T.undefined(), T.undefined());
393  CompileRun("var g = 23;");
394  T.CheckCall(T.Val(23));
395}
396
397
398TEST(GlobalStoreSloppy) {
399  FunctionTester T("(function(a,b) { g = a + b; return g; })");
400
401  T.CheckCall(T.Val(33), T.Val(22), T.Val(11));
402  CompileRun("delete g");
403  CompileRun("const g = 23");
404  T.CheckCall(T.Val(23), T.Val(55), T.Val(44));
405}
406
407
408TEST(GlobalStoreStrict) {
409  FunctionTester T("(function(a,b) { 'use strict'; g = a + b; return g; })");
410
411  T.CheckThrows(T.Val(22), T.Val(11));
412  CompileRun("var g = 'a global variable';");
413  T.CheckCall(T.Val(33), T.Val(22), T.Val(11));
414}
415
416
417TEST(ContextLoad) {
418  FunctionTester T("(function(a,b) { (function(){a}); return a + b; })");
419
420  T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
421  T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
422}
423
424
425TEST(ContextStore) {
426  FunctionTester T("(function(a,b) { (function(){x}); var x = a; return x; })");
427
428  T.CheckCall(T.Val(23), T.Val(23), T.undefined());
429  T.CheckCall(T.Val("a"), T.Val("a"), T.undefined());
430}
431
432
433TEST(LookupLoad) {
434  FunctionTester T("(function(a,b) { with(a) { return x + b; } })");
435
436  T.CheckCall(T.Val(24), T.NewObject("({x:23})"), T.Val(1));
437  T.CheckCall(T.Val(32), T.NewObject("({x:23, b:9})"), T.Val(2));
438  T.CheckCall(T.Val(45), T.NewObject("({__proto__:{x:42}})"), T.Val(3));
439  T.CheckCall(T.Val(69), T.NewObject("({get x() { return 65; }})"), T.Val(4));
440}
441
442
443TEST(LookupStore) {
444  FunctionTester T("(function(a,b) { var x; with(a) { x = b; } return x; })");
445
446  T.CheckCall(T.undefined(), T.NewObject("({x:23})"), T.Val(1));
447  T.CheckCall(T.Val(2), T.NewObject("({y:23})"), T.Val(2));
448  T.CheckCall(T.Val(23), T.NewObject("({b:23})"), T.Val(3));
449  T.CheckCall(T.undefined(), T.NewObject("({__proto__:{x:42}})"), T.Val(4));
450}
451
452
453TEST(BlockLoadStore) {
454  FLAG_harmony_scoping = true;
455  FunctionTester T("(function(a) { 'use strict'; { let x = a+a; return x; }})");
456
457  T.CheckCall(T.Val(46), T.Val(23));
458  T.CheckCall(T.Val("aa"), T.Val("a"));
459}
460
461
462TEST(BlockLoadStoreNested) {
463  FLAG_harmony_scoping = true;
464  const char* src =
465      "(function(a,b) {"
466      "'use strict';"
467      "{ let x = a, y = a;"
468      "  { let y = b;"
469      "    return x + y;"
470      "  }"
471      "}})";
472  FunctionTester T(src);
473
474  T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
475  T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
476}
477
478
479TEST(ObjectLiteralComputed) {
480  FunctionTester T("(function(a,b) { o = { x:a+b }; return o.x; })");
481
482  T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
483  T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
484}
485
486
487TEST(ObjectLiteralNonString) {
488  FunctionTester T("(function(a,b) { o = { 7:a+b }; return o[7]; })");
489
490  T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
491  T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
492}
493
494
495TEST(ObjectLiteralPrototype) {
496  FunctionTester T("(function(a) { o = { __proto__:a }; return o.x; })");
497
498  T.CheckCall(T.Val(23), T.NewObject("({x:23})"), T.undefined());
499  T.CheckCall(T.undefined(), T.NewObject("({y:42})"), T.undefined());
500}
501
502
503TEST(ObjectLiteralGetter) {
504  FunctionTester T("(function(a) { o = { get x() {return a} }; return o.x; })");
505
506  T.CheckCall(T.Val(23), T.Val(23), T.undefined());
507  T.CheckCall(T.Val("x"), T.Val("x"), T.undefined());
508}
509
510
511TEST(ArrayLiteral) {
512  FunctionTester T("(function(a,b) { o = [1, a + b, 3]; return o[1]; })");
513
514  T.CheckCall(T.Val(65), T.Val(23), T.Val(42));
515  T.CheckCall(T.Val("ab"), T.Val("a"), T.Val("b"));
516}
517
518
519TEST(RegExpLiteral) {
520  FunctionTester T("(function(a) { o = /b/; return o.test(a); })");
521
522  T.CheckTrue(T.Val("abc"));
523  T.CheckFalse(T.Val("xyz"));
524}
525