• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include <fstream>
6 
7 #include "src/v8.h"
8 
9 #include "src/compiler.h"
10 #include "src/interpreter/bytecode-array-iterator.h"
11 #include "src/interpreter/bytecode-generator.h"
12 #include "src/interpreter/interpreter.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 REPEAT_2(...) __VA_ARGS__ __VA_ARGS__
27 #define REPEAT_4(...) REPEAT_2(__VA_ARGS__) REPEAT_2(__VA_ARGS__)
28 #define REPEAT_8(...) REPEAT_4(__VA_ARGS__) REPEAT_4(__VA_ARGS__)
29 #define REPEAT_16(...) REPEAT_8(__VA_ARGS__) REPEAT_8(__VA_ARGS__)
30 #define REPEAT_32(...) REPEAT_16(__VA_ARGS__) REPEAT_16(__VA_ARGS__)
31 #define REPEAT_64(...) REPEAT_32(__VA_ARGS__) REPEAT_32(__VA_ARGS__)
32 #define REPEAT_128(...) REPEAT_64(__VA_ARGS__) REPEAT_64(__VA_ARGS__)
33 #define REPEAT_256(...) REPEAT_128(__VA_ARGS__) REPEAT_128(__VA_ARGS__)
34 
35 #define REPEAT_127(...)  \
36   REPEAT_64(__VA_ARGS__) \
37   REPEAT_32(__VA_ARGS__) \
38   REPEAT_16(__VA_ARGS__) \
39   REPEAT_8(__VA_ARGS__)  \
40   REPEAT_4(__VA_ARGS__)  \
41   REPEAT_2(__VA_ARGS__)  \
42   __VA_ARGS__
43 
44 #define REPEAT_249(...)   \
45   REPEAT_127(__VA_ARGS__) \
46   REPEAT_64(__VA_ARGS__)  \
47   REPEAT_32(__VA_ARGS__)  \
48   REPEAT_16(__VA_ARGS__)  \
49   REPEAT_8(__VA_ARGS__)   \
50   REPEAT_2(__VA_ARGS__)
51 
52 #define REPEAT_2_UNIQUE_VARS() UNIQUE_VAR() UNIQUE_VAR()
53 #define REPEAT_4_UNIQUE_VARS() REPEAT_2_UNIQUE_VARS() REPEAT_2_UNIQUE_VARS()
54 #define REPEAT_8_UNIQUE_VARS() REPEAT_4_UNIQUE_VARS() REPEAT_4_UNIQUE_VARS()
55 #define REPEAT_16_UNIQUE_VARS() REPEAT_8_UNIQUE_VARS() REPEAT_8_UNIQUE_VARS()
56 #define REPEAT_32_UNIQUE_VARS() REPEAT_16_UNIQUE_VARS() REPEAT_16_UNIQUE_VARS()
57 #define REPEAT_64_UNIQUE_VARS() REPEAT_32_UNIQUE_VARS() REPEAT_32_UNIQUE_VARS()
58 #define REPEAT_128_UNIQUE_VARS() REPEAT_64_UNIQUE_VARS() REPEAT_64_UNIQUE_VARS()
59 
60 #define REPEAT_249_UNIQUE_VARS() \
61   REPEAT_128_UNIQUE_VARS()       \
62   REPEAT_64_UNIQUE_VARS()        \
63   REPEAT_32_UNIQUE_VARS()        \
64   REPEAT_16_UNIQUE_VARS()        \
65   REPEAT_8_UNIQUE_VARS()         \
66   UNIQUE_VAR()
67 
68 static const char* kGoldenFileDirectory =
69     "test/cctest/interpreter/bytecode_expectations/";
70 
71 class InitializedIgnitionHandleScope : public InitializedHandleScope {
72  public:
InitializedIgnitionHandleScope()73   InitializedIgnitionHandleScope() {
74     i::FLAG_ignition = true;
75     i::FLAG_always_opt = false;
76     i::FLAG_allow_natives_syntax = true;
77     CcTest::i_isolate()->interpreter()->Initialize();
78   }
79 };
80 
SkipGoldenFileHeader(std::istream & stream)81 void SkipGoldenFileHeader(std::istream& stream) {  // NOLINT
82   std::string line;
83   int separators_seen = 0;
84   while (std::getline(stream, line)) {
85     if (line == "---") separators_seen += 1;
86     if (separators_seen == 2) return;
87   }
88 }
89 
LoadGolden(const std::string & golden_filename)90 std::string LoadGolden(const std::string& golden_filename) {
91   std::ifstream expected_file((kGoldenFileDirectory + golden_filename).c_str());
92   CHECK(expected_file.is_open());
93   SkipGoldenFileHeader(expected_file);
94   std::ostringstream expected_stream;
95   // Restore the first separator, which was consumed by SkipGoldenFileHeader
96   expected_stream << "---\n" << expected_file.rdbuf();
97   return expected_stream.str();
98 }
99 
100 template <size_t N>
BuildActual(const BytecodeExpectationsPrinter & printer,const char * (& snippet_list)[N],const char * prologue=nullptr,const char * epilogue=nullptr)101 std::string BuildActual(const BytecodeExpectationsPrinter& printer,
102                         const char* (&snippet_list)[N],
103                         const char* prologue = nullptr,
104                         const char* epilogue = nullptr) {
105   std::ostringstream actual_stream;
106   for (const char* snippet : snippet_list) {
107     std::string source_code;
108     if (prologue) source_code += prologue;
109     source_code += snippet;
110     if (epilogue) source_code += epilogue;
111     printer.PrintExpectation(actual_stream, source_code);
112   }
113   return actual_stream.str();
114 }
115 
CompareTexts(const std::string & generated,const std::string & expected)116 bool CompareTexts(const std::string& generated, const std::string& expected) {
117   std::istringstream generated_stream(generated);
118   std::istringstream expected_stream(expected);
119   std::string generated_line;
120   std::string expected_line;
121   // Line number does not include golden file header.
122   int line_number = 0;
123 
124   do {
125     std::getline(generated_stream, generated_line);
126     std::getline(expected_stream, expected_line);
127 
128     if (!generated_stream.good() && !expected_stream.good()) {
129       return true;
130     }
131 
132     if (!generated_stream.good()) {
133       std::cerr << "Expected has extra lines after line " << line_number
134                 << "\n";
135       std::cerr << "  Expected: '" << expected_line << "'\n";
136       return false;
137     } else if (!expected_stream.good()) {
138       std::cerr << "Generated has extra lines after line " << line_number
139                 << "\n";
140       std::cerr << "  Generated: '" << generated_line << "'\n";
141       return false;
142     }
143 
144     if (generated_line != expected_line) {
145       std::cerr << "Inputs differ at line " << line_number << "\n";
146       std::cerr << "  Generated: '" << generated_line << "'\n";
147       std::cerr << "  Expected:  '" << expected_line << "'\n";
148       return false;
149     }
150     line_number++;
151   } while (true);
152 }
153 
154 using ConstantPoolType = BytecodeExpectationsPrinter::ConstantPoolType;
155 
TEST(PrimitiveReturnStatements)156 TEST(PrimitiveReturnStatements) {
157   InitializedIgnitionHandleScope scope;
158   BytecodeExpectationsPrinter printer(CcTest::isolate(),
159                                       ConstantPoolType::kNumber);
160   const char* snippets[] = {
161       "",
162 
163       "return;\n",
164 
165       "return null;\n",
166 
167       "return true;\n",
168 
169       "return false;\n",
170 
171       "return 0;\n",
172 
173       "return +1;\n",
174 
175       "return -1;\n",
176 
177       "return +127;\n",
178 
179       "return -128;\n",
180   };
181 
182   CHECK(CompareTexts(BuildActual(printer, snippets),
183                      LoadGolden("PrimitiveReturnStatements.golden")));
184 }
185 
TEST(PrimitiveExpressions)186 TEST(PrimitiveExpressions) {
187   InitializedIgnitionHandleScope scope;
188   BytecodeExpectationsPrinter printer(CcTest::isolate(),
189                                       ConstantPoolType::kNumber);
190   const char* snippets[] = {
191       "var x = 0; return x;\n",
192 
193       "var x = 0; return x + 3;\n",
194 
195       "var x = 0; return x - 3;\n",
196 
197       "var x = 4; return x * 3;\n",
198 
199       "var x = 4; return x / 3;\n",
200 
201       "var x = 4; return x % 3;\n",
202 
203       "var x = 1; return x | 2;\n",
204 
205       "var x = 1; return x ^ 2;\n",
206 
207       "var x = 1; return x & 2;\n",
208 
209       "var x = 10; return x << 3;\n",
210 
211       "var x = 10; return x >> 3;\n",
212 
213       "var x = 10; return x >>> 3;\n",
214 
215       "var x = 0; return (x, 3);\n",
216   };
217 
218   CHECK(CompareTexts(BuildActual(printer, snippets),
219                      LoadGolden("PrimitiveExpressions.golden")));
220 }
221 
TEST(LogicalExpressions)222 TEST(LogicalExpressions) {
223   InitializedIgnitionHandleScope scope;
224   BytecodeExpectationsPrinter printer(CcTest::isolate(),
225                                       ConstantPoolType::kNumber);
226   const char* snippets[] = {
227       "var x = 0; return x || 3;\n",
228 
229       "var x = 0; return (x == 1) || 3;\n",
230 
231       "var x = 0; return x && 3;\n",
232 
233       "var x = 0; return (x == 0) && 3;\n",
234 
235       "var x = 0; return x || (1, 2, 3);\n",
236 
237       "var a = 2, b = 3, c = 4; return a || (a, b, a, b, c = 5, 3);\n",
238 
239       "var x = 1; var a = 2, b = 3; return x || ("  //
240       REPEAT_32("\n  a = 1, b = 2, ")               //
241       "3);\n",
242 
243       "var x = 0; var a = 2, b = 3; return x && ("  //
244       REPEAT_32("\n  a = 1, b = 2, ")               //
245       "3);\n",
246 
247       "var x = 1; var a = 2, b = 3; return (x > 3) || ("  //
248       REPEAT_32("\n  a = 1, b = 2, ")                     //
249       "3);\n",
250 
251       "var x = 0; var a = 2, b = 3; return (x < 5) && ("  //
252       REPEAT_32("\n  a = 1, b = 2, ")                     //
253       "3);\n",
254 
255       "return 0 && 3;\n",
256 
257       "return 1 || 3;\n",
258 
259       "var x = 1; return x && 3 || 0, 1;\n",
260   };
261 
262   CHECK(CompareTexts(BuildActual(printer, snippets),
263                      LoadGolden("LogicalExpressions.golden")));
264 }
265 
TEST(Parameters)266 TEST(Parameters) {
267   InitializedIgnitionHandleScope scope;
268   BytecodeExpectationsPrinter printer(CcTest::isolate(),
269                                       ConstantPoolType::kNumber);
270   printer.set_wrap(false);
271   printer.set_test_function_name("f");
272 
273   const char* snippets[] = {
274       "function f() { return this; }",
275 
276       "function f(arg1) { return arg1; }",
277 
278       "function f(arg1) { return this; }",
279 
280       "function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return arg4; }",
281 
282       "function f(arg1, arg2, arg3, arg4, arg5, arg6, arg7) { return this; }",
283 
284       "function f(arg1) { arg1 = 1; }",
285 
286       "function f(arg1, arg2, arg3, arg4) { arg2 = 1; }",
287   };
288 
289   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
290                      LoadGolden("Parameters.golden")));
291 }
292 
TEST(IntegerConstants)293 TEST(IntegerConstants) {
294   InitializedIgnitionHandleScope scope;
295   BytecodeExpectationsPrinter printer(CcTest::isolate(),
296                                       ConstantPoolType::kNumber);
297   const char* snippets[] = {
298       "return 12345678;\n",
299 
300       "var a = 1234; return 5678;\n",
301 
302       "var a = 1234; return 1234;\n",
303   };
304 
305   CHECK(CompareTexts(BuildActual(printer, snippets),
306                      LoadGolden("IntegerConstants.golden")));
307 }
308 
TEST(HeapNumberConstants)309 TEST(HeapNumberConstants) {
310   InitializedIgnitionHandleScope scope;
311   BytecodeExpectationsPrinter printer(CcTest::isolate(),
312                                       ConstantPoolType::kNumber);
313   const char* snippets[] = {
314       "return 1.2;\n",
315 
316       "var a = 1.2; return 2.6;\n",
317 
318       "var a = 3.14; return 3.14;\n",
319 
320       "var a;"                    //
321       REPEAT_256("\na = 1.414;")  //
322       " a = 3.14;\n",
323   };
324 
325   CHECK(CompareTexts(BuildActual(printer, snippets),
326                      LoadGolden("HeapNumberConstants.golden")));
327 }
328 
TEST(StringConstants)329 TEST(StringConstants) {
330   InitializedIgnitionHandleScope scope;
331   BytecodeExpectationsPrinter printer(CcTest::isolate(),
332                                       ConstantPoolType::kString);
333   const char* snippets[] = {
334       "return \"This is a string\";\n",
335 
336       "var a = \"First string\"; return \"Second string\";\n",
337 
338       "var a = \"Same string\"; return \"Same string\";\n",
339   };
340 
341   CHECK(CompareTexts(BuildActual(printer, snippets),
342                      LoadGolden("StringConstants.golden")));
343 }
344 
TEST(PropertyLoads)345 TEST(PropertyLoads) {
346   InitializedIgnitionHandleScope scope;
347   BytecodeExpectationsPrinter printer(CcTest::isolate(),
348                                       ConstantPoolType::kString);
349   printer.set_wrap(false);
350   printer.set_test_function_name("f");
351 
352   const char* snippets[] = {
353     "function f(a) { return a.name; }\n"
354     "f({name : \"test\"});\n",
355 
356     "function f(a) { return a[\"key\"]; }\n"
357     "f({key : \"test\"});\n",
358 
359     "function f(a) { return a[100]; }\n"
360     "f({100 : \"test\"});\n",
361 
362     "function f(a, b) { return a[b]; }\n"
363     "f({arg : \"test\"}, \"arg\");\n",
364 
365     "function f(a) { var b = a.name; return a[-124]; }\n"
366     "f({\"-124\" : \"test\", name : 123 })",
367 
368     "function f(a) {\n"
369     "  var b;\n"
370     "  b = a.name;\n"
371     REPEAT_127("  b = a.name;\n")
372     "  return a.name;\n"
373     "}\n"
374     "f({name : \"test\"})\n",
375 
376     "function f(a, b) {\n"
377     "  var c;\n"
378     "  c = a[b];\n"
379     REPEAT_127("  c = a[b];\n")
380     "  return a[b];\n"
381     "}\n"
382     "f({name : \"test\"}, \"name\")\n",
383   };
384 
385   CHECK(CompareTexts(BuildActual(printer, snippets),
386                      LoadGolden("PropertyLoads.golden")));
387 }
388 
TEST(PropertyStores)389 TEST(PropertyStores) {
390   InitializedIgnitionHandleScope scope;
391   BytecodeExpectationsPrinter printer(CcTest::isolate(),
392                                       ConstantPoolType::kString);
393   printer.set_wrap(false);
394   printer.set_test_function_name("f");
395 
396   const char* snippets[] = {
397     "function f(a) { a.name = \"val\"; }\n"
398     "f({name : \"test\"})",
399 
400     "function f(a) { a[\"key\"] = \"val\"; }\n"
401     "f({key : \"test\"})",
402 
403     "function f(a) { a[100] = \"val\"; }\n"
404     "f({100 : \"test\"})",
405 
406     "function f(a, b) { a[b] = \"val\"; }\n"
407     "f({arg : \"test\"}, \"arg\")",
408 
409     "function f(a) { a.name = a[-124]; }\n"
410     "f({\"-124\" : \"test\", name : 123 })",
411 
412     "function f(a) { \"use strict\"; a.name = \"val\"; }\n"
413     "f({name : \"test\"})",
414 
415     "function f(a, b) { \"use strict\"; a[b] = \"val\"; }\n"
416     "f({arg : \"test\"}, \"arg\")",
417 
418     "function f(a) {\n"
419     "  a.name = 1;\n"
420     REPEAT_127("  a.name = 1;\n")
421     "  a.name = 2;\n"
422     "}\n"
423     "f({name : \"test\"})\n",
424 
425     "function f(a) {\n"
426     " 'use strict';\n"
427     "  a.name = 1;\n"
428     REPEAT_127("  a.name = 1;\n")
429     "  a.name = 2;\n"
430     "}\n"
431     "f({name : \"test\"})\n",
432 
433     "function f(a, b) {\n"
434     "  a[b] = 1;\n"
435     REPEAT_127("  a[b] = 1;\n")
436     "  a[b] = 2;\n"
437     "}\n"
438     "f({name : \"test\"})\n",
439 
440     "function f(a, b) {\n"
441     "  'use strict';\n"
442     "  a[b] = 1;\n"
443     REPEAT_127("  a[b] = 1;\n")
444     "  a[b] = 2;\n"
445     "}\n"
446     "f({name : \"test\"})\n",
447   };
448 
449   CHECK(CompareTexts(BuildActual(printer, snippets),
450                      LoadGolden("PropertyStores.golden")));
451 }
452 
453 #define FUNC_ARG "new (function Obj() { this.func = function() { return; }})()"
454 
TEST(PropertyCall)455 TEST(PropertyCall) {
456   InitializedIgnitionHandleScope scope;
457   BytecodeExpectationsPrinter printer(CcTest::isolate(),
458                                       ConstantPoolType::kString);
459   printer.set_wrap(false);
460   printer.set_test_function_name("f");
461 
462   const char* snippets[] = {
463       "function f(a) { return a.func(); }\n"
464       "f(" FUNC_ARG ")",
465 
466       "function f(a, b, c) { return a.func(b, c); }\n"
467       "f(" FUNC_ARG ", 1, 2)",
468 
469       "function f(a, b) { return a.func(b + b, b); }\n"
470       "f(" FUNC_ARG ", 1)",
471 
472       "function f(a) {\n"
473       " a.func;\n"              //
474       REPEAT_127(" a.func;\n")  //
475       " return a.func(); }\n"
476       "f(" FUNC_ARG ")",
477   };
478 
479   CHECK(CompareTexts(BuildActual(printer, snippets),
480                      LoadGolden("PropertyCall.golden")));
481 }
482 
TEST(LoadGlobal)483 TEST(LoadGlobal) {
484   InitializedIgnitionHandleScope scope;
485   BytecodeExpectationsPrinter printer(CcTest::isolate(),
486                                       ConstantPoolType::kString);
487   printer.set_wrap(false);
488   printer.set_test_function_name("f");
489 
490   const char* snippets[] = {
491     "var a = 1;\n"
492     "function f() { return a; }\n"
493     "f()",
494 
495     "function t() { }\n"
496     "function f() { return t; }\n"
497     "f()",
498 
499     "a = 1;\n"
500     "function f() { return a; }\n"
501     "f()",
502 
503     "a = 1;\n"
504     "function f(b) {\n"
505     "  b.name;\n"
506     REPEAT_127("  b.name;\n")
507     "  return a;\n"
508     "}\n"
509     "f({name: 1});\n",
510   };
511 
512   CHECK(CompareTexts(BuildActual(printer, snippets),
513                      LoadGolden("LoadGlobal.golden")));
514 }
515 
TEST(StoreGlobal)516 TEST(StoreGlobal) {
517   InitializedIgnitionHandleScope scope;
518   BytecodeExpectationsPrinter printer(CcTest::isolate(),
519                                       ConstantPoolType::kString);
520   printer.set_wrap(false);
521   printer.set_test_function_name("f");
522 
523   const char* snippets[] = {
524     "var a = 1;\n"
525     "function f() { a = 2; }\n"
526     "f();\n",
527 
528     "var a = \"test\"; function f(b) { a = b; }\n"
529     "f(\"global\");\n",
530 
531     "'use strict'; var a = 1;\n"
532     "function f() { a = 2; }\n"
533     "f();\n",
534 
535     "a = 1;\n"
536     "function f() { a = 2; }\n"
537     "f();\n",
538 
539     "a = 1;\n"
540     "function f(b) {\n"
541     "  b.name;\n"
542     REPEAT_127("  b.name;\n")
543     "  a = 2;\n"
544     "}\n"
545     "f({name: 1});\n",
546 
547     "a = 1;\n"
548     "function f(b) {\n"
549     "  'use strict';\n"
550     "  b.name;\n"
551     REPEAT_127("  b.name;\n")
552     "  a = 2;\n"
553     "}\n"
554     "f({name: 1});\n",
555   };
556 
557   CHECK(CompareTexts(BuildActual(printer, snippets),
558                      LoadGolden("StoreGlobal.golden")));
559 }
560 
TEST(CallGlobal)561 TEST(CallGlobal) {
562   InitializedIgnitionHandleScope scope;
563   BytecodeExpectationsPrinter printer(CcTest::isolate(),
564                                       ConstantPoolType::kString);
565   printer.set_wrap(false);
566   printer.set_test_function_name("f");
567 
568   const char* snippets[] = {
569       "function t() { }\n"
570       "function f() { return t(); }\n"
571       "f();\n",
572 
573       "function t(a, b, c) { }\n"
574       "function f() { return t(1, 2, 3); }\n"
575       "f();\n",
576   };
577 
578   CHECK(CompareTexts(BuildActual(printer, snippets),
579                      LoadGolden("CallGlobal.golden")));
580 }
581 
TEST(CallRuntime)582 TEST(CallRuntime) {
583   InitializedIgnitionHandleScope scope;
584   BytecodeExpectationsPrinter printer(CcTest::isolate(),
585                                       ConstantPoolType::kMixed);
586   printer.set_wrap(false);
587   printer.set_test_function_name("f");
588 
589   const char* snippets[] = {
590       "function f() { %TheHole() }\n"
591       "f();\n",
592 
593       "function f(a) { return %IsArray(a) }\n"
594       "f(undefined);\n",
595 
596       "function f() { return %Add(1, 2) }\n"
597       "f();\n",
598 
599       "function f() { return %spread_iterable([1]) }\n"
600       "f();\n",
601   };
602 
603   CHECK(CompareTexts(BuildActual(printer, snippets),
604                      LoadGolden("CallRuntime.golden")));
605 }
606 
TEST(IfConditions)607 TEST(IfConditions) {
608   InitializedIgnitionHandleScope scope;
609   BytecodeExpectationsPrinter printer(CcTest::isolate(),
610                                       ConstantPoolType::kMixed);
611   printer.set_wrap(false);
612   printer.set_test_function_name("f");
613 
614   const char* snippets[] = {
615     "function f() {\n"
616     "  if (0) {\n"
617     "    return 1;\n"
618     "  } else {\n"
619     "    return -1;\n"
620     "  }\n"
621     "};\n"
622     "f();\n",
623 
624     "function f() {\n"
625     "  if ('lucky') {\n"
626     "    return 1;\n"
627     "  } else {\n"
628     "    return -1;\n"
629     "  }\n"
630     "};\n"
631     "f();\n",
632 
633     "function f() {\n"
634     "  if (false) {\n"
635     "    return 1;\n"
636     "  } else {\n"
637     "    return -1;\n"
638     "  }\n"
639     "};\n"
640     "f();\n",
641 
642     "function f() {\n"
643     "  if (false) {\n"
644     "    return 1;\n"
645     "  }\n"
646     "};\n"
647     "f();\n",
648 
649     "function f() {\n"
650     "  var a = 1;\n"
651     "  if (a) {\n"
652     "    a += 1;\n"
653     "  } else {\n"
654     "    return 2;\n"
655     "  }\n"
656     "};\n"
657     "f();\n",
658 
659     "function f(a) {\n"
660     "  if (a <= 0) {\n"
661     "    return 200;\n"
662     "  } else {\n"
663     "    return -200;\n"
664     "  }\n"
665     "};\n"
666     "f(99);\n",
667 
668     "function f(a, b) { if (a in b) { return 200; } }"
669     "f('prop', { prop: 'yes'});\n",
670 
671     "function f(z) { var a = 0; var b = 0; if (a === 0.01) {\n"
672     REPEAT_64("  b = a; a = b;\n")
673     " return 200; } else { return -200; } } f(0.001);\n",
674 
675     "function f() {\n"
676     "  var a = 0; var b = 0;\n"
677     "  if (a) {\n"
678     REPEAT_64("  b = a; a = b;\n")
679     "  return 200; } else { return -200; }\n"
680     "};\n"
681     "f();\n",
682 
683     "function f(a, b) {\n"
684     "  if (a == b) { return 1; }\n"
685     "  if (a === b) { return 1; }\n"
686     "  if (a < b) { return 1; }\n"
687     "  if (a > b) { return 1; }\n"
688     "  if (a <= b) { return 1; }\n"
689     "  if (a >= b) { return 1; }\n"
690     "  if (a in b) { return 1; }\n"
691     "  if (a instanceof b) { return 1; }\n"
692     "  return 0;\n"
693     "}\n"
694     "f(1, 1);\n",
695 
696     "function f() {\n"
697     "  var a = 0;\n"
698     "  if (a) {\n"
699     "    return 20;\n"
700     "  } else {\n"
701     "    return -20;\n"
702     "  }\n"
703     "};\n"
704     "f();\n",
705   };
706 
707   CHECK(CompareTexts(BuildActual(printer, snippets),
708                      LoadGolden("IfConditions.golden")));
709 }
710 
TEST(DeclareGlobals)711 TEST(DeclareGlobals) {
712   InitializedIgnitionHandleScope scope;
713   BytecodeExpectationsPrinter printer(CcTest::isolate(),
714                                       ConstantPoolType::kMixed);
715   printer.set_wrap(false);
716   printer.set_test_function_name("f");
717   printer.set_execute(false);
718   printer.set_top_level(true);
719 
720   const char* snippets[] = {
721       "var a = 1;\n",
722 
723       "function f() {}\n",
724 
725       "var a = 1;\n"
726       "a=2;\n",
727 
728       "function f() {}\n"
729       "f();\n",
730   };
731 
732   CHECK(CompareTexts(BuildActual(printer, snippets),
733                      LoadGolden("DeclareGlobals.golden")));
734 }
735 
TEST(BreakableBlocks)736 TEST(BreakableBlocks) {
737   InitializedIgnitionHandleScope scope;
738   BytecodeExpectationsPrinter printer(CcTest::isolate(),
739                                       ConstantPoolType::kMixed);
740 
741   const char* snippets[] = {
742       "var x = 0;\n"
743       "label: {\n"
744       "  x = x + 1;\n"
745       "  break label;\n"
746       "  x = x + 1;\n"
747       "}\n"
748       "return x;\n",
749 
750       "var sum = 0;\n"
751       "outer: {\n"
752       "  for (var x = 0; x < 10; ++x) {\n"
753       "    for (var y = 0; y < 3; ++y) {\n"
754       "      ++sum;\n"
755       "      if (x + y == 12) { break outer; }\n"
756       "    }\n"
757       "  }\n"
758       "}\n"
759       "return sum;\n",
760 
761       "outer: {\n"
762       "  let y = 10;\n"
763       "  function f() { return y; }\n"
764       "  break outer;\n"
765       "}\n",
766 
767       "let x = 1;\n"
768       "outer: {\n"
769       "  inner: {\n"
770       "   let y = 2;\n"
771       "    function f() { return x + y; }\n"
772       "    if (y) break outer;\n"
773       "    y = 3;\n"
774       "  }\n"
775       "}\n"
776       "x = 4;\n",
777   };
778 
779   CHECK(CompareTexts(BuildActual(printer, snippets),
780                      LoadGolden("BreakableBlocks.golden")));
781 }
782 
TEST(BasicLoops)783 TEST(BasicLoops) {
784   InitializedIgnitionHandleScope scope;
785   BytecodeExpectationsPrinter printer(CcTest::isolate(),
786                                       ConstantPoolType::kMixed);
787   const char* snippets[] = {
788       "var x = 0;\n"
789       "while (false) { x = 99; break; continue; }\n"
790       "return x;\n",
791 
792       "var x = 0;\n"
793       "while (false) {\n"
794       "  x = x + 1;\n"
795       "};\n"
796       "return x;\n",
797 
798       "var x = 0;\n"
799       "var y = 1;\n"
800       "while (x < 10) {\n"
801       "  y = y * 12;\n"
802       "  x = x + 1;\n"
803       "  if (x == 3) continue;\n"
804       "  if (x == 4) break;\n"
805       "}\n"
806       "return y;\n",
807 
808       "var i = 0;\n"
809       "while (true) {\n"
810       "  if (i < 0) continue;\n"
811       "  if (i == 3) break;\n"
812       "  if (i == 4) break;\n"
813       "  if (i == 10) continue;\n"
814       "  if (i == 5) break;\n"
815       "  i = i + 1;\n"
816       "}\n"
817       "return i;\n",
818 
819       "var i = 0;\n"
820       "while (true) {\n"
821       "  while (i < 3) {\n"
822       "    if (i == 2) break;\n"
823       "    i = i + 1;\n"
824       "  }\n"
825       "  i = i + 1;\n"
826       "  break;\n"
827       "}\n"
828       "return i;\n",
829 
830       "var x = 10;\n"
831       "var y = 1;\n"
832       "while (x) {\n"
833       "  y = y * 12;\n"
834       "  x = x - 1;\n"
835       "}\n"
836       "return y;\n",
837 
838       "var x = 0; var y = 1;\n"
839       "do {\n"
840       "  y = y * 10;\n"
841       "  if (x == 5) break;\n"
842       "  if (x == 6) continue;\n"
843       "  x = x + 1;\n"
844       "} while (x < 10);\n"
845       "return y;\n",
846 
847       "var x = 10;\n"
848       "var y = 1;\n"
849       "do {\n"
850       "  y = y * 12;\n"
851       "  x = x - 1;\n"
852       "} while (x);\n"
853       "return y;\n",
854 
855       "var x = 0; var y = 1;\n"
856       "do {\n"
857       "  y = y * 10;\n"
858       "  if (x == 5) break;\n"
859       "  x = x + 1;\n"
860       "  if (x == 6) continue;\n"
861       "} while (false);\n"
862       "return y;\n",
863 
864       "var x = 0; var y = 1;\n"
865       "do {\n"
866       "  y = y * 10;\n"
867       "  if (x == 5) break;\n"
868       "  x = x + 1;\n"
869       "  if (x == 6) continue;\n"
870       "} while (true);\n"
871       "return y;\n",
872 
873       "var x = 0;\n"
874       "for (;;) {\n"
875       "  if (x == 1) break;\n"
876       "  if (x == 2) continue;\n"
877       "  x = x + 1;\n"
878       "}\n",
879 
880       "for (var x = 0;;) {\n"
881       "  if (x == 1) break;\n"
882       "  if (x == 2) continue;\n"
883       "  x = x + 1;\n"
884       "}\n",
885 
886       "var x = 0;\n"
887       "for (;; x = x + 1) {\n"
888       "  if (x == 1) break;\n"
889       "  if (x == 2) continue;\n"
890       "}\n",
891 
892       "for (var x = 0;; x = x + 1) {\n"
893       "  if (x == 1) break;\n"
894       "  if (x == 2) continue;\n"
895       "}\n",
896 
897       "var u = 0;\n"
898       "for (var i = 0; i < 100; i = i + 1) {\n"
899       "  u = u + 1;\n"
900       "  continue;\n"
901       "}\n",
902 
903       "var y = 1;\n"
904       "for (var x = 10; x; --x) {\n"
905       "  y = y * 12;\n"
906       "}\n"
907       "return y;\n",
908 
909       "var x = 0;\n"
910       "for (var i = 0; false; i++) {\n"
911       "  x = x + 1;\n"
912       "};\n"
913       "return x;\n",
914 
915       "var x = 0;\n"
916       "for (var i = 0; true; ++i) {\n"
917       "  x = x + 1;\n"
918       "  if (x == 20) break;\n"
919       "};\n"
920       "return x;\n",
921 
922       "var a = 0;\n"
923       "while (a) {\n"
924       "  { \n"
925       "   let z = 1;\n"
926       "   function f() { z = 2; }\n"
927       "   if (z) continue;\n"
928       "   z++;\n"
929       "  }\n"
930       "}\n",
931   };
932 
933   CHECK(CompareTexts(BuildActual(printer, snippets),
934                      LoadGolden("BasicLoops.golden")));
935 }
936 
TEST(JumpsRequiringConstantWideOperands)937 TEST(JumpsRequiringConstantWideOperands) {
938   InitializedIgnitionHandleScope scope;
939   BytecodeExpectationsPrinter printer(CcTest::isolate(),
940                                       ConstantPoolType::kNumber);
941   const char* snippets[] = {
942     REPEAT_256("var x = 0.1;\n")
943     REPEAT_32("var x = 0.2;\n")
944     REPEAT_16("var x = 0.3;\n")
945     REPEAT_8("var x = 0.4;\n")
946     "for (var i = 0; i < 3; i++) {\n"
947     "  if (i == 1) continue;\n"
948     "  if (i == 2) break;\n"
949     "}\n"
950     "return 3;\n",
951   };
952 
953   CHECK(CompareTexts(BuildActual(printer, snippets),
954                      LoadGolden("JumpsRequiringConstantWideOperands.golden")));
955 }
956 
TEST(UnaryOperators)957 TEST(UnaryOperators) {
958   InitializedIgnitionHandleScope scope;
959   BytecodeExpectationsPrinter printer(CcTest::isolate(),
960                                       ConstantPoolType::kNumber);
961   const char* snippets[] = {
962       "var x = 0;\n"
963       "while (x != 10) {\n"
964       "  x = x + 10;\n"
965       "}\n"
966       "return x;\n",
967 
968       "var x = false;\n"
969       "do {\n"
970       "  x = !x;\n"
971       "} while(x == false);\n"
972       "return x;\n",
973 
974       "var x = 101;\n"
975       "return void(x * 3);\n",
976 
977       "var x = 1234;\n"
978       "var y = void (x * x - 1);\n"
979       "return y;\n",
980 
981       "var x = 13;\n"
982       "return ~x;\n",
983 
984       "var x = 13;\n"
985       "return +x;\n",
986 
987       "var x = 13;\n"
988       "return -x;\n",
989   };
990 
991   CHECK(CompareTexts(BuildActual(printer, snippets),
992                      LoadGolden("UnaryOperators.golden")));
993 }
994 
TEST(Typeof)995 TEST(Typeof) {
996   InitializedIgnitionHandleScope scope;
997   BytecodeExpectationsPrinter printer(CcTest::isolate(),
998                                       ConstantPoolType::kString);
999   printer.set_wrap(false);
1000   printer.set_test_function_name("f");
1001 
1002   const char* snippets[] = {
1003       "function f() {\n"
1004       " var x = 13;\n"
1005       " return typeof(x);\n"
1006       "};",
1007 
1008       "var x = 13;\n"
1009       "function f() {\n"
1010       " return typeof(x);\n"
1011       "};",
1012   };
1013 
1014   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1015                      LoadGolden("Typeof.golden")));
1016 }
1017 
TEST(Delete)1018 TEST(Delete) {
1019   InitializedIgnitionHandleScope scope;
1020   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1021                                       ConstantPoolType::kMixed);
1022 
1023   const char* snippets[] = {
1024       "var a = {x:13, y:14}; return delete a.x;\n",
1025 
1026       "'use strict'; var a = {x:13, y:14}; return delete a.x;\n",
1027 
1028       "var a = {1:13, 2:14}; return delete a[2];\n",
1029 
1030       "var a = 10; return delete a;\n",
1031 
1032       "'use strict';\n"
1033       "var a = {1:10};\n"
1034       "(function f1() {return a;});\n"
1035       "return delete a[1];\n",
1036 
1037       "return delete 'test';\n",
1038   };
1039 
1040   CHECK(CompareTexts(BuildActual(printer, snippets),
1041                      LoadGolden("Delete.golden")));
1042 }
1043 
TEST(GlobalDelete)1044 TEST(GlobalDelete) {
1045   InitializedIgnitionHandleScope scope;
1046   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1047                                       ConstantPoolType::kMixed);
1048   printer.set_wrap(false);
1049   printer.set_test_function_name("f");
1050 
1051   const char* snippets[] = {
1052       "var a = {x:13, y:14};\n"
1053       "function f() {\n"
1054       "  return delete a.x;\n"
1055       "};\n"
1056       "f();\n",
1057 
1058       "a = {1:13, 2:14};\n"
1059       "function f() {\n"
1060       "  'use strict';\n"
1061       "  return delete a[1];\n"
1062       "};\n"
1063       "f();\n",
1064 
1065       "var a = {x:13, y:14};\n"
1066       "function f() {\n"
1067       "  return delete a;\n"
1068       "};\n"
1069       "f();\n",
1070 
1071       "b = 30;\n"
1072       "function f() {\n"
1073       "  return delete b;\n"
1074       "};\n"
1075       "f();\n",
1076   };
1077 
1078   CHECK(CompareTexts(BuildActual(printer, snippets),
1079                      LoadGolden("GlobalDelete.golden")));
1080 }
1081 
TEST(FunctionLiterals)1082 TEST(FunctionLiterals) {
1083   InitializedIgnitionHandleScope scope;
1084   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1085                                       ConstantPoolType::kMixed);
1086 
1087   const char* snippets[] = {
1088       "return function(){ }\n",
1089 
1090       "return (function(){ })()\n",
1091 
1092       "return (function(x){ return x; })(1)\n",
1093   };
1094 
1095   CHECK(CompareTexts(BuildActual(printer, snippets),
1096                      LoadGolden("FunctionLiterals.golden")));
1097 }
1098 
TEST(RegExpLiterals)1099 TEST(RegExpLiterals) {
1100   InitializedIgnitionHandleScope scope;
1101   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1102                                       ConstantPoolType::kString);
1103 
1104   const char* snippets[] = {
1105       "return /ab+d/;\n",
1106 
1107       "return /(\\w+)\\s(\\w+)/i;\n",
1108 
1109       "return /ab+d/.exec('abdd');\n",
1110   };
1111 
1112   CHECK(CompareTexts(BuildActual(printer, snippets),
1113                      LoadGolden("RegExpLiterals.golden")));
1114 }
1115 
TEST(RegExpLiteralsWide)1116 TEST(RegExpLiteralsWide) {
1117   InitializedIgnitionHandleScope scope;
1118   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1119                                       ConstantPoolType::kMixed);
1120 
1121   const char* snippets[] = {
1122       "var a;"                   //
1123       REPEAT_256("\na = 1.23;")  //
1124       "\nreturn /ab+d/;\n",
1125   };
1126 
1127   CHECK(CompareTexts(BuildActual(printer, snippets),
1128                      LoadGolden("RegExpLiteralsWide.golden")));
1129 }
1130 
TEST(ArrayLiterals)1131 TEST(ArrayLiterals) {
1132   InitializedIgnitionHandleScope scope;
1133   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1134                                       ConstantPoolType::kMixed);
1135 
1136   const char* snippets[] = {
1137       "return [ 1, 2 ];\n",
1138 
1139       "var a = 1; return [ a, a + 1 ];\n",
1140 
1141       "return [ [ 1, 2 ], [ 3 ] ];\n",
1142 
1143       "var a = 1; return [ [ a, 2 ], [ a + 2 ] ];\n",
1144   };
1145 
1146   CHECK(CompareTexts(BuildActual(printer, snippets),
1147                      LoadGolden("ArrayLiterals.golden")));
1148 }
1149 
TEST(ArrayLiteralsWide)1150 TEST(ArrayLiteralsWide) {
1151   InitializedIgnitionHandleScope scope;
1152   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1153                                       ConstantPoolType::kMixed);
1154 
1155   const char* snippets[] = {
1156       "var a;"                   //
1157       REPEAT_256("\na = 1.23;")  //
1158       "\nreturn [ 1 , 2 ];\n",
1159   };
1160 
1161   CHECK(CompareTexts(BuildActual(printer, snippets),
1162                      LoadGolden("ArrayLiteralsWide.golden")));
1163 }
1164 
TEST(ObjectLiterals)1165 TEST(ObjectLiterals) {
1166   InitializedIgnitionHandleScope scope;
1167   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1168                                       ConstantPoolType::kMixed);
1169 
1170   const char* snippets[] = {
1171       "return { };\n",
1172 
1173       "return { name: 'string', val: 9.2 };\n",
1174 
1175       "var a = 1; return { name: 'string', val: a };\n",
1176 
1177       "var a = 1; return { val: a, val: a + 1 };\n",
1178 
1179       "return { func: function() { } };\n",
1180 
1181       "return { func(a) { return a; } };\n",
1182 
1183       "return { get a() { return 2; } };\n",
1184 
1185       "return { get a() { return this.x; }, set a(val) { this.x = val } };\n",
1186 
1187       "return { set b(val) { this.y = val } };\n",
1188 
1189       "var a = 1; return { 1: a };\n",
1190 
1191       "return { __proto__: null };\n",
1192 
1193       "var a = 'test'; return { [a]: 1 };\n",
1194 
1195       "var a = 'test'; return { val: a, [a]: 1 };\n",
1196 
1197       "var a = 'test'; return { [a]: 1, __proto__: {} };\n",
1198 
1199       "var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} };\n",
1200   };
1201 
1202   CHECK(CompareTexts(BuildActual(printer, snippets),
1203                      LoadGolden("ObjectLiterals.golden")));
1204 }
1205 
TEST(ObjectLiteralsWide)1206 TEST(ObjectLiteralsWide) {
1207   InitializedIgnitionHandleScope scope;
1208   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1209                                       ConstantPoolType::kMixed);
1210   const char* snippets[] = {
1211       "var a;"                   //
1212       REPEAT_256("\na = 1.23;")  //
1213       "\nreturn { name: 'string', val: 9.2 };\n",
1214   };
1215 
1216   CHECK(CompareTexts(BuildActual(printer, snippets),
1217                      LoadGolden("ObjectLiteralsWide.golden")));
1218 }
1219 
TEST(TopLevelObjectLiterals)1220 TEST(TopLevelObjectLiterals) {
1221   InitializedIgnitionHandleScope scope;
1222   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1223                                       ConstantPoolType::kMixed);
1224   printer.set_wrap(false);
1225   printer.set_test_function_name("f");
1226   printer.set_execute(false);
1227   printer.set_top_level(true);
1228 
1229   const char* snippets[] = {
1230       "var a = { func: function() { } };\n",
1231   };
1232 
1233   CHECK(CompareTexts(BuildActual(printer, snippets),
1234                      LoadGolden("TopLevelObjectLiterals.golden")));
1235 }
1236 
TEST(TryCatch)1237 TEST(TryCatch) {
1238   InitializedIgnitionHandleScope scope;
1239   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1240                                       ConstantPoolType::kString);
1241 
1242   const char* snippets[] = {
1243       "try { return 1; } catch(e) { return 2; }\n",
1244 
1245       "var a;\n"
1246       "try { a = 1 } catch(e1) {};\n"
1247       "try { a = 2 } catch(e2) { a = 3 }\n",
1248   };
1249 
1250   CHECK(CompareTexts(BuildActual(printer, snippets),
1251                      LoadGolden("TryCatch.golden")));
1252 }
1253 
TEST(TryFinally)1254 TEST(TryFinally) {
1255   InitializedIgnitionHandleScope scope;
1256   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1257                                       ConstantPoolType::kString);
1258   const char* snippets[] = {
1259       "var a = 1;\n"
1260       "try { a = 2; } finally { a = 3; }\n",
1261 
1262       "var a = 1;\n"
1263       "try { a = 2; } catch(e) { a = 20 } finally { a = 3; }\n",
1264 
1265       "var a; try {\n"
1266       "  try { a = 1 } catch(e) { a = 2 }\n"
1267       "} catch(e) { a = 20 } finally { a = 3; }\n",
1268   };
1269 
1270   CHECK(CompareTexts(BuildActual(printer, snippets),
1271                      LoadGolden("TryFinally.golden")));
1272 }
1273 
TEST(Throw)1274 TEST(Throw) {
1275   InitializedIgnitionHandleScope scope;
1276   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1277                                       ConstantPoolType::kString);
1278   const char* snippets[] = {
1279       "throw 1;\n",
1280 
1281       "throw 'Error';\n",
1282 
1283       "var a = 1; if (a) { throw 'Error'; };\n",
1284   };
1285 
1286   CHECK(
1287       CompareTexts(BuildActual(printer, snippets), LoadGolden("Throw.golden")));
1288 }
1289 
TEST(CallNew)1290 TEST(CallNew) {
1291   InitializedIgnitionHandleScope scope;
1292   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1293                                       ConstantPoolType::kMixed);
1294   printer.set_wrap(false);
1295   printer.set_test_function_name("f");
1296 
1297   const char* snippets[] = {
1298       "function bar() { this.value = 0; }\n"
1299       "function f() { return new bar(); }\n"
1300       "f();\n",
1301 
1302       "function bar(x) { this.value = 18; this.x = x;}\n"
1303       "function f() { return new bar(3); }\n"
1304       "f();\n",
1305 
1306       "function bar(w, x, y, z) {\n"
1307       "  this.value = 18;\n"
1308       "  this.x = x;\n"
1309       "  this.y = y;\n"
1310       "  this.z = z;\n"
1311       "}\n"
1312       "function f() { return new bar(3, 4, 5); }\n"
1313       "f();\n",
1314   };
1315 
1316   CHECK(CompareTexts(BuildActual(printer, snippets),
1317                      LoadGolden("CallNew.golden")));
1318 }
1319 
TEST(ContextVariables)1320 TEST(ContextVariables) {
1321   // The wide check below relies on MIN_CONTEXT_SLOTS + 3 + 249 == 256, if this
1322   // ever changes, the REPEAT_XXX should be changed to output the correct number
1323   // of unique variables to trigger the wide slot load / store.
1324   STATIC_ASSERT(Context::MIN_CONTEXT_SLOTS + 3 + 249 == 256);
1325 
1326   InitializedIgnitionHandleScope scope;
1327   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1328                                       ConstantPoolType::kMixed);
1329   const char* snippets[] = {
1330     "var a; return function() { a = 1; };\n",
1331 
1332     "var a = 1; return function() { a = 2; };\n",
1333 
1334     "var a = 1; var b = 2; return function() { a = 2; b = 3 };\n",
1335 
1336     "var a; (function() { a = 2; })(); return a;\n",
1337 
1338     "'use strict';\n"
1339     "let a = 1;\n"
1340     "{ let b = 2; return function() { a + b; }; }\n",
1341 
1342     "'use strict';\n"
1343     REPEAT_249_UNIQUE_VARS()
1344     "eval();\n"
1345     "var b = 100;\n"
1346     "return b\n",
1347   };
1348 
1349   CHECK(CompareTexts(BuildActual(printer, snippets),
1350                      LoadGolden("ContextVariables.golden")));
1351 }
1352 
TEST(ContextParameters)1353 TEST(ContextParameters) {
1354   InitializedIgnitionHandleScope scope;
1355   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1356                                       ConstantPoolType::kMixed);
1357   printer.set_wrap(false);
1358   printer.set_test_function_name("f");
1359 
1360   const char* snippets[] = {
1361       "function f(arg1) { return function() { arg1 = 2; }; }",
1362 
1363       "function f(arg1) { var a = function() { arg1 = 2; }; return arg1; }",
1364 
1365       "function f(a1, a2, a3, a4) { return function() { a1 = a3; }; }",
1366 
1367       "function f() { var self = this; return function() { self = 2; }; }",
1368   };
1369 
1370   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1371                      LoadGolden("ContextParameters.golden")));
1372 }
1373 
TEST(OuterContextVariables)1374 TEST(OuterContextVariables) {
1375   InitializedIgnitionHandleScope scope;
1376   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1377                                       ConstantPoolType::kMixed);
1378   printer.set_wrap(false);
1379   printer.set_test_function_name("f");
1380 
1381   const char* snippets[] = {
1382       "function Outer() {\n"
1383       "  var outerVar = 1;\n"
1384       "  function Inner(innerArg) {\n"
1385       "    this.innerFunc = function() { return outerVar * innerArg; }\n"
1386       "  }\n"
1387       "  this.getInnerFunc = function() { return new Inner(1).innerFunc; }\n"
1388       "}\n"
1389       "var f = new Outer().getInnerFunc();",
1390 
1391       "function Outer() {\n"
1392       "  var outerVar = 1;\n"
1393       "  function Inner(innerArg) {\n"
1394       "    this.innerFunc = function() { outerVar = innerArg; }\n"
1395       "  }\n"
1396       "  this.getInnerFunc = function() { return new Inner(1).innerFunc; }\n"
1397       "}\n"
1398       "var f = new Outer().getInnerFunc();",
1399   };
1400 
1401   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1402                      LoadGolden("OuterContextVariables.golden")));
1403 }
1404 
TEST(CountOperators)1405 TEST(CountOperators) {
1406   InitializedIgnitionHandleScope scope;
1407   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1408                                       ConstantPoolType::kMixed);
1409   const char* snippets[] = {
1410       "var a = 1; return ++a;\n",
1411 
1412       "var a = 1; return a++;\n",
1413 
1414       "var a = 1; return --a;\n",
1415 
1416       "var a = 1; return a--;\n",
1417 
1418       "var a = { val: 1 }; return a.val++;\n",
1419 
1420       "var a = { val: 1 }; return --a.val;\n",
1421 
1422       "var name = 'var'; var a = { val: 1 }; return a[name]--;\n",
1423 
1424       "var name = 'var'; var a = { val: 1 }; return ++a[name];\n",
1425 
1426       "var a = 1; var b = function() { return a }; return ++a;\n",
1427 
1428       "var a = 1; var b = function() { return a }; return a--;\n",
1429 
1430       "var idx = 1; var a = [1, 2]; return a[idx++] = 2;\n",
1431   };
1432 
1433   CHECK(CompareTexts(BuildActual(printer, snippets),
1434                      LoadGolden("CountOperators.golden")));
1435 }
1436 
TEST(GlobalCountOperators)1437 TEST(GlobalCountOperators) {
1438   InitializedIgnitionHandleScope scope;
1439   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1440                                       ConstantPoolType::kString);
1441   printer.set_wrap(false);
1442   printer.set_test_function_name("f");
1443 
1444   const char* snippets[] = {
1445       "var global = 1;\n"
1446       "function f() { return ++global; }\n"
1447       "f();\n",
1448 
1449       "var global = 1;\n"
1450       "function f() { return global--; }\n"
1451       "f();\n",
1452 
1453       "unallocated = 1;\n"
1454       "function f() { 'use strict'; return --unallocated; }\n"
1455       "f();\n",
1456 
1457       "unallocated = 1;\n"
1458       "function f() { return unallocated++; }\n"
1459       "f();\n",
1460   };
1461 
1462   CHECK(CompareTexts(BuildActual(printer, snippets),
1463                      LoadGolden("GlobalCountOperators.golden")));
1464 }
1465 
TEST(CompoundExpressions)1466 TEST(CompoundExpressions) {
1467   InitializedIgnitionHandleScope scope;
1468   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1469                                       ConstantPoolType::kMixed);
1470   const char* snippets[] = {
1471       "var a = 1; a += 2;\n",
1472 
1473       "var a = 1; a /= 2;\n",
1474 
1475       "var a = { val: 2 }; a.name *= 2;\n",
1476 
1477       "var a = { 1: 2 }; a[1] ^= 2;\n",
1478 
1479       "var a = 1; (function f() { return a; }); a |= 24;\n",
1480   };
1481 
1482   CHECK(CompareTexts(BuildActual(printer, snippets),
1483                      LoadGolden("CompoundExpressions.golden")));
1484 }
1485 
TEST(GlobalCompoundExpressions)1486 TEST(GlobalCompoundExpressions) {
1487   InitializedIgnitionHandleScope scope;
1488   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1489                                       ConstantPoolType::kString);
1490   printer.set_wrap(false);
1491   printer.set_test_function_name("f");
1492 
1493   const char* snippets[] = {
1494       "var global = 1;\n"
1495       "function f() { return global &= 1; }\n"
1496       "f();\n",
1497 
1498       "unallocated = 1;\n"
1499       "function f() { return unallocated += 1; }\n"
1500       "f();\n",
1501   };
1502 
1503   CHECK(CompareTexts(BuildActual(printer, snippets),
1504                      LoadGolden("GlobalCompoundExpressions.golden")));
1505 }
1506 
TEST(CreateArguments)1507 TEST(CreateArguments) {
1508   InitializedIgnitionHandleScope scope;
1509   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1510                                       ConstantPoolType::kString);
1511   printer.set_wrap(false);
1512   printer.set_test_function_name("f");
1513 
1514   const char* snippets[] = {
1515       "function f() { return arguments; }",
1516 
1517       "function f() { return arguments[0]; }",
1518 
1519       "function f() { 'use strict'; return arguments; }",
1520 
1521       "function f(a) { return arguments[0]; }",
1522 
1523       "function f(a, b, c) { return arguments; }",
1524 
1525       "function f(a, b, c) { 'use strict'; return arguments; }",
1526   };
1527 
1528   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1529                      LoadGolden("CreateArguments.golden")));
1530 }
1531 
TEST(CreateRestParameter)1532 TEST(CreateRestParameter) {
1533   InitializedIgnitionHandleScope scope;
1534   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1535                                       ConstantPoolType::kNumber);
1536   printer.set_wrap(false);
1537   printer.set_test_function_name("f");
1538 
1539   const char* snippets[] = {
1540       "function f(...restArgs) { return restArgs; }",
1541 
1542       "function f(a, ...restArgs) { return restArgs; }",
1543 
1544       "function f(a, ...restArgs) { return restArgs[0]; }",
1545 
1546       "function f(a, ...restArgs) { return restArgs[0] + arguments[0]; }",
1547   };
1548 
1549   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1550                      LoadGolden("CreateRestParameter.golden")));
1551 }
1552 
TEST(ForIn)1553 TEST(ForIn) {
1554   InitializedIgnitionHandleScope scope;
1555   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1556                                       ConstantPoolType::kMixed);
1557   const char* snippets[] = {
1558       "for (var p in null) {}\n",
1559 
1560       "for (var p in undefined) {}\n",
1561 
1562       "for (var p in undefined) {}\n",
1563 
1564       "var x = 'potatoes';\n"
1565       "for (var p in x) { return p; }\n",
1566 
1567       "var x = 0;\n"
1568       "for (var p in [1,2,3]) { x += p; }\n",
1569 
1570       "var x = { 'a': 1, 'b': 2 };\n"
1571       "for (x['a'] in [10, 20, 30]) {\n"
1572       "  if (x['a'] == 10) continue;\n"
1573       "  if (x['a'] == 20) break;\n"
1574       "}\n",
1575 
1576       "var x = [ 10, 11, 12 ] ;\n"
1577       "for (x[0] in [1,2,3]) { return x[3]; }\n",
1578   };
1579 
1580   CHECK(
1581       CompareTexts(BuildActual(printer, snippets), LoadGolden("ForIn.golden")));
1582 }
1583 
TEST(ForOf)1584 TEST(ForOf) {
1585   InitializedIgnitionHandleScope scope;
1586   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1587                                       ConstantPoolType::kMixed);
1588   const char* snippets[] = {
1589       "for (var p of [0, 1, 2]) {}\n",
1590 
1591       "var x = 'potatoes';\n"
1592       "for (var p of x) { return p; }\n",
1593 
1594       "for (var x of [10, 20, 30]) {\n"
1595       "  if (x == 10) continue;\n"
1596       "  if (x == 20) break;\n"
1597       "}\n",
1598 
1599       "var x = { 'a': 1, 'b': 2 };\n"
1600       "for (x['a'] of [1,2,3]) { return x['a']; }\n",
1601   };
1602 
1603   CHECK(
1604       CompareTexts(BuildActual(printer, snippets), LoadGolden("ForOf.golden")));
1605 }
1606 
TEST(Conditional)1607 TEST(Conditional) {
1608   InitializedIgnitionHandleScope scope;
1609   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1610                                       ConstantPoolType::kNumber);
1611   const char* snippets[] = {
1612       "return 1 ? 2 : 3;\n",
1613 
1614       "return 1 ? 2 ? 3 : 4 : 5;\n",
1615   };
1616 
1617   CHECK(CompareTexts(BuildActual(printer, snippets),
1618                      LoadGolden("Conditional.golden")));
1619 }
1620 
TEST(Switch)1621 TEST(Switch) {
1622   InitializedIgnitionHandleScope scope;
1623   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1624                                       ConstantPoolType::kNumber);
1625   const char* snippets[] = {
1626     "var a = 1;\n"
1627     "switch(a) {\n"
1628     " case 1: return 2;\n"
1629     " case 2: return 3;\n"
1630     "}\n",
1631 
1632     "var a = 1;\n"
1633     "switch(a) {\n"
1634     " case 1: a = 2; break;\n"
1635     " case 2: a = 3; break;\n"
1636     "}\n",
1637 
1638     "var a = 1;\n"
1639     "switch(a) {\n"
1640     " case 1: a = 2; // fall-through\n"
1641     " case 2: a = 3; break;\n"
1642     "}\n",
1643 
1644     "var a = 1;\n"
1645     "switch(a) {\n"
1646     " case 2: break;\n"
1647     " case 3: break;\n"
1648     " default: a = 1; break;\n"
1649     "}\n",
1650 
1651     "var a = 1;\n"
1652     "switch(typeof(a)) {\n"
1653     " case 2: a = 1; break;\n"
1654     " case 3: a = 2; break;\n"
1655     " default: a = 3; break;\n"
1656     "}\n",
1657 
1658     "var a = 1;\n"
1659     "switch(a) {\n"
1660     " case typeof(a): a = 1; break;\n"
1661     " default: a = 2; break;\n"
1662     "}\n",
1663 
1664     "var a = 1;\n"
1665     "switch(a) {\n"
1666     " case 1:\n"
1667     REPEAT_64("  a = 2;\n")
1668     "  break;\n"
1669     " case 2:\n"
1670     "  a = 3;\n"
1671     "  break;\n"
1672     "}\n",
1673 
1674     "var a = 1;\n"
1675     "switch(a) {\n"
1676     " case 1: \n"
1677     "   switch(a + 1) {\n"
1678     "      case 2 : a = 1; break;\n"
1679     "      default : a = 2; break;\n"
1680     "   }  // fall-through\n"
1681     " case 2: a = 3;\n"
1682     "}\n",
1683   };
1684 
1685   CHECK(CompareTexts(BuildActual(printer, snippets),
1686                      LoadGolden("Switch.golden")));
1687 }
1688 
TEST(BasicBlockToBoolean)1689 TEST(BasicBlockToBoolean) {
1690   InitializedIgnitionHandleScope scope;
1691   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1692                                       ConstantPoolType::kNumber);
1693   const char* snippets[] = {
1694       "var a = 1; if (a || a < 0) { return 1; }\n",
1695 
1696       "var a = 1; if (a && a < 0) { return 1; }\n",
1697 
1698       "var a = 1; a = (a || a < 0) ? 2 : 3;\n",
1699   };
1700 
1701   CHECK(CompareTexts(BuildActual(printer, snippets),
1702                      LoadGolden("BasicBlockToBoolean.golden")));
1703 }
1704 
TEST(DeadCodeRemoval)1705 TEST(DeadCodeRemoval) {
1706   InitializedIgnitionHandleScope scope;
1707   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1708                                       ConstantPoolType::kNumber);
1709   const char* snippets[] = {
1710       "return; var a = 1; a();\n",
1711 
1712       "if (false) { return; }; var a = 1;\n",
1713 
1714       "if (true) { return 1; } else { return 2; };\n",
1715 
1716       "var a = 1; if (a) { return 1; }; return 2;\n",
1717   };
1718 
1719   CHECK(CompareTexts(BuildActual(printer, snippets),
1720                      LoadGolden("DeadCodeRemoval.golden")));
1721 }
1722 
TEST(ThisFunction)1723 TEST(ThisFunction) {
1724   InitializedIgnitionHandleScope scope;
1725   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1726                                       ConstantPoolType::kNumber);
1727   printer.set_wrap(false);
1728   printer.set_test_function_name("f");
1729 
1730   const char* snippets[] = {
1731       "var f;\n"
1732       "f = function f() {};",
1733 
1734       "var f;\n"
1735       "f = function f() { return f; };",
1736   };
1737 
1738   CHECK(CompareTexts(BuildActual(printer, snippets, "", "\nf();"),
1739                      LoadGolden("ThisFunction.golden")));
1740 }
1741 
TEST(NewTarget)1742 TEST(NewTarget) {
1743   InitializedIgnitionHandleScope scope;
1744   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1745                                       ConstantPoolType::kMixed);
1746 
1747   const char* snippets[] = {
1748       "return new.target;\n",
1749 
1750       "new.target;\n",
1751   };
1752 
1753   CHECK(CompareTexts(BuildActual(printer, snippets),
1754                      LoadGolden("NewTarget.golden")));
1755 }
1756 
TEST(RemoveRedundantLdar)1757 TEST(RemoveRedundantLdar) {
1758   InitializedIgnitionHandleScope scope;
1759   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1760                                       ConstantPoolType::kNumber);
1761   const char* snippets[] = {
1762       "var ld_a = 1;\n"          // This test is to check Ldar does not
1763       "while(true) {\n"          // get removed if the preceding Star is
1764       "  ld_a = ld_a + ld_a;\n"  // in a different basicblock.
1765       "  if (ld_a > 10) break;\n"
1766       "}\n"
1767       "return ld_a;\n",
1768 
1769       "var ld_a = 1;\n"
1770       "do {\n"
1771       "  ld_a = ld_a + ld_a;\n"
1772       "  if (ld_a > 10) continue;\n"
1773       "} while(false);\n"
1774       "return ld_a;\n",
1775 
1776       "var ld_a = 1;\n"
1777       "  ld_a = ld_a + ld_a;\n"
1778       "  return ld_a;\n",
1779   };
1780 
1781   CHECK(CompareTexts(BuildActual(printer, snippets),
1782                      LoadGolden("RemoveRedundantLdar.golden")));
1783 }
1784 
TEST(AssignmentsInBinaryExpression)1785 TEST(AssignmentsInBinaryExpression) {
1786   InitializedIgnitionHandleScope scope;
1787   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1788                                       ConstantPoolType::kString);
1789   const char* snippets[] = {
1790       "var x = 0, y = 1;\n"
1791       "return (x = 2, y = 3, x = 4, y = 5);\n",
1792 
1793       "var x = 55;\n"
1794       "var y = (x = 100);\n"
1795       "return y;\n",
1796 
1797       "var x = 55;\n"
1798       "x = x + (x = 100) + (x = 101);\n"
1799       "return x;\n",
1800 
1801       "var x = 55;\n"
1802       "x = (x = 56) - x + (x = 57);\n"
1803       "x++;\n"
1804       "return x;\n",
1805 
1806       "var x = 55;\n"
1807       "var y = x + (x = 1) + (x = 2) + (x = 3);\n"
1808       "return y;\n",
1809 
1810       "var x = 55;\n"
1811       "var x = x + (x = 1) + (x = 2) + (x = 3);\n"
1812       "return x;\n",
1813 
1814       "var x = 10, y = 20;\n"
1815       "return x + (x = 1) + (x + 1) * (y = 2) + (y = 3) + (x = 4) + (y = 5) + "
1816       "y;\n",
1817 
1818       "var x = 17;\n"
1819       "return 1 + x + (x++) + (++x);\n",
1820   };
1821 
1822   CHECK(CompareTexts(BuildActual(printer, snippets),
1823                      LoadGolden("AssignmentsInBinaryExpression.golden")));
1824 }
1825 
TEST(Eval)1826 TEST(Eval) {
1827   InitializedIgnitionHandleScope scope;
1828   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1829                                       ConstantPoolType::kString);
1830   const char* snippets[] = {
1831       "return eval('1;');\n",
1832   };
1833 
1834   CHECK(
1835       CompareTexts(BuildActual(printer, snippets), LoadGolden("Eval.golden")));
1836 }
1837 
TEST(LookupSlot)1838 TEST(LookupSlot) {
1839   InitializedIgnitionHandleScope scope;
1840   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1841                                       ConstantPoolType::kString);
1842 
1843   const char* snippets[] = {
1844       "eval('var x = 10;'); return x;\n",
1845 
1846       "eval('var x = 10;'); return typeof x;\n",
1847 
1848       "x = 20; return eval('');\n",
1849   };
1850 
1851   CHECK(CompareTexts(BuildActual(printer, snippets),
1852                      LoadGolden("LookupSlot.golden")));
1853 }
1854 
TEST(CallLookupSlot)1855 TEST(CallLookupSlot) {
1856   InitializedIgnitionHandleScope scope;
1857   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1858                                       ConstantPoolType::kMixed);
1859   const char* snippets[] = {
1860       "g = function(){}; eval(''); return g();\n",
1861   };
1862 
1863   CHECK(CompareTexts(BuildActual(printer, snippets),
1864                      LoadGolden("CallLookupSlot.golden")));
1865 }
1866 
1867 // TODO(mythria): tests for variable/function declaration in lookup slots.
1868 
TEST(LookupSlotInEval)1869 TEST(LookupSlotInEval) {
1870   InitializedIgnitionHandleScope scope;
1871   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1872                                       ConstantPoolType::kString);
1873   printer.set_wrap(false);
1874   printer.set_test_function_name("f");
1875 
1876   const char* snippets[] = {
1877       "return x;",
1878 
1879       "x = 10;",
1880 
1881       "'use strict'; x = 10;",
1882 
1883       "return typeof x;",
1884   };
1885 
1886   std::string actual = BuildActual(printer, snippets,
1887                                    "var f;\n"
1888                                    "var x = 1;\n"
1889                                    "function f1() {\n"
1890                                    "  eval(\"function t() { ",
1891 
1892                                    " }; f = t; f();\");\n"
1893                                    "}\n"
1894                                    "f1();");
1895 
1896   CHECK(CompareTexts(actual, LoadGolden("LookupSlotInEval.golden")));
1897 }
1898 
TEST(LookupSlotWideInEval)1899 TEST(LookupSlotWideInEval) {
1900   InitializedIgnitionHandleScope scope;
1901   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1902                                       ConstantPoolType::kMixed);
1903   printer.set_wrap(false);
1904   printer.set_test_function_name("f");
1905 
1906   const char* snippets[] = {
1907       REPEAT_256("    \"var y = 2.3;\" +\n")  //
1908       "    \"return x;\" +\n",
1909 
1910       REPEAT_256("    \"var y = 2.3;\" +\n")  //
1911       "    \"return typeof x;\" +\n",
1912 
1913       REPEAT_256("    \"var y = 2.3;\" +\n")  //
1914       "    \"x = 10;\" +\n",
1915 
1916       "    \"'use strict';\" +\n"             //
1917       REPEAT_256("    \"var y = 2.3;\" +\n")  //
1918       "    \"x = 10;\" +\n",
1919   };
1920 
1921   std::string actual = BuildActual(printer, snippets,
1922                                    "var f;\n"
1923                                    "var x = 1;\n"
1924                                    "function f1() {\n"
1925                                    "  eval(\"function t() {\" +\n",
1926 
1927                                    "  \"};\" +\n"
1928                                    "  \"f = t; f();\"\n);\n"
1929                                    "}\n"
1930                                    "f1();");
1931 
1932   CHECK(CompareTexts(actual, LoadGolden("LookupSlotWideInEval.golden")));
1933 }
1934 
TEST(DeleteLookupSlotInEval)1935 TEST(DeleteLookupSlotInEval) {
1936   InitializedIgnitionHandleScope scope;
1937   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1938                                       ConstantPoolType::kString);
1939   printer.set_wrap(false);
1940   printer.set_test_function_name("f");
1941 
1942   const char* snippets[] = {
1943       "delete x;",
1944 
1945       "return delete y;",
1946 
1947       "return delete z;",
1948   };
1949 
1950   std::string actual = BuildActual(printer, snippets,
1951                                    "var f;\n"
1952                                    "var x = 1;\n"
1953                                    "z = 10;\n"
1954                                    "function f1() {\n"
1955                                    "  var y;\n"
1956                                    "  eval(\"function t() { ",
1957 
1958                                    " }; f = t; f();\");\n"
1959                                    "}\n"
1960                                    "f1();");
1961 
1962   CHECK(CompareTexts(actual, LoadGolden("DeleteLookupSlotInEval.golden")));
1963 }
1964 
TEST(WideRegisters)1965 TEST(WideRegisters) {
1966   // Prepare prologue that creates frame for lots of registers.
1967   std::ostringstream os;
1968   for (size_t i = 0; i < 157; ++i) {
1969     os << "var x" << i << ";\n";
1970   }
1971   std::string prologue(os.str());
1972 
1973   InitializedIgnitionHandleScope scope;
1974   BytecodeExpectationsPrinter printer(CcTest::isolate(),
1975                                       ConstantPoolType::kNumber);
1976   const char* snippets[] = {
1977       "x0 = x127;\n"
1978       "return x0;\n",
1979 
1980       "x127 = x126;\n"
1981       "return x127;\n",
1982 
1983       "if (x2 > 3) { return x129; }\n"
1984       "return x128;\n",
1985 
1986       "var x0 = 0;\n"
1987       "if (x129 == 3) { var x129 = x0; }\n"
1988       "if (x2 > 3) { return x0; }\n"
1989       "return x129;\n",
1990 
1991       "var x0 = 0;\n"
1992       "var x1 = 0;\n"
1993       "for (x128 = 0; x128 < 64; x128++) {"
1994       "  x1 += x128;"
1995       "}"
1996       "return x128;\n",
1997 
1998       "var x0 = 1234;\n"
1999       "var x1 = 0;\n"
2000       "for (x128 in x0) {"
2001       "  x1 += x128;"
2002       "}"
2003       "return x1;\n",
2004 
2005       "x0 = %Add(x64, x63);\n"
2006       "x1 = %Add(x27, x143);\n"
2007       "%TheHole();\n"
2008       "return x1;\n",
2009   };
2010 
2011   CHECK(CompareTexts(BuildActual(printer, snippets, prologue.c_str()),
2012                      LoadGolden("WideRegisters.golden")));
2013 }
2014 
TEST(ConstVariable)2015 TEST(ConstVariable) {
2016   InitializedIgnitionHandleScope scope;
2017   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2018                                       ConstantPoolType::kString);
2019   const char* snippets[] = {
2020       "const x = 10;\n",
2021 
2022       "const x = 10; return x;\n",
2023 
2024       "const x = ( x = 20);\n",
2025 
2026       "const x = 10; x = 20;\n",
2027   };
2028 
2029   CHECK(CompareTexts(BuildActual(printer, snippets),
2030                      LoadGolden("ConstVariable.golden")));
2031 }
2032 
TEST(LetVariable)2033 TEST(LetVariable) {
2034   InitializedIgnitionHandleScope scope;
2035   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2036                                       ConstantPoolType::kString);
2037   const char* snippets[] = {
2038       "let x = 10;\n",
2039 
2040       "let x = 10; return x;\n",
2041 
2042       "let x = (x = 20);\n",
2043 
2044       "let x = 10; x = 20;\n",
2045   };
2046 
2047   CHECK(CompareTexts(BuildActual(printer, snippets),
2048                      LoadGolden("LetVariable.golden")));
2049 }
2050 
TEST(ConstVariableContextSlot)2051 TEST(ConstVariableContextSlot) {
2052   // TODO(mythria): Add tests for initialization of this via super calls.
2053   // TODO(mythria): Add tests that walk the context chain.
2054   InitializedIgnitionHandleScope scope;
2055   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2056                                       ConstantPoolType::kMixed);
2057   const char* snippets[] = {
2058       "const x = 10; function f1() {return x;}\n",
2059 
2060       "const x = 10; function f1() {return x;} return x;\n",
2061 
2062       "const x = (x = 20); function f1() {return x;}\n",
2063 
2064       "const x = 10; x = 20; function f1() {return x;}\n",
2065   };
2066 
2067   CHECK(CompareTexts(BuildActual(printer, snippets),
2068                      LoadGolden("ConstVariableContextSlot.golden")));
2069 }
2070 
TEST(LetVariableContextSlot)2071 TEST(LetVariableContextSlot) {
2072   InitializedIgnitionHandleScope scope;
2073   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2074                                       ConstantPoolType::kMixed);
2075   const char* snippets[] = {
2076       "let x = 10; function f1() {return x;}\n",
2077 
2078       "let x = 10; function f1() {return x;} return x;\n",
2079 
2080       "let x = (x = 20); function f1() {return x;}\n",
2081 
2082       "let x = 10; x = 20; function f1() {return x;}\n",
2083   };
2084 
2085   CHECK(CompareTexts(BuildActual(printer, snippets),
2086                      LoadGolden("LetVariableContextSlot.golden")));
2087 }
2088 
TEST(DoExpression)2089 TEST(DoExpression) {
2090   bool old_flag = FLAG_harmony_do_expressions;
2091   FLAG_harmony_do_expressions = true;
2092 
2093   InitializedIgnitionHandleScope scope;
2094   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2095                                       ConstantPoolType::kString);
2096   const char* snippets[] = {
2097       "var a = do { }; return a;\n",
2098 
2099       "var a = do { var x = 100; }; return a;\n",
2100 
2101       "while(true) { var a = 10; a = do { ++a; break; }; a = 20; }\n",
2102   };
2103 
2104   CHECK(CompareTexts(BuildActual(printer, snippets),
2105                      LoadGolden("DoExpression.golden")));
2106 
2107   FLAG_harmony_do_expressions = old_flag;
2108 }
2109 
TEST(WithStatement)2110 TEST(WithStatement) {
2111   InitializedIgnitionHandleScope scope;
2112   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2113                                       ConstantPoolType::kMixed);
2114   const char* snippets[] = {
2115       "with ({x:42}) { return x; }\n",
2116   };
2117 
2118   CHECK(CompareTexts(BuildActual(printer, snippets),
2119                      LoadGolden("WithStatement.golden")));
2120 }
2121 
TEST(DoDebugger)2122 TEST(DoDebugger) {
2123   InitializedIgnitionHandleScope scope;
2124   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2125                                       ConstantPoolType::kString);
2126   const char* snippets[] = {
2127       "debugger;\n",
2128   };
2129 
2130   CHECK(CompareTexts(BuildActual(printer, snippets),
2131                      LoadGolden("DoDebugger.golden")));
2132 }
2133 
TEST(ClassDeclarations)2134 TEST(ClassDeclarations) {
2135   InitializedIgnitionHandleScope scope;
2136   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2137                                       ConstantPoolType::kMixed);
2138   const char* snippets[] = {
2139       "class Person {\n"
2140       "  constructor(name) { this.name = name; }\n"
2141       "  speak() { console.log(this.name + ' is speaking.'); }\n"
2142       "}\n",
2143 
2144       "class person {\n"
2145       "  constructor(name) { this.name = name; }\n"
2146       "  speak() { console.log(this.name + ' is speaking.'); }\n"
2147       "}\n",
2148 
2149       "var n0 = 'a';\n"
2150       "var n1 = 'b';\n"
2151       "class N {\n"
2152       "  [n0]() { return n0; }\n"
2153       "  static [n1]() { return n1; }\n"
2154       "}\n",
2155 
2156       "var count = 0;\n"
2157       "class C { constructor() { count++; }}\n"
2158       "return new C();\n",
2159   };
2160 
2161   CHECK(CompareTexts(BuildActual(printer, snippets),
2162                      LoadGolden("ClassDeclarations.golden")));
2163 }
2164 
TEST(ClassAndSuperClass)2165 TEST(ClassAndSuperClass) {
2166   InitializedIgnitionHandleScope scope;
2167   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2168                                       ConstantPoolType::kMixed);
2169   printer.set_wrap(false);
2170   printer.set_test_function_name("test");
2171   const char* snippets[] = {
2172       "var test;\n"
2173       "(function() {\n"
2174       "  class A {\n"
2175       "    method() { return 2; }\n"
2176       "  }\n"
2177       "  class B extends A {\n"
2178       "    method() { return super.method() + 1; }\n"
2179       "  }\n"
2180       "  test = new B().method;\n"
2181       "  test();\n"
2182       "})();\n",
2183 
2184       "var test;\n"
2185       "(function() {\n"
2186       "  class A {\n"
2187       "    get x() { return 1; }\n"
2188       "    set x(val) { return; }\n"
2189       "  }\n"
2190       "  class B extends A {\n"
2191       "    method() { super.x = 2; return super.x; }\n"
2192       "  }\n"
2193       "  test = new B().method;\n"
2194       "  test();\n"
2195       "})();\n",
2196 
2197       "var test;\n"
2198       "(function() {\n"
2199       "  class A {\n"
2200       "    constructor(x) { this.x_ = x; }\n"
2201       "  }\n"
2202       "  class B extends A {\n"
2203       "    constructor() { super(1); this.y_ = 2; }\n"
2204       "  }\n"
2205       "  test = new B().constructor;\n"
2206       "})();\n",
2207 
2208       "var test;\n"
2209       "(function() {\n"
2210       "  class A {\n"
2211       "    constructor() { this.x_ = 1; }\n"
2212       "  }\n"
2213       "  class B extends A {\n"
2214       "    constructor() { super(); this.y_ = 2; }\n"
2215       "  }\n"
2216       "  test = new B().constructor;\n"
2217       "})();\n",
2218   };
2219 
2220   CHECK(CompareTexts(BuildActual(printer, snippets),
2221                      LoadGolden("ClassAndSuperClass.golden")));
2222 }
2223 
TEST(Generators)2224 TEST(Generators) {
2225   bool old_flag = FLAG_ignition_generators;
2226   FLAG_ignition_generators = true;
2227 
2228   InitializedIgnitionHandleScope scope;
2229   BytecodeExpectationsPrinter printer(CcTest::isolate(),
2230                                       ConstantPoolType::kMixed);
2231   printer.set_wrap(false);
2232   printer.set_test_function_name("f");
2233 
2234   const char* snippets[] = {
2235       "function* f() { }\n"
2236       "f();\n",
2237 
2238       "function* f() { yield 42 }\n"
2239       "f();\n",
2240 
2241       "function* f() { for (let x of [42]) yield x }\n"
2242       "f();\n",
2243   };
2244 
2245   CHECK(CompareTexts(BuildActual(printer, snippets),
2246                      LoadGolden("Generators.golden")));
2247 
2248   FLAG_ignition_generators = old_flag;
2249 }
2250 
2251 }  // namespace interpreter
2252 }  // namespace internal
2253 }  // namespace v8
2254