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