Home | History | Annotate | Download | only in compiler
      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 <utility>
      6 
      7 #include "src/compiler/pipeline.h"
      8 #include "src/execution.h"
      9 #include "src/handles.h"
     10 #include "src/interpreter/bytecode-array-builder.h"
     11 #include "src/interpreter/interpreter.h"
     12 #include "src/parsing/parser.h"
     13 #include "test/cctest/cctest.h"
     14 
     15 namespace v8 {
     16 namespace internal {
     17 namespace compiler {
     18 
     19 
     20 static const char kFunctionName[] = "f";
     21 
     22 static const Token::Value kCompareOperators[] = {
     23     Token::Value::EQ,        Token::Value::NE, Token::Value::EQ_STRICT,
     24     Token::Value::NE_STRICT, Token::Value::LT, Token::Value::LTE,
     25     Token::Value::GT,        Token::Value::GTE};
     26 
     27 static const int SMI_MAX = (1 << 30) - 1;
     28 static const int SMI_MIN = -(1 << 30);
     29 
     30 static MaybeHandle<Object> CallFunction(Isolate* isolate,
     31                                         Handle<JSFunction> function) {
     32   return Execution::Call(isolate, function,
     33                          isolate->factory()->undefined_value(), 0, nullptr);
     34 }
     35 
     36 
     37 template <class... A>
     38 static MaybeHandle<Object> CallFunction(Isolate* isolate,
     39                                         Handle<JSFunction> function,
     40                                         A... args) {
     41   Handle<Object> argv[] = {args...};
     42   return Execution::Call(isolate, function,
     43                          isolate->factory()->undefined_value(), sizeof...(args),
     44                          argv);
     45 }
     46 
     47 
     48 template <class... A>
     49 class BytecodeGraphCallable {
     50  public:
     51   BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
     52       : isolate_(isolate), function_(function) {}
     53   virtual ~BytecodeGraphCallable() {}
     54 
     55   MaybeHandle<Object> operator()(A... args) {
     56     return CallFunction(isolate_, function_, args...);
     57   }
     58 
     59  private:
     60   Isolate* isolate_;
     61   Handle<JSFunction> function_;
     62 };
     63 
     64 
     65 class BytecodeGraphTester {
     66  public:
     67   BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script,
     68                       const char* filter = kFunctionName)
     69       : isolate_(isolate), zone_(zone), script_(script) {
     70     i::FLAG_ignition = true;
     71     i::FLAG_always_opt = false;
     72     i::FLAG_allow_natives_syntax = true;
     73     i::FLAG_ignition_fallback_on_eval_and_catch = false;
     74     // Set ignition filter flag via SetFlagsFromString to avoid double-free
     75     // (or potential leak with StrDup() based on ownership confusion).
     76     ScopedVector<char> ignition_filter(64);
     77     SNPrintF(ignition_filter, "--ignition-filter=%s", filter);
     78     FlagList::SetFlagsFromString(ignition_filter.start(),
     79                                  ignition_filter.length());
     80     // Ensure handler table is generated.
     81     isolate->interpreter()->Initialize();
     82   }
     83   virtual ~BytecodeGraphTester() {}
     84 
     85   template <class... A>
     86   BytecodeGraphCallable<A...> GetCallable(
     87       const char* functionName = kFunctionName) {
     88     return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
     89   }
     90 
     91   Local<Message> CheckThrowsReturnMessage() {
     92     TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
     93     auto callable = GetCallable<>();
     94     MaybeHandle<Object> no_result = callable();
     95     CHECK(isolate_->has_pending_exception());
     96     CHECK(try_catch.HasCaught());
     97     CHECK(no_result.is_null());
     98     isolate_->OptionalRescheduleException(true);
     99     CHECK(!try_catch.Message().IsEmpty());
    100     return try_catch.Message();
    101   }
    102 
    103   static Handle<Object> NewObject(const char* script) {
    104     return v8::Utils::OpenHandle(*CompileRun(script));
    105   }
    106 
    107  private:
    108   Isolate* isolate_;
    109   Zone* zone_;
    110   const char* script_;
    111 
    112   Handle<JSFunction> GetFunction(const char* functionName) {
    113     CompileRun(script_);
    114     Local<Function> api_function = Local<Function>::Cast(
    115         CcTest::global()
    116             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName))
    117             .ToLocalChecked());
    118     Handle<JSFunction> function =
    119         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
    120     CHECK(function->shared()->HasBytecodeArray());
    121 
    122     ParseInfo parse_info(zone_, function);
    123 
    124     CompilationInfo compilation_info(&parse_info);
    125     compilation_info.SetOptimizing(BailoutId::None(), Handle<Code>());
    126     compilation_info.MarkAsDeoptimizationEnabled();
    127     // TODO(mythria): Remove this step once parse_info is not needed.
    128     CHECK(Compiler::ParseAndAnalyze(&parse_info));
    129     compiler::Pipeline pipeline(&compilation_info);
    130     Handle<Code> code = pipeline.GenerateCode();
    131     function->ReplaceCode(*code);
    132 
    133     return function;
    134   }
    135 
    136   DISALLOW_COPY_AND_ASSIGN(BytecodeGraphTester);
    137 };
    138 
    139 
    140 #define SPACE()
    141 
    142 #define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__
    143 #define REPEAT_4(SEP, ...) \
    144   REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
    145 #define REPEAT_8(SEP, ...) \
    146   REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
    147 #define REPEAT_16(SEP, ...) \
    148   REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
    149 #define REPEAT_32(SEP, ...) \
    150   REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
    151 #define REPEAT_64(SEP, ...) \
    152   REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
    153 #define REPEAT_128(SEP, ...) \
    154   REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
    155 #define REPEAT_256(SEP, ...) \
    156   REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
    157 
    158 #define REPEAT_127(SEP, ...)  \
    159   REPEAT_64(SEP, __VA_ARGS__) \
    160   SEP()                       \
    161   REPEAT_32(SEP, __VA_ARGS__) \
    162   SEP()                       \
    163   REPEAT_16(SEP, __VA_ARGS__) \
    164   SEP()                       \
    165   REPEAT_8(SEP, __VA_ARGS__)  \
    166   SEP()                       \
    167   REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__
    168 
    169 
    170 template <int N, typename T = Handle<Object>>
    171 struct ExpectedSnippet {
    172   const char* code_snippet;
    173   T return_value_and_parameters[N + 1];
    174 
    175   inline T return_value() const { return return_value_and_parameters[0]; }
    176 
    177   inline T parameter(int i) const {
    178     CHECK_GE(i, 0);
    179     CHECK_LT(i, N);
    180     return return_value_and_parameters[1 + i];
    181   }
    182 };
    183 
    184 
    185 TEST(BytecodeGraphBuilderReturnStatements) {
    186   HandleAndZoneScope scope;
    187   Isolate* isolate = scope.main_isolate();
    188   Zone* zone = scope.main_zone();
    189   Factory* factory = isolate->factory();
    190 
    191   ExpectedSnippet<0> snippets[] = {
    192       {"return;", {factory->undefined_value()}},
    193       {"return null;", {factory->null_value()}},
    194       {"return true;", {factory->true_value()}},
    195       {"return false;", {factory->false_value()}},
    196       {"return 0;", {factory->NewNumberFromInt(0)}},
    197       {"return +1;", {factory->NewNumberFromInt(1)}},
    198       {"return -1;", {factory->NewNumberFromInt(-1)}},
    199       {"return +127;", {factory->NewNumberFromInt(127)}},
    200       {"return -128;", {factory->NewNumberFromInt(-128)}},
    201       {"return 0.001;", {factory->NewNumber(0.001)}},
    202       {"return 3.7e-60;", {factory->NewNumber(3.7e-60)}},
    203       {"return -3.7e60;", {factory->NewNumber(-3.7e60)}},
    204       {"return '';", {factory->NewStringFromStaticChars("")}},
    205       {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
    206       {"return NaN;", {factory->nan_value()}}};
    207 
    208   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    209   for (size_t i = 0; i < num_snippets; i++) {
    210     ScopedVector<char> script(1024);
    211     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    212              snippets[i].code_snippet, kFunctionName);
    213 
    214     BytecodeGraphTester tester(isolate, zone, script.start());
    215     auto callable = tester.GetCallable<>();
    216     Handle<Object> return_value = callable().ToHandleChecked();
    217     CHECK(return_value->SameValue(*snippets[i].return_value()));
    218   }
    219 }
    220 
    221 
    222 TEST(BytecodeGraphBuilderPrimitiveExpressions) {
    223   HandleAndZoneScope scope;
    224   Isolate* isolate = scope.main_isolate();
    225   Zone* zone = scope.main_zone();
    226   Factory* factory = isolate->factory();
    227 
    228   ExpectedSnippet<0> snippets[] = {
    229       {"return 1 + 1;", {factory->NewNumberFromInt(2)}},
    230       {"return 20 - 30;", {factory->NewNumberFromInt(-10)}},
    231       {"return 4 * 100;", {factory->NewNumberFromInt(400)}},
    232       {"return 100 / 5;", {factory->NewNumberFromInt(20)}},
    233       {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
    234   };
    235 
    236   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    237   for (size_t i = 0; i < num_snippets; i++) {
    238     ScopedVector<char> script(1024);
    239     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    240              snippets[i].code_snippet, kFunctionName);
    241 
    242     BytecodeGraphTester tester(isolate, zone, script.start());
    243     auto callable = tester.GetCallable<>();
    244     Handle<Object> return_value = callable().ToHandleChecked();
    245     CHECK(return_value->SameValue(*snippets[i].return_value()));
    246   }
    247 }
    248 
    249 
    250 TEST(BytecodeGraphBuilderTwoParameterTests) {
    251   HandleAndZoneScope scope;
    252   Isolate* isolate = scope.main_isolate();
    253   Zone* zone = scope.main_zone();
    254   Factory* factory = isolate->factory();
    255 
    256   ExpectedSnippet<2> snippets[] = {
    257       // Integers
    258       {"return p1 + p2;",
    259        {factory->NewNumberFromInt(-70), factory->NewNumberFromInt(3),
    260         factory->NewNumberFromInt(-73)}},
    261       {"return p1 + p2 + 3;",
    262        {factory->NewNumberFromInt(1139044), factory->NewNumberFromInt(300),
    263         factory->NewNumberFromInt(1138741)}},
    264       {"return p1 - p2;",
    265        {factory->NewNumberFromInt(1100), factory->NewNumberFromInt(1000),
    266         factory->NewNumberFromInt(-100)}},
    267       {"return p1 * p2;",
    268        {factory->NewNumberFromInt(-100000), factory->NewNumberFromInt(1000),
    269         factory->NewNumberFromInt(-100)}},
    270       {"return p1 / p2;",
    271        {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(1000),
    272         factory->NewNumberFromInt(-100)}},
    273       {"return p1 % p2;",
    274        {factory->NewNumberFromInt(5), factory->NewNumberFromInt(373),
    275         factory->NewNumberFromInt(16)}},
    276       // Doubles
    277       {"return p1 + p2;",
    278        {factory->NewHeapNumber(9.999), factory->NewHeapNumber(3.333),
    279         factory->NewHeapNumber(6.666)}},
    280       {"return p1 - p2;",
    281        {factory->NewHeapNumber(-3.333), factory->NewHeapNumber(3.333),
    282         factory->NewHeapNumber(6.666)}},
    283       {"return p1 * p2;",
    284        {factory->NewHeapNumber(3.333 * 6.666), factory->NewHeapNumber(3.333),
    285         factory->NewHeapNumber(6.666)}},
    286       {"return p1 / p2;",
    287        {factory->NewHeapNumber(2.25), factory->NewHeapNumber(9),
    288         factory->NewHeapNumber(4)}},
    289       // Strings
    290       {"return p1 + p2;",
    291        {factory->NewStringFromStaticChars("abcdef"),
    292         factory->NewStringFromStaticChars("abc"),
    293         factory->NewStringFromStaticChars("def")}}};
    294 
    295   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    296   for (size_t i = 0; i < num_snippets; i++) {
    297     ScopedVector<char> script(1024);
    298     SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
    299              snippets[i].code_snippet, kFunctionName);
    300 
    301     BytecodeGraphTester tester(isolate, zone, script.start());
    302     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
    303     Handle<Object> return_value =
    304         callable(snippets[i].parameter(0), snippets[i].parameter(1))
    305             .ToHandleChecked();
    306     CHECK(return_value->SameValue(*snippets[i].return_value()));
    307   }
    308 }
    309 
    310 
    311 TEST(BytecodeGraphBuilderNamedLoad) {
    312   HandleAndZoneScope scope;
    313   Isolate* isolate = scope.main_isolate();
    314   Zone* zone = scope.main_zone();
    315   Factory* factory = isolate->factory();
    316 
    317   ExpectedSnippet<1> snippets[] = {
    318       {"return p1.val;",
    319        {factory->NewNumberFromInt(10),
    320         BytecodeGraphTester::NewObject("({val : 10})")}},
    321       {"return p1[\"name\"];",
    322        {factory->NewStringFromStaticChars("abc"),
    323         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    324       {"'use strict'; return p1.val;",
    325        {factory->NewNumberFromInt(10),
    326         BytecodeGraphTester::NewObject("({val : 10 })")}},
    327       {"'use strict'; return p1[\"val\"];",
    328        {factory->NewNumberFromInt(10),
    329         BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
    330       {"var b;\n" REPEAT_127(SPACE, " b = p1.name; ") " return p1.name;\n",
    331        {factory->NewStringFromStaticChars("abc"),
    332         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    333       {"'use strict'; var b;\n"
    334        REPEAT_127(SPACE, " b = p1.name; ")
    335        "return p1.name;\n",
    336        {factory->NewStringFromStaticChars("abc"),
    337         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
    338   };
    339 
    340   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    341   for (size_t i = 0; i < num_snippets; i++) {
    342     ScopedVector<char> script(2048);
    343     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
    344              snippets[i].code_snippet, kFunctionName);
    345 
    346     BytecodeGraphTester tester(isolate, zone, script.start());
    347     auto callable = tester.GetCallable<Handle<Object>>();
    348     Handle<Object> return_value =
    349         callable(snippets[i].parameter(0)).ToHandleChecked();
    350     CHECK(return_value->SameValue(*snippets[i].return_value()));
    351   }
    352 }
    353 
    354 
    355 TEST(BytecodeGraphBuilderKeyedLoad) {
    356   HandleAndZoneScope scope;
    357   Isolate* isolate = scope.main_isolate();
    358   Zone* zone = scope.main_zone();
    359   Factory* factory = isolate->factory();
    360 
    361   ExpectedSnippet<2> snippets[] = {
    362       {"return p1[p2];",
    363        {factory->NewNumberFromInt(10),
    364         BytecodeGraphTester::NewObject("({val : 10})"),
    365         factory->NewStringFromStaticChars("val")}},
    366       {"return p1[100];",
    367        {factory->NewStringFromStaticChars("abc"),
    368         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    369         factory->NewNumberFromInt(0)}},
    370       {"var b = 100; return p1[b];",
    371        {factory->NewStringFromStaticChars("abc"),
    372         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    373         factory->NewNumberFromInt(0)}},
    374       {"'use strict'; return p1[p2];",
    375        {factory->NewNumberFromInt(10),
    376         BytecodeGraphTester::NewObject("({val : 10 })"),
    377         factory->NewStringFromStaticChars("val")}},
    378       {"'use strict'; return p1[100];",
    379        {factory->NewNumberFromInt(10),
    380         BytecodeGraphTester::NewObject("({100 : 10})"),
    381         factory->NewNumberFromInt(0)}},
    382       {"'use strict'; var b = p2; return p1[b];",
    383        {factory->NewStringFromStaticChars("abc"),
    384         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    385         factory->NewNumberFromInt(100)}},
    386       {"var b;\n" REPEAT_127(SPACE, " b = p1[p2]; ") " return p1[p2];\n",
    387        {factory->NewStringFromStaticChars("abc"),
    388         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    389         factory->NewNumberFromInt(100)}},
    390       {"'use strict'; var b;\n" REPEAT_127(SPACE,
    391                                            " b = p1[p2]; ") "return p1[p2];\n",
    392        {factory->NewStringFromStaticChars("abc"),
    393         BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
    394         factory->NewNumberFromInt(100)}},
    395   };
    396 
    397   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    398   for (size_t i = 0; i < num_snippets; i++) {
    399     ScopedVector<char> script(2048);
    400     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
    401              snippets[i].code_snippet, kFunctionName);
    402 
    403     BytecodeGraphTester tester(isolate, zone, script.start());
    404     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
    405     Handle<Object> return_value =
    406         callable(snippets[i].parameter(0), snippets[i].parameter(1))
    407             .ToHandleChecked();
    408     CHECK(return_value->SameValue(*snippets[i].return_value()));
    409   }
    410 }
    411 
    412 
    413 TEST(BytecodeGraphBuilderNamedStore) {
    414   HandleAndZoneScope scope;
    415   Isolate* isolate = scope.main_isolate();
    416   Zone* zone = scope.main_zone();
    417   Factory* factory = isolate->factory();
    418 
    419   ExpectedSnippet<1> snippets[] = {
    420       {"return p1.val = 20;",
    421        {factory->NewNumberFromInt(20),
    422         BytecodeGraphTester::NewObject("({val : 10})")}},
    423       {"p1.type = 'int'; return p1.type;",
    424        {factory->NewStringFromStaticChars("int"),
    425         BytecodeGraphTester::NewObject("({val : 10})")}},
    426       {"p1.name = 'def'; return p1[\"name\"];",
    427        {factory->NewStringFromStaticChars("def"),
    428         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    429       {"'use strict'; p1.val = 20; return p1.val;",
    430        {factory->NewNumberFromInt(20),
    431         BytecodeGraphTester::NewObject("({val : 10 })")}},
    432       {"'use strict'; return p1.type = 'int';",
    433        {factory->NewStringFromStaticChars("int"),
    434         BytecodeGraphTester::NewObject("({val : 10})")}},
    435       {"'use strict'; p1.val = 20; return p1[\"val\"];",
    436        {factory->NewNumberFromInt(20),
    437         BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
    438       {"var b = 'abc';\n" REPEAT_127(
    439            SPACE, " p1.name = b; ") " p1.name = 'def'; return p1.name;\n",
    440        {factory->NewStringFromStaticChars("def"),
    441         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    442       {"'use strict'; var b = 'def';\n" REPEAT_127(
    443            SPACE, " p1.name = 'abc'; ") "p1.name = b; return p1.name;\n",
    444        {factory->NewStringFromStaticChars("def"),
    445         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
    446   };
    447 
    448   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    449   for (size_t i = 0; i < num_snippets; i++) {
    450     ScopedVector<char> script(3072);
    451     SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
    452              snippets[i].code_snippet, kFunctionName);
    453 
    454     BytecodeGraphTester tester(isolate, zone, script.start());
    455     auto callable = tester.GetCallable<Handle<Object>>();
    456     Handle<Object> return_value =
    457         callable(snippets[i].parameter(0)).ToHandleChecked();
    458     CHECK(return_value->SameValue(*snippets[i].return_value()));
    459   }
    460 }
    461 
    462 
    463 TEST(BytecodeGraphBuilderKeyedStore) {
    464   HandleAndZoneScope scope;
    465   Isolate* isolate = scope.main_isolate();
    466   Zone* zone = scope.main_zone();
    467   Factory* factory = isolate->factory();
    468 
    469   ExpectedSnippet<2> snippets[] = {
    470       {"p1[p2] = 20; return p1[p2];",
    471        {factory->NewNumberFromInt(20),
    472         BytecodeGraphTester::NewObject("({val : 10})"),
    473         factory->NewStringFromStaticChars("val")}},
    474       {"return p1[100] = 'def';",
    475        {factory->NewStringFromStaticChars("def"),
    476         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    477         factory->NewNumberFromInt(0)}},
    478       {"var b = 100; p1[b] = 'def'; return p1[b];",
    479        {factory->NewStringFromStaticChars("def"),
    480         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    481         factory->NewNumberFromInt(0)}},
    482       {"'use strict'; p1[p2] = 20; return p1[p2];",
    483        {factory->NewNumberFromInt(20),
    484         BytecodeGraphTester::NewObject("({val : 10 })"),
    485         factory->NewStringFromStaticChars("val")}},
    486       {"'use strict'; return p1[100] = 20;",
    487        {factory->NewNumberFromInt(20),
    488         BytecodeGraphTester::NewObject("({100 : 10})"),
    489         factory->NewNumberFromInt(0)}},
    490       {"'use strict'; var b = p2; p1[b] = 'def'; return p1[b];",
    491        {factory->NewStringFromStaticChars("def"),
    492         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    493         factory->NewNumberFromInt(100)}},
    494       {"var b;\n" REPEAT_127(
    495            SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
    496        {factory->NewStringFromStaticChars("def"),
    497         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    498         factory->NewNumberFromInt(100)}},
    499       {"'use strict'; var b;\n" REPEAT_127(
    500            SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
    501        {factory->NewStringFromStaticChars("def"),
    502         BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
    503         factory->NewNumberFromInt(100)}},
    504   };
    505 
    506   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    507   for (size_t i = 0; i < num_snippets; i++) {
    508     ScopedVector<char> script(2048);
    509     SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
    510              snippets[i].code_snippet, kFunctionName);
    511 
    512     BytecodeGraphTester tester(isolate, zone, script.start());
    513     auto callable = tester.GetCallable<Handle<Object>>();
    514     Handle<Object> return_value =
    515         callable(snippets[i].parameter(0)).ToHandleChecked();
    516     CHECK(return_value->SameValue(*snippets[i].return_value()));
    517   }
    518 }
    519 
    520 
    521 TEST(BytecodeGraphBuilderPropertyCall) {
    522   HandleAndZoneScope scope;
    523   Isolate* isolate = scope.main_isolate();
    524   Zone* zone = scope.main_zone();
    525   Factory* factory = isolate->factory();
    526 
    527   ExpectedSnippet<1> snippets[] = {
    528       {"return p1.func();",
    529        {factory->NewNumberFromInt(25),
    530         BytecodeGraphTester::NewObject("({func() { return 25; }})")}},
    531       {"return p1.func('abc');",
    532        {factory->NewStringFromStaticChars("abc"),
    533         BytecodeGraphTester::NewObject("({func(a) { return a; }})")}},
    534       {"return p1.func(1, 2, 3, 4, 5, 6, 7, 8);",
    535        {factory->NewNumberFromInt(36),
    536         BytecodeGraphTester::NewObject(
    537             "({func(a, b, c, d, e, f, g, h) {\n"
    538             "  return a + b + c + d + e + f + g + h;}})")}},
    539   };
    540 
    541   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    542   for (size_t i = 0; i < num_snippets; i++) {
    543     ScopedVector<char> script(2048);
    544     SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
    545              snippets[i].code_snippet, kFunctionName);
    546 
    547     BytecodeGraphTester tester(isolate, zone, script.start());
    548     auto callable = tester.GetCallable<Handle<Object>>();
    549     Handle<Object> return_value =
    550         callable(snippets[i].parameter(0)).ToHandleChecked();
    551     CHECK(return_value->SameValue(*snippets[i].return_value()));
    552   }
    553 }
    554 
    555 
    556 TEST(BytecodeGraphBuilderCallNew) {
    557   HandleAndZoneScope scope;
    558   Isolate* isolate = scope.main_isolate();
    559   Zone* zone = scope.main_zone();
    560   Factory* factory = isolate->factory();
    561 
    562   ExpectedSnippet<0> snippets[] = {
    563       {"function counter() { this.count = 20; }\n"
    564        "function f() {\n"
    565        "  var c = new counter();\n"
    566        "  return c.count;\n"
    567        "}; f()",
    568        {factory->NewNumberFromInt(20)}},
    569       {"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
    570        "function f() {\n"
    571        "  var c = new counter(6);\n"
    572        "  return c.count + c.x;\n"
    573        "}; f()",
    574        {factory->NewNumberFromInt(23)}},
    575       {"function counter(arg0, arg1) {\n"
    576        "  this.count = 17; this.x = arg0; this.y = arg1;\n"
    577        "}\n"
    578        "function f() {\n"
    579        "  var c = new counter(3, 5);\n"
    580        "  return c.count + c.x + c.y;\n"
    581        "}; f()",
    582        {factory->NewNumberFromInt(25)}},
    583   };
    584 
    585   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    586   for (size_t i = 0; i < num_snippets; i++) {
    587     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    588     auto callable = tester.GetCallable<>();
    589     Handle<Object> return_value = callable().ToHandleChecked();
    590     CHECK(return_value->SameValue(*snippets[i].return_value()));
    591   }
    592 }
    593 
    594 
    595 TEST(BytecodeGraphBuilderCreateClosure) {
    596   HandleAndZoneScope scope;
    597   Isolate* isolate = scope.main_isolate();
    598   Zone* zone = scope.main_zone();
    599   Factory* factory = isolate->factory();
    600 
    601   ExpectedSnippet<0> snippets[] = {
    602       {"function f() {\n"
    603        "  function counter() { this.count = 20; }\n"
    604        "  var c = new counter();\n"
    605        "  return c.count;\n"
    606        "}; f()",
    607        {factory->NewNumberFromInt(20)}},
    608       {"function f() {\n"
    609        "  function counter(arg0) { this.count = 17; this.x = arg0; }\n"
    610        "  var c = new counter(6);\n"
    611        "  return c.count + c.x;\n"
    612        "}; f()",
    613        {factory->NewNumberFromInt(23)}},
    614       {"function f() {\n"
    615        "  function counter(arg0, arg1) {\n"
    616        "    this.count = 17; this.x = arg0; this.y = arg1;\n"
    617        "  }\n"
    618        "  var c = new counter(3, 5);\n"
    619        "  return c.count + c.x + c.y;\n"
    620        "}; f()",
    621        {factory->NewNumberFromInt(25)}},
    622   };
    623 
    624   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    625   for (size_t i = 0; i < num_snippets; i++) {
    626     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    627     auto callable = tester.GetCallable<>();
    628     Handle<Object> return_value = callable().ToHandleChecked();
    629     CHECK(return_value->SameValue(*snippets[i].return_value()));
    630   }
    631 }
    632 
    633 
    634 TEST(BytecodeGraphBuilderCallRuntime) {
    635   HandleAndZoneScope scope;
    636   Isolate* isolate = scope.main_isolate();
    637   Zone* zone = scope.main_zone();
    638   Factory* factory = isolate->factory();
    639 
    640   ExpectedSnippet<1> snippets[] = {
    641       {"function f(arg0) { return %MaxSmi(); }\nf()",
    642        {factory->NewNumberFromInt(Smi::kMaxValue), factory->undefined_value()}},
    643       {"function f(arg0) { return %IsArray(arg0) }\nf(undefined)",
    644        {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
    645       {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
    646        {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
    647       {"function f(arg0) { return %spread_arguments(arg0).length }\nf([])",
    648        {factory->NewNumberFromInt(3),
    649         BytecodeGraphTester::NewObject("[1, 2, 3]")}},
    650   };
    651 
    652   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    653   for (size_t i = 0; i < num_snippets; i++) {
    654     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    655     auto callable = tester.GetCallable<Handle<Object>>();
    656     Handle<Object> return_value =
    657         callable(snippets[i].parameter(0)).ToHandleChecked();
    658     CHECK(return_value->SameValue(*snippets[i].return_value()));
    659   }
    660 }
    661 
    662 
    663 TEST(BytecodeGraphBuilderGlobals) {
    664   HandleAndZoneScope scope;
    665   Isolate* isolate = scope.main_isolate();
    666   Zone* zone = scope.main_zone();
    667   Factory* factory = isolate->factory();
    668 
    669   ExpectedSnippet<0> snippets[] = {
    670       {"var global = 321;\n function f() { return global; };\n f();",
    671        {factory->NewNumberFromInt(321)}},
    672       {"var global = 321;\n"
    673        "function f() { global = 123; return global };\n f();",
    674        {factory->NewNumberFromInt(123)}},
    675       {"var global = function() { return 'abc'};\n"
    676        "function f() { return global(); };\n f();",
    677        {factory->NewStringFromStaticChars("abc")}},
    678       {"var global = 456;\n"
    679        "function f() { 'use strict'; return global; };\n f();",
    680        {factory->NewNumberFromInt(456)}},
    681       {"var global = 987;\n"
    682        "function f() { 'use strict'; global = 789; return global };\n f();",
    683        {factory->NewNumberFromInt(789)}},
    684       {"var global = function() { return 'xyz'};\n"
    685        "function f() { 'use strict'; return global(); };\n f();",
    686        {factory->NewStringFromStaticChars("xyz")}},
    687       {"var global = 'abc'; var global_obj = {val:123};\n"
    688        "function f() {\n" REPEAT_127(
    689            SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
    690        {factory->NewStringFromStaticChars("abc")}},
    691       {"var global = 'abc'; var global_obj = {val:123};\n"
    692        "function f() { 'use strict';\n" REPEAT_127(
    693            SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
    694                                                  "global };\n f();\n",
    695        {factory->NewStringFromStaticChars("xyz")}},
    696       {"function f() { return typeof(undeclared_var); }\n; f();\n",
    697        {factory->NewStringFromStaticChars("undefined")}},
    698       {"var defined_var = 10; function f() { return typeof(defined_var); }\n; "
    699        "f();\n",
    700        {factory->NewStringFromStaticChars("number")}},
    701   };
    702 
    703   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    704   for (size_t i = 0; i < num_snippets; i++) {
    705     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    706     auto callable = tester.GetCallable<>();
    707     Handle<Object> return_value = callable().ToHandleChecked();
    708     CHECK(return_value->SameValue(*snippets[i].return_value()));
    709   }
    710 }
    711 
    712 
    713 TEST(BytecodeGraphBuilderToObject) {
    714   // TODO(mythria): tests for ToObject. Needs ForIn.
    715 }
    716 
    717 
    718 TEST(BytecodeGraphBuilderToName) {
    719   HandleAndZoneScope scope;
    720   Isolate* isolate = scope.main_isolate();
    721   Zone* zone = scope.main_zone();
    722   Factory* factory = isolate->factory();
    723 
    724   ExpectedSnippet<0> snippets[] = {
    725       {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
    726        {factory->NewNumberFromInt(10)}},
    727       {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
    728        {factory->NewNumberFromInt(10)}},
    729       {"var a = 20; var obj = {[a] : 10}; return obj[20];",
    730        {factory->NewNumberFromInt(10)}},
    731       {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
    732        {factory->NewNumberFromInt(10)}},
    733       {"var a = {val:23}; var obj = {[a] : 10}; return obj['[object Object]'];",
    734        {factory->NewNumberFromInt(10)}},
    735       {"var a = {toString : function() { return 'x'}};\n"
    736        "var obj = {[a] : 10};\n"
    737        "return obj.x;",
    738        {factory->NewNumberFromInt(10)}},
    739       {"var a = {valueOf : function() { return 'x'}};\n"
    740        "var obj = {[a] : 10};\n"
    741        "return obj.x;",
    742        {factory->undefined_value()}},
    743       {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
    744        "var obj = {[a] : 10};\n"
    745        "return obj.x;",
    746        {factory->NewNumberFromInt(10)}},
    747   };
    748 
    749   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    750   for (size_t i = 0; i < num_snippets; i++) {
    751     ScopedVector<char> script(1024);
    752     SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
    753              snippets[i].code_snippet, kFunctionName);
    754 
    755     BytecodeGraphTester tester(isolate, zone, script.start());
    756     auto callable = tester.GetCallable<>();
    757     Handle<Object> return_value = callable().ToHandleChecked();
    758     CHECK(return_value->SameValue(*snippets[i].return_value()));
    759   }
    760 }
    761 
    762 
    763 TEST(BytecodeGraphBuilderLogicalNot) {
    764   HandleAndZoneScope scope;
    765   Isolate* isolate = scope.main_isolate();
    766   Zone* zone = scope.main_zone();
    767   Factory* factory = isolate->factory();
    768 
    769   ExpectedSnippet<1> snippets[] = {
    770       {"return !p1;",
    771        {factory->false_value(),
    772         BytecodeGraphTester::NewObject("({val : 10})")}},
    773       {"return !p1;", {factory->true_value(), factory->NewNumberFromInt(0)}},
    774       {"return !p1;", {factory->true_value(), factory->undefined_value()}},
    775       {"return !p1;", {factory->false_value(), factory->NewNumberFromInt(10)}},
    776       {"return !p1;", {factory->false_value(), factory->true_value()}},
    777       {"return !p1;",
    778        {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
    779   };
    780 
    781   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    782   for (size_t i = 0; i < num_snippets; i++) {
    783     ScopedVector<char> script(1024);
    784     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    785              snippets[i].code_snippet, kFunctionName);
    786 
    787     BytecodeGraphTester tester(isolate, zone, script.start());
    788     auto callable = tester.GetCallable<Handle<Object>>();
    789     Handle<Object> return_value =
    790         callable(snippets[i].parameter(0)).ToHandleChecked();
    791     CHECK(return_value->SameValue(*snippets[i].return_value()));
    792   }
    793 }
    794 
    795 
    796 TEST(BytecodeGraphBuilderTypeOf) {
    797   HandleAndZoneScope scope;
    798   Isolate* isolate = scope.main_isolate();
    799   Zone* zone = scope.main_zone();
    800   Factory* factory = isolate->factory();
    801 
    802   ExpectedSnippet<1> snippets[] = {
    803       {"return typeof p1;",
    804        {factory->NewStringFromStaticChars("object"),
    805         BytecodeGraphTester::NewObject("({val : 10})")}},
    806       {"return typeof p1;",
    807        {factory->NewStringFromStaticChars("undefined"),
    808         factory->undefined_value()}},
    809       {"return typeof p1;",
    810        {factory->NewStringFromStaticChars("number"),
    811         factory->NewNumberFromInt(10)}},
    812       {"return typeof p1;",
    813        {factory->NewStringFromStaticChars("boolean"), factory->true_value()}},
    814       {"return typeof p1;",
    815        {factory->NewStringFromStaticChars("string"),
    816         factory->NewStringFromStaticChars("abc")}},
    817   };
    818 
    819   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    820   for (size_t i = 0; i < num_snippets; i++) {
    821     ScopedVector<char> script(1024);
    822     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    823              snippets[i].code_snippet, kFunctionName);
    824 
    825     BytecodeGraphTester tester(isolate, zone, script.start());
    826     auto callable = tester.GetCallable<Handle<Object>>();
    827     Handle<Object> return_value =
    828         callable(snippets[i].parameter(0)).ToHandleChecked();
    829     CHECK(return_value->SameValue(*snippets[i].return_value()));
    830   }
    831 }
    832 
    833 
    834 TEST(BytecodeGraphBuilderCountOperation) {
    835   HandleAndZoneScope scope;
    836   Isolate* isolate = scope.main_isolate();
    837   Zone* zone = scope.main_zone();
    838   Factory* factory = isolate->factory();
    839 
    840   ExpectedSnippet<1> snippets[] = {
    841       {"return ++p1;",
    842        {factory->NewNumberFromInt(11), factory->NewNumberFromInt(10)}},
    843       {"return p1++;",
    844        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
    845       {"return p1++ + 10;",
    846        {factory->NewHeapNumber(15.23), factory->NewHeapNumber(5.23)}},
    847       {"return 20 + ++p1;",
    848        {factory->NewHeapNumber(27.23), factory->NewHeapNumber(6.23)}},
    849       {"return --p1;",
    850        {factory->NewHeapNumber(9.8), factory->NewHeapNumber(10.8)}},
    851       {"return p1--;",
    852        {factory->NewHeapNumber(10.8), factory->NewHeapNumber(10.8)}},
    853       {"return p1-- + 10;",
    854        {factory->NewNumberFromInt(20), factory->NewNumberFromInt(10)}},
    855       {"return 20 + --p1;",
    856        {factory->NewNumberFromInt(29), factory->NewNumberFromInt(10)}},
    857       {"return p1.val--;",
    858        {factory->NewNumberFromInt(10),
    859         BytecodeGraphTester::NewObject("({val : 10})")}},
    860       {"return ++p1['val'];",
    861        {factory->NewNumberFromInt(11),
    862         BytecodeGraphTester::NewObject("({val : 10})")}},
    863       {"return ++p1[1];",
    864        {factory->NewNumberFromInt(11),
    865         BytecodeGraphTester::NewObject("({1 : 10})")}},
    866       {" function inner() { return p1 } return --p1;",
    867        {factory->NewNumberFromInt(9), factory->NewNumberFromInt(10)}},
    868       {" function inner() { return p1 } return p1--;",
    869        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
    870       {"return ++p1;",
    871        {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
    872   };
    873 
    874   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    875   for (size_t i = 0; i < num_snippets; i++) {
    876     ScopedVector<char> script(1024);
    877     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    878              snippets[i].code_snippet, kFunctionName);
    879 
    880     BytecodeGraphTester tester(isolate, zone, script.start());
    881     auto callable = tester.GetCallable<Handle<Object>>();
    882     Handle<Object> return_value =
    883         callable(snippets[i].parameter(0)).ToHandleChecked();
    884     CHECK(return_value->SameValue(*snippets[i].return_value()));
    885   }
    886 }
    887 
    888 
    889 TEST(BytecodeGraphBuilderDelete) {
    890   HandleAndZoneScope scope;
    891   Isolate* isolate = scope.main_isolate();
    892   Zone* zone = scope.main_zone();
    893   Factory* factory = isolate->factory();
    894 
    895   ExpectedSnippet<1> snippets[] = {
    896       {"return delete p1.val;",
    897        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
    898       {"delete p1.val; return p1.val;",
    899        {factory->undefined_value(),
    900         BytecodeGraphTester::NewObject("({val : 10})")}},
    901       {"delete p1.name; return p1.val;",
    902        {factory->NewNumberFromInt(10),
    903         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
    904       {"'use strict'; return delete p1.val;",
    905        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
    906       {"'use strict'; delete p1.val; return p1.val;",
    907        {factory->undefined_value(),
    908         BytecodeGraphTester::NewObject("({val : 10})")}},
    909       {"'use strict'; delete p1.name; return p1.val;",
    910        {factory->NewNumberFromInt(10),
    911         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
    912   };
    913 
    914   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    915   for (size_t i = 0; i < num_snippets; i++) {
    916     ScopedVector<char> script(1024);
    917     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    918              snippets[i].code_snippet, kFunctionName);
    919 
    920     BytecodeGraphTester tester(isolate, zone, script.start());
    921     auto callable = tester.GetCallable<Handle<Object>>();
    922     Handle<Object> return_value =
    923         callable(snippets[i].parameter(0)).ToHandleChecked();
    924     CHECK(return_value->SameValue(*snippets[i].return_value()));
    925   }
    926 }
    927 
    928 
    929 TEST(BytecodeGraphBuilderDeleteGlobal) {
    930   HandleAndZoneScope scope;
    931   Isolate* isolate = scope.main_isolate();
    932   Zone* zone = scope.main_zone();
    933   Factory* factory = isolate->factory();
    934 
    935   ExpectedSnippet<0> snippets[] = {
    936       {"var obj = {val : 10, type : 'int'};"
    937        "function f() {return delete obj;};",
    938        {factory->false_value()}},
    939       {"function f() {return delete this;};", {factory->true_value()}},
    940       {"var obj = {val : 10, type : 'int'};"
    941        "function f() {return delete obj.val;};",
    942        {factory->true_value()}},
    943       {"var obj = {val : 10, type : 'int'};"
    944        "function f() {'use strict'; return delete obj.val;};",
    945        {factory->true_value()}},
    946       {"var obj = {val : 10, type : 'int'};"
    947        "function f() {delete obj.val; return obj.val;};",
    948        {factory->undefined_value()}},
    949       {"var obj = {val : 10, type : 'int'};"
    950        "function f() {'use strict'; delete obj.val; return obj.val;};",
    951        {factory->undefined_value()}},
    952       {"var obj = {1 : 10, 2 : 20};"
    953        "function f() { return delete obj[1]; };",
    954        {factory->true_value()}},
    955       {"var obj = {1 : 10, 2 : 20};"
    956        "function f() { 'use strict';  return delete obj[1];};",
    957        {factory->true_value()}},
    958       {"obj = {1 : 10, 2 : 20};"
    959        "function f() { delete obj[1]; return obj[2];};",
    960        {factory->NewNumberFromInt(20)}},
    961       {"function f() {"
    962        "  var obj = {1 : 10, 2 : 20};"
    963        "  function inner() { return obj[1]; };"
    964        "  return delete obj[1];"
    965        "}",
    966        {factory->true_value()}},
    967   };
    968 
    969   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
    970   for (size_t i = 0; i < num_snippets; i++) {
    971     ScopedVector<char> script(1024);
    972     SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
    973 
    974     BytecodeGraphTester tester(isolate, zone, script.start());
    975     auto callable = tester.GetCallable<>();
    976     Handle<Object> return_value = callable().ToHandleChecked();
    977     CHECK(return_value->SameValue(*snippets[i].return_value()));
    978   }
    979 }
    980 
    981 
    982 TEST(BytecodeGraphBuilderDeleteLookupSlot) {
    983   HandleAndZoneScope scope;
    984   Isolate* isolate = scope.main_isolate();
    985   Zone* zone = scope.main_zone();
    986   Factory* factory = isolate->factory();
    987 
    988   // TODO(mythria): Add more tests when we have support for LdaLookupSlot.
    989   const char* function_prologue = "var f;"
    990                                   "var x = 1;"
    991                                   "y = 10;"
    992                                   "var obj = {val:10};"
    993                                   "var z = 30;"
    994                                   "function f1() {"
    995                                   "  var z = 20;"
    996                                   "  eval(\"function t() {";
    997   const char* function_epilogue = "        }; f = t; t();\");"
    998                                   "}"
    999                                   "f1();";
   1000 
   1001   ExpectedSnippet<0> snippets[] = {
   1002       {"return delete y;", {factory->true_value()}},
   1003       {"return delete z;", {factory->false_value()}},
   1004   };
   1005 
   1006   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1007   for (size_t i = 0; i < num_snippets; i++) {
   1008     ScopedVector<char> script(1024);
   1009     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
   1010              function_epilogue);
   1011 
   1012     BytecodeGraphTester tester(isolate, zone, script.start(), "t");
   1013     auto callable = tester.GetCallable<>();
   1014     Handle<Object> return_value = callable().ToHandleChecked();
   1015     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1016   }
   1017 }
   1018 
   1019 
   1020 TEST(BytecodeGraphBuilderLookupSlot) {
   1021   HandleAndZoneScope scope;
   1022   Isolate* isolate = scope.main_isolate();
   1023   Zone* zone = scope.main_zone();
   1024   Factory* factory = isolate->factory();
   1025 
   1026   const char* function_prologue = "var f;"
   1027                                   "var x = 12;"
   1028                                   "y = 10;"
   1029                                   "var obj = {val:3.1414};"
   1030                                   "var z = 30;"
   1031                                   "function f1() {"
   1032                                   "  var z = 20;"
   1033                                   "  eval(\"function t() {";
   1034   const char* function_epilogue = "        }; f = t; t();\");"
   1035                                   "}"
   1036                                   "f1();";
   1037 
   1038   ExpectedSnippet<0> snippets[] = {
   1039       {"return x;", {factory->NewNumber(12)}},
   1040       {"return obj.val;", {factory->NewNumber(3.1414)}},
   1041       {"return typeof x;", {factory->NewStringFromStaticChars("number")}},
   1042       {"return typeof dummy;",
   1043        {factory->NewStringFromStaticChars("undefined")}},
   1044       {"x = 23; return x;", {factory->NewNumber(23)}},
   1045       {"'use strict'; obj.val = 23.456; return obj.val;",
   1046        {factory->NewNumber(23.456)}}};
   1047 
   1048   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1049   for (size_t i = 0; i < num_snippets; i++) {
   1050     ScopedVector<char> script(1024);
   1051     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
   1052              function_epilogue);
   1053 
   1054     BytecodeGraphTester tester(isolate, zone, script.start(), "t");
   1055     auto callable = tester.GetCallable<>();
   1056     Handle<Object> return_value = callable().ToHandleChecked();
   1057     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1058   }
   1059 }
   1060 
   1061 
   1062 TEST(BytecodeGraphBuilderLookupSlotWide) {
   1063   HandleAndZoneScope scope;
   1064   Isolate* isolate = scope.main_isolate();
   1065   Zone* zone = scope.main_zone();
   1066   Factory* factory = isolate->factory();
   1067 
   1068   const char* function_prologue =
   1069       "var f;"
   1070       "var x = 12;"
   1071       "y = 10;"
   1072       "var obj = {val:3.1414};"
   1073       "var z = 30;"
   1074       "function f1() {"
   1075       "  var z = 20;"
   1076       "  eval(\"function t() {";
   1077   const char* function_epilogue =
   1078       "        }; f = t; t();\");"
   1079       "}"
   1080       "f1();";
   1081 
   1082   ExpectedSnippet<0> snippets[] = {
   1083       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x;",
   1084        {factory->NewNumber(12)}},
   1085       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return typeof x;",
   1086        {factory->NewStringFromStaticChars("number")}},
   1087       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x = 23;",
   1088        {factory->NewNumber(23)}},
   1089       {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
   1090        {factory->NewNumber(23.456)}}};
   1091 
   1092   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1093   for (size_t i = 0; i < num_snippets; i++) {
   1094     ScopedVector<char> script(3072);
   1095     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
   1096              function_epilogue);
   1097 
   1098     BytecodeGraphTester tester(isolate, zone, script.start(), "t");
   1099     auto callable = tester.GetCallable<>();
   1100     Handle<Object> return_value = callable().ToHandleChecked();
   1101     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1102   }
   1103 }
   1104 
   1105 
   1106 TEST(BytecodeGraphBuilderCallLookupSlot) {
   1107   HandleAndZoneScope scope;
   1108   Isolate* isolate = scope.main_isolate();
   1109   Zone* zone = scope.main_zone();
   1110 
   1111   ExpectedSnippet<0> snippets[] = {
   1112       {"g = function(){ return 2 }; eval(''); return g();",
   1113        {handle(Smi::FromInt(2), isolate)}},
   1114       {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
   1115        "return g();",
   1116        {handle(Smi::FromInt(3), isolate)}},
   1117       {"g = { x: function(){ return this.y }, y: 20 };\n"
   1118        "eval('g = { x: g.x, y: 30 }');\n"
   1119        "return g.x();",
   1120        {handle(Smi::FromInt(30), isolate)}},
   1121   };
   1122 
   1123   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1124   for (size_t i = 0; i < num_snippets; i++) {
   1125     ScopedVector<char> script(1024);
   1126     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1127              snippets[i].code_snippet, kFunctionName);
   1128     BytecodeGraphTester tester(isolate, zone, script.start());
   1129     auto callable = tester.GetCallable<>();
   1130     Handle<Object> return_value = callable().ToHandleChecked();
   1131     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1132   }
   1133 }
   1134 
   1135 
   1136 TEST(BytecodeGraphBuilderEval) {
   1137   HandleAndZoneScope scope;
   1138   Isolate* isolate = scope.main_isolate();
   1139   Zone* zone = scope.main_zone();
   1140   Factory* factory = isolate->factory();
   1141 
   1142   ExpectedSnippet<0> snippets[] = {
   1143       {"return eval('1;');", {handle(Smi::FromInt(1), isolate)}},
   1144       {"return eval('100 * 20;');", {handle(Smi::FromInt(2000), isolate)}},
   1145       {"var x = 10; return eval('x + 20;');",
   1146        {handle(Smi::FromInt(30), isolate)}},
   1147       {"var x = 10; eval('x = 33;'); return x;",
   1148        {handle(Smi::FromInt(33), isolate)}},
   1149       {"'use strict'; var x = 20; var z = 0;\n"
   1150        "eval('var x = 33; z = x;'); return x + z;",
   1151        {handle(Smi::FromInt(53), isolate)}},
   1152       {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
   1153        {handle(Smi::FromInt(86), isolate)}},
   1154       {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
   1155        {handle(Smi::FromInt(11), isolate)}},
   1156       {"var x = 10; eval('var x = 20;'); return x;",
   1157        {handle(Smi::FromInt(20), isolate)}},
   1158       {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
   1159        {handle(Smi::FromInt(1), isolate)}},
   1160       {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
   1161        {handle(Smi::FromInt(1), isolate)}},
   1162       {"var x = 10; eval('x + 20;'); return typeof x;",
   1163        {factory->NewStringFromStaticChars("number")}},
   1164       {"eval('var y = 10;'); return typeof unallocated;",
   1165        {factory->NewStringFromStaticChars("undefined")}},
   1166       {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
   1167        {factory->NewStringFromStaticChars("undefined")}},
   1168       {"eval('var x = 10;'); return typeof x;",
   1169        {factory->NewStringFromStaticChars("number")}},
   1170       {"var x = {}; eval('var x = 10;'); return typeof x;",
   1171        {factory->NewStringFromStaticChars("number")}},
   1172       {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
   1173        {factory->NewStringFromStaticChars("object")}},
   1174   };
   1175 
   1176   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1177   for (size_t i = 0; i < num_snippets; i++) {
   1178     ScopedVector<char> script(1024);
   1179     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1180              snippets[i].code_snippet, kFunctionName);
   1181     BytecodeGraphTester tester(isolate, zone, script.start());
   1182     auto callable = tester.GetCallable<>();
   1183     Handle<Object> return_value = callable().ToHandleChecked();
   1184     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1185   }
   1186 }
   1187 
   1188 
   1189 TEST(BytecodeGraphBuilderEvalParams) {
   1190   HandleAndZoneScope scope;
   1191   Isolate* isolate = scope.main_isolate();
   1192   Zone* zone = scope.main_zone();
   1193 
   1194   ExpectedSnippet<1> snippets[] = {
   1195       {"var x = 10; return eval('x + p1;');",
   1196        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
   1197       {"var x = 10; eval('p1 = x;'); return p1;",
   1198        {handle(Smi::FromInt(10), isolate), handle(Smi::FromInt(20), isolate)}},
   1199       {"var a = 10;"
   1200        "function inner() { return eval('a + p1;');}"
   1201        "return inner();",
   1202        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
   1203   };
   1204 
   1205   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1206   for (size_t i = 0; i < num_snippets; i++) {
   1207     ScopedVector<char> script(1024);
   1208     SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
   1209              snippets[i].code_snippet, kFunctionName);
   1210     BytecodeGraphTester tester(isolate, zone, script.start());
   1211     auto callable = tester.GetCallable<Handle<Object>>();
   1212     Handle<Object> return_value =
   1213         callable(snippets[i].parameter(0)).ToHandleChecked();
   1214     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1215   }
   1216 }
   1217 
   1218 
   1219 TEST(BytecodeGraphBuilderEvalGlobal) {
   1220   HandleAndZoneScope scope;
   1221   Isolate* isolate = scope.main_isolate();
   1222   Zone* zone = scope.main_zone();
   1223   Factory* factory = isolate->factory();
   1224 
   1225   ExpectedSnippet<0> snippets[] = {
   1226       {"function add_global() { eval('function f() { z = 33; }; f()'); };"
   1227        "function f() { add_global(); return z; }; f();",
   1228        {handle(Smi::FromInt(33), isolate)}},
   1229       {"function add_global() {\n"
   1230        " eval('\"use strict\"; function f() { y = 33; };"
   1231        "      try { f() } catch(e) {}');\n"
   1232        "}\n"
   1233        "function f() { add_global(); return typeof y; } f();",
   1234        {factory->NewStringFromStaticChars("undefined")}},
   1235   };
   1236 
   1237   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1238   for (size_t i = 0; i < num_snippets; i++) {
   1239     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
   1240     auto callable = tester.GetCallable<>();
   1241     Handle<Object> return_value = callable().ToHandleChecked();
   1242     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1243   }
   1244 }
   1245 
   1246 
   1247 bool get_compare_result(Token::Value opcode, Handle<Object> lhs_value,
   1248                         Handle<Object> rhs_value) {
   1249   switch (opcode) {
   1250     case Token::Value::EQ:
   1251       return Object::Equals(lhs_value, rhs_value).FromJust();
   1252     case Token::Value::NE:
   1253       return !Object::Equals(lhs_value, rhs_value).FromJust();
   1254     case Token::Value::EQ_STRICT:
   1255       return lhs_value->StrictEquals(*rhs_value);
   1256     case Token::Value::NE_STRICT:
   1257       return !lhs_value->StrictEquals(*rhs_value);
   1258     case Token::Value::LT:
   1259       return Object::LessThan(lhs_value, rhs_value).FromJust();
   1260     case Token::Value::LTE:
   1261       return Object::LessThanOrEqual(lhs_value, rhs_value).FromJust();
   1262     case Token::Value::GT:
   1263       return Object::GreaterThan(lhs_value, rhs_value).FromJust();
   1264     case Token::Value::GTE:
   1265       return Object::GreaterThanOrEqual(lhs_value, rhs_value).FromJust();
   1266     default:
   1267       UNREACHABLE();
   1268       return false;
   1269   }
   1270 }
   1271 
   1272 
   1273 const char* get_code_snippet(Token::Value opcode) {
   1274   switch (opcode) {
   1275     case Token::Value::EQ:
   1276       return "return p1 == p2;";
   1277     case Token::Value::NE:
   1278       return "return p1 != p2;";
   1279     case Token::Value::EQ_STRICT:
   1280       return "return p1 === p2;";
   1281     case Token::Value::NE_STRICT:
   1282       return "return p1 !== p2;";
   1283     case Token::Value::LT:
   1284       return "return p1 < p2;";
   1285     case Token::Value::LTE:
   1286       return "return p1 <= p2;";
   1287     case Token::Value::GT:
   1288       return "return p1 > p2;";
   1289     case Token::Value::GTE:
   1290       return "return p1 >= p2;";
   1291     default:
   1292       UNREACHABLE();
   1293       return "";
   1294   }
   1295 }
   1296 
   1297 
   1298 TEST(BytecodeGraphBuilderCompare) {
   1299   HandleAndZoneScope scope;
   1300   Isolate* isolate = scope.main_isolate();
   1301   Zone* zone = scope.main_zone();
   1302   Factory* factory = isolate->factory();
   1303   Handle<Object> lhs_values[] = {
   1304       factory->NewNumberFromInt(10), factory->NewHeapNumber(3.45),
   1305       factory->NewStringFromStaticChars("abc"),
   1306       factory->NewNumberFromInt(SMI_MAX), factory->NewNumberFromInt(SMI_MIN)};
   1307   Handle<Object> rhs_values[] = {factory->NewNumberFromInt(10),
   1308                                  factory->NewStringFromStaticChars("10"),
   1309                                  factory->NewNumberFromInt(20),
   1310                                  factory->NewStringFromStaticChars("abc"),
   1311                                  factory->NewHeapNumber(3.45),
   1312                                  factory->NewNumberFromInt(SMI_MAX),
   1313                                  factory->NewNumberFromInt(SMI_MIN)};
   1314 
   1315   for (size_t i = 0; i < arraysize(kCompareOperators); i++) {
   1316     ScopedVector<char> script(1024);
   1317     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
   1318              get_code_snippet(kCompareOperators[i]), kFunctionName);
   1319 
   1320     BytecodeGraphTester tester(isolate, zone, script.start());
   1321     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   1322     for (size_t j = 0; j < arraysize(lhs_values); j++) {
   1323       for (size_t k = 0; k < arraysize(rhs_values); k++) {
   1324         Handle<Object> return_value =
   1325             callable(lhs_values[j], rhs_values[k]).ToHandleChecked();
   1326         bool result = get_compare_result(kCompareOperators[i], lhs_values[j],
   1327                                          rhs_values[k]);
   1328         CHECK(return_value->SameValue(*factory->ToBoolean(result)));
   1329       }
   1330     }
   1331   }
   1332 }
   1333 
   1334 
   1335 TEST(BytecodeGraphBuilderTestIn) {
   1336   HandleAndZoneScope scope;
   1337   Isolate* isolate = scope.main_isolate();
   1338   Zone* zone = scope.main_zone();
   1339   Factory* factory = isolate->factory();
   1340 
   1341   ExpectedSnippet<2> snippets[] = {
   1342       {"return p2 in p1;",
   1343        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1344         factory->NewStringFromStaticChars("val")}},
   1345       {"return p2 in p1;",
   1346        {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
   1347         factory->NewStringFromStaticChars("length")}},
   1348       {"return p2 in p1;",
   1349        {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
   1350         factory->NewStringFromStaticChars("toString")}},
   1351       {"return p2 in p1;",
   1352        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1353         factory->NewStringFromStaticChars("toString")}},
   1354       {"return p2 in p1;",
   1355        {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1356         factory->NewStringFromStaticChars("abc")}},
   1357       {"return p2 in p1;",
   1358        {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1359         factory->NewNumberFromInt(10)}},
   1360       {"return p2 in p1;",
   1361        {factory->true_value(), BytecodeGraphTester::NewObject("({10 : 'val'})"),
   1362         factory->NewNumberFromInt(10)}},
   1363       {"return p2 in p1;",
   1364        {factory->false_value(),
   1365         BytecodeGraphTester::NewObject("({10 : 'val'})"),
   1366         factory->NewNumberFromInt(1)}},
   1367   };
   1368 
   1369   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1370   for (size_t i = 0; i < num_snippets; i++) {
   1371     ScopedVector<char> script(1024);
   1372     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
   1373              snippets[i].code_snippet, kFunctionName);
   1374 
   1375     BytecodeGraphTester tester(isolate, zone, script.start());
   1376     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   1377     Handle<Object> return_value =
   1378         callable(snippets[i].parameter(0), snippets[i].parameter(1))
   1379             .ToHandleChecked();
   1380     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1381   }
   1382 }
   1383 
   1384 
   1385 TEST(BytecodeGraphBuilderTestInstanceOf) {
   1386   HandleAndZoneScope scope;
   1387   Isolate* isolate = scope.main_isolate();
   1388   Zone* zone = scope.main_zone();
   1389   Factory* factory = isolate->factory();
   1390 
   1391   ExpectedSnippet<1> snippets[] = {
   1392       {"return p1 instanceof Object;",
   1393        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
   1394       {"return p1 instanceof String;",
   1395        {factory->false_value(), factory->NewStringFromStaticChars("string")}},
   1396       {"var cons = function() {};"
   1397        "var obj = new cons();"
   1398        "return obj instanceof cons;",
   1399        {factory->true_value(), factory->undefined_value()}},
   1400   };
   1401 
   1402   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1403   for (size_t i = 0; i < num_snippets; i++) {
   1404     ScopedVector<char> script(1024);
   1405     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
   1406              snippets[i].code_snippet, kFunctionName);
   1407 
   1408     BytecodeGraphTester tester(isolate, zone, script.start());
   1409     auto callable = tester.GetCallable<Handle<Object>>();
   1410     Handle<Object> return_value =
   1411         callable(snippets[i].parameter(0)).ToHandleChecked();
   1412     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1413   }
   1414 }
   1415 
   1416 
   1417 TEST(BytecodeGraphBuilderThrow) {
   1418   HandleAndZoneScope scope;
   1419   Isolate* isolate = scope.main_isolate();
   1420   Zone* zone = scope.main_zone();
   1421 
   1422   // TODO(mythria): Add more tests when real try-catch and deoptimization
   1423   // information are supported.
   1424   ExpectedSnippet<0, const char*> snippets[] = {
   1425       {"throw undefined;", {"Uncaught undefined"}},
   1426       {"throw 1;", {"Uncaught 1"}},
   1427       {"throw 'Error';", {"Uncaught Error"}},
   1428       {"throw 'Error1'; throw 'Error2'", {"Uncaught Error1"}},
   1429       // TODO(mythria): Enable these tests when JumpIfTrue is supported.
   1430       // {"var a = true; if (a) { throw 'Error'; }", {"Error"}},
   1431   };
   1432 
   1433   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1434   for (size_t i = 0; i < num_snippets; i++) {
   1435     ScopedVector<char> script(1024);
   1436     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1437              snippets[i].code_snippet, kFunctionName);
   1438     BytecodeGraphTester tester(isolate, zone, script.start());
   1439     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   1440     v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
   1441     CHECK(
   1442         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   1443             .FromJust());
   1444   }
   1445 }
   1446 
   1447 
   1448 TEST(BytecodeGraphBuilderContext) {
   1449   HandleAndZoneScope scope;
   1450   Isolate* isolate = scope.main_isolate();
   1451   Zone* zone = scope.main_zone();
   1452   Factory* factory = isolate->factory();
   1453 
   1454   ExpectedSnippet<0> snippets[] = {
   1455       {"var x = 'outer';"
   1456        "function f() {"
   1457        " 'use strict';"
   1458        " {"
   1459        "   let x = 'inner';"
   1460        "   (function() {x});"
   1461        " }"
   1462        "return(x);"
   1463        "}"
   1464        "f();",
   1465        {factory->NewStringFromStaticChars("outer")}},
   1466       {"var x = 'outer';"
   1467        "function f() {"
   1468        " 'use strict';"
   1469        " {"
   1470        "   let x = 'inner ';"
   1471        "   var innerFunc = function() {return x};"
   1472        " }"
   1473        "return(innerFunc() + x);"
   1474        "}"
   1475        "f();",
   1476        {factory->NewStringFromStaticChars("inner outer")}},
   1477       {"var x = 'outer';"
   1478        "function f() {"
   1479        " 'use strict';"
   1480        " {"
   1481        "   let x = 'inner ';"
   1482        "   var innerFunc = function() {return x;};"
   1483        "   {"
   1484        "     let x = 'innermost ';"
   1485        "     var innerMostFunc = function() {return x + innerFunc();};"
   1486        "   }"
   1487        "   x = 'inner_changed ';"
   1488        " }"
   1489        " return(innerMostFunc() + x);"
   1490        "}"
   1491        "f();",
   1492        {factory->NewStringFromStaticChars("innermost inner_changed outer")}},
   1493   };
   1494 
   1495   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1496   for (size_t i = 0; i < num_snippets; i++) {
   1497     ScopedVector<char> script(1024);
   1498     SNPrintF(script, "%s", snippets[i].code_snippet);
   1499 
   1500     BytecodeGraphTester tester(isolate, zone, script.start(), "f");
   1501     auto callable = tester.GetCallable<>("f");
   1502     Handle<Object> return_value = callable().ToHandleChecked();
   1503     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1504   }
   1505 }
   1506 
   1507 
   1508 TEST(BytecodeGraphBuilderLoadContext) {
   1509   HandleAndZoneScope scope;
   1510   Isolate* isolate = scope.main_isolate();
   1511   Zone* zone = scope.main_zone();
   1512   Factory* factory = isolate->factory();
   1513 
   1514   ExpectedSnippet<1> snippets[] = {
   1515       {"function Outer() {"
   1516        "  var outerVar = 2;"
   1517        "  function Inner(innerArg) {"
   1518        "    this.innerFunc = function () {"
   1519        "     return outerVar * innerArg;"
   1520        "    };"
   1521        "  };"
   1522        "  this.getInnerFunc = function GetInner() {"
   1523        "     return new Inner(3).innerFunc;"
   1524        "   }"
   1525        "}"
   1526        "var f = new Outer().getInnerFunc();"
   1527        "f();",
   1528        {factory->NewNumberFromInt(6), factory->undefined_value()}},
   1529       {"function Outer() {"
   1530        "  var outerVar = 2;"
   1531        "  function Inner(innerArg) {"
   1532        "    this.innerFunc = function () {"
   1533        "     outerVar = innerArg; return outerVar;"
   1534        "    };"
   1535        "  };"
   1536        "  this.getInnerFunc = function GetInner() {"
   1537        "     return new Inner(10).innerFunc;"
   1538        "   }"
   1539        "}"
   1540        "var f = new Outer().getInnerFunc();"
   1541        "f();",
   1542        {factory->NewNumberFromInt(10), factory->undefined_value()}},
   1543       {"function testOuter(outerArg) {"
   1544        " this.testinnerFunc = function testInner(innerArg) {"
   1545        "   return innerArg + outerArg;"
   1546        " }"
   1547        "}"
   1548        "var f = new testOuter(10).testinnerFunc;"
   1549        "f(0);",
   1550        {factory->NewNumberFromInt(14), factory->NewNumberFromInt(4)}},
   1551       {"function testOuter(outerArg) {"
   1552        " var outerVar = outerArg * 2;"
   1553        " this.testinnerFunc = function testInner(innerArg) {"
   1554        "   outerVar = outerVar + innerArg; return outerVar;"
   1555        " }"
   1556        "}"
   1557        "var f = new testOuter(10).testinnerFunc;"
   1558        "f(0);",
   1559        {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
   1560 
   1561   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1562   for (size_t i = 0; i < num_snippets; i++) {
   1563     ScopedVector<char> script(1024);
   1564     SNPrintF(script, "%s", snippets[i].code_snippet);
   1565 
   1566     BytecodeGraphTester tester(isolate, zone, script.start(), "*");
   1567     auto callable = tester.GetCallable<Handle<Object>>("f");
   1568     Handle<Object> return_value =
   1569         callable(snippets[i].parameter(0)).ToHandleChecked();
   1570     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1571   }
   1572 }
   1573 
   1574 
   1575 TEST(BytecodeGraphBuilderCreateArgumentsNoParameters) {
   1576   HandleAndZoneScope scope;
   1577   Isolate* isolate = scope.main_isolate();
   1578   Zone* zone = scope.main_zone();
   1579   Factory* factory = isolate->factory();
   1580 
   1581   ExpectedSnippet<0> snippets[] = {
   1582       {"function f() {return arguments[0];}", {factory->undefined_value()}},
   1583       {"function f(a) {return arguments[0];}", {factory->undefined_value()}},
   1584       {"function f() {'use strict'; return arguments[0];}",
   1585        {factory->undefined_value()}},
   1586       {"function f(a) {'use strict'; return arguments[0];}",
   1587        {factory->undefined_value()}},
   1588   };
   1589 
   1590   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1591   for (size_t i = 0; i < num_snippets; i++) {
   1592     ScopedVector<char> script(1024);
   1593     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
   1594 
   1595     BytecodeGraphTester tester(isolate, zone, script.start());
   1596     auto callable = tester.GetCallable<>();
   1597     Handle<Object> return_value = callable().ToHandleChecked();
   1598     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1599   }
   1600 }
   1601 
   1602 
   1603 TEST(BytecodeGraphBuilderCreateArguments) {
   1604   HandleAndZoneScope scope;
   1605   Isolate* isolate = scope.main_isolate();
   1606   Zone* zone = scope.main_zone();
   1607   Factory* factory = isolate->factory();
   1608 
   1609   ExpectedSnippet<3> snippets[] = {
   1610       {"function f(a, b, c) {return arguments[0];}",
   1611        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
   1612         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1613       {"function f(a, b, c) {return arguments[3];}",
   1614        {factory->undefined_value(), factory->NewNumberFromInt(1),
   1615         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1616       {"function f(a, b, c) { b = c; return arguments[1];}",
   1617        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1618         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1619       {"function f(a, b, c) {'use strict'; return arguments[0];}",
   1620        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
   1621         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1622       {"function f(a, b, c) {'use strict'; return arguments[3];}",
   1623        {factory->undefined_value(), factory->NewNumberFromInt(1),
   1624         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1625       {"function f(a, b, c) {'use strict'; b = c; return arguments[1];}",
   1626        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
   1627         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1628       {"function inline_func(a, b) { return arguments[0] }"
   1629        "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
   1630        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1631         factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
   1632   };
   1633 
   1634   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1635   for (size_t i = 0; i < num_snippets; i++) {
   1636     ScopedVector<char> script(1024);
   1637     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
   1638 
   1639     BytecodeGraphTester tester(isolate, zone, script.start());
   1640     auto callable =
   1641         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
   1642     Handle<Object> return_value =
   1643         callable(snippets[i].parameter(0), snippets[i].parameter(1),
   1644                  snippets[i].parameter(2))
   1645             .ToHandleChecked();
   1646     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1647   }
   1648 }
   1649 
   1650 
   1651 TEST(BytecodeGraphBuilderRegExpLiterals) {
   1652   HandleAndZoneScope scope;
   1653   Isolate* isolate = scope.main_isolate();
   1654   Zone* zone = scope.main_zone();
   1655   Factory* factory = isolate->factory();
   1656 
   1657   ExpectedSnippet<0> snippets[] = {
   1658       {"return /abd/.exec('cccabbdd');", {factory->null_value()}},
   1659       {"return /ab+d/.exec('cccabbdd')[0];",
   1660        {factory->NewStringFromStaticChars("abbd")}},
   1661       {"var a = 3.1414;"
   1662        REPEAT_256(SPACE, "a = 3.1414;")
   1663        "return /ab+d/.exec('cccabbdd')[0];",
   1664        {factory->NewStringFromStaticChars("abbd")}},
   1665       {"return /ab+d/.exec('cccabbdd')[1];", {factory->undefined_value()}},
   1666       {"return /AbC/i.exec('ssaBC')[0];",
   1667        {factory->NewStringFromStaticChars("aBC")}},
   1668       {"return 'ssaBC'.match(/AbC/i)[0];",
   1669        {factory->NewStringFromStaticChars("aBC")}},
   1670       {"return 'ssaBCtAbC'.match(/(AbC)/gi)[1];",
   1671        {factory->NewStringFromStaticChars("AbC")}},
   1672   };
   1673 
   1674   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1675   for (size_t i = 0; i < num_snippets; i++) {
   1676     ScopedVector<char> script(4096);
   1677     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1678              snippets[i].code_snippet, kFunctionName);
   1679 
   1680     BytecodeGraphTester tester(isolate, zone, script.start());
   1681     auto callable = tester.GetCallable<>();
   1682     Handle<Object> return_value = callable().ToHandleChecked();
   1683     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1684   }
   1685 }
   1686 
   1687 
   1688 TEST(BytecodeGraphBuilderArrayLiterals) {
   1689   HandleAndZoneScope scope;
   1690   Isolate* isolate = scope.main_isolate();
   1691   Zone* zone = scope.main_zone();
   1692   Factory* factory = isolate->factory();
   1693 
   1694   ExpectedSnippet<0> snippets[] = {
   1695       {"return [][0];", {factory->undefined_value()}},
   1696       {"return [1, 3, 2][1];", {factory->NewNumberFromInt(3)}},
   1697       {"var a;" REPEAT_256(SPACE, "a = 9.87;") "return [1, 3, 2][1];",
   1698        {factory->NewNumberFromInt(3)}},
   1699       {"return ['a', 'b', 'c'][2];", {factory->NewStringFromStaticChars("c")}},
   1700       {"var a = 100; return [a, a++, a + 2, a + 3][2];",
   1701        {factory->NewNumberFromInt(103)}},
   1702       {"var a = 100; return [a, ++a, a + 2, a + 3][1];",
   1703        {factory->NewNumberFromInt(101)}},
   1704       {"var a = 9.2;"
   1705        REPEAT_256(SPACE, "a = 9.34;")
   1706        "return [a, ++a, a + 2, a + 3][2];",
   1707        {factory->NewHeapNumber(12.34)}},
   1708       {"return [[1, 2, 3], ['a', 'b', 'c']][1][0];",
   1709        {factory->NewStringFromStaticChars("a")}},
   1710       {"var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];",
   1711        {factory->NewStringFromStaticChars("test")}},
   1712       {"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
   1713        {factory->NewStringFromStaticChars("1t")}}};
   1714 
   1715   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1716   for (size_t i = 0; i < num_snippets; i++) {
   1717     ScopedVector<char> script(4096);
   1718     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1719              snippets[i].code_snippet, kFunctionName);
   1720 
   1721     BytecodeGraphTester tester(isolate, zone, script.start());
   1722     auto callable = tester.GetCallable<>();
   1723     Handle<Object> return_value = callable().ToHandleChecked();
   1724     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1725   }
   1726 }
   1727 
   1728 
   1729 TEST(BytecodeGraphBuilderObjectLiterals) {
   1730   HandleAndZoneScope scope;
   1731   Isolate* isolate = scope.main_isolate();
   1732   Zone* zone = scope.main_zone();
   1733   Factory* factory = isolate->factory();
   1734 
   1735   ExpectedSnippet<0> snippets[] = {
   1736       {"return { }.name;", {factory->undefined_value()}},
   1737       {"return { name: 'string', val: 9.2 }.name;",
   1738        {factory->NewStringFromStaticChars("string")}},
   1739       {"var a;\n"
   1740        REPEAT_256(SPACE, "a = 1.23;\n")
   1741        "return { name: 'string', val: 9.2 }.name;",
   1742        {factory->NewStringFromStaticChars("string")}},
   1743       {"return { name: 'string', val: 9.2 }['name'];",
   1744        {factory->NewStringFromStaticChars("string")}},
   1745       {"var a = 15; return { name: 'string', val: a }.val;",
   1746        {factory->NewNumberFromInt(15)}},
   1747       {"var a;"
   1748        REPEAT_256(SPACE, "a = 1.23;")
   1749        "return { name: 'string', val: a }.val;",
   1750        {factory->NewHeapNumber(1.23)}},
   1751       {"var a = 15; var b = 'val'; return { name: 'string', val: a }[b];",
   1752        {factory->NewNumberFromInt(15)}},
   1753       {"var a = 5; return { val: a, val: a + 1 }.val;",
   1754        {factory->NewNumberFromInt(6)}},
   1755       {"return { func: function() { return 'test' } }.func();",
   1756        {factory->NewStringFromStaticChars("test")}},
   1757       {"return { func(a) { return a + 'st'; } }.func('te');",
   1758        {factory->NewStringFromStaticChars("test")}},
   1759       {"return { get a() { return 22; } }.a;", {factory->NewNumberFromInt(22)}},
   1760       {"var a = { get b() { return this.x + 't'; },\n"
   1761        "          set b(val) { this.x = val + 's' } };\n"
   1762        "a.b = 'te';\n"
   1763        "return a.b;",
   1764        {factory->NewStringFromStaticChars("test")}},
   1765       {"var a = 123; return { 1: a }[1];", {factory->NewNumberFromInt(123)}},
   1766       {"return Object.getPrototypeOf({ __proto__: null });",
   1767        {factory->null_value()}},
   1768       {"var a = 'test'; return { [a]: 1 }.test;",
   1769        {factory->NewNumberFromInt(1)}},
   1770       {"var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
   1771        {factory->NewStringFromStaticChars("testing")}},
   1772       {"var a = 'proto_str';\n"
   1773        "var b = { [a]: 1, __proto__: { var : a } };\n"
   1774        "return Object.getPrototypeOf(b).var",
   1775        {factory->NewStringFromStaticChars("proto_str")}},
   1776       {"var n = 'name';\n"
   1777        "return { [n]: 'val', get a() { return 987 } }['a'];",
   1778        {factory->NewNumberFromInt(987)}},
   1779   };
   1780 
   1781   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1782   for (size_t i = 0; i < num_snippets; i++) {
   1783     ScopedVector<char> script(4096);
   1784     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1785              snippets[i].code_snippet, kFunctionName);
   1786     BytecodeGraphTester tester(isolate, zone, script.start());
   1787     auto callable = tester.GetCallable<>();
   1788     Handle<Object> return_value = callable().ToHandleChecked();
   1789     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1790   }
   1791 }
   1792 
   1793 
   1794 TEST(BytecodeGraphBuilderIf) {
   1795   HandleAndZoneScope scope;
   1796   Isolate* isolate = scope.main_isolate();
   1797   Zone* zone = scope.main_zone();
   1798   Factory* factory = isolate->factory();
   1799 
   1800   ExpectedSnippet<1> snippets[] = {
   1801       {"if (p1 > 1) return 1;\n"
   1802        "return -1;",
   1803        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   1804       {"if (p1 > 1) return 1;\n"
   1805        "return -1;",
   1806        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
   1807       {"if (p1 > 1) { return 1; } else { return -1; }",
   1808        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   1809       {"if (p1 > 1) { return 1; } else { return -1; }",
   1810        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
   1811       {"if (p1 > 50) {\n"
   1812        "  return 1;\n"
   1813        "} else if (p1 < 10) {\n"
   1814        "   return 10;\n"
   1815        "} else {\n"
   1816        "   return -10;\n"
   1817        "}",
   1818        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(51)}},
   1819       {"if (p1 > 50) {\n"
   1820        "  return 1;\n"
   1821        "} else if (p1 < 10) {\n"
   1822        "   return 10;\n"
   1823        "} else {\n"
   1824        "   return 100;\n"
   1825        "}",
   1826        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
   1827       {"if (p1 > 50) {\n"
   1828        "  return 1;\n"
   1829        "} else if (p1 < 10) {\n"
   1830        "   return 10;\n"
   1831        "} else {\n"
   1832        "   return 100;\n"
   1833        "}",
   1834        {factory->NewNumberFromInt(100), factory->NewNumberFromInt(10)}},
   1835       {"if (p1 >= 0) {\n"
   1836        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1837        "} else {\n"
   1838        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1839        "}",
   1840        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(100)}},
   1841       {"if (p1 >= 0) {\n"
   1842        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1843        "} else {\n"
   1844        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1845        "}",
   1846        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(10)}},
   1847       {"if (p1 >= 0) {\n"
   1848        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1849        "} else {\n"
   1850        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1851        "}",
   1852        {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(-11)}},
   1853       {"if (p1 >= 0) {\n"
   1854        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1855        "} else {\n"
   1856        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1857        "}",
   1858        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-10)}},
   1859   };
   1860 
   1861   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1862   for (size_t i = 0; i < num_snippets; i++) {
   1863     ScopedVector<char> script(2048);
   1864     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   1865              snippets[i].code_snippet, kFunctionName);
   1866 
   1867     BytecodeGraphTester tester(isolate, zone, script.start());
   1868     auto callable = tester.GetCallable<Handle<Object>>();
   1869     Handle<Object> return_value =
   1870         callable(snippets[i].parameter(0)).ToHandleChecked();
   1871     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1872   }
   1873 }
   1874 
   1875 
   1876 TEST(BytecodeGraphBuilderConditionalOperator) {
   1877   HandleAndZoneScope scope;
   1878   Isolate* isolate = scope.main_isolate();
   1879   Zone* zone = scope.main_zone();
   1880   Factory* factory = isolate->factory();
   1881 
   1882   ExpectedSnippet<1> snippets[] = {
   1883       {"return (p1 > 1) ? 1 : -1;",
   1884        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   1885       {"return (p1 > 1) ? 1 : -1;",
   1886        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0)}},
   1887       {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
   1888        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(2)}},
   1889       {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
   1890        {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(20)}},
   1891   };
   1892 
   1893   size_t num_snippets = sizeof(snippets) / sizeof(snippets[0]);
   1894   for (size_t i = 0; i < num_snippets; i++) {
   1895     ScopedVector<char> script(2048);
   1896     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   1897              snippets[i].code_snippet, kFunctionName);
   1898 
   1899     BytecodeGraphTester tester(isolate, zone, script.start());
   1900     auto callable = tester.GetCallable<Handle<Object>>();
   1901     Handle<Object> return_value =
   1902         callable(snippets[i].parameter(0)).ToHandleChecked();
   1903     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1904   }
   1905 }
   1906 
   1907 
   1908 TEST(BytecodeGraphBuilderSwitch) {
   1909   HandleAndZoneScope scope;
   1910   Isolate* isolate = scope.main_isolate();
   1911   Zone* zone = scope.main_zone();
   1912   Factory* factory = isolate->factory();
   1913 
   1914   const char* switch_code =
   1915       "switch (p1) {\n"
   1916       "  case 1: return 0;\n"
   1917       "  case 2: return 1;\n"
   1918       "  case 3:\n"
   1919       "  case 4: return 2;\n"
   1920       "  case 9: break;\n"
   1921       "  default: return 3;\n"
   1922       "}\n"
   1923       "return 9;";
   1924 
   1925   ExpectedSnippet<1> snippets[] = {
   1926       {switch_code,
   1927        {factory->NewNumberFromInt(0), factory->NewNumberFromInt(1)}},
   1928       {switch_code,
   1929        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   1930       {switch_code,
   1931        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1932       {switch_code,
   1933        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
   1934       {switch_code,
   1935        {factory->NewNumberFromInt(9), factory->NewNumberFromInt(9)}},
   1936       {switch_code,
   1937        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
   1938       {switch_code,
   1939        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(6)}},
   1940   };
   1941 
   1942   for (size_t i = 0; i < arraysize(snippets); i++) {
   1943     ScopedVector<char> script(2048);
   1944     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   1945              snippets[i].code_snippet, kFunctionName);
   1946 
   1947     BytecodeGraphTester tester(isolate, zone, script.start());
   1948     auto callable = tester.GetCallable<Handle<Object>>();
   1949     Handle<Object> return_value =
   1950         callable(snippets[i].parameter(0)).ToHandleChecked();
   1951     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1952   }
   1953 }
   1954 
   1955 
   1956 TEST(BytecodeGraphBuilderNestedSwitch) {
   1957   HandleAndZoneScope scope;
   1958   Isolate* isolate = scope.main_isolate();
   1959   Zone* zone = scope.main_zone();
   1960   Factory* factory = isolate->factory();
   1961 
   1962   const char* switch_code =
   1963       "switch (p1) {\n"
   1964       "  case 0: {"
   1965       "    switch (p2) { case 0: return 0; case 1: return 1; case 2: break; }\n"
   1966       "    return -1;"
   1967       "  }\n"
   1968       "  case 1: {"
   1969       "    switch (p2) { case 0: return 2; case 1: return 3; }\n"
   1970       "  }\n"
   1971       "  case 2: break;"
   1972       "  }\n"
   1973       "return -2;";
   1974 
   1975   ExpectedSnippet<2> snippets[] = {
   1976       {switch_code,
   1977        {factory->NewNumberFromInt(0), factory->NewNumberFromInt(0),
   1978         factory->NewNumberFromInt(0)}},
   1979       {switch_code,
   1980        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(0),
   1981         factory->NewNumberFromInt(1)}},
   1982       {switch_code,
   1983        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
   1984         factory->NewNumberFromInt(2)}},
   1985       {switch_code,
   1986        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
   1987         factory->NewNumberFromInt(3)}},
   1988       {switch_code,
   1989        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
   1990         factory->NewNumberFromInt(0)}},
   1991       {switch_code,
   1992        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1993         factory->NewNumberFromInt(1)}},
   1994       {switch_code,
   1995        {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(1),
   1996         factory->NewNumberFromInt(2)}},
   1997       {switch_code,
   1998        {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(2),
   1999         factory->NewNumberFromInt(0)}},
   2000   };
   2001 
   2002   for (size_t i = 0; i < arraysize(snippets); i++) {
   2003     ScopedVector<char> script(2048);
   2004     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0, 0);", kFunctionName,
   2005              snippets[i].code_snippet, kFunctionName);
   2006 
   2007     BytecodeGraphTester tester(isolate, zone, script.start());
   2008     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   2009     Handle<Object> return_value =
   2010         callable(snippets[i].parameter(0), snippets[i].parameter(1))
   2011             .ToHandleChecked();
   2012     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2013   }
   2014 }
   2015 
   2016 
   2017 TEST(BytecodeGraphBuilderBreakableBlocks) {
   2018   HandleAndZoneScope scope;
   2019   Isolate* isolate = scope.main_isolate();
   2020   Zone* zone = scope.main_zone();
   2021   Factory* factory = isolate->factory();
   2022 
   2023   ExpectedSnippet<0> snippets[] = {
   2024       {"var x = 0;\n"
   2025        "my_heart: {\n"
   2026        "  x = x + 1;\n"
   2027        "  break my_heart;\n"
   2028        "  x = x + 2;\n"
   2029        "}\n"
   2030        "return x;\n",
   2031        {factory->NewNumberFromInt(1)}},
   2032       {"var sum = 0;\n"
   2033        "outta_here: {\n"
   2034        "  for (var x = 0; x < 10; ++x) {\n"
   2035        "    for (var y = 0; y < 3; ++y) {\n"
   2036        "      ++sum;\n"
   2037        "      if (x + y == 12) { break outta_here; }\n"
   2038        "    }\n"
   2039        "  }\n"
   2040        "}\n"
   2041        "return sum;",
   2042        {factory->NewNumber(30)}},
   2043   };
   2044 
   2045   for (size_t i = 0; i < arraysize(snippets); i++) {
   2046     ScopedVector<char> script(1024);
   2047     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2048              snippets[i].code_snippet, kFunctionName);
   2049 
   2050     BytecodeGraphTester tester(isolate, zone, script.start());
   2051     auto callable = tester.GetCallable<>();
   2052     Handle<Object> return_value = callable().ToHandleChecked();
   2053     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2054   }
   2055 }
   2056 
   2057 
   2058 TEST(BytecodeGraphBuilderWhile) {
   2059   HandleAndZoneScope scope;
   2060   Isolate* isolate = scope.main_isolate();
   2061   Zone* zone = scope.main_zone();
   2062   Factory* factory = isolate->factory();
   2063 
   2064   ExpectedSnippet<0> snippets[] = {
   2065       {"var x = 1; while (x < 1) { x *= 100; } return x;",
   2066        {factory->NewNumberFromInt(1)}},
   2067       {"var x = 1, y = 0; while (x < 7) { y += x * x; x += 1; } return y;",
   2068        {factory->NewNumberFromInt(91)}},
   2069       {"var x = 1; while (true) { x += 1; if (x == 10) break; } return x;",
   2070        {factory->NewNumberFromInt(10)}},
   2071       {"var x = 1; while (false) { x += 1; } return x;",
   2072        {factory->NewNumberFromInt(1)}},
   2073       {"var x = 0;\n"
   2074        "while (true) {\n"
   2075        "  while (x < 10) {\n"
   2076        "    x = x * x + 1;\n"
   2077        "  }"
   2078        "  x += 1;\n"
   2079        "  break;\n"
   2080        "}\n"
   2081        "return x;",
   2082        {factory->NewNumberFromInt(27)}},
   2083       {"var x = 1, y = 0;\n"
   2084        "while (x < 7) {\n"
   2085        "  x += 1;\n"
   2086        "  if (x == 2) continue;\n"
   2087        "  if (x == 3) continue;\n"
   2088        "  y += x * x;\n"
   2089        "  if (x == 4) break;\n"
   2090        "}\n"
   2091        "return y;",
   2092        {factory->NewNumberFromInt(16)}}};
   2093 
   2094   for (size_t i = 0; i < arraysize(snippets); i++) {
   2095     ScopedVector<char> script(1024);
   2096     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2097              snippets[i].code_snippet, kFunctionName);
   2098 
   2099     BytecodeGraphTester tester(isolate, zone, script.start());
   2100     auto callable = tester.GetCallable<>();
   2101     Handle<Object> return_value = callable().ToHandleChecked();
   2102     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2103   }
   2104 }
   2105 
   2106 
   2107 TEST(BytecodeGraphBuilderDo) {
   2108   HandleAndZoneScope scope;
   2109   Isolate* isolate = scope.main_isolate();
   2110   Zone* zone = scope.main_zone();
   2111   Factory* factory = isolate->factory();
   2112 
   2113   ExpectedSnippet<0> snippets[] = {
   2114       {"var x = 1; do { x *= 100; } while (x < 100); return x;",
   2115        {factory->NewNumberFromInt(100)}},
   2116       {"var x = 1; do { x = x * x + 1; } while (x < 7) return x;",
   2117        {factory->NewNumberFromInt(26)}},
   2118       {"var x = 1; do { x += 1; } while (false); return x;",
   2119        {factory->NewNumberFromInt(2)}},
   2120       {"var x = 1, y = 0;\n"
   2121        "do {\n"
   2122        "  x += 1;\n"
   2123        "  if (x == 2) continue;\n"
   2124        "  if (x == 3) continue;\n"
   2125        "  y += x * x;\n"
   2126        "  if (x == 4) break;\n"
   2127        "} while (x < 7);\n"
   2128        "return y;",
   2129        {factory->NewNumberFromInt(16)}}};
   2130 
   2131   for (size_t i = 0; i < arraysize(snippets); i++) {
   2132     ScopedVector<char> script(1024);
   2133     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2134              snippets[i].code_snippet, kFunctionName);
   2135 
   2136     BytecodeGraphTester tester(isolate, zone, script.start());
   2137     auto callable = tester.GetCallable<>();
   2138     Handle<Object> return_value = callable().ToHandleChecked();
   2139     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2140   }
   2141 }
   2142 
   2143 
   2144 TEST(BytecodeGraphBuilderFor) {
   2145   HandleAndZoneScope scope;
   2146   Isolate* isolate = scope.main_isolate();
   2147   Zone* zone = scope.main_zone();
   2148   Factory* factory = isolate->factory();
   2149 
   2150   ExpectedSnippet<0> snippets[] = {
   2151       {"for (var x = 0;; x = 2 * x + 1) { if (x > 10) return x; }",
   2152        {factory->NewNumberFromInt(15)}},
   2153       {"for (var x = 0; true; x = 2 * x + 1) { if (x > 100) return x; }",
   2154        {factory->NewNumberFromInt(127)}},
   2155       {"for (var x = 0; false; x = 2 * x + 1) { if (x > 100) return x; } "
   2156        "return 0;",
   2157        {factory->NewNumberFromInt(0)}},
   2158       {"for (var x = 0; x < 200; x = 2 * x + 1) { x = x; } return x;",
   2159        {factory->NewNumberFromInt(255)}},
   2160       {"for (var x = 0; x < 200; x = 2 * x + 1) {} return x;",
   2161        {factory->NewNumberFromInt(255)}},
   2162       {"var sum = 0;\n"
   2163        "for (var x = 0; x < 200; x += 1) {\n"
   2164        "  if (x % 2) continue;\n"
   2165        "  if (sum > 10) break;\n"
   2166        "  sum += x;\n"
   2167        "}\n"
   2168        "return sum;",
   2169        {factory->NewNumberFromInt(12)}},
   2170       {"var sum = 0;\n"
   2171        "for (var w = 0; w < 2; w++) {\n"
   2172        "  for (var x = 0; x < 200; x += 1) {\n"
   2173        "    if (x % 2) continue;\n"
   2174        "    if (x > 4) break;\n"
   2175        "    sum += x + w;\n"
   2176        "  }\n"
   2177        "}\n"
   2178        "return sum;",
   2179        {factory->NewNumberFromInt(15)}},
   2180       {"var sum = 0;\n"
   2181        "for (var w = 0; w < 2; w++) {\n"
   2182        "  if (w == 1) break;\n"
   2183        "  for (var x = 0; x < 200; x += 1) {\n"
   2184        "    if (x % 2) continue;\n"
   2185        "    if (x > 4) break;\n"
   2186        "    sum += x + w;\n"
   2187        "  }\n"
   2188        "}\n"
   2189        "return sum;",
   2190        {factory->NewNumberFromInt(6)}},
   2191       {"var sum = 0;\n"
   2192        "for (var w = 0; w < 3; w++) {\n"
   2193        "  if (w == 1) continue;\n"
   2194        "  for (var x = 0; x < 200; x += 1) {\n"
   2195        "    if (x % 2) continue;\n"
   2196        "    if (x > 4) break;\n"
   2197        "    sum += x + w;\n"
   2198        "  }\n"
   2199        "}\n"
   2200        "return sum;",
   2201        {factory->NewNumberFromInt(18)}},
   2202       {"var sum = 0;\n"
   2203        "for (var x = 1; x < 10; x += 2) {\n"
   2204        "  for (var y = x; y < x + 2; y++) {\n"
   2205        "    sum += y * y;\n"
   2206        "  }\n"
   2207        "}\n"
   2208        "return sum;",
   2209        {factory->NewNumberFromInt(385)}},
   2210   };
   2211 
   2212   for (size_t i = 0; i < arraysize(snippets); i++) {
   2213     ScopedVector<char> script(1024);
   2214     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2215              snippets[i].code_snippet, kFunctionName);
   2216 
   2217     BytecodeGraphTester tester(isolate, zone, script.start());
   2218     auto callable = tester.GetCallable<>();
   2219     Handle<Object> return_value = callable().ToHandleChecked();
   2220     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2221   }
   2222 }
   2223 
   2224 
   2225 TEST(BytecodeGraphBuilderForIn) {
   2226   HandleAndZoneScope scope;
   2227   Isolate* isolate = scope.main_isolate();
   2228   Zone* zone = scope.main_zone();
   2229   Factory* factory = isolate->factory();
   2230   ExpectedSnippet<0> snippets[] = {
   2231       {"var sum = 0;\n"
   2232        "var empty = null;\n"
   2233        "for (var x in empty) { sum++; }\n"
   2234        "return sum;",
   2235        {factory->NewNumberFromInt(0)}},
   2236       {"var sum = 100;\n"
   2237        "var empty = 1;\n"
   2238        "for (var x in empty) { sum++; }\n"
   2239        "return sum;",
   2240        {factory->NewNumberFromInt(100)}},
   2241       {"for (var x in [ 10, 20, 30 ]) {}\n"
   2242        "return 2;",
   2243        {factory->NewNumberFromInt(2)}},
   2244       {"var last = 0;\n"
   2245        "for (var x in [ 10, 20, 30 ]) {\n"
   2246        "  last = x;\n"
   2247        "}\n"
   2248        "return +last;",
   2249        {factory->NewNumberFromInt(2)}},
   2250       {"var first = -1;\n"
   2251        "for (var x in [ 10, 20, 30 ]) {\n"
   2252        "  first = +x;\n"
   2253        "  if (first > 0) break;\n"
   2254        "}\n"
   2255        "return first;",
   2256        {factory->NewNumberFromInt(1)}},
   2257       {"var first = -1;\n"
   2258        "for (var x in [ 10, 20, 30 ]) {\n"
   2259        "  if (first >= 0) continue;\n"
   2260        "  first = x;\n"
   2261        "}\n"
   2262        "return +first;",
   2263        {factory->NewNumberFromInt(0)}},
   2264       {"var sum = 0;\n"
   2265        "for (var x in [ 10, 20, 30 ]) {\n"
   2266        "  for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
   2267        "    sum += 1;\n"
   2268        "  }\n"
   2269        "}\n"
   2270        "return sum;",
   2271        {factory->NewNumberFromInt(21)}},
   2272       {"var sum = 0;\n"
   2273        "for (var x in [ 10, 20, 30 ]) {\n"
   2274        "  for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
   2275        "    if (sum == 7) break;\n"
   2276        "    if (sum == 6) continue;\n"
   2277        "    sum += 1;\n"
   2278        "  }\n"
   2279        "}\n"
   2280        "return sum;",
   2281        {factory->NewNumberFromInt(6)}},
   2282   };
   2283 
   2284   for (size_t i = 0; i < arraysize(snippets); i++) {
   2285     ScopedVector<char> script(1024);
   2286     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2287              snippets[i].code_snippet, kFunctionName);
   2288 
   2289     BytecodeGraphTester tester(isolate, zone, script.start());
   2290     auto callable = tester.GetCallable<>();
   2291     Handle<Object> return_value = callable().ToHandleChecked();
   2292     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2293   }
   2294 }
   2295 
   2296 
   2297 TEST(JumpWithConstantsAndWideConstants) {
   2298   HandleAndZoneScope scope;
   2299   auto isolate = scope.main_isolate();
   2300   const int kStep = 19;
   2301   int start = 7;
   2302   for (int constants = start; constants < 256 + 3 * kStep; constants += kStep) {
   2303     std::stringstream filler_os;
   2304     // Generate a string that consumes constant pool entries and
   2305     // spread out branch distances in script below.
   2306     for (int i = 0; i < constants; i++) {
   2307       filler_os << "var x_ = 'x_" << i << "';\n";
   2308     }
   2309     std::string filler(filler_os.str());
   2310 
   2311     std::stringstream script_os;
   2312     script_os << "function " << kFunctionName << "(a) {\n";
   2313     script_os << "  " << filler;
   2314     script_os << "  for (var i = a; i < 2; i++) {\n";
   2315     script_os << "  " << filler;
   2316     script_os << "    if (i == 0) { " << filler << "i = 10; continue; }\n";
   2317     script_os << "    else if (i == a) { " << filler << "i = 12; break; }\n";
   2318     script_os << "    else { " << filler << " }\n";
   2319     script_os << "  }\n";
   2320     script_os << "  return i;\n";
   2321     script_os << "}\n";
   2322     script_os << kFunctionName << "(0);\n";
   2323     std::string script(script_os.str());
   2324     auto factory = isolate->factory();
   2325     auto zone = scope.main_zone();
   2326     for (int a = 0; a < 3; a++) {
   2327       BytecodeGraphTester tester(isolate, zone, script.c_str());
   2328       auto callable = tester.GetCallable<Handle<Object>>();
   2329       Handle<Object> return_val =
   2330           callable(factory->NewNumberFromInt(a)).ToHandleChecked();
   2331       static const int results[] = {11, 12, 2};
   2332       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
   2333     }
   2334   }
   2335 }
   2336 
   2337 }  // namespace compiler
   2338 }  // namespace internal
   2339 }  // namespace v8
   2340