Line data Source code
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 : #include <fstream>
6 :
7 : #include "src/v8.h"
8 :
9 : #include "src/interpreter/bytecode-array-iterator.h"
10 : #include "src/interpreter/bytecode-generator.h"
11 : #include "src/interpreter/interpreter.h"
12 : #include "src/objects-inl.h"
13 : #include "test/cctest/cctest.h"
14 : #include "test/cctest/interpreter/bytecode-expectations-printer.h"
15 : #include "test/cctest/test-feedback-vector.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 : namespace interpreter {
20 :
21 : #define XSTR(A) #A
22 : #define STR(A) XSTR(A)
23 :
24 : #define UNIQUE_VAR() "var a" STR(__COUNTER__) " = 0;\n"
25 :
26 : #define LOAD_UNIQUE_PROPERTY() " b.name" STR(__COUNTER__) ";\n"
27 :
28 : #define REPEAT_2(...) __VA_ARGS__ __VA_ARGS__
29 : #define REPEAT_4(...) REPEAT_2(__VA_ARGS__) REPEAT_2(__VA_ARGS__)
30 : #define REPEAT_8(...) REPEAT_4(__VA_ARGS__) REPEAT_4(__VA_ARGS__)
31 : #define REPEAT_16(...) REPEAT_8(__VA_ARGS__) REPEAT_8(__VA_ARGS__)
32 : #define REPEAT_32(...) REPEAT_16(__VA_ARGS__) REPEAT_16(__VA_ARGS__)
33 : #define REPEAT_64(...) REPEAT_32(__VA_ARGS__) REPEAT_32(__VA_ARGS__)
34 : #define REPEAT_128(...) REPEAT_64(__VA_ARGS__) REPEAT_64(__VA_ARGS__)
35 : #define REPEAT_256(...) REPEAT_128(__VA_ARGS__) REPEAT_128(__VA_ARGS__)
36 :
37 : #define REPEAT_127(...) \
38 : REPEAT_64(__VA_ARGS__) \
39 : REPEAT_32(__VA_ARGS__) \
40 : REPEAT_16(__VA_ARGS__) \
41 : REPEAT_8(__VA_ARGS__) \
42 : REPEAT_4(__VA_ARGS__) \
43 : REPEAT_2(__VA_ARGS__) \
44 : __VA_ARGS__
45 :
46 : #define REPEAT_249(...) \
47 : REPEAT_127(__VA_ARGS__) \
48 : REPEAT_64(__VA_ARGS__) \
49 : REPEAT_32(__VA_ARGS__) \
50 : REPEAT_16(__VA_ARGS__) \
51 : REPEAT_8(__VA_ARGS__) \
52 : REPEAT_2(__VA_ARGS__)
53 :
54 : #define REPEAT_2_UNIQUE_VARS() UNIQUE_VAR() UNIQUE_VAR()
55 : #define REPEAT_4_UNIQUE_VARS() REPEAT_2_UNIQUE_VARS() REPEAT_2_UNIQUE_VARS()
56 : #define REPEAT_8_UNIQUE_VARS() REPEAT_4_UNIQUE_VARS() REPEAT_4_UNIQUE_VARS()
57 : #define REPEAT_16_UNIQUE_VARS() REPEAT_8_UNIQUE_VARS() REPEAT_8_UNIQUE_VARS()
58 : #define REPEAT_32_UNIQUE_VARS() REPEAT_16_UNIQUE_VARS() REPEAT_16_UNIQUE_VARS()
59 : #define REPEAT_64_UNIQUE_VARS() REPEAT_32_UNIQUE_VARS() REPEAT_32_UNIQUE_VARS()
60 : #define REPEAT_128_UNIQUE_VARS() REPEAT_64_UNIQUE_VARS() REPEAT_64_UNIQUE_VARS()
61 :
62 : #define REPEAT_250_UNIQUE_VARS() \
63 : REPEAT_128_UNIQUE_VARS() \
64 : REPEAT_64_UNIQUE_VARS() \
65 : REPEAT_32_UNIQUE_VARS() \
66 : REPEAT_16_UNIQUE_VARS() \
67 : REPEAT_8_UNIQUE_VARS() \
68 : UNIQUE_VAR() \
69 : UNIQUE_VAR()
70 :
71 : #define REPEAT_2_LOAD_UNIQUE_PROPERTY() \
72 : LOAD_UNIQUE_PROPERTY() LOAD_UNIQUE_PROPERTY()
73 : #define REPEAT_4_LOAD_UNIQUE_PROPERTY() \
74 : REPEAT_2_LOAD_UNIQUE_PROPERTY() REPEAT_2_LOAD_UNIQUE_PROPERTY()
75 : #define REPEAT_8_LOAD_UNIQUE_PROPERTY() \
76 : REPEAT_4_LOAD_UNIQUE_PROPERTY() REPEAT_4_LOAD_UNIQUE_PROPERTY()
77 : #define REPEAT_16_LOAD_UNIQUE_PROPERTY() \
78 : REPEAT_8_LOAD_UNIQUE_PROPERTY() REPEAT_8_LOAD_UNIQUE_PROPERTY()
79 : #define REPEAT_32_LOAD_UNIQUE_PROPERTY() \
80 : REPEAT_16_LOAD_UNIQUE_PROPERTY() REPEAT_16_LOAD_UNIQUE_PROPERTY()
81 : #define REPEAT_64_LOAD_UNIQUE_PROPERTY() \
82 : REPEAT_32_LOAD_UNIQUE_PROPERTY() REPEAT_32_LOAD_UNIQUE_PROPERTY()
83 : #define REPEAT_128_LOAD_UNIQUE_PROPERTY() \
84 : REPEAT_64_LOAD_UNIQUE_PROPERTY() REPEAT_64_LOAD_UNIQUE_PROPERTY()
85 :
86 : static const char* kGoldenFileDirectory =
87 : "test/cctest/interpreter/bytecode_expectations/";
88 :
89 430 : class InitializedIgnitionHandleScope : public InitializedHandleScope {
90 : public:
91 430 : InitializedIgnitionHandleScope() {
92 430 : i::FLAG_always_opt = false;
93 430 : i::FLAG_allow_natives_syntax = true;
94 : }
95 : };
96 :
97 430 : void SkipGoldenFileHeader(std::istream& stream) { // NOLINT
98 : std::string line;
99 : int separators_seen = 0;
100 7780 : while (std::getline(stream, line)) {
101 3675 : if (line == "---") separators_seen += 1;
102 4105 : if (separators_seen == 2) return;
103 : }
104 : }
105 :
106 430 : std::string LoadGolden(const std::string& golden_filename) {
107 1290 : std::ifstream expected_file((kGoldenFileDirectory + golden_filename).c_str());
108 430 : CHECK(expected_file.is_open());
109 430 : SkipGoldenFileHeader(expected_file);
110 860 : std::ostringstream expected_stream;
111 : // Restore the first separator, which was consumed by SkipGoldenFileHeader
112 430 : expected_stream << "---\n" << expected_file.rdbuf();
113 430 : return expected_stream.str();
114 : }
115 :
116 : template <size_t N>
117 430 : std::string BuildActual(const BytecodeExpectationsPrinter& printer,
118 : const char* (&snippet_list)[N],
119 : const char* prologue = nullptr,
120 : const char* epilogue = nullptr) {
121 430 : std::ostringstream actual_stream;
122 2750 : for (const char* snippet : snippet_list) {
123 : std::string source_code;
124 2320 : if (prologue) source_code += prologue;
125 : source_code += snippet;
126 2320 : if (epilogue) source_code += epilogue;
127 2320 : printer.PrintExpectation(actual_stream, source_code);
128 : }
129 430 : return actual_stream.str();
130 : }
131 :
132 : // inplace left trim
133 242140 : static inline void ltrim(std::string& str) {
134 : str.erase(str.begin(),
135 : std::find_if(str.begin(), str.end(),
136 2060635 : [](unsigned char ch) { return !std::isspace(ch); }));
137 242140 : }
138 :
139 : // inplace right trim
140 242140 : static inline void rtrim(std::string& str) {
141 : str.erase(std::find_if(str.rbegin(), str.rend(),
142 238020 : [](unsigned char ch) { return !std::isspace(ch); })
143 : .base(),
144 484280 : str.end());
145 242140 : }
146 :
147 242140 : static inline std::string trim(std::string& str) {
148 242140 : ltrim(str);
149 242140 : rtrim(str);
150 242140 : return str;
151 : }
152 :
153 430 : bool CompareTexts(const std::string& generated, const std::string& expected) {
154 430 : std::istringstream generated_stream(generated);
155 860 : std::istringstream expected_stream(expected);
156 : std::string generated_line;
157 : std::string expected_line;
158 : // Line number does not include golden file header.
159 : int line_number = 0;
160 : bool strings_match = true;
161 :
162 : do {
163 121500 : std::getline(generated_stream, generated_line);
164 121500 : std::getline(expected_stream, expected_line);
165 :
166 121930 : if (!generated_stream.good() && !expected_stream.good()) {
167 : return strings_match;
168 : }
169 :
170 121070 : if (!generated_stream.good()) {
171 0 : std::cerr << "Expected has extra lines after line " << line_number
172 0 : << "\n";
173 0 : std::cerr << " Expected: '" << expected_line << "'\n";
174 0 : return false;
175 121070 : } else if (!expected_stream.good()) {
176 0 : std::cerr << "Generated has extra lines after line " << line_number
177 0 : << "\n";
178 0 : std::cerr << " Generated: '" << generated_line << "'\n";
179 0 : return false;
180 : }
181 :
182 363210 : if (trim(generated_line) != trim(expected_line)) {
183 0 : std::cerr << "Inputs differ at line " << line_number << "\n";
184 0 : std::cerr << " Generated: '" << generated_line << "'\n";
185 0 : std::cerr << " Expected: '" << expected_line << "'\n";
186 : strings_match = false;
187 : }
188 121070 : line_number++;
189 430 : } while (true);
190 : }
191 :
192 28342 : TEST(PrimitiveReturnStatements) {
193 : InitializedIgnitionHandleScope scope;
194 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
195 : const char* snippets[] = {
196 : "",
197 :
198 : "return;\n",
199 :
200 : "return null;\n",
201 :
202 : "return true;\n",
203 :
204 : "return false;\n",
205 :
206 : "return 0;\n",
207 :
208 : "return +1;\n",
209 :
210 : "return -1;\n",
211 :
212 : "return +127;\n",
213 :
214 : "return -128;\n",
215 :
216 : "return 2.0;\n",
217 5 : };
218 :
219 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
220 : LoadGolden("PrimitiveReturnStatements.golden")));
221 5 : }
222 :
223 28342 : TEST(PrimitiveExpressions) {
224 : InitializedIgnitionHandleScope scope;
225 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
226 : const char* snippets[] = {
227 : "var x = 0; return x;\n",
228 :
229 : "var x = 0; return x + 3;\n",
230 :
231 : "var x = 0; return 3 + x;\n",
232 :
233 : "var x = 0; return x - 3;\n",
234 :
235 : "var x = 0; return 3 - x;\n",
236 :
237 : "var x = 4; return x * 3;\n",
238 :
239 : "var x = 4; return 3 * x;\n",
240 :
241 : "var x = 4; return x / 3;\n",
242 :
243 : "var x = 4; return 3 / x;\n",
244 :
245 : "var x = 4; return x % 3;\n",
246 :
247 : "var x = 4; return 3 % x;\n",
248 :
249 : "var x = 1; return x | 2;\n",
250 :
251 : "var x = 1; return 2 | x;\n",
252 :
253 : "var x = 1; return x ^ 2;\n",
254 :
255 : "var x = 1; return 2 ^ x;\n",
256 :
257 : "var x = 1; return x & 2;\n",
258 :
259 : "var x = 1; return 2 & x;\n",
260 :
261 : "var x = 10; return x << 3;\n",
262 :
263 : "var x = 10; return 3 << x;\n",
264 :
265 : "var x = 10; return x >> 3;\n",
266 :
267 : "var x = 10; return 3 >> x;\n",
268 :
269 : "var x = 10; return x >>> 3;\n",
270 :
271 : "var x = 10; return 3 >>> x;\n",
272 :
273 : "var x = 0; return (x, 3);\n",
274 5 : };
275 :
276 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
277 : LoadGolden("PrimitiveExpressions.golden")));
278 5 : }
279 :
280 28342 : TEST(LogicalExpressions) {
281 : InitializedIgnitionHandleScope scope;
282 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
283 : const char* snippets[] = {
284 : "var x = 0; return x || 3;\n",
285 :
286 : "var x = 0; return (x == 1) || 3;\n",
287 :
288 : "var x = 0; return x && 3;\n",
289 :
290 : "var x = 0; return (x == 0) && 3;\n",
291 :
292 : "var x = 0; return x || (1, 2, 3);\n",
293 :
294 : "var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);\n",
295 :
296 : "var x = 1; var a = 2, b = 3; return x || (" //
297 : REPEAT_32("\n a = 1, b = 2, ") //
298 : "3);\n",
299 :
300 : "var x = 0; var a = 2, b = 3; return x && (" //
301 : REPEAT_32("\n a = 1, b = 2, ") //
302 : "3);\n",
303 :
304 : "var x = 1; var a = 2, b = 3; return (x > 3) || (" //
305 : REPEAT_32("\n a = 1, b = 2, ") //
306 : "3);\n",
307 :
308 : "var x = 0; var a = 2, b = 3; return (x < 5) && (" //
309 : REPEAT_32("\n a = 1, b = 2, ") //
310 : "3);\n",
311 :
312 : "return 0 && 3;\n",
313 :
314 : "return 1 || 3;\n",
315 :
316 : "var x = 1; return x && 3 || 0, 1;\n",
317 5 : };
318 :
319 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
320 : LoadGolden("LogicalExpressions.golden")));
321 5 : }
322 :
323 28342 : TEST(Parameters) {
324 : InitializedIgnitionHandleScope scope;
325 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
326 : printer.set_wrap(false);
327 10 : printer.set_test_function_name("f");
328 :
329 : const char* snippets[] = {
330 : "function f() { return this; }",
331 :
332 : "function f(arg1) { return arg1; }",
333 :
334 : "function f(arg1) { return this; }",
335 :
336 : "function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
337 :
338 : "function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
339 :
340 : "function f(arg1) { arg1 = 1; }",
341 :
342 : "function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
343 5 : };
344 :
345 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
346 : LoadGolden("Parameters.golden")));
347 5 : }
348 :
349 28342 : TEST(IntegerConstants) {
350 : InitializedIgnitionHandleScope scope;
351 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
352 : const char* snippets[] = {
353 : "return 12345678;\n",
354 :
355 : "var a = 1234; return 5678;\n",
356 :
357 : "var a = 1234; return 1234;\n",
358 5 : };
359 :
360 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
361 : LoadGolden("IntegerConstants.golden")));
362 5 : }
363 :
364 28342 : TEST(HeapNumberConstants) {
365 : InitializedIgnitionHandleScope scope;
366 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
367 : const char* snippets[] = {
368 : "return 1.2;\n",
369 :
370 : "var a = 1.2; return 2.6;\n",
371 :
372 : "var a = 3.14; return 3.14;\n",
373 5 : };
374 :
375 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
376 : LoadGolden("HeapNumberConstants.golden")));
377 5 : }
378 :
379 28342 : TEST(StringConstants) {
380 : InitializedIgnitionHandleScope scope;
381 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
382 : const char* snippets[] = {
383 : "return \"This is a string\";\n",
384 :
385 : "var a = \"First string\"; return \"Second string\";\n",
386 :
387 : "var a = \"Same string\"; return \"Same string\";\n",
388 5 : };
389 :
390 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
391 : LoadGolden("StringConstants.golden")));
392 5 : }
393 :
394 28342 : TEST(PropertyLoads) {
395 : InitializedIgnitionHandleScope scope;
396 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
397 : printer.set_wrap(false);
398 10 : printer.set_test_function_name("f");
399 :
400 : const char* snippets[] = {
401 : "function f(a) { return a.name; }\n"
402 : "f({name : \"test\"});\n",
403 :
404 : "function f(a) { return a[\"key\"]; }\n"
405 : "f({key : \"test\"});\n",
406 :
407 : "function f(a) { return a[100]; }\n"
408 : "f({100 : \"test\"});\n",
409 :
410 : "function f(a, b) { return a[b]; }\n"
411 : "f({arg : \"test\"}, \"arg\");\n",
412 :
413 : "function f(a) { var b = a.name; return a[-124]; }\n"
414 : "f({\"-124\" : \"test\", name : 123 })",
415 :
416 : "function f(a) {\n"
417 : " var b = {};\n"
418 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
419 : " return a.name;\n"
420 : "}\n"
421 : "f({name : \"test\"})\n",
422 :
423 : "function f(a, b) {\n"
424 : " var c;\n"
425 : " c = a[b];\n"
426 : REPEAT_127(" c = a[b];\n")
427 : " return a[b];\n"
428 : "}\n"
429 : "f({name : \"test\"}, \"name\")\n",
430 5 : };
431 :
432 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
433 : LoadGolden("PropertyLoads.golden")));
434 5 : }
435 :
436 28342 : TEST(PropertyLoadStoreOneShot) {
437 : InitializedIgnitionHandleScope scope;
438 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
439 : printer.set_wrap(false);
440 : printer.set_top_level(true);
441 : printer.set_oneshot_opt(true);
442 :
443 : const char* snippets[] = {
444 : R"(
445 : l = {
446 : 'a': 1,
447 : 'b': 2
448 : };
449 :
450 : v = l['a'] + l['b'];
451 : l['b'] = 7;
452 : l['a'] = l['b'];
453 : )",
454 :
455 : R"(
456 : l = {
457 : 'a': 1.1,
458 : 'b': 2.2
459 : };
460 : for (i = 0; i < 5; ++i) {
461 : l['a'] = l['a'] + l['b'];
462 : l['b'] = l['a'] + l['b'];
463 : }
464 : )",
465 :
466 : R"(
467 : l = {
468 : 'a': 1.1,
469 : 'b': 2.2
470 : };
471 : while (s > 0) {
472 : l['a'] = l['a'] - l['b'];
473 : l['b'] = l['b'] - l['a'];
474 : }
475 : )",
476 :
477 : R"(
478 : l = {
479 : 'a': 1.1,
480 : 'b': 2.2
481 : };
482 : s = 10;
483 : do {
484 : l['a'] = l['b'] - l['a'];
485 : } while (s < 10);
486 : )",
487 :
488 : R"(
489 : l = {
490 : 'c': 1.1,
491 : 'd': 2.2
492 : };
493 : if (l['c'] < 3) {
494 : l['c'] = 3;
495 : } else {
496 : l['d'] = 3;
497 : }
498 : )",
499 :
500 : R"(
501 : a = [1.1, [2.2, 4.5]];
502 : )",
503 :
504 : R"(
505 : b = [];
506 : )",
507 5 : };
508 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
509 : LoadGolden("PropertyLoadStoreOneShot.golden")));
510 5 : }
511 :
512 28342 : TEST(PropertyLoadStoreWithoutOneShot) {
513 : InitializedIgnitionHandleScope scope;
514 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
515 : printer.set_wrap(false);
516 : printer.set_top_level(true);
517 :
518 : const char* snippets[] = {
519 : R"(
520 : l = {
521 : 'aa': 1.1,
522 : 'bb': 2.2
523 : };
524 :
525 : v = l['aa'] + l['bb'];
526 : l['bb'] = 7;
527 : l['aa'] = l['bb'];
528 : )",
529 :
530 : R"(
531 : l = {
532 : 'cc': 3.1,
533 : 'dd': 4.2
534 : };
535 : if (l['cc'] < 3) {
536 : l['cc'] = 3;
537 : } else {
538 : l['dd'] = 3;
539 : }
540 : )",
541 5 : };
542 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
543 : LoadGolden("PropertyLoadStoreWithoutOneShot.golden")));
544 5 : }
545 :
546 28342 : TEST(IIFEWithOneshotOpt) {
547 : InitializedIgnitionHandleScope scope;
548 5 : v8::Isolate* isolate = CcTest::isolate();
549 : BytecodeExpectationsPrinter printer(isolate);
550 : printer.set_wrap(false);
551 : printer.set_top_level(true);
552 : printer.set_print_callee(true);
553 : printer.set_oneshot_opt(true);
554 :
555 : const char* snippets[] = {
556 : // No feedback vectors for top-level loads/store named property in an IIFE
557 : R"(
558 : (function() {
559 : l = {};
560 : l.aa = 2;
561 : l.bb = l.aa;
562 : return arguments.callee;
563 : })();
564 : )",
565 : // Normal load/store within loops of an IIFE
566 : R"(
567 : (function() {
568 : l = {};
569 : for (i = 0; i < 5; ++i) {
570 : l.aa = 2;
571 : l.bb = l.aa;
572 : }
573 : return arguments.callee;
574 : })();
575 : )",
576 :
577 : R"(
578 : (function() {
579 : l = {};
580 : c = 4;
581 : while(c > 4) {
582 : l.aa = 2;
583 : l.bb = l.aa;
584 : c--;
585 : }
586 : return arguments.callee;
587 : })();
588 : )",
589 :
590 : R"(
591 : (function() {
592 : l = {};
593 : c = 4;
594 : do {
595 : l.aa = 2;
596 : l.bb = l.aa;
597 : c--;
598 : } while(c > 4)
599 : return arguments.callee;
600 : })();
601 : )",
602 : // No feedback vectors for loads/stores in conditionals
603 : R"(
604 : (function() {
605 : l = {
606 : 'aa': 3.3,
607 : 'bb': 4.4
608 : };
609 : if (l.aa < 3) {
610 : l.aa = 3;
611 : } else {
612 : l.aa = l.bb;
613 : }
614 : return arguments.callee;
615 : })();
616 : )",
617 :
618 : R"(
619 : (function() {
620 : a = [0, [1, 1,2,], 3];
621 : return arguments.callee;
622 : })();
623 : )",
624 :
625 : R"(
626 : (function() {
627 : a = [];
628 : return arguments.callee;
629 : })();
630 : )",
631 : // CallNoFeedback instead of CallProperty
632 : R"(
633 : this.f0 = function() {};
634 : this.f1 = function(a) {};
635 : this.f2 = function(a, b) {};
636 : this.f3 = function(a, b, c) {};
637 : this.f4 = function(a, b, c, d) {};
638 : this.f5 = function(a, b, c, d, e) {};
639 : (function() {
640 : this.f0();
641 : this.f1(1);
642 : this.f2(1, 2);
643 : this.f3(1, 2, 3);
644 : this.f4(1, 2, 3, 4);
645 : this.f5(1, 2, 3, 4, 5);
646 : return arguments.callee;
647 : })();
648 : )",
649 : // CallNoFeedback instead of CallUndefinedReceiver
650 : R"(
651 : function f0() {}
652 : function f1(a) {}
653 : function f2(a, b) {}
654 : function f3(a, b, c) {}
655 : function f4(a, b, c, d) {}
656 : function f5(a, b, c, d, e) {}
657 : (function() {
658 : f0();
659 : f1(1);
660 : f2(1, 2);
661 : f3(1, 2, 3);
662 : f4(1, 2, 3, 4);
663 : f5(1, 2, 3, 4, 5);
664 : return arguments.callee;
665 : })();
666 : )",
667 : R"(
668 : var t = 0;
669 : function f2() {};
670 : if (t == 0) {
671 : (function(){
672 : l = {};
673 : l.a = 3;
674 : l.b = 4;
675 : f2();
676 : return arguments.callee;
677 : })();
678 : }
679 : )",
680 : // No one-shot opt for IIFE`s within a function
681 : R"(
682 : function f2() {};
683 : function f() {
684 : return (function(){
685 : l = {};
686 : l.a = 3;
687 : l.b = 4;
688 : f2();
689 : return arguments.callee;
690 : })();
691 : }
692 : f();
693 : )",
694 : R"(
695 : var f = function(l) { l.a = 3; return l; };
696 : f({});
697 : f;
698 : )",
699 : // No one-shot opt for top-level functions enclosed in parentheses
700 : R"(
701 : var f = (function(l) { l.a = 3; return l; });
702 : f;
703 : )",
704 : R"(
705 : var f = (function foo(l) { l.a = 3; return l; });
706 : f;
707 : )",
708 : R"(
709 : var f = function foo(l) { l.a = 3; return l; };
710 : f({});
711 : f;
712 : )",
713 : R"(
714 : l = {};
715 : var f = (function foo(l) { l.a = 3; return arguments.callee; })(l);
716 : f;
717 : )",
718 : R"(
719 : var f = (function foo(l) { l.a = 3; return arguments.callee; })({});
720 : f;
721 : )",
722 5 : };
723 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
724 : LoadGolden("IIFEWithOneshotOpt.golden")));
725 5 : }
726 :
727 28342 : TEST(IIFEWithoutOneshotOpt) {
728 : InitializedIgnitionHandleScope scope;
729 5 : v8::Isolate* isolate = CcTest::isolate();
730 : BytecodeExpectationsPrinter printer(isolate);
731 : printer.set_wrap(false);
732 : printer.set_top_level(true);
733 : printer.set_print_callee(true);
734 :
735 : const char* snippets[] = {
736 : R"(
737 : (function() {
738 : l = {};
739 : l.a = 2;
740 : l.b = l.a;
741 : return arguments.callee;
742 : })();
743 : )",
744 : R"(
745 : (function() {
746 : l = {
747 : 'a': 4.3,
748 : 'b': 3.4
749 : };
750 : if (l.a < 3) {
751 : l.a = 3;
752 : } else {
753 : l.a = l.b;
754 : }
755 : return arguments.callee;
756 : })();
757 : )",
758 : R"(
759 : this.f0 = function() {};
760 : this.f1 = function(a) {};
761 : this.f2 = function(a, b) {};
762 : this.f3 = function(a, b, c) {};
763 : this.f4 = function(a, b, c, d) {};
764 : this.f5 = function(a, b, c, d, e) {};
765 : (function() {
766 : this.f0();
767 : this.f1(1);
768 : this.f2(1, 2);
769 : this.f3(1, 2, 3);
770 : this.f4(1, 2, 3, 4);
771 : this.f5(1, 2, 3, 4, 5);
772 : return arguments.callee;
773 : })();
774 : )",
775 : R"(
776 : function f0() {}
777 : function f1(a) {}
778 : function f2(a, b) {}
779 : function f3(a, b, c) {}
780 : function f4(a, b, c, d) {}
781 : function f5(a, b, c, d, e) {}
782 : (function() {
783 : f0();
784 : f1(1);
785 : f2(1, 2);
786 : f3(1, 2, 3);
787 : f4(1, 2, 3, 4);
788 : f5(1, 2, 3, 4, 5);
789 : return arguments.callee;
790 : })();
791 : )",
792 5 : };
793 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
794 : LoadGolden("IIFEWithoutOneshotOpt.golden")));
795 5 : }
796 :
797 28342 : TEST(PropertyStores) {
798 : InitializedIgnitionHandleScope scope;
799 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
800 : printer.set_wrap(false);
801 10 : printer.set_test_function_name("f");
802 :
803 : const char* snippets[] = {
804 : "function f(a) { a.name = \"val\"; }\n"
805 : "f({name : \"test\"})",
806 :
807 : "function f(a) { a[\"key\"] = \"val\"; }\n"
808 : "f({key : \"test\"})",
809 :
810 : "function f(a) { a[100] = \"val\"; }\n"
811 : "f({100 : \"test\"})",
812 :
813 : "function f(a, b) { a[b] = \"val\"; }\n"
814 : "f({arg : \"test\"}, \"arg\")",
815 :
816 : "function f(a) { a.name = a[-124]; }\n"
817 : "f({\"-124\" : \"test\", name : 123 })",
818 :
819 : "function f(a) { \"use strict\"; a.name = \"val\"; }\n"
820 : "f({name : \"test\"})",
821 :
822 : "function f(a, b) { \"use strict\"; a[b] = \"val\"; }\n"
823 : "f({arg : \"test\"}, \"arg\")",
824 :
825 : "function f(a) {\n"
826 : " a.name = 1;\n"
827 : " var b = {};\n"
828 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
829 : " a.name = 2;\n"
830 : "}\n"
831 : "f({name : \"test\"})\n",
832 :
833 : "function f(a) {\n"
834 : " 'use strict';\n"
835 : " a.name = 1;\n"
836 : " var b = {};\n"
837 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
838 : " a.name = 2;\n"
839 : "}\n"
840 : "f({name : \"test\"})\n",
841 :
842 : "function f(a, b) {\n"
843 : " a[b] = 1;\n"
844 : REPEAT_127(" a[b] = 1;\n")
845 : " a[b] = 2;\n"
846 : "}\n"
847 : "f({name : \"test\"})\n",
848 :
849 : "function f(a, b) {\n"
850 : " 'use strict';\n"
851 : " a[b] = 1;\n"
852 : REPEAT_127(" a[b] = 1;\n")
853 : " a[b] = 2;\n"
854 : "}\n"
855 : "f({name : \"test\"})\n",
856 5 : };
857 :
858 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
859 : LoadGolden("PropertyStores.golden")));
860 5 : }
861 :
862 : #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()"
863 :
864 28342 : TEST(PropertyCall) {
865 : InitializedIgnitionHandleScope scope;
866 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
867 : printer.set_wrap(false);
868 10 : printer.set_test_function_name("f");
869 :
870 : const char* snippets[] = {
871 : "function f(a) { return a.func(); }\n"
872 : "f(" FUNC_ARG ")",
873 :
874 : "function f(a, b, c) { return a.func(b, c); }\n"
875 : "f(" FUNC_ARG ", 1, 2)",
876 :
877 : "function f(a, b) { return a.func(b + b, b); }\n"
878 : "f(" FUNC_ARG ", 1)",
879 :
880 : "function f(a) {\n"
881 : " var b = {};\n"
882 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
883 : " a.func;\n" //
884 : " return a.func(); }\n"
885 : "f(" FUNC_ARG ")",
886 :
887 : "function f(a) { return a.func(1).func(2).func(3); }\n"
888 : "f(new (function Obj() { this.func = function(a) { return this; }})())",
889 5 : };
890 :
891 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
892 : LoadGolden("PropertyCall.golden")));
893 5 : }
894 :
895 28342 : TEST(LoadGlobal) {
896 : InitializedIgnitionHandleScope scope;
897 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
898 : printer.set_wrap(false);
899 10 : printer.set_test_function_name("f");
900 :
901 : const char* snippets[] = {
902 : "var a = 1;\n"
903 : "function f() { return a; }\n"
904 : "f()",
905 :
906 : "function t() { }\n"
907 : "function f() { return t; }\n"
908 : "f()",
909 :
910 : "a = 1;\n"
911 : "function f() { return a; }\n"
912 : "f()",
913 :
914 : "a = 1;\n"
915 : "function f(c) {\n"
916 : " var b = {};\n"
917 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
918 : " return a;\n"
919 : "}\n"
920 : "f({name: 1});\n",
921 5 : };
922 :
923 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
924 : LoadGolden("LoadGlobal.golden")));
925 5 : }
926 :
927 28342 : TEST(StoreGlobal) {
928 : InitializedIgnitionHandleScope scope;
929 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
930 : printer.set_wrap(false);
931 10 : printer.set_test_function_name("f");
932 :
933 : const char* snippets[] = {
934 : "var a = 1;\n"
935 : "function f() { a = 2; }\n"
936 : "f();\n",
937 :
938 : "var a = \"test\"; function f(b) { a = b; }\n"
939 : "f(\"global\");\n",
940 :
941 : "'use strict'; var a = 1;\n"
942 : "function f() { a = 2; }\n"
943 : "f();\n",
944 :
945 : "a = 1;\n"
946 : "function f() { a = 2; }\n"
947 : "f();\n",
948 :
949 : "a = 1;\n"
950 : "function f(c) {\n"
951 : " var b = {};\n"
952 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
953 : " a = 2;\n"
954 : "}\n"
955 : "f({name: 1});\n",
956 :
957 : "a = 1;\n"
958 : "function f(c) {\n"
959 : " 'use strict';\n"
960 : " var b = {};\n"
961 : REPEAT_128_LOAD_UNIQUE_PROPERTY()
962 : " a = 2;\n"
963 : "}\n"
964 : "f({name: 1});\n",
965 5 : };
966 :
967 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
968 : LoadGolden("StoreGlobal.golden")));
969 5 : }
970 :
971 28342 : TEST(CallGlobal) {
972 : InitializedIgnitionHandleScope scope;
973 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
974 : printer.set_wrap(false);
975 10 : printer.set_test_function_name("f");
976 :
977 : const char* snippets[] = {
978 : "function t() { }\n"
979 : "function f() { return t(); }\n"
980 : "f();\n",
981 :
982 : "function t(a, b, c) { }\n"
983 : "function f() { return t(1, 2, 3); }\n"
984 : "f();\n",
985 5 : };
986 :
987 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
988 : LoadGolden("CallGlobal.golden")));
989 5 : }
990 :
991 28342 : TEST(CallRuntime) {
992 : InitializedIgnitionHandleScope scope;
993 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
994 : printer.set_wrap(false);
995 10 : printer.set_test_function_name("f");
996 :
997 : const char* snippets[] = {
998 : "function f() { %TheHole() }\n"
999 : "f();\n",
1000 :
1001 : "function f(a) { return %IsArray(a) }\n"
1002 : "f(undefined);\n",
1003 :
1004 : "function f() { return %Add(1, 2) }\n"
1005 : "f();\n",
1006 5 : };
1007 :
1008 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1009 : LoadGolden("CallRuntime.golden")));
1010 5 : }
1011 :
1012 28342 : TEST(IfConditions) {
1013 : InitializedIgnitionHandleScope scope;
1014 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1015 : printer.set_wrap(false);
1016 10 : printer.set_test_function_name("f");
1017 :
1018 : const char* snippets[] = {
1019 : "function f() {\n"
1020 : " if (0) {\n"
1021 : " return 1;\n"
1022 : " } else {\n"
1023 : " return -1;\n"
1024 : " }\n"
1025 : "};\n"
1026 : "f();\n",
1027 :
1028 : "function f() {\n"
1029 : " if ('lucky') {\n"
1030 : " return 1;\n"
1031 : " } else {\n"
1032 : " return -1;\n"
1033 : " }\n"
1034 : "};\n"
1035 : "f();\n",
1036 :
1037 : "function f() {\n"
1038 : " if (false) {\n"
1039 : " return 1;\n"
1040 : " } else {\n"
1041 : " return -1;\n"
1042 : " }\n"
1043 : "};\n"
1044 : "f();\n",
1045 :
1046 : "function f() {\n"
1047 : " if (false) {\n"
1048 : " return 1;\n"
1049 : " }\n"
1050 : "};\n"
1051 : "f();\n",
1052 :
1053 : "function f() {\n"
1054 : " var a = 1;\n"
1055 : " if (a) {\n"
1056 : " a += 1;\n"
1057 : " } else {\n"
1058 : " return 2;\n"
1059 : " }\n"
1060 : "};\n"
1061 : "f();\n",
1062 :
1063 : "function f(a) {\n"
1064 : " if (a <= 0) {\n"
1065 : " return 200;\n"
1066 : " } else {\n"
1067 : " return -200;\n"
1068 : " }\n"
1069 : "};\n"
1070 : "f(99);\n",
1071 :
1072 : "function f(a, b) { if (a in b) { return 200; } }"
1073 : "f('prop', { prop: 'yes'});\n",
1074 :
1075 : "function f(z) { var a = 0; var b = 0; if (a === 0.01) {\n"
1076 : REPEAT_64(" b = a; a = b;\n")
1077 : " return 200; } else { return -200; } } f(0.001);\n",
1078 :
1079 : "function f() {\n"
1080 : " var a = 0; var b = 0;\n"
1081 : " if (a) {\n"
1082 : REPEAT_64(" b = a; a = b;\n")
1083 : " return 200; } else { return -200; }\n"
1084 : "};\n"
1085 : "f();\n",
1086 :
1087 : "function f(a, b) {\n"
1088 : " if (a == b) { return 1; }\n"
1089 : " if (a === b) { return 1; }\n"
1090 : " if (a < b) { return 1; }\n"
1091 : " if (a > b) { return 1; }\n"
1092 : " if (a <= b) { return 1; }\n"
1093 : " if (a >= b) { return 1; }\n"
1094 : " if (a in b) { return 1; }\n"
1095 : " if (a instanceof b) { return 1; }\n"
1096 : " return 0;\n"
1097 : "}\n"
1098 : "f(1, 1);\n",
1099 :
1100 : "function f() {\n"
1101 : " var a = 0;\n"
1102 : " if (a) {\n"
1103 : " return 20;\n"
1104 : " } else {\n"
1105 : " return -20;\n"
1106 : " }\n"
1107 : "};\n"
1108 : "f();\n",
1109 :
1110 : "function f(a, b) {\n"
1111 : " if (a == b || a < 0) {\n"
1112 : " return 1;\n"
1113 : " } else if (a > 0 && b > 0) {\n"
1114 : " return 0;\n"
1115 : " } else {\n"
1116 : " return -1;\n"
1117 : " }\n"
1118 : "};\n"
1119 : "f(-1, 1);\n",
1120 5 : };
1121 :
1122 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1123 : LoadGolden("IfConditions.golden")));
1124 5 : }
1125 :
1126 28342 : TEST(DeclareGlobals) {
1127 : InitializedIgnitionHandleScope scope;
1128 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1129 : printer.set_wrap(false);
1130 10 : printer.set_test_function_name("f");
1131 : printer.set_top_level(true);
1132 :
1133 : const char* snippets[] = {
1134 : "var a = 1;\n",
1135 :
1136 : "function f() {}\n",
1137 :
1138 : "var a = 1;\n"
1139 : "a=2;\n",
1140 :
1141 : "function f() {}\n"
1142 : "f();\n",
1143 5 : };
1144 :
1145 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1146 : LoadGolden("DeclareGlobals.golden")));
1147 5 : }
1148 :
1149 28342 : TEST(BreakableBlocks) {
1150 : InitializedIgnitionHandleScope scope;
1151 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1152 :
1153 : const char* snippets[] = {
1154 : "var x = 0;\n"
1155 : "label: {\n"
1156 : " x = x + 1;\n"
1157 : " break label;\n"
1158 : " x = x + 1;\n"
1159 : "}\n"
1160 : "return x;\n",
1161 :
1162 : "var sum = 0;\n"
1163 : "outer: {\n"
1164 : " for (var x = 0; x < 10; ++x) {\n"
1165 : " for (var y = 0; y < 3; ++y) {\n"
1166 : " ++sum;\n"
1167 : " if (x + y == 12) { break outer; }\n"
1168 : " }\n"
1169 : " }\n"
1170 : "}\n"
1171 : "return sum;\n",
1172 :
1173 : "outer: {\n"
1174 : " let y = 10;\n"
1175 : " function f() { return y; }\n"
1176 : " break outer;\n"
1177 : "}\n",
1178 :
1179 : "let x = 1;\n"
1180 : "outer: {\n"
1181 : " inner: {\n"
1182 : " let y = 2;\n"
1183 : " function f() { return x + y; }\n"
1184 : " if (y) break outer;\n"
1185 : " y = 3;\n"
1186 : " }\n"
1187 : "}\n"
1188 : "x = 4;\n",
1189 5 : };
1190 :
1191 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1192 : LoadGolden("BreakableBlocks.golden")));
1193 5 : }
1194 :
1195 28342 : TEST(BasicLoops) {
1196 : InitializedIgnitionHandleScope scope;
1197 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1198 : const char* snippets[] = {
1199 : "var x = 0;\n"
1200 : "while (false) { x = 99; break; continue; }\n"
1201 : "return x;\n",
1202 :
1203 : "var x = 0;\n"
1204 : "while (false) {\n"
1205 : " x = x + 1;\n"
1206 : "};\n"
1207 : "return x;\n",
1208 :
1209 : "var x = 0;\n"
1210 : "var y = 1;\n"
1211 : "while (x < 10) {\n"
1212 : " y = y * 12;\n"
1213 : " x = x + 1;\n"
1214 : " if (x == 3) continue;\n"
1215 : " if (x == 4) break;\n"
1216 : "}\n"
1217 : "return y;\n",
1218 :
1219 : "var i = 0;\n"
1220 : "while (true) {\n"
1221 : " if (i < 0) continue;\n"
1222 : " if (i == 3) break;\n"
1223 : " if (i == 4) break;\n"
1224 : " if (i == 10) continue;\n"
1225 : " if (i == 5) break;\n"
1226 : " i = i + 1;\n"
1227 : "}\n"
1228 : "return i;\n",
1229 :
1230 : "var i = 0;\n"
1231 : "while (true) {\n"
1232 : " while (i < 3) {\n"
1233 : " if (i == 2) break;\n"
1234 : " i = i + 1;\n"
1235 : " }\n"
1236 : " i = i + 1;\n"
1237 : " break;\n"
1238 : "}\n"
1239 : "return i;\n",
1240 :
1241 : "var x = 10;\n"
1242 : "var y = 1;\n"
1243 : "while (x) {\n"
1244 : " y = y * 12;\n"
1245 : " x = x - 1;\n"
1246 : "}\n"
1247 : "return y;\n",
1248 :
1249 : "var x = 0; var y = 1;\n"
1250 : "do {\n"
1251 : " y = y * 10;\n"
1252 : " if (x == 5) break;\n"
1253 : " if (x == 6) continue;\n"
1254 : " x = x + 1;\n"
1255 : "} while (x < 10);\n"
1256 : "return y;\n",
1257 :
1258 : "var x = 10;\n"
1259 : "var y = 1;\n"
1260 : "do {\n"
1261 : " y = y * 12;\n"
1262 : " x = x - 1;\n"
1263 : "} while (x);\n"
1264 : "return y;\n",
1265 :
1266 : "var x = 0; var y = 1;\n"
1267 : "do {\n"
1268 : " y = y * 10;\n"
1269 : " if (x == 5) break;\n"
1270 : " x = x + 1;\n"
1271 : " if (x == 6) continue;\n"
1272 : "} while (false);\n"
1273 : "return y;\n",
1274 :
1275 : "var x = 0; var y = 1;\n"
1276 : "do {\n"
1277 : " y = y * 10;\n"
1278 : " if (x == 5) break;\n"
1279 : " x = x + 1;\n"
1280 : " if (x == 6) continue;\n"
1281 : "} while (true);\n"
1282 : "return y;\n",
1283 :
1284 : "var x = 0;\n"
1285 : "for (;;) {\n"
1286 : " if (x == 1) break;\n"
1287 : " if (x == 2) continue;\n"
1288 : " x = x + 1;\n"
1289 : "}\n",
1290 :
1291 : "for (var x = 0;;) {\n"
1292 : " if (x == 1) break;\n"
1293 : " if (x == 2) continue;\n"
1294 : " x = x + 1;\n"
1295 : "}\n",
1296 :
1297 : "var x = 0;\n"
1298 : "for (;; x = x + 1) {\n"
1299 : " if (x == 1) break;\n"
1300 : " if (x == 2) continue;\n"
1301 : "}\n",
1302 :
1303 : "for (var x = 0;; x = x + 1) {\n"
1304 : " if (x == 1) break;\n"
1305 : " if (x == 2) continue;\n"
1306 : "}\n",
1307 :
1308 : "var u = 0;\n"
1309 : "for (var i = 0; i < 100; i = i + 1) {\n"
1310 : " u = u + 1;\n"
1311 : " continue;\n"
1312 : "}\n",
1313 :
1314 : "var y = 1;\n"
1315 : "for (var x = 10; x; --x) {\n"
1316 : " y = y * 12;\n"
1317 : "}\n"
1318 : "return y;\n",
1319 :
1320 : "var x = 0;\n"
1321 : "for (var i = 0; false; i++) {\n"
1322 : " x = x + 1;\n"
1323 : "};\n"
1324 : "return x;\n",
1325 :
1326 : "var x = 0;\n"
1327 : "for (var i = 0; true; ++i) {\n"
1328 : " x = x + 1;\n"
1329 : " if (x == 20) break;\n"
1330 : "};\n"
1331 : "return x;\n",
1332 :
1333 : "var a = 0;\n"
1334 : "while (a) {\n"
1335 : " { \n"
1336 : " let z = 1;\n"
1337 : " function f() { z = 2; }\n"
1338 : " if (z) continue;\n"
1339 : " z++;\n"
1340 : " }\n"
1341 : "}\n",
1342 5 : };
1343 :
1344 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1345 : LoadGolden("BasicLoops.golden")));
1346 5 : }
1347 :
1348 28342 : TEST(UnaryOperators) {
1349 : InitializedIgnitionHandleScope scope;
1350 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1351 : const char* snippets[] = {
1352 : "var x = 0;\n"
1353 : "while (x != 10) {\n"
1354 : " x = x + 10;\n"
1355 : "}\n"
1356 : "return x;\n",
1357 :
1358 : "var x = false;\n"
1359 : "do {\n"
1360 : " x = !x;\n"
1361 : "} while(x == false);\n"
1362 : "return x;\n",
1363 :
1364 : "var x = 101;\n"
1365 : "return void(x * 3);\n",
1366 :
1367 : "var x = 1234;\n"
1368 : "var y = void (x * x - 1);\n"
1369 : "return y;\n",
1370 :
1371 : "var x = 13;\n"
1372 : "return ~x;\n",
1373 :
1374 : "var x = 13;\n"
1375 : "return +x;\n",
1376 :
1377 : "var x = 13;\n"
1378 : "return -x;\n",
1379 5 : };
1380 :
1381 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1382 : LoadGolden("UnaryOperators.golden")));
1383 5 : }
1384 :
1385 28342 : TEST(Typeof) {
1386 : InitializedIgnitionHandleScope scope;
1387 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1388 : printer.set_wrap(false);
1389 10 : printer.set_test_function_name("f");
1390 :
1391 : const char* snippets[] = {
1392 : "function f() {\n"
1393 : " var x = 13;\n"
1394 : " return typeof(x);\n"
1395 : "};",
1396 :
1397 : "var x = 13;\n"
1398 : "function f() {\n"
1399 : " return typeof(x);\n"
1400 : "};",
1401 5 : };
1402 :
1403 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1404 : LoadGolden("Typeof.golden")));
1405 5 : }
1406 :
1407 28342 : TEST(CompareTypeOf) {
1408 : InitializedIgnitionHandleScope scope;
1409 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1410 :
1411 : const char* snippets[] = {
1412 : "return typeof(1) === 'number';\n",
1413 :
1414 : "return 'string' === typeof('foo');\n",
1415 :
1416 : "return typeof(true) == 'boolean';\n",
1417 :
1418 : "return 'string' === typeof(undefined);\n",
1419 :
1420 : "return 'unknown' === typeof(undefined);\n",
1421 5 : };
1422 :
1423 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1424 : LoadGolden("CompareTypeOf.golden")));
1425 5 : }
1426 :
1427 28342 : TEST(CompareNil) {
1428 : InitializedIgnitionHandleScope scope;
1429 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1430 :
1431 : const char* snippets[] = {
1432 : "var a = 1;\n"
1433 : "return a === null;\n",
1434 :
1435 : "var a = undefined;\n"
1436 : "return undefined === a;\n",
1437 :
1438 : "var a = undefined;\n"
1439 : "return undefined !== a;\n",
1440 :
1441 : "var a = 2;\n"
1442 : "return a != null;\n",
1443 :
1444 : "var a = undefined;\n"
1445 : "return undefined == a;\n",
1446 :
1447 : "var a = undefined;\n"
1448 : "return undefined === a ? 1 : 2;\n",
1449 :
1450 : "var a = 0;\n"
1451 : "return null == a ? 1 : 2;\n",
1452 :
1453 : "var a = 0;\n"
1454 : "return undefined !== a ? 1 : 2;\n",
1455 :
1456 : "var a = 0;\n"
1457 : "return a === null ? 1 : 2;\n",
1458 :
1459 : "var a = 0;\n"
1460 : "if (a === null) {\n"
1461 : " return 1;\n"
1462 : "} else {\n"
1463 : " return 2;\n"
1464 : "}\n",
1465 :
1466 : "var a = 0;\n"
1467 : "if (a != undefined) {\n"
1468 : " return 1;\n"
1469 : "}\n",
1470 :
1471 : "var a = undefined;\n"
1472 : "var b = 0;\n"
1473 : "while (a !== undefined) {\n"
1474 : " b++;\n"
1475 : "}\n",
1476 5 : };
1477 :
1478 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1479 : LoadGolden("CompareNil.golden")));
1480 5 : }
1481 :
1482 28342 : TEST(Delete) {
1483 : InitializedIgnitionHandleScope scope;
1484 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1485 :
1486 : const char* snippets[] = {
1487 : "var a = {x:13, y:14}; return delete a.x;\n",
1488 :
1489 : "'use strict'; var a = {x:13, y:14}; return delete a.x;\n",
1490 :
1491 : "var a = {1:13, 2:14}; return delete a[2];\n",
1492 :
1493 : "var a = 10; return delete a;\n",
1494 :
1495 : "'use strict';\n"
1496 : "var a = {1:10};\n"
1497 : "(function f1() {return a;});\n"
1498 : "return delete a[1];\n",
1499 :
1500 : "return delete 'test';\n",
1501 5 : };
1502 :
1503 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1504 : LoadGolden("Delete.golden")));
1505 5 : }
1506 :
1507 28342 : TEST(GlobalDelete) {
1508 : InitializedIgnitionHandleScope scope;
1509 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1510 : printer.set_wrap(false);
1511 10 : printer.set_test_function_name("f");
1512 :
1513 : const char* snippets[] = {
1514 : "var a = {x:13, y:14};\n"
1515 : "function f() {\n"
1516 : " return delete a.x;\n"
1517 : "};\n"
1518 : "f();\n",
1519 :
1520 : "a = {1:13, 2:14};\n"
1521 : "function f() {\n"
1522 : " 'use strict';\n"
1523 : " return delete a[1];\n"
1524 : "};\n"
1525 : "f();\n",
1526 :
1527 : "var a = {x:13, y:14};\n"
1528 : "function f() {\n"
1529 : " return delete a;\n"
1530 : "};\n"
1531 : "f();\n",
1532 :
1533 : "b = 30;\n"
1534 : "function f() {\n"
1535 : " return delete b;\n"
1536 : "};\n"
1537 : "f();\n",
1538 5 : };
1539 :
1540 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1541 : LoadGolden("GlobalDelete.golden")));
1542 5 : }
1543 :
1544 28342 : TEST(FunctionLiterals) {
1545 : InitializedIgnitionHandleScope scope;
1546 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1547 :
1548 : const char* snippets[] = {
1549 : "return function(){ }\n",
1550 :
1551 : "return (function(){ })()\n",
1552 :
1553 : "return (function(x){ return x; })(1)\n",
1554 5 : };
1555 :
1556 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1557 : LoadGolden("FunctionLiterals.golden")));
1558 5 : }
1559 :
1560 28342 : TEST(RegExpLiterals) {
1561 : InitializedIgnitionHandleScope scope;
1562 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1563 :
1564 : const char* snippets[] = {
1565 : "return /ab+d/;\n",
1566 :
1567 : "return /(\\w+)\\s(\\w+)/i;\n",
1568 :
1569 : "return /ab+d/.exec('abdd');\n",
1570 5 : };
1571 :
1572 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1573 : LoadGolden("RegExpLiterals.golden")));
1574 5 : }
1575 :
1576 28342 : TEST(ArrayLiterals) {
1577 : InitializedIgnitionHandleScope scope;
1578 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1579 :
1580 : const char* snippets[] = {
1581 : "return [ 1, 2 ];\n",
1582 :
1583 : "var a = 1; return [ a, a + 1 ];\n",
1584 :
1585 : "return [ [ 1, 2 ], [ 3 ] ];\n",
1586 :
1587 : "var a = 1; return [ [ a, 2 ], [ a + 2 ] ];\n",
1588 :
1589 : "var a = [ 1, 2 ]; return [ ...a ];\n",
1590 :
1591 : "var a = [ 1, 2 ]; return [ 0, ...a ];\n",
1592 :
1593 : "var a = [ 1, 2 ]; return [ ...a, 3 ];\n",
1594 5 : };
1595 :
1596 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1597 : LoadGolden("ArrayLiterals.golden")));
1598 5 : }
1599 :
1600 28342 : TEST(ObjectLiterals) {
1601 : InitializedIgnitionHandleScope scope;
1602 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1603 :
1604 : const char* snippets[] = {
1605 : "return { };\n",
1606 :
1607 : "return { name: 'string', val: 9.2 };\n",
1608 :
1609 : "var a = 1; return { name: 'string', val: a };\n",
1610 :
1611 : "var a = 1; return { val: a, val: a + 1 };\n",
1612 :
1613 : "return { func: function() { } };\n",
1614 :
1615 : "return { func(a) { return a; } };\n",
1616 :
1617 : "return { get a() { return 2; } };\n",
1618 :
1619 : "return { get a() { return this.x; }, set a(val) { this.x = val } };\n",
1620 :
1621 : "return { set b(val) { this.y = val } };\n",
1622 :
1623 : "var a = 1; return { 1: a };\n",
1624 :
1625 : "return { __proto__: null };\n",
1626 :
1627 : "var a = 'test'; return { [a]: 1 };\n",
1628 :
1629 : "var a = 'test'; return { val: a, [a]: 1 };\n",
1630 :
1631 : "var a = 'test'; return { [a]: 1, __proto__: {} };\n",
1632 :
1633 : "var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };\n",
1634 5 : };
1635 :
1636 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1637 : LoadGolden("ObjectLiterals.golden")));
1638 5 : }
1639 :
1640 28342 : TEST(TopLevelObjectLiterals) {
1641 : InitializedIgnitionHandleScope scope;
1642 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1643 : printer.set_wrap(false);
1644 10 : printer.set_test_function_name("f");
1645 : printer.set_top_level(true);
1646 :
1647 : const char* snippets[] = {
1648 : "var a = { func: function() { } };\n",
1649 5 : };
1650 :
1651 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1652 : LoadGolden("TopLevelObjectLiterals.golden")));
1653 5 : }
1654 :
1655 28342 : TEST(TryCatch) {
1656 : InitializedIgnitionHandleScope scope;
1657 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1658 :
1659 : const char* snippets[] = {
1660 : "try { return 1; } catch(e) { return 2; }\n",
1661 :
1662 : "var a;\n"
1663 : "try { a = 1 } catch(e1) {};\n"
1664 : "try { a = 2 } catch(e2) { a = 3 }\n",
1665 5 : };
1666 :
1667 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1668 : LoadGolden("TryCatch.golden")));
1669 5 : }
1670 :
1671 28342 : TEST(TryFinally) {
1672 : InitializedIgnitionHandleScope scope;
1673 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1674 : const char* snippets[] = {
1675 : "var a = 1;\n"
1676 : "try { a = 2; } finally { a = 3; }\n",
1677 :
1678 : "var a = 1;\n"
1679 : "try { a = 2; } catch(e) { a = 20 } finally { a = 3; }\n",
1680 :
1681 : "var a; try {\n"
1682 : " try { a = 1 } catch(e) { a = 2 }\n"
1683 : "} catch(e) { a = 20 } finally { a = 3; }\n",
1684 5 : };
1685 :
1686 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1687 : LoadGolden("TryFinally.golden")));
1688 5 : }
1689 :
1690 28342 : TEST(Throw) {
1691 : InitializedIgnitionHandleScope scope;
1692 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1693 : const char* snippets[] = {
1694 : "throw 1;\n",
1695 :
1696 : "throw 'Error';\n",
1697 :
1698 : "var a = 1; if (a) { throw 'Error'; };\n",
1699 5 : };
1700 :
1701 20 : CHECK(
1702 : CompareTexts(BuildActual(printer, snippets), LoadGolden("Throw.golden")));
1703 5 : }
1704 :
1705 28342 : TEST(CallNew) {
1706 : InitializedIgnitionHandleScope scope;
1707 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1708 : printer.set_wrap(false);
1709 10 : printer.set_test_function_name("f");
1710 :
1711 : const char* snippets[] = {
1712 : "function bar() { this.value = 0; }\n"
1713 : "function f() { return new bar(); }\n"
1714 : "f();\n",
1715 :
1716 : "function bar(x) { this.value = 18; this.x = x;}\n"
1717 : "function f() { return new bar(3); }\n"
1718 : "f();\n",
1719 :
1720 : "function bar(w, x, y, z) {\n"
1721 : " this.value = 18;\n"
1722 : " this.x = x;\n"
1723 : " this.y = y;\n"
1724 : " this.z = z;\n"
1725 : "}\n"
1726 : "function f() { return new bar(3, 4, 5); }\n"
1727 : "f();\n",
1728 5 : };
1729 :
1730 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1731 : LoadGolden("CallNew.golden")));
1732 5 : }
1733 :
1734 28342 : TEST(ContextVariables) {
1735 : // The wide check below relies on MIN_CONTEXT_SLOTS + 3 + 249 == 256, if this
1736 : // ever changes, the REPEAT_XXX should be changed to output the correct number
1737 : // of unique variables to trigger the wide slot load / store.
1738 : STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
1739 :
1740 : InitializedIgnitionHandleScope scope;
1741 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1742 : const char* snippets[] = {
1743 : "var a; return function() { a = 1; };\n",
1744 :
1745 : "var a = 1; return function() { a = 2; };\n",
1746 :
1747 : "var a = 1; var b = 2; return function() { a = 2; b = 3 };\n",
1748 :
1749 : "var a; (function() { a = 2; })(); return a;\n",
1750 :
1751 : "'use strict';\n"
1752 : "let a = 1;\n"
1753 : "{ let b = 2; return function() { a + b; }; }\n",
1754 :
1755 : "'use strict';\n"
1756 : REPEAT_250_UNIQUE_VARS()
1757 : "eval();\n"
1758 : "var b = 100;\n"
1759 : "return b\n",
1760 5 : };
1761 :
1762 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1763 : LoadGolden("ContextVariables.golden")));
1764 5 : }
1765 :
1766 28342 : TEST(ContextParameters) {
1767 : InitializedIgnitionHandleScope scope;
1768 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1769 : printer.set_wrap(false);
1770 10 : printer.set_test_function_name("f");
1771 :
1772 : const char* snippets[] = {
1773 : "function f(arg1) { return function() { arg1 = 2; }; }",
1774 :
1775 : "function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
1776 :
1777 : "function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
1778 :
1779 : "function f() { var self = this; return function() { self = 2; }; }",
1780 5 : };
1781 :
1782 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1783 : LoadGolden("ContextParameters.golden")));
1784 5 : }
1785 :
1786 28342 : TEST(OuterContextVariables) {
1787 : InitializedIgnitionHandleScope scope;
1788 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1789 : printer.set_wrap(false);
1790 10 : printer.set_test_function_name("f");
1791 :
1792 : const char* snippets[] = {
1793 : "function Outer() {\n"
1794 : " var outerVar = 1;\n"
1795 : " function Inner(innerArg) {\n"
1796 : " this.innerFunc = function() { return outerVar * innerArg; }\n"
1797 : " }\n"
1798 : " this.getInnerFunc = function() { return new Inner(1).innerFunc; }\n"
1799 : "}\n"
1800 : "var f = new Outer().getInnerFunc();",
1801 :
1802 : "function Outer() {\n"
1803 : " var outerVar = 1;\n"
1804 : " function Inner(innerArg) {\n"
1805 : " this.innerFunc = function() { outerVar = innerArg; }\n"
1806 : " }\n"
1807 : " this.getInnerFunc = function() { return new Inner(1).innerFunc; }\n"
1808 : "}\n"
1809 : "var f = new Outer().getInnerFunc();",
1810 5 : };
1811 :
1812 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1813 : LoadGolden("OuterContextVariables.golden")));
1814 5 : }
1815 :
1816 28342 : TEST(CountOperators) {
1817 : InitializedIgnitionHandleScope scope;
1818 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1819 : const char* snippets[] = {
1820 : "var a = 1; return ++a;\n",
1821 :
1822 : "var a = 1; return a++;\n",
1823 :
1824 : "var a = 1; return --a;\n",
1825 :
1826 : "var a = 1; return a--;\n",
1827 :
1828 : "var a = { val: 1 }; return a.val++;\n",
1829 :
1830 : "var a = { val: 1 }; return --a.val;\n",
1831 :
1832 : "var name = 'var'; var a = { val: 1 }; return a[name]--;\n",
1833 :
1834 : "var name = 'var'; var a = { val: 1 }; return ++a[name];\n",
1835 :
1836 : "var a = 1; var b = function() { return a }; return ++a;\n",
1837 :
1838 : "var a = 1; var b = function() { return a }; return a--;\n",
1839 :
1840 : "var idx = 1; var a = [1, 2]; return a[idx++] = 2;\n",
1841 5 : };
1842 :
1843 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1844 : LoadGolden("CountOperators.golden")));
1845 5 : }
1846 :
1847 28342 : TEST(GlobalCountOperators) {
1848 : InitializedIgnitionHandleScope scope;
1849 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1850 : printer.set_wrap(false);
1851 10 : printer.set_test_function_name("f");
1852 :
1853 : const char* snippets[] = {
1854 : "var global = 1;\n"
1855 : "function f() { return ++global; }\n"
1856 : "f();\n",
1857 :
1858 : "var global = 1;\n"
1859 : "function f() { return global--; }\n"
1860 : "f();\n",
1861 :
1862 : "unallocated = 1;\n"
1863 : "function f() { 'use strict'; return --unallocated; }\n"
1864 : "f();\n",
1865 :
1866 : "unallocated = 1;\n"
1867 : "function f() { return unallocated++; }\n"
1868 : "f();\n",
1869 5 : };
1870 :
1871 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1872 : LoadGolden("GlobalCountOperators.golden")));
1873 5 : }
1874 :
1875 28342 : TEST(CompoundExpressions) {
1876 : InitializedIgnitionHandleScope scope;
1877 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1878 : const char* snippets[] = {
1879 : "var a = 1; a += 2;\n",
1880 :
1881 : "var a = 1; a /= 2;\n",
1882 :
1883 : "var a = { val: 2 }; a.name *= 2;\n",
1884 :
1885 : "var a = { 1: 2 }; a[1] ^= 2;\n",
1886 :
1887 : "var a = 1; (function f() { return a; }); a |= 24;\n",
1888 5 : };
1889 :
1890 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1891 : LoadGolden("CompoundExpressions.golden")));
1892 5 : }
1893 :
1894 28342 : TEST(GlobalCompoundExpressions) {
1895 : InitializedIgnitionHandleScope scope;
1896 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1897 : printer.set_wrap(false);
1898 10 : printer.set_test_function_name("f");
1899 :
1900 : const char* snippets[] = {
1901 : "var global = 1;\n"
1902 : "function f() { return global &= 1; }\n"
1903 : "f();\n",
1904 :
1905 : "unallocated = 1;\n"
1906 : "function f() { return unallocated += 1; }\n"
1907 : "f();\n",
1908 5 : };
1909 :
1910 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
1911 : LoadGolden("GlobalCompoundExpressions.golden")));
1912 5 : }
1913 :
1914 28342 : TEST(CreateArguments) {
1915 : InitializedIgnitionHandleScope scope;
1916 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1917 : printer.set_wrap(false);
1918 10 : printer.set_test_function_name("f");
1919 :
1920 : const char* snippets[] = {
1921 : "function f() { return arguments; }",
1922 :
1923 : "function f() { return arguments[0]; }",
1924 :
1925 : "function f() { 'use strict'; return arguments; }",
1926 :
1927 : "function f(a) { return arguments[0]; }",
1928 :
1929 : "function f(a, b, c) { return arguments; }",
1930 :
1931 : "function f(a, b, c) { 'use strict'; return arguments; }",
1932 5 : };
1933 :
1934 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1935 : LoadGolden("CreateArguments.golden")));
1936 5 : }
1937 :
1938 28342 : TEST(CreateRestParameter) {
1939 : InitializedIgnitionHandleScope scope;
1940 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1941 : printer.set_wrap(false);
1942 10 : printer.set_test_function_name("f");
1943 :
1944 : const char* snippets[] = {
1945 : "function f(...restArgs) { return restArgs; }",
1946 :
1947 : "function f(a, ...restArgs) { return restArgs; }",
1948 :
1949 : "function f(a, ...restArgs) { return restArgs[0]; }",
1950 :
1951 : "function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }",
1952 5 : };
1953 :
1954 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1955 : LoadGolden("CreateRestParameter.golden")));
1956 5 : }
1957 :
1958 28342 : TEST(ForIn) {
1959 : InitializedIgnitionHandleScope scope;
1960 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1961 : const char* snippets[] = {
1962 : "for (var p in null) {}\n",
1963 :
1964 : "for (var p in undefined) {}\n",
1965 :
1966 : "for (var p in undefined) {}\n",
1967 :
1968 : "var x = 'potatoes';\n"
1969 : "for (var p in x) { return p; }\n",
1970 :
1971 : "var x = 0;\n"
1972 : "for (var p in [1,2,3]) { x += p; }\n",
1973 :
1974 : "var x = { 'a': 1, 'b': 2 };\n"
1975 : "for (x['a'] in [10, 20, 30]) {\n"
1976 : " if (x['a'] == 10) continue;\n"
1977 : " if (x['a'] == 20) break;\n"
1978 : "}\n",
1979 :
1980 : "var x = [ 10, 11, 12 ] ;\n"
1981 : "for (x[0] in [1,2,3]) { return x[3]; }\n",
1982 5 : };
1983 :
1984 20 : CHECK(
1985 : CompareTexts(BuildActual(printer, snippets), LoadGolden("ForIn.golden")));
1986 5 : }
1987 :
1988 28342 : TEST(ForOf) {
1989 : InitializedIgnitionHandleScope scope;
1990 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
1991 : const char* snippets[] = {
1992 : "for (var p of [0, 1, 2]) {}\n",
1993 :
1994 : "var x = 'potatoes';\n"
1995 : "for (var p of x) { return p; }\n",
1996 :
1997 : "for (var x of [10, 20, 30]) {\n"
1998 : " if (x == 10) continue;\n"
1999 : " if (x == 20) break;\n"
2000 : "}\n",
2001 :
2002 : "var x = { 'a': 1, 'b': 2 };\n"
2003 : "for (x['a'] of [1,2,3]) { return x['a']; }\n",
2004 5 : };
2005 :
2006 20 : CHECK(
2007 : CompareTexts(BuildActual(printer, snippets), LoadGolden("ForOf.golden")));
2008 5 : }
2009 :
2010 28342 : TEST(Conditional) {
2011 : InitializedIgnitionHandleScope scope;
2012 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2013 : const char* snippets[] = {
2014 : "return 1 ? 2 : 3;\n",
2015 :
2016 : "return 1 ? 2 ? 3 : 4 : 5;\n",
2017 :
2018 : "return 0 < 1 ? 2 : 3;\n",
2019 :
2020 : "var x = 0;\n"
2021 : "return x ? 2 : 3;\n",
2022 5 : };
2023 :
2024 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2025 : LoadGolden("Conditional.golden")));
2026 5 : }
2027 :
2028 28342 : TEST(Switch) {
2029 : InitializedIgnitionHandleScope scope;
2030 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2031 : const char* snippets[] = {
2032 : "var a = 1;\n"
2033 : "switch(a) {\n"
2034 : " case 1: return 2;\n"
2035 : " case 2: return 3;\n"
2036 : "}\n",
2037 :
2038 : "var a = 1;\n"
2039 : "switch(a) {\n"
2040 : " case 1: a = 2; break;\n"
2041 : " case 2: a = 3; break;\n"
2042 : "}\n",
2043 :
2044 : "var a = 1;\n"
2045 : "switch(a) {\n"
2046 : " case 1: a = 2; // fall-through\n"
2047 : " case 2: a = 3; break;\n"
2048 : "}\n",
2049 :
2050 : "var a = 1;\n"
2051 : "switch(a) {\n"
2052 : " case 2: break;\n"
2053 : " case 3: break;\n"
2054 : " default: a = 1; break;\n"
2055 : "}\n",
2056 :
2057 : "var a = 1;\n"
2058 : "switch(typeof(a)) {\n"
2059 : " case 2: a = 1; break;\n"
2060 : " case 3: a = 2; break;\n"
2061 : " default: a = 3; break;\n"
2062 : "}\n",
2063 :
2064 : "var a = 1;\n"
2065 : "switch(a) {\n"
2066 : " case typeof(a): a = 1; break;\n"
2067 : " default: a = 2; break;\n"
2068 : "}\n",
2069 :
2070 : "var a = 1;\n"
2071 : "switch(a) {\n"
2072 : " case 1:\n"
2073 : REPEAT_64(" a = 2;\n")
2074 : " break;\n"
2075 : " case 2:\n"
2076 : " a = 3;\n"
2077 : " break;\n"
2078 : "}\n",
2079 :
2080 : "var a = 1;\n"
2081 : "switch(a) {\n"
2082 : " case 1: \n"
2083 : " switch(a + 1) {\n"
2084 : " case 2 : a = 1; break;\n"
2085 : " default : a = 2; break;\n"
2086 : " } // fall-through\n"
2087 : " case 2: a = 3;\n"
2088 : "}\n",
2089 5 : };
2090 :
2091 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2092 : LoadGolden("Switch.golden")));
2093 5 : }
2094 :
2095 28342 : TEST(BasicBlockToBoolean) {
2096 : InitializedIgnitionHandleScope scope;
2097 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2098 : const char* snippets[] = {
2099 : "var a = 1; if (a || a < 0) { return 1; }\n",
2100 :
2101 : "var a = 1; if (a && a < 0) { return 1; }\n",
2102 :
2103 : "var a = 1; a = (a || a < 0) ? 2 : 3;\n",
2104 5 : };
2105 :
2106 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2107 : LoadGolden("BasicBlockToBoolean.golden")));
2108 5 : }
2109 :
2110 28342 : TEST(DeadCodeRemoval) {
2111 : InitializedIgnitionHandleScope scope;
2112 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2113 : const char* snippets[] = {
2114 : "return; var a = 1; a();\n",
2115 :
2116 : "if (false) { return; }; var a = 1;\n",
2117 :
2118 : "if (true) { return 1; } else { return 2; };\n",
2119 :
2120 : "var a = 1; if (a) { return 1; }; return 2;\n",
2121 5 : };
2122 :
2123 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2124 : LoadGolden("DeadCodeRemoval.golden")));
2125 5 : }
2126 :
2127 28342 : TEST(ThisFunction) {
2128 : InitializedIgnitionHandleScope scope;
2129 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2130 : printer.set_wrap(false);
2131 10 : printer.set_test_function_name("f");
2132 :
2133 : const char* snippets[] = {
2134 : "var f;\n"
2135 : "f = function f() {};",
2136 :
2137 : "var f;\n"
2138 : "f = function f() { return f; };",
2139 5 : };
2140 :
2141 20 : CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
2142 : LoadGolden("ThisFunction.golden")));
2143 5 : }
2144 :
2145 28342 : TEST(NewTarget) {
2146 : InitializedIgnitionHandleScope scope;
2147 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2148 :
2149 : const char* snippets[] = {
2150 : "return new.target;\n",
2151 :
2152 : "new.target;\n",
2153 5 : };
2154 :
2155 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2156 : LoadGolden("NewTarget.golden")));
2157 5 : }
2158 :
2159 28342 : TEST(RemoveRedundantLdar) {
2160 : InitializedIgnitionHandleScope scope;
2161 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2162 : const char* snippets[] = {
2163 : "var ld_a = 1;\n" // This test is to check Ldar does not
2164 : "while(true) {\n" // get removed if the preceding Star is
2165 : " ld_a = ld_a + ld_a;\n" // in a different basicblock.
2166 : " if (ld_a > 10) break;\n"
2167 : "}\n"
2168 : "return ld_a;\n",
2169 :
2170 : "var ld_a = 1;\n"
2171 : "do {\n"
2172 : " ld_a = ld_a + ld_a;\n"
2173 : " if (ld_a > 10) continue;\n"
2174 : "} while(false);\n"
2175 : "return ld_a;\n",
2176 :
2177 : "var ld_a = 1;\n"
2178 : " ld_a = ld_a + ld_a;\n"
2179 : " return ld_a;\n",
2180 5 : };
2181 :
2182 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2183 : LoadGolden("RemoveRedundantLdar.golden")));
2184 5 : }
2185 :
2186 28342 : TEST(GenerateTestUndetectable) {
2187 : InitializedIgnitionHandleScope scope;
2188 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2189 : const char* snippets[] = {
2190 : "var obj_a = {val:1};\n"
2191 : "var b = 10;\n"
2192 : "if (obj_a == null) { b = 20;}\n"
2193 : "return b;\n",
2194 :
2195 : "var obj_a = {val:1};\n"
2196 : "var b = 10;\n"
2197 : "if (obj_a == undefined) { b = 20;}\n"
2198 : "return b;\n",
2199 :
2200 : "var obj_a = {val:1};\n"
2201 : "var b = 10;\n"
2202 : "if (obj_a != null) { b = 20;}\n"
2203 : "return b;\n",
2204 :
2205 : "var obj_a = {val:1};\n"
2206 : "var b = 10;\n"
2207 : "if (obj_a != undefined) { b = 20;}\n"
2208 : "return b;\n",
2209 :
2210 : "var obj_a = {val:1};\n"
2211 : "var b = 10;\n"
2212 : "if (obj_a === null) { b = 20;}\n"
2213 : "return b;\n",
2214 :
2215 : "var obj_a = {val:1};\n"
2216 : "var b = 10;\n"
2217 : "if (obj_a === undefined) { b = 20;}\n"
2218 : "return b;\n",
2219 :
2220 : "var obj_a = {val:1};\n"
2221 : "var b = 10;\n"
2222 : "if (obj_a !== null) { b = 20;}\n"
2223 : "return b;\n",
2224 :
2225 : "var obj_a = {val:1};\n"
2226 : "var b = 10;\n"
2227 : "if (obj_a !== undefined) { b = 20;}\n"
2228 5 : "return b;\n"};
2229 :
2230 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2231 : LoadGolden("GenerateTestUndetectable.golden")));
2232 5 : }
2233 :
2234 28342 : TEST(AssignmentsInBinaryExpression) {
2235 : InitializedIgnitionHandleScope scope;
2236 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2237 : const char* snippets[] = {
2238 : "var x = 0, y = 1;\n"
2239 : "return (x = 2, y = 3, x = 4, y = 5);\n",
2240 :
2241 : "var x = 55;\n"
2242 : "var y = (x = 100);\n"
2243 : "return y;\n",
2244 :
2245 : "var x = 55;\n"
2246 : "x = x + (x = 100) + (x = 101);\n"
2247 : "return x;\n",
2248 :
2249 : "var x = 55;\n"
2250 : "x = (x = 56) - x + (x = 57);\n"
2251 : "x++;\n"
2252 : "return x;\n",
2253 :
2254 : "var x = 55;\n"
2255 : "var y = x + (x = 1) + (x = 2) + (x = 3);\n"
2256 : "return y;\n",
2257 :
2258 : "var x = 55;\n"
2259 : "var x = x + (x = 1) + (x = 2) + (x = 3);\n"
2260 : "return x;\n",
2261 :
2262 : "var x = 10, y = 20;\n"
2263 : "return x + (x = 1) + (x + 1) * (y = 2) + (y = 3) + (x = 4) + (y = 5) + "
2264 : "y;\n",
2265 :
2266 : "var x = 17;\n"
2267 : "return 1 + x + (x++) + (++x);\n",
2268 5 : };
2269 :
2270 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2271 : LoadGolden("AssignmentsInBinaryExpression.golden")));
2272 5 : }
2273 :
2274 28342 : TEST(DestructuringAssignment) {
2275 : InitializedIgnitionHandleScope scope;
2276 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2277 : const char* snippets[] = {
2278 : "var x, a = [0,1,2,3];\n"
2279 : "[x] = a;\n",
2280 :
2281 : "var x, y, a = [0,1,2,3];\n"
2282 : "[,x,...y] = a;\n",
2283 :
2284 : "var x={}, y, a = [0];\n"
2285 : "[x.foo,y=4] = a;\n",
2286 :
2287 : "var x, a = {x:1};\n"
2288 : "({x} = a);\n",
2289 :
2290 : "var x={}, a = {y:1};\n"
2291 : "({y:x.foo} = a);\n",
2292 :
2293 : "var x, a = {y:1, w:2, v:3};\n"
2294 : "({x=0,...y} = a);\n",
2295 5 : };
2296 :
2297 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2298 : LoadGolden("DestructuringAssignment.golden")));
2299 5 : }
2300 :
2301 28342 : TEST(Eval) {
2302 : InitializedIgnitionHandleScope scope;
2303 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2304 : const char* snippets[] = {
2305 : "return eval('1;');\n",
2306 5 : };
2307 :
2308 20 : CHECK(
2309 : CompareTexts(BuildActual(printer, snippets), LoadGolden("Eval.golden")));
2310 5 : }
2311 :
2312 28342 : TEST(LookupSlot) {
2313 : InitializedIgnitionHandleScope scope;
2314 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2315 10 : printer.set_test_function_name("f");
2316 :
2317 : // clang-format off
2318 : const char* snippets[] = {
2319 : "eval('var x = 10;'); return x;\n",
2320 :
2321 : "eval('var x = 10;'); return typeof x;\n",
2322 :
2323 : "x = 20; return eval('');\n",
2324 :
2325 : "var x = 20;\n"
2326 : "f = function(){\n"
2327 : " eval('var x = 10');\n"
2328 : " return x;\n"
2329 : "}\n"
2330 : "f();\n",
2331 :
2332 : "x = 20;\n"
2333 : "f = function(){\n"
2334 : " eval('var x = 10');\n"
2335 : " return x;\n"
2336 : "}\n"
2337 : "f();\n"
2338 5 : };
2339 : // clang-format on
2340 :
2341 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2342 : LoadGolden("LookupSlot.golden")));
2343 5 : }
2344 :
2345 28342 : TEST(CallLookupSlot) {
2346 : InitializedIgnitionHandleScope scope;
2347 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2348 : const char* snippets[] = {
2349 : "g = function(){}; eval(''); return g();\n",
2350 5 : };
2351 :
2352 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2353 : LoadGolden("CallLookupSlot.golden")));
2354 5 : }
2355 :
2356 : // TODO(mythria): tests for variable/function declaration in lookup slots.
2357 :
2358 28342 : TEST(LookupSlotInEval) {
2359 : InitializedIgnitionHandleScope scope;
2360 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2361 : printer.set_wrap(false);
2362 10 : printer.set_test_function_name("f");
2363 :
2364 : const char* snippets[] = {
2365 : "return x;",
2366 :
2367 : "x = 10;",
2368 :
2369 : "'use strict'; x = 10;",
2370 :
2371 : "return typeof x;",
2372 5 : };
2373 :
2374 : std::string actual = BuildActual(printer, snippets,
2375 : "var f;\n"
2376 : "var x = 1;\n"
2377 : "function f1() {\n"
2378 : " eval(\"function t() { ",
2379 :
2380 : " }; f = t; f();\");\n"
2381 : "}\n"
2382 5 : "f1();");
2383 :
2384 15 : CHECK(CompareTexts(actual, LoadGolden("LookupSlotInEval.golden")));
2385 5 : }
2386 :
2387 28342 : TEST(DeleteLookupSlotInEval) {
2388 : InitializedIgnitionHandleScope scope;
2389 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2390 : printer.set_wrap(false);
2391 10 : printer.set_test_function_name("f");
2392 :
2393 : const char* snippets[] = {
2394 : "delete x;",
2395 :
2396 : "return delete y;",
2397 :
2398 : "return delete z;",
2399 5 : };
2400 :
2401 : std::string actual = BuildActual(printer, snippets,
2402 : "var f;\n"
2403 : "var x = 1;\n"
2404 : "z = 10;\n"
2405 : "function f1() {\n"
2406 : " var y;\n"
2407 : " eval(\"function t() { ",
2408 :
2409 : " }; f = t; f();\");\n"
2410 : "}\n"
2411 5 : "f1();");
2412 :
2413 15 : CHECK(CompareTexts(actual, LoadGolden("DeleteLookupSlotInEval.golden")));
2414 5 : }
2415 :
2416 28342 : TEST(WideRegisters) {
2417 : // Prepare prologue that creates frame for lots of registers.
2418 5 : std::ostringstream os;
2419 790 : for (size_t i = 0; i < 157; ++i) {
2420 1570 : os << "var x" << i << ";\n";
2421 : }
2422 : std::string prologue(os.str());
2423 :
2424 : InitializedIgnitionHandleScope scope;
2425 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2426 : const char* snippets[] = {
2427 : "x0 = x127;\n"
2428 : "return x0;\n",
2429 :
2430 : "x127 = x126;\n"
2431 : "return x127;\n",
2432 :
2433 : "if (x2 > 3) { return x129; }\n"
2434 : "return x128;\n",
2435 :
2436 : "var x0 = 0;\n"
2437 : "if (x129 == 3) { var x129 = x0; }\n"
2438 : "if (x2 > 3) { return x0; }\n"
2439 : "return x129;\n",
2440 :
2441 : "var x0 = 0;\n"
2442 : "var x1 = 0;\n"
2443 : "for (x128 = 0; x128 < 64; x128++) {"
2444 : " x1 += x128;"
2445 : "}"
2446 : "return x128;\n",
2447 :
2448 : "var x0 = 1234;\n"
2449 : "var x1 = 0;\n"
2450 : "for (x128 in x0) {"
2451 : " x1 += x128;"
2452 : "}"
2453 : "return x1;\n",
2454 :
2455 : "x0 = %Add(x64, x63);\n"
2456 : "x1 = %Add(x27, x143);\n"
2457 : "%TheHole();\n"
2458 : "return x1;\n",
2459 5 : };
2460 :
2461 25 : CHECK(CompareTexts(BuildActual(printer, snippets, prologue.c_str()),
2462 5 : LoadGolden("WideRegisters.golden")));
2463 5 : }
2464 :
2465 28342 : TEST(ConstVariable) {
2466 : InitializedIgnitionHandleScope scope;
2467 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2468 : const char* snippets[] = {
2469 : "const x = 10;\n",
2470 :
2471 : "const x = 10; return x;\n",
2472 :
2473 : "const x = ( x = 20);\n",
2474 :
2475 : "const x = 10; x = 20;\n",
2476 5 : };
2477 :
2478 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2479 : LoadGolden("ConstVariable.golden")));
2480 5 : }
2481 :
2482 28342 : TEST(LetVariable) {
2483 : InitializedIgnitionHandleScope scope;
2484 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2485 : const char* snippets[] = {
2486 : "let x = 10;\n",
2487 :
2488 : "let x = 10; return x;\n",
2489 :
2490 : "let x = (x = 20);\n",
2491 :
2492 : "let x = 10; x = 20;\n",
2493 5 : };
2494 :
2495 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2496 : LoadGolden("LetVariable.golden")));
2497 5 : }
2498 :
2499 28342 : TEST(ConstVariableContextSlot) {
2500 : // TODO(mythria): Add tests for initialization of this via super calls.
2501 : // TODO(mythria): Add tests that walk the context chain.
2502 : InitializedIgnitionHandleScope scope;
2503 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2504 : const char* snippets[] = {
2505 : "const x = 10; function f1() {return x;}\n",
2506 :
2507 : "const x = 10; function f1() {return x;} return x;\n",
2508 :
2509 : "const x = (x = 20); function f1() {return x;}\n",
2510 :
2511 : "const x = 10; x = 20; function f1() {return x;}\n",
2512 5 : };
2513 :
2514 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2515 : LoadGolden("ConstVariableContextSlot.golden")));
2516 5 : }
2517 :
2518 28342 : TEST(LetVariableContextSlot) {
2519 : InitializedIgnitionHandleScope scope;
2520 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2521 : const char* snippets[] = {
2522 : "let x = 10; function f1() {return x;}\n",
2523 :
2524 : "let x = 10; function f1() {return x;} return x;\n",
2525 :
2526 : "let x = (x = 20); function f1() {return x;}\n",
2527 :
2528 : "let x = 10; x = 20; function f1() {return x;}\n",
2529 5 : };
2530 :
2531 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2532 : LoadGolden("LetVariableContextSlot.golden")));
2533 5 : }
2534 :
2535 28342 : TEST(WithStatement) {
2536 : InitializedIgnitionHandleScope scope;
2537 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2538 : const char* snippets[] = {
2539 : "with ({x:42}) { return x; }\n",
2540 5 : };
2541 :
2542 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2543 : LoadGolden("WithStatement.golden")));
2544 5 : }
2545 :
2546 28342 : TEST(DoDebugger) {
2547 : InitializedIgnitionHandleScope scope;
2548 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2549 : const char* snippets[] = {
2550 : "debugger;\n",
2551 5 : };
2552 :
2553 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2554 : LoadGolden("DoDebugger.golden")));
2555 5 : }
2556 :
2557 28342 : TEST(ClassDeclarations) {
2558 : InitializedIgnitionHandleScope scope;
2559 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2560 : const char* snippets[] = {
2561 : "class Person {\n"
2562 : " constructor(name) { this.name = name; }\n"
2563 : " speak() { console.log(this.name + ' is speaking.'); }\n"
2564 : "}\n",
2565 :
2566 : "class person {\n"
2567 : " constructor(name) { this.name = name; }\n"
2568 : " speak() { console.log(this.name + ' is speaking.'); }\n"
2569 : "}\n",
2570 :
2571 : "var n0 = 'a';\n"
2572 : "var n1 = 'b';\n"
2573 : "class N {\n"
2574 : " [n0]() { return n0; }\n"
2575 : " static [n1]() { return n1; }\n"
2576 : "}\n",
2577 :
2578 : "var count = 0;\n"
2579 : "class C { constructor() { count++; }}\n"
2580 : "return new C();\n",
2581 :
2582 : "(class {})\n"
2583 : "class E { static name () {}}\n",
2584 5 : };
2585 :
2586 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2587 : LoadGolden("ClassDeclarations.golden")));
2588 5 : }
2589 :
2590 28342 : TEST(ClassAndSuperClass) {
2591 : InitializedIgnitionHandleScope scope;
2592 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2593 : printer.set_wrap(false);
2594 10 : printer.set_test_function_name("test");
2595 : const char* snippets[] = {
2596 : "var test;\n"
2597 : "(function() {\n"
2598 : " class A {\n"
2599 : " method() { return 2; }\n"
2600 : " }\n"
2601 : " class B extends A {\n"
2602 : " method() { return super.method() + 1; }\n"
2603 : " }\n"
2604 : " test = new B().method;\n"
2605 : " test();\n"
2606 : "})();\n",
2607 :
2608 : "var test;\n"
2609 : "(function() {\n"
2610 : " class A {\n"
2611 : " get x() { return 1; }\n"
2612 : " set x(val) { return; }\n"
2613 : " }\n"
2614 : " class B extends A {\n"
2615 : " method() { super.x = 2; return super.x; }\n"
2616 : " }\n"
2617 : " test = new B().method;\n"
2618 : " test();\n"
2619 : "})();\n",
2620 :
2621 : "var test;\n"
2622 : "(function() {\n"
2623 : " class A {\n"
2624 : " constructor(x) { this.x_ = x; }\n"
2625 : " }\n"
2626 : " class B extends A {\n"
2627 : " constructor() { super(1); this.y_ = 2; }\n"
2628 : " }\n"
2629 : " test = new B().constructor;\n"
2630 : "})();\n",
2631 :
2632 : "var test;\n"
2633 : "(function() {\n"
2634 : " class A {\n"
2635 : " constructor() { this.x_ = 1; }\n"
2636 : " }\n"
2637 : " class B extends A {\n"
2638 : " constructor() { super(); this.y_ = 2; }\n"
2639 : " }\n"
2640 : " test = new B().constructor;\n"
2641 : "})();\n",
2642 5 : };
2643 :
2644 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2645 : LoadGolden("ClassAndSuperClass.golden")));
2646 5 : }
2647 :
2648 28342 : TEST(PublicClassFields) {
2649 5 : bool old_flag = i::FLAG_harmony_public_fields;
2650 5 : i::FLAG_harmony_public_fields = true;
2651 : InitializedIgnitionHandleScope scope;
2652 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2653 :
2654 : const char* snippets[] = {
2655 : "{\n"
2656 : " class A {\n"
2657 : " a;\n"
2658 : " ['b'];\n"
2659 : " }\n"
2660 : "\n"
2661 : " class B {\n"
2662 : " a = 1;\n"
2663 : " ['b'] = this.a;\n"
2664 : " }\n"
2665 : " new A;\n"
2666 : " new B;\n"
2667 : "}\n",
2668 :
2669 : "{\n"
2670 : " class A extends class {} {\n"
2671 : " a;\n"
2672 : " ['b'];\n"
2673 : " }\n"
2674 : "\n"
2675 : " class B extends class {} {\n"
2676 : " a = 1;\n"
2677 : " ['b'] = this.a;\n"
2678 : " foo() { return 1; }\n"
2679 : " constructor() {\n"
2680 : " super();\n"
2681 : " }\n"
2682 : " }\n"
2683 : "\n"
2684 : " class C extends B {\n"
2685 : " a = 1;\n"
2686 : " ['b'] = this.a;\n"
2687 : " constructor() {\n"
2688 : " (() => super())();\n"
2689 : " }\n"
2690 : " }\n"
2691 : "\n"
2692 : " new A;\n"
2693 : " new B;\n"
2694 : " new C;\n"
2695 5 : "}\n"};
2696 :
2697 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2698 : LoadGolden("PublicClassFields.golden")));
2699 5 : i::FLAG_harmony_public_fields = old_flag;
2700 5 : }
2701 :
2702 28342 : TEST(PrivateClassFields) {
2703 5 : bool old_flag = i::FLAG_harmony_private_fields;
2704 5 : i::FLAG_harmony_private_fields = true;
2705 : InitializedIgnitionHandleScope scope;
2706 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2707 :
2708 : const char* snippets[] = {
2709 : "{\n"
2710 : " class A {\n"
2711 : " #a;\n"
2712 : " constructor() {\n"
2713 : " this.#a = 1;\n"
2714 : " }\n"
2715 : " }\n"
2716 : "\n"
2717 : " class B {\n"
2718 : " #a = 1;\n"
2719 : " }\n"
2720 : " new A;\n"
2721 : " new B;\n"
2722 : "}\n",
2723 :
2724 : "{\n"
2725 : " class A extends class {} {\n"
2726 : " #a;\n"
2727 : " constructor() {\n"
2728 : " super();\n"
2729 : " this.#a = 1;\n"
2730 : " }\n"
2731 : " }\n"
2732 : "\n"
2733 : " class B extends class {} {\n"
2734 : " #a = 1;\n"
2735 : " #b = this.#a;\n"
2736 : " foo() { return this.#a; }\n"
2737 : " bar(v) { this.#b = v; }\n"
2738 : " constructor() {\n"
2739 : " super();\n"
2740 : " this.foo();\n"
2741 : " this.bar(3);\n"
2742 : " }\n"
2743 : " }\n"
2744 : "\n"
2745 : " class C extends B {\n"
2746 : " #a = 2;\n"
2747 : " constructor() {\n"
2748 : " (() => super())();\n"
2749 : " }\n"
2750 : " }\n"
2751 : "\n"
2752 : " new A;\n"
2753 : " new B;\n"
2754 : " new C;\n"
2755 5 : "};\n"};
2756 :
2757 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2758 : LoadGolden("PrivateClassFields.golden")));
2759 5 : i::FLAG_harmony_private_fields = old_flag;
2760 5 : }
2761 :
2762 28342 : TEST(StaticClassFields) {
2763 5 : bool old_flag = i::FLAG_harmony_public_fields;
2764 5 : bool old_static_flag = i::FLAG_harmony_static_fields;
2765 5 : i::FLAG_harmony_public_fields = true;
2766 5 : i::FLAG_harmony_static_fields = true;
2767 : InitializedIgnitionHandleScope scope;
2768 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2769 :
2770 : const char* snippets[] = {
2771 : "{\n"
2772 : " class A {\n"
2773 : " a;\n"
2774 : " ['b'];\n"
2775 : " static c;\n"
2776 : " static ['d'];\n"
2777 : " }\n"
2778 : "\n"
2779 : " class B {\n"
2780 : " a = 1;\n"
2781 : " ['b'] = this.a;\n"
2782 : " static c = 3;\n"
2783 : " static ['d'] = this.c;\n"
2784 : " }\n"
2785 : " new A;\n"
2786 : " new B;\n"
2787 : "}\n",
2788 :
2789 : "{\n"
2790 : " class A extends class {} {\n"
2791 : " a;\n"
2792 : " ['b'];\n"
2793 : " static c;\n"
2794 : " static ['d'];\n"
2795 : " }\n"
2796 : "\n"
2797 : " class B extends class {} {\n"
2798 : " a = 1;\n"
2799 : " ['b'] = this.a;\n"
2800 : " static c = 3;\n"
2801 : " static ['d'] = this.c;\n"
2802 : " foo() { return 1; }\n"
2803 : " constructor() {\n"
2804 : " super();\n"
2805 : " }\n"
2806 : " }\n"
2807 : "\n"
2808 : " class C extends B {\n"
2809 : " a = 1;\n"
2810 : " ['b'] = this.a;\n"
2811 : " static c = 3;\n"
2812 : " static ['d'] = super.foo();\n"
2813 : " constructor() {\n"
2814 : " (() => super())();\n"
2815 : " }\n"
2816 : " }\n"
2817 : "\n"
2818 : " new A;\n"
2819 : " new B;\n"
2820 : " new C;\n"
2821 5 : "}\n"};
2822 :
2823 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2824 : LoadGolden("StaticClassFields.golden")));
2825 5 : i::FLAG_harmony_public_fields = old_flag;
2826 5 : i::FLAG_harmony_static_fields = old_static_flag;
2827 5 : }
2828 :
2829 28342 : TEST(Generators) {
2830 : InitializedIgnitionHandleScope scope;
2831 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2832 : printer.set_wrap(false);
2833 10 : printer.set_test_function_name("f");
2834 :
2835 : const char* snippets[] = {
2836 : "function* f() { }\n"
2837 : "f();\n",
2838 :
2839 : "function* f() { yield 42 }\n"
2840 : "f();\n",
2841 :
2842 : "function* f() { for (let x of [42]) yield x }\n"
2843 : "f();\n",
2844 :
2845 : "function* g() { yield 42 }\n"
2846 : "function* f() { yield* g() }\n"
2847 : "f();\n",
2848 5 : };
2849 :
2850 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2851 : LoadGolden("Generators.golden")));
2852 5 : }
2853 :
2854 28342 : TEST(AsyncGenerators) {
2855 : InitializedIgnitionHandleScope scope;
2856 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2857 : printer.set_wrap(false);
2858 10 : printer.set_test_function_name("f");
2859 :
2860 : const char* snippets[] = {
2861 : "async function* f() { }\n"
2862 : "f();\n",
2863 :
2864 : "async function* f() { yield 42 }\n"
2865 : "f();\n",
2866 :
2867 : "async function* f() { for (let x of [42]) yield x }\n"
2868 : "f();\n",
2869 :
2870 : "function* g() { yield 42 }\n"
2871 : "async function* f() { yield* g() }\n"
2872 : "f();\n",
2873 5 : };
2874 :
2875 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2876 : LoadGolden("AsyncGenerators.golden")));
2877 5 : }
2878 :
2879 28342 : TEST(Modules) {
2880 : InitializedIgnitionHandleScope scope;
2881 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2882 : printer.set_wrap(false);
2883 : printer.set_module(true);
2884 : printer.set_top_level(true);
2885 :
2886 : const char* snippets[] = {
2887 : "import \"bar\";\n",
2888 :
2889 : "import {foo} from \"bar\";\n",
2890 :
2891 : "import {foo as goo} from \"bar\";\n"
2892 : "goo(42);\n"
2893 : "{ let x; { goo(42) } };\n",
2894 :
2895 : "export var foo = 42;\n"
2896 : "foo++;\n"
2897 : "{ let x; { foo++ } };\n",
2898 :
2899 : "export let foo = 42;\n"
2900 : "foo++;\n"
2901 : "{ let x; { foo++ } };\n",
2902 :
2903 : "export const foo = 42;\n"
2904 : "foo++;\n"
2905 : "{ let x; { foo++ } };\n",
2906 :
2907 : "export default (function () {});\n",
2908 :
2909 : "export default (class {});\n",
2910 :
2911 : "export {foo as goo} from \"bar\"\n",
2912 :
2913 : "export * from \"bar\"\n",
2914 :
2915 : "import * as foo from \"bar\"\n"
2916 : "foo.f(foo, foo.x);\n",
2917 5 : };
2918 :
2919 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2920 : LoadGolden("Modules.golden")));
2921 5 : }
2922 :
2923 28342 : TEST(SuperCallAndSpread) {
2924 : InitializedIgnitionHandleScope scope;
2925 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2926 : printer.set_wrap(false);
2927 10 : printer.set_test_function_name("test");
2928 : const char* snippets[] = {
2929 : "var test;\n"
2930 : "(function() {\n"
2931 : " class A {\n"
2932 : " constructor(...args) { this.baseArgs = args; }\n"
2933 : " }\n"
2934 : " class B extends A {}\n"
2935 : " test = new B(1, 2, 3).constructor;\n"
2936 : "})();\n",
2937 :
2938 : "var test;\n"
2939 : "(function() {\n"
2940 : " class A {\n"
2941 : " constructor(...args) { this.baseArgs = args; }\n"
2942 : " }\n"
2943 : " class B extends A {\n"
2944 : " constructor(...args) { super(1, ...args); }\n"
2945 : " }\n"
2946 : " test = new B(1, 2, 3).constructor;\n"
2947 : "})();\n",
2948 :
2949 : "var test;\n"
2950 : "(function() {\n"
2951 : " class A {\n"
2952 : " constructor(...args) { this.baseArgs = args; }\n"
2953 : " }\n"
2954 : " class B extends A {\n"
2955 : " constructor(...args) { super(1, ...args, 1); }\n"
2956 : " }\n"
2957 : " test = new B(1, 2, 3).constructor;\n"
2958 : "})();\n",
2959 5 : };
2960 :
2961 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2962 : LoadGolden("SuperCallAndSpread.golden")));
2963 5 : }
2964 :
2965 28342 : TEST(CallAndSpread) {
2966 : InitializedIgnitionHandleScope scope;
2967 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2968 : const char* snippets[] = {"Math.max(...[1, 2, 3]);\n",
2969 : "Math.max(0, ...[1, 2, 3]);\n",
2970 5 : "Math.max(0, ...[1, 2, 3], 4);\n"};
2971 :
2972 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2973 : LoadGolden("CallAndSpread.golden")));
2974 5 : }
2975 :
2976 28342 : TEST(NewAndSpread) {
2977 : InitializedIgnitionHandleScope scope;
2978 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2979 : const char* snippets[] = {
2980 : "class A { constructor(...args) { this.args = args; } }\n"
2981 : "new A(...[1, 2, 3]);\n",
2982 :
2983 : "class A { constructor(...args) { this.args = args; } }\n"
2984 : "new A(0, ...[1, 2, 3]);\n",
2985 :
2986 : "class A { constructor(...args) { this.args = args; } }\n"
2987 5 : "new A(0, ...[1, 2, 3], 4);\n"};
2988 :
2989 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
2990 : LoadGolden("NewAndSpread.golden")));
2991 5 : }
2992 :
2993 28342 : TEST(ForAwaitOf) {
2994 : InitializedIgnitionHandleScope scope;
2995 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
2996 : printer.set_wrap(false);
2997 10 : printer.set_test_function_name("f");
2998 :
2999 : const char* snippets[] = {
3000 : "async function f() {\n"
3001 : " for await (let x of [1, 2, 3]) {}\n"
3002 : "}\n"
3003 : "f();\n",
3004 :
3005 : "async function f() {\n"
3006 : " for await (let x of [1, 2, 3]) { return x; }\n"
3007 : "}\n"
3008 : "f();\n",
3009 :
3010 : "async function f() {\n"
3011 : " for await (let x of [10, 20, 30]) {\n"
3012 : " if (x == 10) continue;\n"
3013 : " if (x == 20) break;\n"
3014 : " }\n"
3015 : "}\n"
3016 : "f();\n",
3017 :
3018 : "async function f() {\n"
3019 : " var x = { 'a': 1, 'b': 2 };\n"
3020 : " for (x['a'] of [1,2,3]) { return x['a']; }\n"
3021 : "}\n"
3022 5 : "f();\n"};
3023 :
3024 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
3025 : LoadGolden("ForAwaitOf.golden")));
3026 5 : }
3027 :
3028 28342 : TEST(StandardForLoop) {
3029 : InitializedIgnitionHandleScope scope;
3030 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
3031 : printer.set_wrap(false);
3032 10 : printer.set_test_function_name("f");
3033 :
3034 : const char* snippets[] = {
3035 : "function f() {\n"
3036 : " for (let x = 0; x < 10; ++x) { let y = x; }\n"
3037 : "}\n"
3038 : "f();\n",
3039 :
3040 : "function f() {\n"
3041 : " for (let x = 0; x < 10; ++x) { eval('1'); }\n"
3042 : "}\n"
3043 : "f();\n",
3044 :
3045 : "function f() {\n"
3046 : " for (let x = 0; x < 10; ++x) { (function() { return x; })(); }\n"
3047 : "}\n"
3048 : "f();\n",
3049 :
3050 : "function f() {\n"
3051 : " for (let { x, y } = { x: 0, y: 3 }; y > 0; --y) { let z = x + y; }\n"
3052 : "}\n"
3053 : "f();\n",
3054 :
3055 : "function* f() {\n"
3056 : " for (let x = 0; x < 10; ++x) { let y = x; }\n"
3057 : "}\n"
3058 : "f();\n",
3059 :
3060 : "function* f() {\n"
3061 : " for (let x = 0; x < 10; ++x) yield x;\n"
3062 : "}\n"
3063 : "f();\n",
3064 :
3065 : "async function f() {\n"
3066 : " for (let x = 0; x < 10; ++x) { let y = x; }\n"
3067 : "}\n"
3068 : "f();\n",
3069 :
3070 : "async function f() {\n"
3071 : " for (let x = 0; x < 10; ++x) await x;\n"
3072 : "}\n"
3073 5 : "f();\n"};
3074 :
3075 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
3076 : LoadGolden("StandardForLoop.golden")));
3077 5 : }
3078 :
3079 28342 : TEST(ForOfLoop) {
3080 : InitializedIgnitionHandleScope scope;
3081 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
3082 : printer.set_wrap(false);
3083 10 : printer.set_test_function_name("f");
3084 :
3085 : const char* snippets[] = {
3086 : "function f(arr) {\n"
3087 : " for (let x of arr) { let y = x; }\n"
3088 : "}\n"
3089 : "f([1, 2, 3]);\n",
3090 :
3091 : "function f(arr) {\n"
3092 : " for (let x of arr) { eval('1'); }\n"
3093 : "}\n"
3094 : "f([1, 2, 3]);\n",
3095 :
3096 : "function f(arr) {\n"
3097 : " for (let x of arr) { (function() { return x; })(); }\n"
3098 : "}\n"
3099 : "f([1, 2, 3]);\n",
3100 :
3101 : "function f(arr) {\n"
3102 : " for (let { x, y } of arr) { let z = x + y; }\n"
3103 : "}\n"
3104 : "f([{ x: 0, y: 3 }, { x: 1, y: 9 }, { x: -12, y: 17 }]);\n",
3105 :
3106 : "function* f(arr) {\n"
3107 : " for (let x of arr) { let y = x; }\n"
3108 : "}\n"
3109 : "f([1, 2, 3]);\n",
3110 :
3111 : "function* f(arr) {\n"
3112 : " for (let x of arr) yield x;\n"
3113 : "}\n"
3114 : "f([1, 2, 3]);\n",
3115 :
3116 : "async function f(arr) {\n"
3117 : " for (let x of arr) { let y = x; }\n"
3118 : "}\n"
3119 : "f([1, 2, 3]);\n",
3120 :
3121 : "async function f(arr) {\n"
3122 : " for (let x of arr) await x;\n"
3123 : "}\n"
3124 5 : "f([1, 2, 3]);\n"};
3125 :
3126 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
3127 : LoadGolden("ForOfLoop.golden")));
3128 5 : }
3129 :
3130 28342 : TEST(StringConcat) {
3131 : InitializedIgnitionHandleScope scope;
3132 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
3133 :
3134 : const char* snippets[] = {
3135 : "var a = 1;\n"
3136 : "var b = 2;\n"
3137 : "return a + b + 'string';\n",
3138 :
3139 : "var a = 1;\n"
3140 : "var b = 2;\n"
3141 : "return 'string' + a + b;\n",
3142 :
3143 : "var a = 1;\n"
3144 : "var b = 2;\n"
3145 : "return a + 'string' + b;\n",
3146 :
3147 : "var a = 1;\n"
3148 : "var b = 2;\n"
3149 : "return 'foo' + a + 'bar' + b + 'baz' + 1;\n",
3150 :
3151 : "var a = 1;\n"
3152 : "var b = 2;\n"
3153 : "return (a + 'string') + ('string' + b);\n",
3154 :
3155 : "var a = 1;\n"
3156 : "var b = 2;\n"
3157 : "function foo(a, b) { };\n"
3158 : "return 'string' + foo(a, b) + a + b;\n",
3159 5 : };
3160 :
3161 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
3162 : LoadGolden("StringConcat.golden")));
3163 5 : }
3164 :
3165 28342 : TEST(TemplateLiterals) {
3166 : InitializedIgnitionHandleScope scope;
3167 5 : BytecodeExpectationsPrinter printer(CcTest::isolate());
3168 :
3169 : const char* snippets[] = {
3170 : "var a = 1;\n"
3171 : "var b = 2;\n"
3172 : "return `${a}${b}string`;\n",
3173 :
3174 : "var a = 1;\n"
3175 : "var b = 2;\n"
3176 : "return `string${a}${b}`;\n",
3177 :
3178 : "var a = 1;\n"
3179 : "var b = 2;\n"
3180 : "return `${a}string${b}`;\n",
3181 :
3182 : "var a = 1;\n"
3183 : "var b = 2;\n"
3184 : "return `foo${a}bar${b}baz${1}`;\n",
3185 :
3186 : "var a = 1;\n"
3187 : "var b = 2;\n"
3188 : "return `${a}string` + `string${b}`;\n",
3189 :
3190 : "var a = 1;\n"
3191 : "var b = 2;\n"
3192 : "function foo(a, b) { };\n"
3193 : "return `string${foo(a, b)}${a}${b}`;\n",
3194 5 : };
3195 :
3196 20 : CHECK(CompareTexts(BuildActual(printer, snippets),
3197 : LoadGolden("TemplateLiterals.golden")));
3198 5 : }
3199 :
3200 : #undef XSTR
3201 : #undef STR
3202 : #undef UNIQUE_VAR
3203 : #undef REPEAT_2
3204 : #undef REPEAT_4
3205 : #undef REPEAT_8
3206 : #undef REPEAT_16
3207 : #undef REPEAT_32
3208 : #undef REPEAT_64
3209 : #undef REPEAT_128
3210 : #undef REPEAT_256
3211 : #undef REPEAT_127
3212 : #undef REPEAT_249
3213 : #undef REPEAT_2_UNIQUE_VARS
3214 : #undef REPEAT_4_UNIQUE_VARS
3215 : #undef REPEAT_8_UNIQUE_VARS
3216 : #undef REPEAT_16_UNIQUE_VARS
3217 : #undef REPEAT_32_UNIQUE_VARS
3218 : #undef REPEAT_64_UNIQUE_VARS
3219 : #undef REPEAT_128_UNIQUE_VARS
3220 : #undef REPEAT_250_UNIQUE_VARS
3221 : #undef LOAD_UNIQUE_PROPERTY
3222 : #undef REPEAT_2_LOAD_UNIQUE_PROPERTY
3223 : #undef REPEAT_4_LOAD_UNIQUE_PROPERTY
3224 : #undef REPEAT_8_LOAD_UNIQUE_PROPERTY
3225 : #undef REPEAT_16_LOAD_UNIQUE_PROPERTY
3226 : #undef REPEAT_32_LOAD_UNIQUE_PROPERTY
3227 : #undef REPEAT_64_LOAD_UNIQUE_PROPERTY
3228 : #undef REPEAT_128_LOAD_UNIQUE_PROPERTY
3229 : #undef FUNC_ARG
3230 :
3231 : } // namespace interpreter
3232 : } // namespace internal
3233 85011 : } // namespace v8
|