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 #define SHARD_TEST_BY_2(x)    \
     20   TEST(x##_0) { Test##x(0); } \
     21   TEST(x##_1) { Test##x(1); }
     22 #define SHARD_TEST_BY_4(x)    \
     23   TEST(x##_0) { Test##x(0); } \
     24   TEST(x##_1) { Test##x(1); } \
     25   TEST(x##_2) { Test##x(2); } \
     26   TEST(x##_3) { Test##x(3); }
     27 
     28 static const char kFunctionName[] = "f";
     29 
     30 static const Token::Value kCompareOperators[] = {
     31     Token::Value::EQ,        Token::Value::NE, Token::Value::EQ_STRICT,
     32     Token::Value::NE_STRICT, Token::Value::LT, Token::Value::LTE,
     33     Token::Value::GT,        Token::Value::GTE};
     34 
     35 static const int SMI_MAX = (1 << 30) - 1;
     36 static const int SMI_MIN = -(1 << 30);
     37 
     38 static MaybeHandle<Object> CallFunction(Isolate* isolate,
     39                                         Handle<JSFunction> function) {
     40   return Execution::Call(isolate, function,
     41                          isolate->factory()->undefined_value(), 0, nullptr);
     42 }
     43 
     44 
     45 template <class... A>
     46 static MaybeHandle<Object> CallFunction(Isolate* isolate,
     47                                         Handle<JSFunction> function,
     48                                         A... args) {
     49   Handle<Object> argv[] = {args...};
     50   return Execution::Call(isolate, function,
     51                          isolate->factory()->undefined_value(), sizeof...(args),
     52                          argv);
     53 }
     54 
     55 
     56 template <class... A>
     57 class BytecodeGraphCallable {
     58  public:
     59   BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
     60       : isolate_(isolate), function_(function) {}
     61   virtual ~BytecodeGraphCallable() {}
     62 
     63   MaybeHandle<Object> operator()(A... args) {
     64     return CallFunction(isolate_, function_, args...);
     65   }
     66 
     67  private:
     68   Isolate* isolate_;
     69   Handle<JSFunction> function_;
     70 };
     71 
     72 
     73 class BytecodeGraphTester {
     74  public:
     75   BytecodeGraphTester(Isolate* isolate, Zone* zone, const char* script,
     76                       const char* filter = kFunctionName)
     77       : isolate_(isolate), zone_(zone), script_(script) {
     78     i::FLAG_ignition = true;
     79     i::FLAG_always_opt = false;
     80     i::FLAG_allow_natives_syntax = true;
     81     i::FLAG_loop_assignment_analysis = false;
     82     // Ensure handler table is generated.
     83     isolate->interpreter()->Initialize();
     84   }
     85   virtual ~BytecodeGraphTester() {}
     86 
     87   template <class... A>
     88   BytecodeGraphCallable<A...> GetCallable(
     89       const char* functionName = kFunctionName) {
     90     return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
     91   }
     92 
     93   Local<Message> CheckThrowsReturnMessage() {
     94     TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
     95     auto callable = GetCallable<>();
     96     MaybeHandle<Object> no_result = callable();
     97     CHECK(isolate_->has_pending_exception());
     98     CHECK(try_catch.HasCaught());
     99     CHECK(no_result.is_null());
    100     isolate_->OptionalRescheduleException(true);
    101     CHECK(!try_catch.Message().IsEmpty());
    102     return try_catch.Message();
    103   }
    104 
    105   static Handle<Object> NewObject(const char* script) {
    106     return v8::Utils::OpenHandle(*CompileRun(script));
    107   }
    108 
    109  private:
    110   Isolate* isolate_;
    111   Zone* zone_;
    112   const char* script_;
    113 
    114   Handle<JSFunction> GetFunction(const char* functionName) {
    115     CompileRun(script_);
    116     Local<Function> api_function = Local<Function>::Cast(
    117         CcTest::global()
    118             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName))
    119             .ToLocalChecked());
    120     Handle<JSFunction> function =
    121         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
    122     CHECK(function->shared()->HasBytecodeArray());
    123 
    124     // TODO(mstarzinger): We should be able to prime CompilationInfo without
    125     // having to instantiate a ParseInfo first. Fix this!
    126     ParseInfo parse_info(zone_, function);
    127 
    128     CompilationInfo compilation_info(&parse_info, function);
    129     compilation_info.SetOptimizing();
    130     compilation_info.MarkAsDeoptimizationEnabled();
    131     compilation_info.MarkAsOptimizeFromBytecode();
    132     Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
    133     function->ReplaceCode(*code);
    134 
    135     return function;
    136   }
    137 
    138   DISALLOW_COPY_AND_ASSIGN(BytecodeGraphTester);
    139 };
    140 
    141 
    142 #define SPACE()
    143 
    144 #define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__
    145 #define REPEAT_4(SEP, ...) \
    146   REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
    147 #define REPEAT_8(SEP, ...) \
    148   REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
    149 #define REPEAT_16(SEP, ...) \
    150   REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
    151 #define REPEAT_32(SEP, ...) \
    152   REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
    153 #define REPEAT_64(SEP, ...) \
    154   REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
    155 #define REPEAT_128(SEP, ...) \
    156   REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
    157 #define REPEAT_256(SEP, ...) \
    158   REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
    159 
    160 #define REPEAT_127(SEP, ...)  \
    161   REPEAT_64(SEP, __VA_ARGS__) \
    162   SEP()                       \
    163   REPEAT_32(SEP, __VA_ARGS__) \
    164   SEP()                       \
    165   REPEAT_16(SEP, __VA_ARGS__) \
    166   SEP()                       \
    167   REPEAT_8(SEP, __VA_ARGS__)  \
    168   SEP()                       \
    169   REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__
    170 
    171 
    172 template <int N, typename T = Handle<Object>>
    173 struct ExpectedSnippet {
    174   const char* code_snippet;
    175   T return_value_and_parameters[N + 1];
    176 
    177   inline T return_value() const { return return_value_and_parameters[0]; }
    178 
    179   inline T parameter(int i) const {
    180     CHECK_GE(i, 0);
    181     CHECK_LT(i, N);
    182     return return_value_and_parameters[1 + i];
    183   }
    184 };
    185 
    186 
    187 TEST(BytecodeGraphBuilderReturnStatements) {
    188   HandleAndZoneScope scope;
    189   Isolate* isolate = scope.main_isolate();
    190   Zone* zone = scope.main_zone();
    191   Factory* factory = isolate->factory();
    192 
    193   ExpectedSnippet<0> snippets[] = {
    194       {"return;", {factory->undefined_value()}},
    195       {"return null;", {factory->null_value()}},
    196       {"return true;", {factory->true_value()}},
    197       {"return false;", {factory->false_value()}},
    198       {"return 0;", {factory->NewNumberFromInt(0)}},
    199       {"return +1;", {factory->NewNumberFromInt(1)}},
    200       {"return -1;", {factory->NewNumberFromInt(-1)}},
    201       {"return +127;", {factory->NewNumberFromInt(127)}},
    202       {"return -128;", {factory->NewNumberFromInt(-128)}},
    203       {"return 0.001;", {factory->NewNumber(0.001)}},
    204       {"return 3.7e-60;", {factory->NewNumber(3.7e-60)}},
    205       {"return -3.7e60;", {factory->NewNumber(-3.7e60)}},
    206       {"return '';", {factory->NewStringFromStaticChars("")}},
    207       {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
    208       {"return NaN;", {factory->nan_value()}}};
    209 
    210   for (size_t i = 0; i < arraysize(snippets); i++) {
    211     ScopedVector<char> script(1024);
    212     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    213              snippets[i].code_snippet, kFunctionName);
    214 
    215     BytecodeGraphTester tester(isolate, zone, script.start());
    216     auto callable = tester.GetCallable<>();
    217     Handle<Object> return_value = callable().ToHandleChecked();
    218     CHECK(return_value->SameValue(*snippets[i].return_value()));
    219   }
    220 }
    221 
    222 
    223 TEST(BytecodeGraphBuilderPrimitiveExpressions) {
    224   HandleAndZoneScope scope;
    225   Isolate* isolate = scope.main_isolate();
    226   Zone* zone = scope.main_zone();
    227   Factory* factory = isolate->factory();
    228 
    229   ExpectedSnippet<0> snippets[] = {
    230       {"return 1 + 1;", {factory->NewNumberFromInt(2)}},
    231       {"return 20 - 30;", {factory->NewNumberFromInt(-10)}},
    232       {"return 4 * 100;", {factory->NewNumberFromInt(400)}},
    233       {"return 100 / 5;", {factory->NewNumberFromInt(20)}},
    234       {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
    235   };
    236 
    237   for (size_t i = 0; i < arraysize(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   for (size_t i = 0; i < arraysize(snippets); i++) {
    296     ScopedVector<char> script(1024);
    297     SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
    298              snippets[i].code_snippet, kFunctionName);
    299 
    300     BytecodeGraphTester tester(isolate, zone, script.start());
    301     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
    302     Handle<Object> return_value =
    303         callable(snippets[i].parameter(0), snippets[i].parameter(1))
    304             .ToHandleChecked();
    305     CHECK(return_value->SameValue(*snippets[i].return_value()));
    306   }
    307 }
    308 
    309 
    310 TEST(BytecodeGraphBuilderNamedLoad) {
    311   HandleAndZoneScope scope;
    312   Isolate* isolate = scope.main_isolate();
    313   Zone* zone = scope.main_zone();
    314   Factory* factory = isolate->factory();
    315 
    316   ExpectedSnippet<1> snippets[] = {
    317       {"return p1.val;",
    318        {factory->NewNumberFromInt(10),
    319         BytecodeGraphTester::NewObject("({val : 10})")}},
    320       {"return p1[\"name\"];",
    321        {factory->NewStringFromStaticChars("abc"),
    322         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    323       {"'use strict'; return p1.val;",
    324        {factory->NewNumberFromInt(10),
    325         BytecodeGraphTester::NewObject("({val : 10 })")}},
    326       {"'use strict'; return p1[\"val\"];",
    327        {factory->NewNumberFromInt(10),
    328         BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
    329       {"var b;\n" REPEAT_127(SPACE, " b = p1.name; ") " return p1.name;\n",
    330        {factory->NewStringFromStaticChars("abc"),
    331         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    332       {"'use strict'; var b;\n"
    333        REPEAT_127(SPACE, " b = p1.name; ")
    334        "return p1.name;\n",
    335        {factory->NewStringFromStaticChars("abc"),
    336         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
    337   };
    338 
    339   for (size_t i = 0; i < arraysize(snippets); i++) {
    340     ScopedVector<char> script(2048);
    341     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
    342              snippets[i].code_snippet, kFunctionName);
    343 
    344     BytecodeGraphTester tester(isolate, zone, script.start());
    345     auto callable = tester.GetCallable<Handle<Object>>();
    346     Handle<Object> return_value =
    347         callable(snippets[i].parameter(0)).ToHandleChecked();
    348     CHECK(return_value->SameValue(*snippets[i].return_value()));
    349   }
    350 }
    351 
    352 
    353 TEST(BytecodeGraphBuilderKeyedLoad) {
    354   HandleAndZoneScope scope;
    355   Isolate* isolate = scope.main_isolate();
    356   Zone* zone = scope.main_zone();
    357   Factory* factory = isolate->factory();
    358 
    359   ExpectedSnippet<2> snippets[] = {
    360       {"return p1[p2];",
    361        {factory->NewNumberFromInt(10),
    362         BytecodeGraphTester::NewObject("({val : 10})"),
    363         factory->NewStringFromStaticChars("val")}},
    364       {"return p1[100];",
    365        {factory->NewStringFromStaticChars("abc"),
    366         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    367         factory->NewNumberFromInt(0)}},
    368       {"var b = 100; return p1[b];",
    369        {factory->NewStringFromStaticChars("abc"),
    370         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    371         factory->NewNumberFromInt(0)}},
    372       {"'use strict'; return p1[p2];",
    373        {factory->NewNumberFromInt(10),
    374         BytecodeGraphTester::NewObject("({val : 10 })"),
    375         factory->NewStringFromStaticChars("val")}},
    376       {"'use strict'; return p1[100];",
    377        {factory->NewNumberFromInt(10),
    378         BytecodeGraphTester::NewObject("({100 : 10})"),
    379         factory->NewNumberFromInt(0)}},
    380       {"'use strict'; var b = p2; return p1[b];",
    381        {factory->NewStringFromStaticChars("abc"),
    382         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    383         factory->NewNumberFromInt(100)}},
    384       {"var b;\n" REPEAT_127(SPACE, " b = p1[p2]; ") " return p1[p2];\n",
    385        {factory->NewStringFromStaticChars("abc"),
    386         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    387         factory->NewNumberFromInt(100)}},
    388       {"'use strict'; var b;\n" REPEAT_127(SPACE,
    389                                            " b = p1[p2]; ") "return p1[p2];\n",
    390        {factory->NewStringFromStaticChars("abc"),
    391         BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
    392         factory->NewNumberFromInt(100)}},
    393   };
    394 
    395   for (size_t i = 0; i < arraysize(snippets); i++) {
    396     ScopedVector<char> script(2048);
    397     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
    398              snippets[i].code_snippet, kFunctionName);
    399 
    400     BytecodeGraphTester tester(isolate, zone, script.start());
    401     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
    402     Handle<Object> return_value =
    403         callable(snippets[i].parameter(0), snippets[i].parameter(1))
    404             .ToHandleChecked();
    405     CHECK(return_value->SameValue(*snippets[i].return_value()));
    406   }
    407 }
    408 
    409 void TestBytecodeGraphBuilderNamedStore(size_t shard) {
    410   HandleAndZoneScope scope;
    411   Isolate* isolate = scope.main_isolate();
    412   Zone* zone = scope.main_zone();
    413   Factory* factory = isolate->factory();
    414 
    415   ExpectedSnippet<1> snippets[] = {
    416       {"return p1.val = 20;",
    417        {factory->NewNumberFromInt(20),
    418         BytecodeGraphTester::NewObject("({val : 10})")}},
    419       {"p1.type = 'int'; return p1.type;",
    420        {factory->NewStringFromStaticChars("int"),
    421         BytecodeGraphTester::NewObject("({val : 10})")}},
    422       {"p1.name = 'def'; return p1[\"name\"];",
    423        {factory->NewStringFromStaticChars("def"),
    424         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    425       {"'use strict'; p1.val = 20; return p1.val;",
    426        {factory->NewNumberFromInt(20),
    427         BytecodeGraphTester::NewObject("({val : 10 })")}},
    428       {"'use strict'; return p1.type = 'int';",
    429        {factory->NewStringFromStaticChars("int"),
    430         BytecodeGraphTester::NewObject("({val : 10})")}},
    431       {"'use strict'; p1.val = 20; return p1[\"val\"];",
    432        {factory->NewNumberFromInt(20),
    433         BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
    434       {"var b = 'abc';\n" REPEAT_127(
    435            SPACE, " p1.name = b; ") " p1.name = 'def'; return p1.name;\n",
    436        {factory->NewStringFromStaticChars("def"),
    437         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
    438       {"'use strict'; var b = 'def';\n" REPEAT_127(
    439            SPACE, " p1.name = 'abc'; ") "p1.name = b; return p1.name;\n",
    440        {factory->NewStringFromStaticChars("def"),
    441         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
    442   };
    443 
    444   for (size_t i = 0; i < arraysize(snippets); i++) {
    445     if ((i % 2) != shard) continue;
    446     ScopedVector<char> script(3072);
    447     SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
    448              snippets[i].code_snippet, kFunctionName);
    449 
    450     BytecodeGraphTester tester(isolate, zone, script.start());
    451     auto callable = tester.GetCallable<Handle<Object>>();
    452     Handle<Object> return_value =
    453         callable(snippets[i].parameter(0)).ToHandleChecked();
    454     CHECK(return_value->SameValue(*snippets[i].return_value()));
    455   }
    456 }
    457 
    458 SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
    459 
    460 void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
    461   HandleAndZoneScope scope;
    462   Isolate* isolate = scope.main_isolate();
    463   Zone* zone = scope.main_zone();
    464   Factory* factory = isolate->factory();
    465 
    466   ExpectedSnippet<2> snippets[] = {
    467       {"p1[p2] = 20; return p1[p2];",
    468        {factory->NewNumberFromInt(20),
    469         BytecodeGraphTester::NewObject("({val : 10})"),
    470         factory->NewStringFromStaticChars("val")}},
    471       {"return p1[100] = 'def';",
    472        {factory->NewStringFromStaticChars("def"),
    473         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    474         factory->NewNumberFromInt(0)}},
    475       {"var b = 100; p1[b] = 'def'; return p1[b];",
    476        {factory->NewStringFromStaticChars("def"),
    477         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    478         factory->NewNumberFromInt(0)}},
    479       {"'use strict'; p1[p2] = 20; return p1[p2];",
    480        {factory->NewNumberFromInt(20),
    481         BytecodeGraphTester::NewObject("({val : 10 })"),
    482         factory->NewStringFromStaticChars("val")}},
    483       {"'use strict'; return p1[100] = 20;",
    484        {factory->NewNumberFromInt(20),
    485         BytecodeGraphTester::NewObject("({100 : 10})"),
    486         factory->NewNumberFromInt(0)}},
    487       {"'use strict'; var b = p2; p1[b] = 'def'; return p1[b];",
    488        {factory->NewStringFromStaticChars("def"),
    489         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    490         factory->NewNumberFromInt(100)}},
    491       {"var b;\n" REPEAT_127(
    492            SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
    493        {factory->NewStringFromStaticChars("def"),
    494         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
    495         factory->NewNumberFromInt(100)}},
    496       {"'use strict'; var b;\n" REPEAT_127(
    497            SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
    498        {factory->NewStringFromStaticChars("def"),
    499         BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
    500         factory->NewNumberFromInt(100)}},
    501   };
    502 
    503   for (size_t i = 0; i < arraysize(snippets); i++) {
    504     if ((i % 2) != shard) continue;
    505     ScopedVector<char> script(2048);
    506     SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
    507              snippets[i].code_snippet, kFunctionName);
    508 
    509     BytecodeGraphTester tester(isolate, zone, script.start());
    510     auto callable = tester.GetCallable<Handle<Object>>();
    511     Handle<Object> return_value =
    512         callable(snippets[i].parameter(0)).ToHandleChecked();
    513     CHECK(return_value->SameValue(*snippets[i].return_value()));
    514   }
    515 }
    516 
    517 SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
    518 
    519 TEST(BytecodeGraphBuilderPropertyCall) {
    520   HandleAndZoneScope scope;
    521   Isolate* isolate = scope.main_isolate();
    522   Zone* zone = scope.main_zone();
    523   Factory* factory = isolate->factory();
    524 
    525   ExpectedSnippet<1> snippets[] = {
    526       {"return p1.func();",
    527        {factory->NewNumberFromInt(25),
    528         BytecodeGraphTester::NewObject("({func() { return 25; }})")}},
    529       {"return p1.func('abc');",
    530        {factory->NewStringFromStaticChars("abc"),
    531         BytecodeGraphTester::NewObject("({func(a) { return a; }})")}},
    532       {"return p1.func(1, 2, 3, 4, 5, 6, 7, 8);",
    533        {factory->NewNumberFromInt(36),
    534         BytecodeGraphTester::NewObject(
    535             "({func(a, b, c, d, e, f, g, h) {\n"
    536             "  return a + b + c + d + e + f + g + h;}})")}},
    537   };
    538 
    539   for (size_t i = 0; i < arraysize(snippets); i++) {
    540     ScopedVector<char> script(2048);
    541     SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
    542              snippets[i].code_snippet, kFunctionName);
    543 
    544     BytecodeGraphTester tester(isolate, zone, script.start());
    545     auto callable = tester.GetCallable<Handle<Object>>();
    546     Handle<Object> return_value =
    547         callable(snippets[i].parameter(0)).ToHandleChecked();
    548     CHECK(return_value->SameValue(*snippets[i].return_value()));
    549   }
    550 }
    551 
    552 
    553 TEST(BytecodeGraphBuilderCallNew) {
    554   HandleAndZoneScope scope;
    555   Isolate* isolate = scope.main_isolate();
    556   Zone* zone = scope.main_zone();
    557   Factory* factory = isolate->factory();
    558 
    559   ExpectedSnippet<0> snippets[] = {
    560       {"function counter() { this.count = 20; }\n"
    561        "function f() {\n"
    562        "  var c = new counter();\n"
    563        "  return c.count;\n"
    564        "}; f()",
    565        {factory->NewNumberFromInt(20)}},
    566       {"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
    567        "function f() {\n"
    568        "  var c = new counter(6);\n"
    569        "  return c.count + c.x;\n"
    570        "}; f()",
    571        {factory->NewNumberFromInt(23)}},
    572       {"function counter(arg0, arg1) {\n"
    573        "  this.count = 17; this.x = arg0; this.y = arg1;\n"
    574        "}\n"
    575        "function f() {\n"
    576        "  var c = new counter(3, 5);\n"
    577        "  return c.count + c.x + c.y;\n"
    578        "}; f()",
    579        {factory->NewNumberFromInt(25)}},
    580   };
    581 
    582   for (size_t i = 0; i < arraysize(snippets); i++) {
    583     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    584     auto callable = tester.GetCallable<>();
    585     Handle<Object> return_value = callable().ToHandleChecked();
    586     CHECK(return_value->SameValue(*snippets[i].return_value()));
    587   }
    588 }
    589 
    590 
    591 TEST(BytecodeGraphBuilderCreateClosure) {
    592   HandleAndZoneScope scope;
    593   Isolate* isolate = scope.main_isolate();
    594   Zone* zone = scope.main_zone();
    595   Factory* factory = isolate->factory();
    596 
    597   ExpectedSnippet<0> snippets[] = {
    598       {"function f() {\n"
    599        "  function counter() { this.count = 20; }\n"
    600        "  var c = new counter();\n"
    601        "  return c.count;\n"
    602        "}; f()",
    603        {factory->NewNumberFromInt(20)}},
    604       {"function f() {\n"
    605        "  function counter(arg0) { this.count = 17; this.x = arg0; }\n"
    606        "  var c = new counter(6);\n"
    607        "  return c.count + c.x;\n"
    608        "}; f()",
    609        {factory->NewNumberFromInt(23)}},
    610       {"function f() {\n"
    611        "  function counter(arg0, arg1) {\n"
    612        "    this.count = 17; this.x = arg0; this.y = arg1;\n"
    613        "  }\n"
    614        "  var c = new counter(3, 5);\n"
    615        "  return c.count + c.x + c.y;\n"
    616        "}; f()",
    617        {factory->NewNumberFromInt(25)}},
    618   };
    619 
    620   for (size_t i = 0; i < arraysize(snippets); i++) {
    621     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    622     auto callable = tester.GetCallable<>();
    623     Handle<Object> return_value = callable().ToHandleChecked();
    624     CHECK(return_value->SameValue(*snippets[i].return_value()));
    625   }
    626 }
    627 
    628 
    629 TEST(BytecodeGraphBuilderCallRuntime) {
    630   HandleAndZoneScope scope;
    631   Isolate* isolate = scope.main_isolate();
    632   Zone* zone = scope.main_zone();
    633   Factory* factory = isolate->factory();
    634 
    635   ExpectedSnippet<1> snippets[] = {
    636       {"function f(arg0) { return %MaxSmi(); }\nf()",
    637        {factory->NewNumberFromInt(Smi::kMaxValue), factory->undefined_value()}},
    638       {"function f(arg0) { return %IsArray(arg0) }\nf(undefined)",
    639        {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
    640       {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
    641        {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
    642       {"function f(arg0) { return %spread_arguments(arg0).length }\nf([])",
    643        {factory->NewNumberFromInt(3),
    644         BytecodeGraphTester::NewObject("[1, 2, 3]")}},
    645   };
    646 
    647   for (size_t i = 0; i < arraysize(snippets); i++) {
    648     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    649     auto callable = tester.GetCallable<Handle<Object>>();
    650     Handle<Object> return_value =
    651         callable(snippets[i].parameter(0)).ToHandleChecked();
    652     CHECK(return_value->SameValue(*snippets[i].return_value()));
    653   }
    654 }
    655 
    656 TEST(BytecodeGraphBuilderInvokeIntrinsic) {
    657   HandleAndZoneScope scope;
    658   Isolate* isolate = scope.main_isolate();
    659   Zone* zone = scope.main_zone();
    660   Factory* factory = isolate->factory();
    661 
    662   ExpectedSnippet<1> snippets[] = {
    663       {"function f(arg0) { return %_IsJSReceiver(arg0); }\nf()",
    664        {factory->false_value(), factory->NewNumberFromInt(1)}},
    665       {"function f(arg0) { return %_IsArray(arg0) }\nf(undefined)",
    666        {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
    667   };
    668 
    669   for (size_t i = 0; i < arraysize(snippets); i++) {
    670     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    671     auto callable = tester.GetCallable<Handle<Object>>();
    672     Handle<Object> return_value =
    673         callable(snippets[i].parameter(0)).ToHandleChecked();
    674     CHECK(return_value->SameValue(*snippets[i].return_value()));
    675   }
    676 }
    677 
    678 void TestBytecodeGraphBuilderGlobals(size_t shard) {
    679   HandleAndZoneScope scope;
    680   Isolate* isolate = scope.main_isolate();
    681   Zone* zone = scope.main_zone();
    682   Factory* factory = isolate->factory();
    683 
    684   ExpectedSnippet<0> snippets[] = {
    685       {"var global = 321;\n function f() { return global; };\n f();",
    686        {factory->NewNumberFromInt(321)}},
    687       {"var global = 321;\n"
    688        "function f() { global = 123; return global };\n f();",
    689        {factory->NewNumberFromInt(123)}},
    690       {"var global = function() { return 'abc'};\n"
    691        "function f() { return global(); };\n f();",
    692        {factory->NewStringFromStaticChars("abc")}},
    693       {"var global = 456;\n"
    694        "function f() { 'use strict'; return global; };\n f();",
    695        {factory->NewNumberFromInt(456)}},
    696       {"var global = 987;\n"
    697        "function f() { 'use strict'; global = 789; return global };\n f();",
    698        {factory->NewNumberFromInt(789)}},
    699       {"var global = function() { return 'xyz'};\n"
    700        "function f() { 'use strict'; return global(); };\n f();",
    701        {factory->NewStringFromStaticChars("xyz")}},
    702       {"var global = 'abc'; var global_obj = {val:123};\n"
    703        "function f() {\n" REPEAT_127(
    704            SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
    705        {factory->NewStringFromStaticChars("abc")}},
    706       {"var global = 'abc'; var global_obj = {val:123};\n"
    707        "function f() { 'use strict';\n" REPEAT_127(
    708            SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
    709                                                  "global };\n f();\n",
    710        {factory->NewStringFromStaticChars("xyz")}},
    711       {"function f() { return typeof(undeclared_var); }\n; f();\n",
    712        {factory->NewStringFromStaticChars("undefined")}},
    713       {"var defined_var = 10; function f() { return typeof(defined_var); }\n; "
    714        "f();\n",
    715        {factory->NewStringFromStaticChars("number")}},
    716   };
    717 
    718   for (size_t i = 0; i < arraysize(snippets); i++) {
    719     if ((i % 2) != shard) continue;
    720     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
    721     auto callable = tester.GetCallable<>();
    722     Handle<Object> return_value = callable().ToHandleChecked();
    723     CHECK(return_value->SameValue(*snippets[i].return_value()));
    724   }
    725 }
    726 
    727 SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
    728 
    729 TEST(BytecodeGraphBuilderToObject) {
    730   // TODO(mythria): tests for ToObject. Needs ForIn.
    731 }
    732 
    733 
    734 TEST(BytecodeGraphBuilderToName) {
    735   HandleAndZoneScope scope;
    736   Isolate* isolate = scope.main_isolate();
    737   Zone* zone = scope.main_zone();
    738   Factory* factory = isolate->factory();
    739 
    740   ExpectedSnippet<0> snippets[] = {
    741       {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
    742        {factory->NewNumberFromInt(10)}},
    743       {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
    744        {factory->NewNumberFromInt(10)}},
    745       {"var a = 20; var obj = {[a] : 10}; return obj[20];",
    746        {factory->NewNumberFromInt(10)}},
    747       {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
    748        {factory->NewNumberFromInt(10)}},
    749       {"var a = {val:23}; var obj = {[a] : 10}; return obj['[object Object]'];",
    750        {factory->NewNumberFromInt(10)}},
    751       {"var a = {toString : function() { return 'x'}};\n"
    752        "var obj = {[a] : 10};\n"
    753        "return obj.x;",
    754        {factory->NewNumberFromInt(10)}},
    755       {"var a = {valueOf : function() { return 'x'}};\n"
    756        "var obj = {[a] : 10};\n"
    757        "return obj.x;",
    758        {factory->undefined_value()}},
    759       {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
    760        "var obj = {[a] : 10};\n"
    761        "return obj.x;",
    762        {factory->NewNumberFromInt(10)}},
    763   };
    764 
    765   for (size_t i = 0; i < arraysize(snippets); i++) {
    766     ScopedVector<char> script(1024);
    767     SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
    768              snippets[i].code_snippet, kFunctionName);
    769 
    770     BytecodeGraphTester tester(isolate, zone, script.start());
    771     auto callable = tester.GetCallable<>();
    772     Handle<Object> return_value = callable().ToHandleChecked();
    773     CHECK(return_value->SameValue(*snippets[i].return_value()));
    774   }
    775 }
    776 
    777 
    778 TEST(BytecodeGraphBuilderLogicalNot) {
    779   HandleAndZoneScope scope;
    780   Isolate* isolate = scope.main_isolate();
    781   Zone* zone = scope.main_zone();
    782   Factory* factory = isolate->factory();
    783 
    784   ExpectedSnippet<1> snippets[] = {
    785       {"return !p1;",
    786        {factory->false_value(),
    787         BytecodeGraphTester::NewObject("({val : 10})")}},
    788       {"return !p1;", {factory->true_value(), factory->NewNumberFromInt(0)}},
    789       {"return !p1;", {factory->true_value(), factory->undefined_value()}},
    790       {"return !p1;", {factory->false_value(), factory->NewNumberFromInt(10)}},
    791       {"return !p1;", {factory->false_value(), factory->true_value()}},
    792       {"return !p1;",
    793        {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
    794   };
    795 
    796   for (size_t i = 0; i < arraysize(snippets); i++) {
    797     ScopedVector<char> script(1024);
    798     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    799              snippets[i].code_snippet, kFunctionName);
    800 
    801     BytecodeGraphTester tester(isolate, zone, script.start());
    802     auto callable = tester.GetCallable<Handle<Object>>();
    803     Handle<Object> return_value =
    804         callable(snippets[i].parameter(0)).ToHandleChecked();
    805     CHECK(return_value->SameValue(*snippets[i].return_value()));
    806   }
    807 }
    808 
    809 
    810 TEST(BytecodeGraphBuilderTypeOf) {
    811   HandleAndZoneScope scope;
    812   Isolate* isolate = scope.main_isolate();
    813   Zone* zone = scope.main_zone();
    814   Factory* factory = isolate->factory();
    815 
    816   ExpectedSnippet<1> snippets[] = {
    817       {"return typeof p1;",
    818        {factory->NewStringFromStaticChars("object"),
    819         BytecodeGraphTester::NewObject("({val : 10})")}},
    820       {"return typeof p1;",
    821        {factory->NewStringFromStaticChars("undefined"),
    822         factory->undefined_value()}},
    823       {"return typeof p1;",
    824        {factory->NewStringFromStaticChars("number"),
    825         factory->NewNumberFromInt(10)}},
    826       {"return typeof p1;",
    827        {factory->NewStringFromStaticChars("boolean"), factory->true_value()}},
    828       {"return typeof p1;",
    829        {factory->NewStringFromStaticChars("string"),
    830         factory->NewStringFromStaticChars("abc")}},
    831   };
    832 
    833   for (size_t i = 0; i < arraysize(snippets); i++) {
    834     ScopedVector<char> script(1024);
    835     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    836              snippets[i].code_snippet, kFunctionName);
    837 
    838     BytecodeGraphTester tester(isolate, zone, script.start());
    839     auto callable = tester.GetCallable<Handle<Object>>();
    840     Handle<Object> return_value =
    841         callable(snippets[i].parameter(0)).ToHandleChecked();
    842     CHECK(return_value->SameValue(*snippets[i].return_value()));
    843   }
    844 }
    845 
    846 
    847 TEST(BytecodeGraphBuilderCountOperation) {
    848   HandleAndZoneScope scope;
    849   Isolate* isolate = scope.main_isolate();
    850   Zone* zone = scope.main_zone();
    851   Factory* factory = isolate->factory();
    852 
    853   ExpectedSnippet<1> snippets[] = {
    854       {"return ++p1;",
    855        {factory->NewNumberFromInt(11), factory->NewNumberFromInt(10)}},
    856       {"return p1++;",
    857        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
    858       {"return p1++ + 10;",
    859        {factory->NewHeapNumber(15.23), factory->NewHeapNumber(5.23)}},
    860       {"return 20 + ++p1;",
    861        {factory->NewHeapNumber(27.23), factory->NewHeapNumber(6.23)}},
    862       {"return --p1;",
    863        {factory->NewHeapNumber(9.8), factory->NewHeapNumber(10.8)}},
    864       {"return p1--;",
    865        {factory->NewHeapNumber(10.8), factory->NewHeapNumber(10.8)}},
    866       {"return p1-- + 10;",
    867        {factory->NewNumberFromInt(20), factory->NewNumberFromInt(10)}},
    868       {"return 20 + --p1;",
    869        {factory->NewNumberFromInt(29), factory->NewNumberFromInt(10)}},
    870       {"return p1.val--;",
    871        {factory->NewNumberFromInt(10),
    872         BytecodeGraphTester::NewObject("({val : 10})")}},
    873       {"return ++p1['val'];",
    874        {factory->NewNumberFromInt(11),
    875         BytecodeGraphTester::NewObject("({val : 10})")}},
    876       {"return ++p1[1];",
    877        {factory->NewNumberFromInt(11),
    878         BytecodeGraphTester::NewObject("({1 : 10})")}},
    879       {" function inner() { return p1 } return --p1;",
    880        {factory->NewNumberFromInt(9), factory->NewNumberFromInt(10)}},
    881       {" function inner() { return p1 } return p1--;",
    882        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
    883       {"return ++p1;",
    884        {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
    885   };
    886 
    887   for (size_t i = 0; i < arraysize(snippets); i++) {
    888     ScopedVector<char> script(1024);
    889     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    890              snippets[i].code_snippet, kFunctionName);
    891 
    892     BytecodeGraphTester tester(isolate, zone, script.start());
    893     auto callable = tester.GetCallable<Handle<Object>>();
    894     Handle<Object> return_value =
    895         callable(snippets[i].parameter(0)).ToHandleChecked();
    896     CHECK(return_value->SameValue(*snippets[i].return_value()));
    897   }
    898 }
    899 
    900 
    901 TEST(BytecodeGraphBuilderDelete) {
    902   HandleAndZoneScope scope;
    903   Isolate* isolate = scope.main_isolate();
    904   Zone* zone = scope.main_zone();
    905   Factory* factory = isolate->factory();
    906 
    907   ExpectedSnippet<1> snippets[] = {
    908       {"return delete p1.val;",
    909        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
    910       {"delete p1.val; return p1.val;",
    911        {factory->undefined_value(),
    912         BytecodeGraphTester::NewObject("({val : 10})")}},
    913       {"delete p1.name; return p1.val;",
    914        {factory->NewNumberFromInt(10),
    915         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
    916       {"'use strict'; return delete p1.val;",
    917        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
    918       {"'use strict'; delete p1.val; return p1.val;",
    919        {factory->undefined_value(),
    920         BytecodeGraphTester::NewObject("({val : 10})")}},
    921       {"'use strict'; delete p1.name; return p1.val;",
    922        {factory->NewNumberFromInt(10),
    923         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
    924   };
    925 
    926   for (size_t i = 0; i < arraysize(snippets); i++) {
    927     ScopedVector<char> script(1024);
    928     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    929              snippets[i].code_snippet, kFunctionName);
    930 
    931     BytecodeGraphTester tester(isolate, zone, script.start());
    932     auto callable = tester.GetCallable<Handle<Object>>();
    933     Handle<Object> return_value =
    934         callable(snippets[i].parameter(0)).ToHandleChecked();
    935     CHECK(return_value->SameValue(*snippets[i].return_value()));
    936   }
    937 }
    938 
    939 
    940 TEST(BytecodeGraphBuilderDeleteGlobal) {
    941   HandleAndZoneScope scope;
    942   Isolate* isolate = scope.main_isolate();
    943   Zone* zone = scope.main_zone();
    944   Factory* factory = isolate->factory();
    945 
    946   ExpectedSnippet<0> snippets[] = {
    947       {"var obj = {val : 10, type : 'int'};"
    948        "function f() {return delete obj;};",
    949        {factory->false_value()}},
    950       {"function f() {return delete this;};", {factory->true_value()}},
    951       {"var obj = {val : 10, type : 'int'};"
    952        "function f() {return delete obj.val;};",
    953        {factory->true_value()}},
    954       {"var obj = {val : 10, type : 'int'};"
    955        "function f() {'use strict'; return delete obj.val;};",
    956        {factory->true_value()}},
    957       {"var obj = {val : 10, type : 'int'};"
    958        "function f() {delete obj.val; return obj.val;};",
    959        {factory->undefined_value()}},
    960       {"var obj = {val : 10, type : 'int'};"
    961        "function f() {'use strict'; delete obj.val; return obj.val;};",
    962        {factory->undefined_value()}},
    963       {"var obj = {1 : 10, 2 : 20};"
    964        "function f() { return delete obj[1]; };",
    965        {factory->true_value()}},
    966       {"var obj = {1 : 10, 2 : 20};"
    967        "function f() { 'use strict';  return delete obj[1];};",
    968        {factory->true_value()}},
    969       {"obj = {1 : 10, 2 : 20};"
    970        "function f() { delete obj[1]; return obj[2];};",
    971        {factory->NewNumberFromInt(20)}},
    972       {"function f() {"
    973        "  var obj = {1 : 10, 2 : 20};"
    974        "  function inner() { return obj[1]; };"
    975        "  return delete obj[1];"
    976        "}",
    977        {factory->true_value()}},
    978   };
    979 
    980   for (size_t i = 0; i < arraysize(snippets); i++) {
    981     ScopedVector<char> script(1024);
    982     SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
    983 
    984     BytecodeGraphTester tester(isolate, zone, script.start());
    985     auto callable = tester.GetCallable<>();
    986     Handle<Object> return_value = callable().ToHandleChecked();
    987     CHECK(return_value->SameValue(*snippets[i].return_value()));
    988   }
    989 }
    990 
    991 
    992 TEST(BytecodeGraphBuilderDeleteLookupSlot) {
    993   HandleAndZoneScope scope;
    994   Isolate* isolate = scope.main_isolate();
    995   Zone* zone = scope.main_zone();
    996   Factory* factory = isolate->factory();
    997 
    998   // TODO(mythria): Add more tests when we have support for LdaLookupSlot.
    999   const char* function_prologue = "var f;"
   1000                                   "var x = 1;"
   1001                                   "y = 10;"
   1002                                   "var obj = {val:10};"
   1003                                   "var z = 30;"
   1004                                   "function f1() {"
   1005                                   "  var z = 20;"
   1006                                   "  eval(\"function t() {";
   1007   const char* function_epilogue = "        }; f = t; t();\");"
   1008                                   "}"
   1009                                   "f1();";
   1010 
   1011   ExpectedSnippet<0> snippets[] = {
   1012       {"return delete y;", {factory->true_value()}},
   1013       {"return delete z;", {factory->false_value()}},
   1014   };
   1015 
   1016   for (size_t i = 0; i < arraysize(snippets); i++) {
   1017     ScopedVector<char> script(1024);
   1018     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
   1019              function_epilogue);
   1020 
   1021     BytecodeGraphTester tester(isolate, zone, script.start(), "t");
   1022     auto callable = tester.GetCallable<>();
   1023     Handle<Object> return_value = callable().ToHandleChecked();
   1024     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1025   }
   1026 }
   1027 
   1028 
   1029 TEST(BytecodeGraphBuilderLookupSlot) {
   1030   HandleAndZoneScope scope;
   1031   Isolate* isolate = scope.main_isolate();
   1032   Zone* zone = scope.main_zone();
   1033   Factory* factory = isolate->factory();
   1034 
   1035   const char* function_prologue = "var f;"
   1036                                   "var x = 12;"
   1037                                   "y = 10;"
   1038                                   "var obj = {val:3.1414};"
   1039                                   "var z = 30;"
   1040                                   "function f1() {"
   1041                                   "  var z = 20;"
   1042                                   "  eval(\"function t() {";
   1043   const char* function_epilogue = "        }; f = t; t();\");"
   1044                                   "}"
   1045                                   "f1();";
   1046 
   1047   ExpectedSnippet<0> snippets[] = {
   1048       {"return x;", {factory->NewNumber(12)}},
   1049       {"return obj.val;", {factory->NewNumber(3.1414)}},
   1050       {"return typeof x;", {factory->NewStringFromStaticChars("number")}},
   1051       {"return typeof dummy;",
   1052        {factory->NewStringFromStaticChars("undefined")}},
   1053       {"x = 23; return x;", {factory->NewNumber(23)}},
   1054       {"'use strict'; obj.val = 23.456; return obj.val;",
   1055        {factory->NewNumber(23.456)}}};
   1056 
   1057   for (size_t i = 0; i < arraysize(snippets); i++) {
   1058     ScopedVector<char> script(1024);
   1059     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
   1060              function_epilogue);
   1061 
   1062     BytecodeGraphTester tester(isolate, zone, script.start(), "t");
   1063     auto callable = tester.GetCallable<>();
   1064     Handle<Object> return_value = callable().ToHandleChecked();
   1065     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1066   }
   1067 }
   1068 
   1069 
   1070 TEST(BytecodeGraphBuilderLookupSlotWide) {
   1071   HandleAndZoneScope scope;
   1072   Isolate* isolate = scope.main_isolate();
   1073   Zone* zone = scope.main_zone();
   1074   Factory* factory = isolate->factory();
   1075 
   1076   const char* function_prologue =
   1077       "var f;"
   1078       "var x = 12;"
   1079       "y = 10;"
   1080       "var obj = {val:3.1414};"
   1081       "var z = 30;"
   1082       "function f1() {"
   1083       "  var z = 20;"
   1084       "  eval(\"function t() {";
   1085   const char* function_epilogue =
   1086       "        }; f = t; t();\");"
   1087       "}"
   1088       "f1();";
   1089 
   1090   ExpectedSnippet<0> snippets[] = {
   1091       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x;",
   1092        {factory->NewNumber(12)}},
   1093       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return typeof x;",
   1094        {factory->NewStringFromStaticChars("number")}},
   1095       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x = 23;",
   1096        {factory->NewNumber(23)}},
   1097       {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
   1098        {factory->NewNumber(23.456)}}};
   1099 
   1100   for (size_t i = 0; i < arraysize(snippets); i++) {
   1101     ScopedVector<char> script(3072);
   1102     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
   1103              function_epilogue);
   1104 
   1105     BytecodeGraphTester tester(isolate, zone, script.start(), "t");
   1106     auto callable = tester.GetCallable<>();
   1107     Handle<Object> return_value = callable().ToHandleChecked();
   1108     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1109   }
   1110 }
   1111 
   1112 
   1113 TEST(BytecodeGraphBuilderCallLookupSlot) {
   1114   HandleAndZoneScope scope;
   1115   Isolate* isolate = scope.main_isolate();
   1116   Zone* zone = scope.main_zone();
   1117 
   1118   ExpectedSnippet<0> snippets[] = {
   1119       {"g = function(){ return 2 }; eval(''); return g();",
   1120        {handle(Smi::FromInt(2), isolate)}},
   1121       {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
   1122        "return g();",
   1123        {handle(Smi::FromInt(3), isolate)}},
   1124       {"g = { x: function(){ return this.y }, y: 20 };\n"
   1125        "eval('g = { x: g.x, y: 30 }');\n"
   1126        "return g.x();",
   1127        {handle(Smi::FromInt(30), isolate)}},
   1128   };
   1129 
   1130   for (size_t i = 0; i < arraysize(snippets); i++) {
   1131     ScopedVector<char> script(1024);
   1132     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1133              snippets[i].code_snippet, kFunctionName);
   1134     BytecodeGraphTester tester(isolate, zone, script.start());
   1135     auto callable = tester.GetCallable<>();
   1136     Handle<Object> return_value = callable().ToHandleChecked();
   1137     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1138   }
   1139 }
   1140 
   1141 
   1142 TEST(BytecodeGraphBuilderEval) {
   1143   HandleAndZoneScope scope;
   1144   Isolate* isolate = scope.main_isolate();
   1145   Zone* zone = scope.main_zone();
   1146   Factory* factory = isolate->factory();
   1147 
   1148   ExpectedSnippet<0> snippets[] = {
   1149       {"return eval('1;');", {handle(Smi::FromInt(1), isolate)}},
   1150       {"return eval('100 * 20;');", {handle(Smi::FromInt(2000), isolate)}},
   1151       {"var x = 10; return eval('x + 20;');",
   1152        {handle(Smi::FromInt(30), isolate)}},
   1153       {"var x = 10; eval('x = 33;'); return x;",
   1154        {handle(Smi::FromInt(33), isolate)}},
   1155       {"'use strict'; var x = 20; var z = 0;\n"
   1156        "eval('var x = 33; z = x;'); return x + z;",
   1157        {handle(Smi::FromInt(53), isolate)}},
   1158       {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
   1159        {handle(Smi::FromInt(86), isolate)}},
   1160       {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
   1161        {handle(Smi::FromInt(11), isolate)}},
   1162       {"var x = 10; eval('var x = 20;'); return x;",
   1163        {handle(Smi::FromInt(20), isolate)}},
   1164       {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
   1165        {handle(Smi::FromInt(1), isolate)}},
   1166       {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
   1167        {handle(Smi::FromInt(1), isolate)}},
   1168       {"var x = 10; eval('x + 20;'); return typeof x;",
   1169        {factory->NewStringFromStaticChars("number")}},
   1170       {"eval('var y = 10;'); return typeof unallocated;",
   1171        {factory->NewStringFromStaticChars("undefined")}},
   1172       {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
   1173        {factory->NewStringFromStaticChars("undefined")}},
   1174       {"eval('var x = 10;'); return typeof x;",
   1175        {factory->NewStringFromStaticChars("number")}},
   1176       {"var x = {}; eval('var x = 10;'); return typeof x;",
   1177        {factory->NewStringFromStaticChars("number")}},
   1178       {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
   1179        {factory->NewStringFromStaticChars("object")}},
   1180   };
   1181 
   1182   for (size_t i = 0; i < arraysize(snippets); i++) {
   1183     ScopedVector<char> script(1024);
   1184     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1185              snippets[i].code_snippet, kFunctionName);
   1186     BytecodeGraphTester tester(isolate, zone, script.start());
   1187     auto callable = tester.GetCallable<>();
   1188     Handle<Object> return_value = callable().ToHandleChecked();
   1189     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1190   }
   1191 }
   1192 
   1193 
   1194 TEST(BytecodeGraphBuilderEvalParams) {
   1195   HandleAndZoneScope scope;
   1196   Isolate* isolate = scope.main_isolate();
   1197   Zone* zone = scope.main_zone();
   1198 
   1199   ExpectedSnippet<1> snippets[] = {
   1200       {"var x = 10; return eval('x + p1;');",
   1201        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
   1202       {"var x = 10; eval('p1 = x;'); return p1;",
   1203        {handle(Smi::FromInt(10), isolate), handle(Smi::FromInt(20), isolate)}},
   1204       {"var a = 10;"
   1205        "function inner() { return eval('a + p1;');}"
   1206        "return inner();",
   1207        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
   1208   };
   1209 
   1210   for (size_t i = 0; i < arraysize(snippets); i++) {
   1211     ScopedVector<char> script(1024);
   1212     SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
   1213              snippets[i].code_snippet, kFunctionName);
   1214     BytecodeGraphTester tester(isolate, zone, script.start());
   1215     auto callable = tester.GetCallable<Handle<Object>>();
   1216     Handle<Object> return_value =
   1217         callable(snippets[i].parameter(0)).ToHandleChecked();
   1218     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1219   }
   1220 }
   1221 
   1222 
   1223 TEST(BytecodeGraphBuilderEvalGlobal) {
   1224   HandleAndZoneScope scope;
   1225   Isolate* isolate = scope.main_isolate();
   1226   Zone* zone = scope.main_zone();
   1227   Factory* factory = isolate->factory();
   1228 
   1229   ExpectedSnippet<0> snippets[] = {
   1230       {"function add_global() { eval('function f() { z = 33; }; f()'); };"
   1231        "function f() { add_global(); return z; }; f();",
   1232        {handle(Smi::FromInt(33), isolate)}},
   1233       {"function add_global() {\n"
   1234        " eval('\"use strict\"; function f() { y = 33; };"
   1235        "      try { f() } catch(e) {}');\n"
   1236        "}\n"
   1237        "function f() { add_global(); return typeof y; } f();",
   1238        {factory->NewStringFromStaticChars("undefined")}},
   1239   };
   1240 
   1241   for (size_t i = 0; i < arraysize(snippets); i++) {
   1242     BytecodeGraphTester tester(isolate, zone, snippets[i].code_snippet);
   1243     auto callable = tester.GetCallable<>();
   1244     Handle<Object> return_value = callable().ToHandleChecked();
   1245     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1246   }
   1247 }
   1248 
   1249 
   1250 bool get_compare_result(Token::Value opcode, Handle<Object> lhs_value,
   1251                         Handle<Object> rhs_value) {
   1252   switch (opcode) {
   1253     case Token::Value::EQ:
   1254       return Object::Equals(lhs_value, rhs_value).FromJust();
   1255     case Token::Value::NE:
   1256       return !Object::Equals(lhs_value, rhs_value).FromJust();
   1257     case Token::Value::EQ_STRICT:
   1258       return lhs_value->StrictEquals(*rhs_value);
   1259     case Token::Value::NE_STRICT:
   1260       return !lhs_value->StrictEquals(*rhs_value);
   1261     case Token::Value::LT:
   1262       return Object::LessThan(lhs_value, rhs_value).FromJust();
   1263     case Token::Value::LTE:
   1264       return Object::LessThanOrEqual(lhs_value, rhs_value).FromJust();
   1265     case Token::Value::GT:
   1266       return Object::GreaterThan(lhs_value, rhs_value).FromJust();
   1267     case Token::Value::GTE:
   1268       return Object::GreaterThanOrEqual(lhs_value, rhs_value).FromJust();
   1269     default:
   1270       UNREACHABLE();
   1271       return false;
   1272   }
   1273 }
   1274 
   1275 
   1276 const char* get_code_snippet(Token::Value opcode) {
   1277   switch (opcode) {
   1278     case Token::Value::EQ:
   1279       return "return p1 == p2;";
   1280     case Token::Value::NE:
   1281       return "return p1 != p2;";
   1282     case Token::Value::EQ_STRICT:
   1283       return "return p1 === p2;";
   1284     case Token::Value::NE_STRICT:
   1285       return "return p1 !== p2;";
   1286     case Token::Value::LT:
   1287       return "return p1 < p2;";
   1288     case Token::Value::LTE:
   1289       return "return p1 <= p2;";
   1290     case Token::Value::GT:
   1291       return "return p1 > p2;";
   1292     case Token::Value::GTE:
   1293       return "return p1 >= p2;";
   1294     default:
   1295       UNREACHABLE();
   1296       return "";
   1297   }
   1298 }
   1299 
   1300 
   1301 TEST(BytecodeGraphBuilderCompare) {
   1302   HandleAndZoneScope scope;
   1303   Isolate* isolate = scope.main_isolate();
   1304   Zone* zone = scope.main_zone();
   1305   Factory* factory = isolate->factory();
   1306   Handle<Object> lhs_values[] = {
   1307       factory->NewNumberFromInt(10), factory->NewHeapNumber(3.45),
   1308       factory->NewStringFromStaticChars("abc"),
   1309       factory->NewNumberFromInt(SMI_MAX), factory->NewNumberFromInt(SMI_MIN)};
   1310   Handle<Object> rhs_values[] = {factory->NewNumberFromInt(10),
   1311                                  factory->NewStringFromStaticChars("10"),
   1312                                  factory->NewNumberFromInt(20),
   1313                                  factory->NewStringFromStaticChars("abc"),
   1314                                  factory->NewHeapNumber(3.45),
   1315                                  factory->NewNumberFromInt(SMI_MAX),
   1316                                  factory->NewNumberFromInt(SMI_MIN)};
   1317 
   1318   for (size_t i = 0; i < arraysize(kCompareOperators); i++) {
   1319     ScopedVector<char> script(1024);
   1320     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
   1321              get_code_snippet(kCompareOperators[i]), kFunctionName);
   1322 
   1323     BytecodeGraphTester tester(isolate, zone, script.start());
   1324     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   1325     for (size_t j = 0; j < arraysize(lhs_values); j++) {
   1326       for (size_t k = 0; k < arraysize(rhs_values); k++) {
   1327         Handle<Object> return_value =
   1328             callable(lhs_values[j], rhs_values[k]).ToHandleChecked();
   1329         bool result = get_compare_result(kCompareOperators[i], lhs_values[j],
   1330                                          rhs_values[k]);
   1331         CHECK(return_value->SameValue(*factory->ToBoolean(result)));
   1332       }
   1333     }
   1334   }
   1335 }
   1336 
   1337 
   1338 TEST(BytecodeGraphBuilderTestIn) {
   1339   HandleAndZoneScope scope;
   1340   Isolate* isolate = scope.main_isolate();
   1341   Zone* zone = scope.main_zone();
   1342   Factory* factory = isolate->factory();
   1343 
   1344   ExpectedSnippet<2> snippets[] = {
   1345       {"return p2 in p1;",
   1346        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1347         factory->NewStringFromStaticChars("val")}},
   1348       {"return p2 in p1;",
   1349        {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
   1350         factory->NewStringFromStaticChars("length")}},
   1351       {"return p2 in p1;",
   1352        {factory->true_value(), BytecodeGraphTester::NewObject("[]"),
   1353         factory->NewStringFromStaticChars("toString")}},
   1354       {"return p2 in p1;",
   1355        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1356         factory->NewStringFromStaticChars("toString")}},
   1357       {"return p2 in p1;",
   1358        {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1359         factory->NewStringFromStaticChars("abc")}},
   1360       {"return p2 in p1;",
   1361        {factory->false_value(), BytecodeGraphTester::NewObject("({val : 10})"),
   1362         factory->NewNumberFromInt(10)}},
   1363       {"return p2 in p1;",
   1364        {factory->true_value(), BytecodeGraphTester::NewObject("({10 : 'val'})"),
   1365         factory->NewNumberFromInt(10)}},
   1366       {"return p2 in p1;",
   1367        {factory->false_value(),
   1368         BytecodeGraphTester::NewObject("({10 : 'val'})"),
   1369         factory->NewNumberFromInt(1)}},
   1370   };
   1371 
   1372   for (size_t i = 0; i < arraysize(snippets); i++) {
   1373     ScopedVector<char> script(1024);
   1374     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
   1375              snippets[i].code_snippet, kFunctionName);
   1376 
   1377     BytecodeGraphTester tester(isolate, zone, script.start());
   1378     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   1379     Handle<Object> return_value =
   1380         callable(snippets[i].parameter(0), snippets[i].parameter(1))
   1381             .ToHandleChecked();
   1382     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1383   }
   1384 }
   1385 
   1386 
   1387 TEST(BytecodeGraphBuilderTestInstanceOf) {
   1388   HandleAndZoneScope scope;
   1389   Isolate* isolate = scope.main_isolate();
   1390   Zone* zone = scope.main_zone();
   1391   Factory* factory = isolate->factory();
   1392 
   1393   ExpectedSnippet<1> snippets[] = {
   1394       {"return p1 instanceof Object;",
   1395        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
   1396       {"return p1 instanceof String;",
   1397        {factory->false_value(), factory->NewStringFromStaticChars("string")}},
   1398       {"var cons = function() {};"
   1399        "var obj = new cons();"
   1400        "return obj instanceof cons;",
   1401        {factory->true_value(), factory->undefined_value()}},
   1402   };
   1403 
   1404   for (size_t i = 0; i < arraysize(snippets); i++) {
   1405     ScopedVector<char> script(1024);
   1406     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
   1407              snippets[i].code_snippet, kFunctionName);
   1408 
   1409     BytecodeGraphTester tester(isolate, zone, script.start());
   1410     auto callable = tester.GetCallable<Handle<Object>>();
   1411     Handle<Object> return_value =
   1412         callable(snippets[i].parameter(0)).ToHandleChecked();
   1413     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1414   }
   1415 }
   1416 
   1417 TEST(BytecodeGraphBuilderTryCatch) {
   1418   HandleAndZoneScope scope;
   1419   Isolate* isolate = scope.main_isolate();
   1420   Zone* zone = scope.main_zone();
   1421 
   1422   ExpectedSnippet<0> snippets[] = {
   1423       {"var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
   1424        {handle(Smi::FromInt(2), isolate)}},
   1425       {"var a; try { undef.x } catch(e) { a = 2 }; return a;",
   1426        {handle(Smi::FromInt(2), isolate)}},
   1427       {"var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
   1428        {handle(Smi::FromInt(3), isolate)}},
   1429       {"var a; try { throw 1 } catch(e) { a = e + 2 };"
   1430        "       try { throw a } catch(e) { a = e + 3 }; return a;",
   1431        {handle(Smi::FromInt(6), isolate)}},
   1432   };
   1433 
   1434   for (size_t i = 0; i < arraysize(snippets); i++) {
   1435     ScopedVector<char> script(1024);
   1436     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1437              snippets[i].code_snippet, kFunctionName);
   1438 
   1439     BytecodeGraphTester tester(isolate, zone, script.start());
   1440     auto callable = tester.GetCallable<>();
   1441     Handle<Object> return_value = callable().ToHandleChecked();
   1442     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1443   }
   1444 }
   1445 
   1446 TEST(BytecodeGraphBuilderTryFinally1) {
   1447   HandleAndZoneScope scope;
   1448   Isolate* isolate = scope.main_isolate();
   1449   Zone* zone = scope.main_zone();
   1450 
   1451   ExpectedSnippet<0> snippets[] = {
   1452       {"var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
   1453        {handle(Smi::FromInt(4), isolate)}},
   1454       {"var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
   1455        {handle(Smi::FromInt(23), isolate)}},
   1456       {"var a = 1; try { a = 2; throw 23; } finally { return a; };",
   1457        {handle(Smi::FromInt(2), isolate)}},
   1458       {"var a = 1; for (var i = 10; i < 20; i += 5) {"
   1459        "  try { a = 2; break; } finally { a = 3; }"
   1460        "} return a + i;",
   1461        {handle(Smi::FromInt(13), isolate)}},
   1462       {"var a = 1; for (var i = 10; i < 20; i += 5) {"
   1463        "  try { a = 2; continue; } finally { a = 3; }"
   1464        "} return a + i;",
   1465        {handle(Smi::FromInt(23), isolate)}},
   1466       {"var a = 1; try { a = 2;"
   1467        "  try { a = 3; throw 23; } finally { a = 4; }"
   1468        "} catch(e) { a = a + e; } return a;",
   1469        {handle(Smi::FromInt(27), isolate)}},
   1470   };
   1471 
   1472   for (size_t i = 0; i < arraysize(snippets); i++) {
   1473     ScopedVector<char> script(1024);
   1474     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1475              snippets[i].code_snippet, kFunctionName);
   1476 
   1477     BytecodeGraphTester tester(isolate, zone, script.start());
   1478     auto callable = tester.GetCallable<>();
   1479     Handle<Object> return_value = callable().ToHandleChecked();
   1480     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1481   }
   1482 }
   1483 
   1484 TEST(BytecodeGraphBuilderTryFinally2) {
   1485   HandleAndZoneScope scope;
   1486   Isolate* isolate = scope.main_isolate();
   1487   Zone* zone = scope.main_zone();
   1488 
   1489   ExpectedSnippet<0, const char*> snippets[] = {
   1490       {"var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
   1491        {"Uncaught 23"}},
   1492       {"var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
   1493        {"Uncaught 42"}},
   1494   };
   1495 
   1496   for (size_t i = 0; i < arraysize(snippets); i++) {
   1497     ScopedVector<char> script(1024);
   1498     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1499              snippets[i].code_snippet, kFunctionName);
   1500 
   1501     BytecodeGraphTester tester(isolate, zone, script.start());
   1502     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   1503     v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
   1504     CHECK(
   1505         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   1506             .FromJust());
   1507   }
   1508 }
   1509 
   1510 TEST(BytecodeGraphBuilderThrow) {
   1511   HandleAndZoneScope scope;
   1512   Isolate* isolate = scope.main_isolate();
   1513   Zone* zone = scope.main_zone();
   1514 
   1515   // TODO(mythria): Add more tests when real try-catch and deoptimization
   1516   // information are supported.
   1517   ExpectedSnippet<0, const char*> snippets[] = {
   1518       {"throw undefined;", {"Uncaught undefined"}},
   1519       {"throw 1;", {"Uncaught 1"}},
   1520       {"throw 'Error';", {"Uncaught Error"}},
   1521       {"throw 'Error1'; throw 'Error2'", {"Uncaught Error1"}},
   1522       {"var a = true; if (a) { throw 'Error'; }", {"Uncaught Error"}},
   1523   };
   1524 
   1525   for (size_t i = 0; i < arraysize(snippets); i++) {
   1526     ScopedVector<char> script(1024);
   1527     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1528              snippets[i].code_snippet, kFunctionName);
   1529 
   1530     BytecodeGraphTester tester(isolate, zone, script.start());
   1531     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   1532     v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
   1533     CHECK(
   1534         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   1535             .FromJust());
   1536   }
   1537 }
   1538 
   1539 
   1540 TEST(BytecodeGraphBuilderContext) {
   1541   HandleAndZoneScope scope;
   1542   Isolate* isolate = scope.main_isolate();
   1543   Zone* zone = scope.main_zone();
   1544   Factory* factory = isolate->factory();
   1545 
   1546   ExpectedSnippet<0> snippets[] = {
   1547       {"var x = 'outer';"
   1548        "function f() {"
   1549        " 'use strict';"
   1550        " {"
   1551        "   let x = 'inner';"
   1552        "   (function() {x});"
   1553        " }"
   1554        "return(x);"
   1555        "}"
   1556        "f();",
   1557        {factory->NewStringFromStaticChars("outer")}},
   1558       {"var x = 'outer';"
   1559        "function f() {"
   1560        " 'use strict';"
   1561        " {"
   1562        "   let x = 'inner ';"
   1563        "   var innerFunc = function() {return x};"
   1564        " }"
   1565        "return(innerFunc() + x);"
   1566        "}"
   1567        "f();",
   1568        {factory->NewStringFromStaticChars("inner outer")}},
   1569       {"var x = 'outer';"
   1570        "function f() {"
   1571        " 'use strict';"
   1572        " {"
   1573        "   let x = 'inner ';"
   1574        "   var innerFunc = function() {return x;};"
   1575        "   {"
   1576        "     let x = 'innermost ';"
   1577        "     var innerMostFunc = function() {return x + innerFunc();};"
   1578        "   }"
   1579        "   x = 'inner_changed ';"
   1580        " }"
   1581        " return(innerMostFunc() + x);"
   1582        "}"
   1583        "f();",
   1584        {factory->NewStringFromStaticChars("innermost inner_changed outer")}},
   1585   };
   1586 
   1587   for (size_t i = 0; i < arraysize(snippets); i++) {
   1588     ScopedVector<char> script(1024);
   1589     SNPrintF(script, "%s", snippets[i].code_snippet);
   1590 
   1591     BytecodeGraphTester tester(isolate, zone, script.start(), "f");
   1592     auto callable = tester.GetCallable<>("f");
   1593     Handle<Object> return_value = callable().ToHandleChecked();
   1594     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1595   }
   1596 }
   1597 
   1598 
   1599 TEST(BytecodeGraphBuilderLoadContext) {
   1600   HandleAndZoneScope scope;
   1601   Isolate* isolate = scope.main_isolate();
   1602   Zone* zone = scope.main_zone();
   1603   Factory* factory = isolate->factory();
   1604 
   1605   ExpectedSnippet<1> snippets[] = {
   1606       {"function Outer() {"
   1607        "  var outerVar = 2;"
   1608        "  function Inner(innerArg) {"
   1609        "    this.innerFunc = function () {"
   1610        "     return outerVar * innerArg;"
   1611        "    };"
   1612        "  };"
   1613        "  this.getInnerFunc = function GetInner() {"
   1614        "     return new Inner(3).innerFunc;"
   1615        "   }"
   1616        "}"
   1617        "var f = new Outer().getInnerFunc();"
   1618        "f();",
   1619        {factory->NewNumberFromInt(6), factory->undefined_value()}},
   1620       {"function Outer() {"
   1621        "  var outerVar = 2;"
   1622        "  function Inner(innerArg) {"
   1623        "    this.innerFunc = function () {"
   1624        "     outerVar = innerArg; return outerVar;"
   1625        "    };"
   1626        "  };"
   1627        "  this.getInnerFunc = function GetInner() {"
   1628        "     return new Inner(10).innerFunc;"
   1629        "   }"
   1630        "}"
   1631        "var f = new Outer().getInnerFunc();"
   1632        "f();",
   1633        {factory->NewNumberFromInt(10), factory->undefined_value()}},
   1634       {"function testOuter(outerArg) {"
   1635        " this.testinnerFunc = function testInner(innerArg) {"
   1636        "   return innerArg + outerArg;"
   1637        " }"
   1638        "}"
   1639        "var f = new testOuter(10).testinnerFunc;"
   1640        "f(0);",
   1641        {factory->NewNumberFromInt(14), factory->NewNumberFromInt(4)}},
   1642       {"function testOuter(outerArg) {"
   1643        " var outerVar = outerArg * 2;"
   1644        " this.testinnerFunc = function testInner(innerArg) {"
   1645        "   outerVar = outerVar + innerArg; return outerVar;"
   1646        " }"
   1647        "}"
   1648        "var f = new testOuter(10).testinnerFunc;"
   1649        "f(0);",
   1650        {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
   1651 
   1652   for (size_t i = 0; i < arraysize(snippets); i++) {
   1653     ScopedVector<char> script(1024);
   1654     SNPrintF(script, "%s", snippets[i].code_snippet);
   1655 
   1656     BytecodeGraphTester tester(isolate, zone, script.start(), "*");
   1657     auto callable = tester.GetCallable<Handle<Object>>("f");
   1658     Handle<Object> return_value =
   1659         callable(snippets[i].parameter(0)).ToHandleChecked();
   1660     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1661   }
   1662 }
   1663 
   1664 
   1665 TEST(BytecodeGraphBuilderCreateArgumentsNoParameters) {
   1666   HandleAndZoneScope scope;
   1667   Isolate* isolate = scope.main_isolate();
   1668   Zone* zone = scope.main_zone();
   1669   Factory* factory = isolate->factory();
   1670 
   1671   ExpectedSnippet<0> snippets[] = {
   1672       {"function f() {return arguments[0];}", {factory->undefined_value()}},
   1673       {"function f(a) {return arguments[0];}", {factory->undefined_value()}},
   1674       {"function f() {'use strict'; return arguments[0];}",
   1675        {factory->undefined_value()}},
   1676       {"function f(a) {'use strict'; return arguments[0];}",
   1677        {factory->undefined_value()}},
   1678       {"function f(...restArgs) {return restArgs[0];}",
   1679        {factory->undefined_value()}},
   1680       {"function f(a, ...restArgs) {return restArgs[0];}",
   1681        {factory->undefined_value()}},
   1682   };
   1683 
   1684   for (size_t i = 0; i < arraysize(snippets); i++) {
   1685     ScopedVector<char> script(1024);
   1686     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
   1687 
   1688     BytecodeGraphTester tester(isolate, zone, script.start());
   1689     auto callable = tester.GetCallable<>();
   1690     Handle<Object> return_value = callable().ToHandleChecked();
   1691     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1692   }
   1693 }
   1694 
   1695 
   1696 TEST(BytecodeGraphBuilderCreateArguments) {
   1697   HandleAndZoneScope scope;
   1698   Isolate* isolate = scope.main_isolate();
   1699   Zone* zone = scope.main_zone();
   1700   Factory* factory = isolate->factory();
   1701 
   1702   ExpectedSnippet<3> snippets[] = {
   1703       {"function f(a, b, c) {return arguments[0];}",
   1704        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
   1705         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1706       {"function f(a, b, c) {return arguments[3];}",
   1707        {factory->undefined_value(), factory->NewNumberFromInt(1),
   1708         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1709       {"function f(a, b, c) { b = c; return arguments[1];}",
   1710        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1711         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1712       {"function f(a, b, c) {'use strict'; return arguments[0];}",
   1713        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
   1714         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1715       {"function f(a, b, c) {'use strict'; return arguments[3];}",
   1716        {factory->undefined_value(), factory->NewNumberFromInt(1),
   1717         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1718       {"function f(a, b, c) {'use strict'; b = c; return arguments[1];}",
   1719        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
   1720         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1721       {"function inline_func(a, b) { return arguments[0] }"
   1722        "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
   1723        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1724         factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
   1725   };
   1726 
   1727   for (size_t i = 0; i < arraysize(snippets); i++) {
   1728     ScopedVector<char> script(1024);
   1729     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
   1730 
   1731     BytecodeGraphTester tester(isolate, zone, script.start());
   1732     auto callable =
   1733         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
   1734     Handle<Object> return_value =
   1735         callable(snippets[i].parameter(0), snippets[i].parameter(1),
   1736                  snippets[i].parameter(2))
   1737             .ToHandleChecked();
   1738     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1739   }
   1740 }
   1741 
   1742 TEST(BytecodeGraphBuilderCreateRestArguments) {
   1743   HandleAndZoneScope scope;
   1744   Isolate* isolate = scope.main_isolate();
   1745   Zone* zone = scope.main_zone();
   1746   Factory* factory = isolate->factory();
   1747 
   1748   ExpectedSnippet<3> snippets[] = {
   1749       {"function f(...restArgs) {return restArgs[0];}",
   1750        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(1),
   1751         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1752       {"function f(a, b, ...restArgs) {return restArgs[0];}",
   1753        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1754         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1755       {"function f(a, b, ...restArgs) {return arguments[2];}",
   1756        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   1757         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1758       {"function f(a, ...restArgs) { return restArgs[2];}",
   1759        {factory->undefined_value(), factory->NewNumberFromInt(1),
   1760         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1761       {"function f(a, ...restArgs) { return arguments[0] + restArgs[1];}",
   1762        {factory->NewNumberFromInt(4), factory->NewNumberFromInt(1),
   1763         factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   1764       {"function inline_func(a, ...restArgs) { return restArgs[0] }"
   1765        "function f(a, b, c) {return inline_func(b, c) + arguments[0];}",
   1766        {factory->NewNumberFromInt(31), factory->NewNumberFromInt(1),
   1767         factory->NewNumberFromInt(2), factory->NewNumberFromInt(30)}},
   1768   };
   1769 
   1770   for (size_t i = 0; i < arraysize(snippets); i++) {
   1771     ScopedVector<char> script(1024);
   1772     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
   1773 
   1774     BytecodeGraphTester tester(isolate, zone, script.start());
   1775     auto callable =
   1776         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
   1777     Handle<Object> return_value =
   1778         callable(snippets[i].parameter(0), snippets[i].parameter(1),
   1779                  snippets[i].parameter(2))
   1780             .ToHandleChecked();
   1781     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1782   }
   1783 }
   1784 
   1785 TEST(BytecodeGraphBuilderRegExpLiterals) {
   1786   HandleAndZoneScope scope;
   1787   Isolate* isolate = scope.main_isolate();
   1788   Zone* zone = scope.main_zone();
   1789   Factory* factory = isolate->factory();
   1790 
   1791   ExpectedSnippet<0> snippets[] = {
   1792       {"return /abd/.exec('cccabbdd');", {factory->null_value()}},
   1793       {"return /ab+d/.exec('cccabbdd')[0];",
   1794        {factory->NewStringFromStaticChars("abbd")}},
   1795       {"var a = 3.1414;"
   1796        REPEAT_256(SPACE, "a = 3.1414;")
   1797        "return /ab+d/.exec('cccabbdd')[0];",
   1798        {factory->NewStringFromStaticChars("abbd")}},
   1799       {"return /ab+d/.exec('cccabbdd')[1];", {factory->undefined_value()}},
   1800       {"return /AbC/i.exec('ssaBC')[0];",
   1801        {factory->NewStringFromStaticChars("aBC")}},
   1802       {"return 'ssaBC'.match(/AbC/i)[0];",
   1803        {factory->NewStringFromStaticChars("aBC")}},
   1804       {"return 'ssaBCtAbC'.match(/(AbC)/gi)[1];",
   1805        {factory->NewStringFromStaticChars("AbC")}},
   1806   };
   1807 
   1808   for (size_t i = 0; i < arraysize(snippets); i++) {
   1809     ScopedVector<char> script(4096);
   1810     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1811              snippets[i].code_snippet, kFunctionName);
   1812 
   1813     BytecodeGraphTester tester(isolate, zone, script.start());
   1814     auto callable = tester.GetCallable<>();
   1815     Handle<Object> return_value = callable().ToHandleChecked();
   1816     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1817   }
   1818 }
   1819 
   1820 
   1821 TEST(BytecodeGraphBuilderArrayLiterals) {
   1822   HandleAndZoneScope scope;
   1823   Isolate* isolate = scope.main_isolate();
   1824   Zone* zone = scope.main_zone();
   1825   Factory* factory = isolate->factory();
   1826 
   1827   ExpectedSnippet<0> snippets[] = {
   1828       {"return [][0];", {factory->undefined_value()}},
   1829       {"return [1, 3, 2][1];", {factory->NewNumberFromInt(3)}},
   1830       {"var a;" REPEAT_256(SPACE, "a = 9.87;") "return [1, 3, 2][1];",
   1831        {factory->NewNumberFromInt(3)}},
   1832       {"return ['a', 'b', 'c'][2];", {factory->NewStringFromStaticChars("c")}},
   1833       {"var a = 100; return [a, a++, a + 2, a + 3][2];",
   1834        {factory->NewNumberFromInt(103)}},
   1835       {"var a = 100; return [a, ++a, a + 2, a + 3][1];",
   1836        {factory->NewNumberFromInt(101)}},
   1837       {"var a = 9.2;"
   1838        REPEAT_256(SPACE, "a = 9.34;")
   1839        "return [a, ++a, a + 2, a + 3][2];",
   1840        {factory->NewHeapNumber(12.34)}},
   1841       {"return [[1, 2, 3], ['a', 'b', 'c']][1][0];",
   1842        {factory->NewStringFromStaticChars("a")}},
   1843       {"var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];",
   1844        {factory->NewStringFromStaticChars("test")}},
   1845       {"var t = 't'; return [[t, t + 'est'], [1 + t]][1][0];",
   1846        {factory->NewStringFromStaticChars("1t")}}};
   1847 
   1848   for (size_t i = 0; i < arraysize(snippets); i++) {
   1849     ScopedVector<char> script(4096);
   1850     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1851              snippets[i].code_snippet, kFunctionName);
   1852 
   1853     BytecodeGraphTester tester(isolate, zone, script.start());
   1854     auto callable = tester.GetCallable<>();
   1855     Handle<Object> return_value = callable().ToHandleChecked();
   1856     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1857   }
   1858 }
   1859 
   1860 
   1861 TEST(BytecodeGraphBuilderObjectLiterals) {
   1862   HandleAndZoneScope scope;
   1863   Isolate* isolate = scope.main_isolate();
   1864   Zone* zone = scope.main_zone();
   1865   Factory* factory = isolate->factory();
   1866 
   1867   ExpectedSnippet<0> snippets[] = {
   1868       {"return { }.name;", {factory->undefined_value()}},
   1869       {"return { name: 'string', val: 9.2 }.name;",
   1870        {factory->NewStringFromStaticChars("string")}},
   1871       {"var a;\n"
   1872        REPEAT_256(SPACE, "a = 1.23;\n")
   1873        "return { name: 'string', val: 9.2 }.name;",
   1874        {factory->NewStringFromStaticChars("string")}},
   1875       {"return { name: 'string', val: 9.2 }['name'];",
   1876        {factory->NewStringFromStaticChars("string")}},
   1877       {"var a = 15; return { name: 'string', val: a }.val;",
   1878        {factory->NewNumberFromInt(15)}},
   1879       {"var a;"
   1880        REPEAT_256(SPACE, "a = 1.23;")
   1881        "return { name: 'string', val: a }.val;",
   1882        {factory->NewHeapNumber(1.23)}},
   1883       {"var a = 15; var b = 'val'; return { name: 'string', val: a }[b];",
   1884        {factory->NewNumberFromInt(15)}},
   1885       {"var a = 5; return { val: a, val: a + 1 }.val;",
   1886        {factory->NewNumberFromInt(6)}},
   1887       {"return { func: function() { return 'test' } }.func();",
   1888        {factory->NewStringFromStaticChars("test")}},
   1889       {"return { func(a) { return a + 'st'; } }.func('te');",
   1890        {factory->NewStringFromStaticChars("test")}},
   1891       {"return { get a() { return 22; } }.a;", {factory->NewNumberFromInt(22)}},
   1892       {"var a = { get b() { return this.x + 't'; },\n"
   1893        "          set b(val) { this.x = val + 's' } };\n"
   1894        "a.b = 'te';\n"
   1895        "return a.b;",
   1896        {factory->NewStringFromStaticChars("test")}},
   1897       {"var a = 123; return { 1: a }[1];", {factory->NewNumberFromInt(123)}},
   1898       {"return Object.getPrototypeOf({ __proto__: null });",
   1899        {factory->null_value()}},
   1900       {"var a = 'test'; return { [a]: 1 }.test;",
   1901        {factory->NewNumberFromInt(1)}},
   1902       {"var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
   1903        {factory->NewStringFromStaticChars("testing")}},
   1904       {"var a = 'proto_str';\n"
   1905        "var b = { [a]: 1, __proto__: { var : a } };\n"
   1906        "return Object.getPrototypeOf(b).var",
   1907        {factory->NewStringFromStaticChars("proto_str")}},
   1908       {"var n = 'name';\n"
   1909        "return { [n]: 'val', get a() { return 987 } }['a'];",
   1910        {factory->NewNumberFromInt(987)}},
   1911   };
   1912 
   1913   for (size_t i = 0; i < arraysize(snippets); i++) {
   1914     ScopedVector<char> script(4096);
   1915     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   1916              snippets[i].code_snippet, kFunctionName);
   1917     BytecodeGraphTester tester(isolate, zone, script.start());
   1918     auto callable = tester.GetCallable<>();
   1919     Handle<Object> return_value = callable().ToHandleChecked();
   1920     CHECK(return_value->SameValue(*snippets[i].return_value()));
   1921   }
   1922 }
   1923 
   1924 
   1925 TEST(BytecodeGraphBuilderIf) {
   1926   HandleAndZoneScope scope;
   1927   Isolate* isolate = scope.main_isolate();
   1928   Zone* zone = scope.main_zone();
   1929   Factory* factory = isolate->factory();
   1930 
   1931   ExpectedSnippet<1> snippets[] = {
   1932       {"if (p1 > 1) return 1;\n"
   1933        "return -1;",
   1934        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   1935       {"if (p1 > 1) return 1;\n"
   1936        "return -1;",
   1937        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
   1938       {"if (p1 > 1) { return 1; } else { return -1; }",
   1939        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   1940       {"if (p1 > 1) { return 1; } else { return -1; }",
   1941        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(1)}},
   1942       {"if (p1 > 50) {\n"
   1943        "  return 1;\n"
   1944        "} else if (p1 < 10) {\n"
   1945        "   return 10;\n"
   1946        "} else {\n"
   1947        "   return -10;\n"
   1948        "}",
   1949        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(51)}},
   1950       {"if (p1 > 50) {\n"
   1951        "  return 1;\n"
   1952        "} else if (p1 < 10) {\n"
   1953        "   return 10;\n"
   1954        "} else {\n"
   1955        "   return 100;\n"
   1956        "}",
   1957        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
   1958       {"if (p1 > 50) {\n"
   1959        "  return 1;\n"
   1960        "} else if (p1 < 10) {\n"
   1961        "   return 10;\n"
   1962        "} else {\n"
   1963        "   return 100;\n"
   1964        "}",
   1965        {factory->NewNumberFromInt(100), factory->NewNumberFromInt(10)}},
   1966       {"if (p1 >= 0) {\n"
   1967        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1968        "} else {\n"
   1969        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1970        "}",
   1971        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(100)}},
   1972       {"if (p1 >= 0) {\n"
   1973        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1974        "} else {\n"
   1975        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1976        "}",
   1977        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(10)}},
   1978       {"if (p1 >= 0) {\n"
   1979        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1980        "} else {\n"
   1981        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1982        "}",
   1983        {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(-11)}},
   1984       {"if (p1 >= 0) {\n"
   1985        "   if (p1 > 10) { return 2; } else { return 1; }\n"
   1986        "} else {\n"
   1987        "   if (p1 < -10) { return -2; } else { return -1; }\n"
   1988        "}",
   1989        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-10)}},
   1990       {"var b = 20, c;"
   1991        "if (p1 >= 0) {\n"
   1992        "   if (b > 0) { c = 2; } else { c = 3; }\n"
   1993        "} else {\n"
   1994        "   if (b < -10) { c = -2; } else { c = -1; }\n"
   1995        "}"
   1996        "return c;",
   1997        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(-1)}},
   1998       {"var b = 20, c = 10;"
   1999        "if (p1 >= 0) {\n"
   2000        "   if (b < 0) { c = 2; }\n"
   2001        "} else {\n"
   2002        "   if (b < -10) { c = -2; } else { c = -1; }\n"
   2003        "}"
   2004        "return c;",
   2005        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(1)}},
   2006       {"var x = 2, a = 10, b = 20, c, d;"
   2007        "x = 0;"
   2008        "if (a) {\n"
   2009        "   b = x;"
   2010        "   if (b > 0) { c = 2; } else { c = 3; }\n"
   2011        "   x = 4; d = 2;"
   2012        "} else {\n"
   2013        "   d = 3;\n"
   2014        "}"
   2015        "x = d;"
   2016        "function f1() {x}"
   2017        "return x + c;",
   2018        {factory->NewNumberFromInt(5), factory->NewNumberFromInt(-1)}},
   2019   };
   2020 
   2021   for (size_t i = 0; i < arraysize(snippets); i++) {
   2022     ScopedVector<char> script(2048);
   2023     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   2024              snippets[i].code_snippet, kFunctionName);
   2025 
   2026     BytecodeGraphTester tester(isolate, zone, script.start());
   2027     auto callable = tester.GetCallable<Handle<Object>>();
   2028     Handle<Object> return_value =
   2029         callable(snippets[i].parameter(0)).ToHandleChecked();
   2030     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2031   }
   2032 }
   2033 
   2034 
   2035 TEST(BytecodeGraphBuilderConditionalOperator) {
   2036   HandleAndZoneScope scope;
   2037   Isolate* isolate = scope.main_isolate();
   2038   Zone* zone = scope.main_zone();
   2039   Factory* factory = isolate->factory();
   2040 
   2041   ExpectedSnippet<1> snippets[] = {
   2042       {"return (p1 > 1) ? 1 : -1;",
   2043        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   2044       {"return (p1 > 1) ? 1 : -1;",
   2045        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0)}},
   2046       {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
   2047        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(2)}},
   2048       {"return (p1 > 50) ? 1 : ((p1 < 10) ? 10 : -10);",
   2049        {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(20)}},
   2050   };
   2051 
   2052   for (size_t i = 0; i < arraysize(snippets); i++) {
   2053     ScopedVector<char> script(2048);
   2054     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   2055              snippets[i].code_snippet, kFunctionName);
   2056 
   2057     BytecodeGraphTester tester(isolate, zone, script.start());
   2058     auto callable = tester.GetCallable<Handle<Object>>();
   2059     Handle<Object> return_value =
   2060         callable(snippets[i].parameter(0)).ToHandleChecked();
   2061     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2062   }
   2063 }
   2064 
   2065 
   2066 TEST(BytecodeGraphBuilderSwitch) {
   2067   HandleAndZoneScope scope;
   2068   Isolate* isolate = scope.main_isolate();
   2069   Zone* zone = scope.main_zone();
   2070   Factory* factory = isolate->factory();
   2071 
   2072   const char* switch_code =
   2073       "switch (p1) {\n"
   2074       "  case 1: return 0;\n"
   2075       "  case 2: return 1;\n"
   2076       "  case 3:\n"
   2077       "  case 4: return 2;\n"
   2078       "  case 9: break;\n"
   2079       "  default: return 3;\n"
   2080       "}\n"
   2081       "return 9;";
   2082 
   2083   ExpectedSnippet<1> snippets[] = {
   2084       {switch_code,
   2085        {factory->NewNumberFromInt(0), factory->NewNumberFromInt(1)}},
   2086       {switch_code,
   2087        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(2)}},
   2088       {switch_code,
   2089        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   2090       {switch_code,
   2091        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
   2092       {switch_code,
   2093        {factory->NewNumberFromInt(9), factory->NewNumberFromInt(9)}},
   2094       {switch_code,
   2095        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
   2096       {switch_code,
   2097        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(6)}},
   2098   };
   2099 
   2100   for (size_t i = 0; i < arraysize(snippets); i++) {
   2101     ScopedVector<char> script(2048);
   2102     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   2103              snippets[i].code_snippet, kFunctionName);
   2104 
   2105     BytecodeGraphTester tester(isolate, zone, script.start());
   2106     auto callable = tester.GetCallable<Handle<Object>>();
   2107     Handle<Object> return_value =
   2108         callable(snippets[i].parameter(0)).ToHandleChecked();
   2109     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2110   }
   2111 }
   2112 
   2113 TEST(BytecodeGraphBuilderSwitchMerge) {
   2114   HandleAndZoneScope scope;
   2115   Isolate* isolate = scope.main_isolate();
   2116   Zone* zone = scope.main_zone();
   2117   Factory* factory = isolate->factory();
   2118 
   2119   const char* switch_code =
   2120       "var x = 10;"
   2121       "switch (p1) {\n"
   2122       "  case 1: x = 0;\n"
   2123       "  case 2: x = 1;\n"
   2124       "  case 3:\n"
   2125       "  case 4: x = 2; break;\n"
   2126       "  case 5: x = 3;\n"
   2127       "  case 9: break;\n"
   2128       "  default: x = 4;\n"
   2129       "}\n"
   2130       "return x;";
   2131 
   2132   ExpectedSnippet<1> snippets[] = {
   2133       {switch_code,
   2134        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1)}},
   2135       {switch_code,
   2136        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(2)}},
   2137       {switch_code,
   2138        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(3)}},
   2139       {switch_code,
   2140        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(4)}},
   2141       {switch_code,
   2142        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(5)}},
   2143       {switch_code,
   2144        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(9)}},
   2145       {switch_code,
   2146        {factory->NewNumberFromInt(4), factory->NewNumberFromInt(6)}},
   2147   };
   2148 
   2149   for (size_t i = 0; i < arraysize(snippets); i++) {
   2150     ScopedVector<char> script(2048);
   2151     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
   2152              snippets[i].code_snippet, kFunctionName);
   2153 
   2154     BytecodeGraphTester tester(isolate, zone, script.start());
   2155     auto callable = tester.GetCallable<Handle<Object>>();
   2156     Handle<Object> return_value =
   2157         callable(snippets[i].parameter(0)).ToHandleChecked();
   2158     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2159   }
   2160 }
   2161 
   2162 TEST(BytecodeGraphBuilderNestedSwitch) {
   2163   HandleAndZoneScope scope;
   2164   Isolate* isolate = scope.main_isolate();
   2165   Zone* zone = scope.main_zone();
   2166   Factory* factory = isolate->factory();
   2167 
   2168   const char* switch_code =
   2169       "switch (p1) {\n"
   2170       "  case 0: {"
   2171       "    switch (p2) { case 0: return 0; case 1: return 1; case 2: break; }\n"
   2172       "    return -1;"
   2173       "  }\n"
   2174       "  case 1: {"
   2175       "    switch (p2) { case 0: return 2; case 1: return 3; }\n"
   2176       "  }\n"
   2177       "  case 2: break;"
   2178       "  }\n"
   2179       "return -2;";
   2180 
   2181   ExpectedSnippet<2> snippets[] = {
   2182       {switch_code,
   2183        {factory->NewNumberFromInt(0), factory->NewNumberFromInt(0),
   2184         factory->NewNumberFromInt(0)}},
   2185       {switch_code,
   2186        {factory->NewNumberFromInt(1), factory->NewNumberFromInt(0),
   2187         factory->NewNumberFromInt(1)}},
   2188       {switch_code,
   2189        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
   2190         factory->NewNumberFromInt(2)}},
   2191       {switch_code,
   2192        {factory->NewNumberFromInt(-1), factory->NewNumberFromInt(0),
   2193         factory->NewNumberFromInt(3)}},
   2194       {switch_code,
   2195        {factory->NewNumberFromInt(2), factory->NewNumberFromInt(1),
   2196         factory->NewNumberFromInt(0)}},
   2197       {switch_code,
   2198        {factory->NewNumberFromInt(3), factory->NewNumberFromInt(1),
   2199         factory->NewNumberFromInt(1)}},
   2200       {switch_code,
   2201        {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(1),
   2202         factory->NewNumberFromInt(2)}},
   2203       {switch_code,
   2204        {factory->NewNumberFromInt(-2), factory->NewNumberFromInt(2),
   2205         factory->NewNumberFromInt(0)}},
   2206   };
   2207 
   2208   for (size_t i = 0; i < arraysize(snippets); i++) {
   2209     ScopedVector<char> script(2048);
   2210     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0, 0);", kFunctionName,
   2211              snippets[i].code_snippet, kFunctionName);
   2212 
   2213     BytecodeGraphTester tester(isolate, zone, script.start());
   2214     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   2215     Handle<Object> return_value =
   2216         callable(snippets[i].parameter(0), snippets[i].parameter(1))
   2217             .ToHandleChecked();
   2218     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2219   }
   2220 }
   2221 
   2222 
   2223 TEST(BytecodeGraphBuilderBreakableBlocks) {
   2224   HandleAndZoneScope scope;
   2225   Isolate* isolate = scope.main_isolate();
   2226   Zone* zone = scope.main_zone();
   2227   Factory* factory = isolate->factory();
   2228 
   2229   ExpectedSnippet<0> snippets[] = {
   2230       {"var x = 0;\n"
   2231        "my_heart: {\n"
   2232        "  x = x + 1;\n"
   2233        "  break my_heart;\n"
   2234        "  x = x + 2;\n"
   2235        "}\n"
   2236        "return x;\n",
   2237        {factory->NewNumberFromInt(1)}},
   2238       {"var sum = 0;\n"
   2239        "outta_here: {\n"
   2240        "  for (var x = 0; x < 10; ++x) {\n"
   2241        "    for (var y = 0; y < 3; ++y) {\n"
   2242        "      ++sum;\n"
   2243        "      if (x + y == 12) { break outta_here; }\n"
   2244        "    }\n"
   2245        "  }\n"
   2246        "}\n"
   2247        "return sum;",
   2248        {factory->NewNumber(30)}},
   2249   };
   2250 
   2251   for (size_t i = 0; i < arraysize(snippets); i++) {
   2252     ScopedVector<char> script(1024);
   2253     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2254              snippets[i].code_snippet, kFunctionName);
   2255 
   2256     BytecodeGraphTester tester(isolate, zone, script.start());
   2257     auto callable = tester.GetCallable<>();
   2258     Handle<Object> return_value = callable().ToHandleChecked();
   2259     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2260   }
   2261 }
   2262 
   2263 
   2264 TEST(BytecodeGraphBuilderWhile) {
   2265   HandleAndZoneScope scope;
   2266   Isolate* isolate = scope.main_isolate();
   2267   Zone* zone = scope.main_zone();
   2268   Factory* factory = isolate->factory();
   2269 
   2270   ExpectedSnippet<0> snippets[] = {
   2271       {"var x = 1; while (x < 1) { x *= 100; } return x;",
   2272        {factory->NewNumberFromInt(1)}},
   2273       {"var x = 1, y = 0; while (x < 7) { y += x * x; x += 1; } return y;",
   2274        {factory->NewNumberFromInt(91)}},
   2275       {"var x = 1; while (true) { x += 1; if (x == 10) break; } return x;",
   2276        {factory->NewNumberFromInt(10)}},
   2277       {"var x = 1; while (false) { x += 1; } return x;",
   2278        {factory->NewNumberFromInt(1)}},
   2279       {"var x = 0;\n"
   2280        "while (true) {\n"
   2281        "  while (x < 10) {\n"
   2282        "    x = x * x + 1;\n"
   2283        "  }"
   2284        "  x += 1;\n"
   2285        "  break;\n"
   2286        "}\n"
   2287        "return x;",
   2288        {factory->NewNumberFromInt(27)}},
   2289       {"var x = 1, y = 0;\n"
   2290        "while (x < 7) {\n"
   2291        "  x += 1;\n"
   2292        "  if (x == 2) continue;\n"
   2293        "  if (x == 3) continue;\n"
   2294        "  y += x * x;\n"
   2295        "  if (x == 4) break;\n"
   2296        "}\n"
   2297        "return y;",
   2298        {factory->NewNumberFromInt(16)}}};
   2299 
   2300   for (size_t i = 0; i < arraysize(snippets); i++) {
   2301     ScopedVector<char> script(1024);
   2302     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2303              snippets[i].code_snippet, kFunctionName);
   2304 
   2305     BytecodeGraphTester tester(isolate, zone, script.start());
   2306     auto callable = tester.GetCallable<>();
   2307     Handle<Object> return_value = callable().ToHandleChecked();
   2308     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2309   }
   2310 }
   2311 
   2312 
   2313 TEST(BytecodeGraphBuilderDo) {
   2314   HandleAndZoneScope scope;
   2315   Isolate* isolate = scope.main_isolate();
   2316   Zone* zone = scope.main_zone();
   2317   Factory* factory = isolate->factory();
   2318 
   2319   ExpectedSnippet<0> snippets[] = {
   2320       {"var x = 1; do { x *= 100; } while (x < 100); return x;",
   2321        {factory->NewNumberFromInt(100)}},
   2322       {"var x = 1; do { x = x * x + 1; } while (x < 7) return x;",
   2323        {factory->NewNumberFromInt(26)}},
   2324       {"var x = 1; do { x += 1; } while (false); return x;",
   2325        {factory->NewNumberFromInt(2)}},
   2326       {"var x = 1, y = 0;\n"
   2327        "do {\n"
   2328        "  x += 1;\n"
   2329        "  if (x == 2) continue;\n"
   2330        "  if (x == 3) continue;\n"
   2331        "  y += x * x;\n"
   2332        "  if (x == 4) break;\n"
   2333        "} while (x < 7);\n"
   2334        "return y;",
   2335        {factory->NewNumberFromInt(16)}}};
   2336 
   2337   for (size_t i = 0; i < arraysize(snippets); i++) {
   2338     ScopedVector<char> script(1024);
   2339     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2340              snippets[i].code_snippet, kFunctionName);
   2341 
   2342     BytecodeGraphTester tester(isolate, zone, script.start());
   2343     auto callable = tester.GetCallable<>();
   2344     Handle<Object> return_value = callable().ToHandleChecked();
   2345     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2346   }
   2347 }
   2348 
   2349 
   2350 TEST(BytecodeGraphBuilderFor) {
   2351   HandleAndZoneScope scope;
   2352   Isolate* isolate = scope.main_isolate();
   2353   Zone* zone = scope.main_zone();
   2354   Factory* factory = isolate->factory();
   2355 
   2356   ExpectedSnippet<0> snippets[] = {
   2357       {"for (var x = 0;; x = 2 * x + 1) { if (x > 10) return x; }",
   2358        {factory->NewNumberFromInt(15)}},
   2359       {"for (var x = 0; true; x = 2 * x + 1) { if (x > 100) return x; }",
   2360        {factory->NewNumberFromInt(127)}},
   2361       {"for (var x = 0; false; x = 2 * x + 1) { if (x > 100) return x; } "
   2362        "return 0;",
   2363        {factory->NewNumberFromInt(0)}},
   2364       {"for (var x = 0; x < 200; x = 2 * x + 1) { x = x; } return x;",
   2365        {factory->NewNumberFromInt(255)}},
   2366       {"for (var x = 0; x < 200; x = 2 * x + 1) {} return x;",
   2367        {factory->NewNumberFromInt(255)}},
   2368       {"var sum = 0;\n"
   2369        "for (var x = 0; x < 200; x += 1) {\n"
   2370        "  if (x % 2) continue;\n"
   2371        "  if (sum > 10) break;\n"
   2372        "  sum += x;\n"
   2373        "}\n"
   2374        "return sum;",
   2375        {factory->NewNumberFromInt(12)}},
   2376       {"var sum = 0;\n"
   2377        "for (var w = 0; w < 2; w++) {\n"
   2378        "  for (var x = 0; x < 200; x += 1) {\n"
   2379        "    if (x % 2) continue;\n"
   2380        "    if (x > 4) break;\n"
   2381        "    sum += x + w;\n"
   2382        "  }\n"
   2383        "}\n"
   2384        "return sum;",
   2385        {factory->NewNumberFromInt(15)}},
   2386       {"var sum = 0;\n"
   2387        "for (var w = 0; w < 2; w++) {\n"
   2388        "  if (w == 1) break;\n"
   2389        "  for (var x = 0; x < 200; x += 1) {\n"
   2390        "    if (x % 2) continue;\n"
   2391        "    if (x > 4) break;\n"
   2392        "    sum += x + w;\n"
   2393        "  }\n"
   2394        "}\n"
   2395        "return sum;",
   2396        {factory->NewNumberFromInt(6)}},
   2397       {"var sum = 0;\n"
   2398        "for (var w = 0; w < 3; w++) {\n"
   2399        "  if (w == 1) continue;\n"
   2400        "  for (var x = 0; x < 200; x += 1) {\n"
   2401        "    if (x % 2) continue;\n"
   2402        "    if (x > 4) break;\n"
   2403        "    sum += x + w;\n"
   2404        "  }\n"
   2405        "}\n"
   2406        "return sum;",
   2407        {factory->NewNumberFromInt(18)}},
   2408       {"var sum = 0;\n"
   2409        "for (var x = 1; x < 10; x += 2) {\n"
   2410        "  for (var y = x; y < x + 2; y++) {\n"
   2411        "    sum += y * y;\n"
   2412        "  }\n"
   2413        "}\n"
   2414        "return sum;",
   2415        {factory->NewNumberFromInt(385)}},
   2416   };
   2417 
   2418   for (size_t i = 0; i < arraysize(snippets); i++) {
   2419     ScopedVector<char> script(1024);
   2420     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2421              snippets[i].code_snippet, kFunctionName);
   2422 
   2423     BytecodeGraphTester tester(isolate, zone, script.start());
   2424     auto callable = tester.GetCallable<>();
   2425     Handle<Object> return_value = callable().ToHandleChecked();
   2426     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2427   }
   2428 }
   2429 
   2430 
   2431 TEST(BytecodeGraphBuilderForIn) {
   2432   HandleAndZoneScope scope;
   2433   Isolate* isolate = scope.main_isolate();
   2434   Zone* zone = scope.main_zone();
   2435   Factory* factory = isolate->factory();
   2436   ExpectedSnippet<0> snippets[] = {
   2437       {"var sum = 0;\n"
   2438        "var empty = null;\n"
   2439        "for (var x in empty) { sum++; }\n"
   2440        "return sum;",
   2441        {factory->NewNumberFromInt(0)}},
   2442       {"var sum = 100;\n"
   2443        "var empty = 1;\n"
   2444        "for (var x in empty) { sum++; }\n"
   2445        "return sum;",
   2446        {factory->NewNumberFromInt(100)}},
   2447       {"for (var x in [ 10, 20, 30 ]) {}\n"
   2448        "return 2;",
   2449        {factory->NewNumberFromInt(2)}},
   2450       {"var last = 0;\n"
   2451        "for (var x in [ 10, 20, 30 ]) {\n"
   2452        "  last = x;\n"
   2453        "}\n"
   2454        "return +last;",
   2455        {factory->NewNumberFromInt(2)}},
   2456       {"var first = -1;\n"
   2457        "for (var x in [ 10, 20, 30 ]) {\n"
   2458        "  first = +x;\n"
   2459        "  if (first > 0) break;\n"
   2460        "}\n"
   2461        "return first;",
   2462        {factory->NewNumberFromInt(1)}},
   2463       {"var first = -1;\n"
   2464        "for (var x in [ 10, 20, 30 ]) {\n"
   2465        "  if (first >= 0) continue;\n"
   2466        "  first = x;\n"
   2467        "}\n"
   2468        "return +first;",
   2469        {factory->NewNumberFromInt(0)}},
   2470       {"var sum = 0;\n"
   2471        "for (var x in [ 10, 20, 30 ]) {\n"
   2472        "  for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
   2473        "    sum += 1;\n"
   2474        "  }\n"
   2475        "}\n"
   2476        "return sum;",
   2477        {factory->NewNumberFromInt(21)}},
   2478       {"var sum = 0;\n"
   2479        "for (var x in [ 10, 20, 30 ]) {\n"
   2480        "  for (var y in [ 11, 22, 33, 44, 55, 66, 77 ]) {\n"
   2481        "    if (sum == 7) break;\n"
   2482        "    if (sum == 6) continue;\n"
   2483        "    sum += 1;\n"
   2484        "  }\n"
   2485        "}\n"
   2486        "return sum;",
   2487        {factory->NewNumberFromInt(6)}},
   2488   };
   2489 
   2490   for (size_t i = 0; i < arraysize(snippets); i++) {
   2491     ScopedVector<char> script(1024);
   2492     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2493              snippets[i].code_snippet, kFunctionName);
   2494 
   2495     BytecodeGraphTester tester(isolate, zone, script.start());
   2496     auto callable = tester.GetCallable<>();
   2497     Handle<Object> return_value = callable().ToHandleChecked();
   2498     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2499   }
   2500 }
   2501 
   2502 
   2503 TEST(BytecodeGraphBuilderForOf) {
   2504   HandleAndZoneScope scope;
   2505   Isolate* isolate = scope.main_isolate();
   2506   Zone* zone = scope.main_zone();
   2507   Factory* factory = isolate->factory();
   2508   ExpectedSnippet<0> snippets[] = {
   2509       {"  var r = 0;\n"
   2510        "  for (var a of [0,6,7,9]) { r += a; }\n"
   2511        "  return r;\n",
   2512        {handle(Smi::FromInt(22), isolate)}},
   2513       {"  var r = '';\n"
   2514        "  for (var a of 'foobar') { r = a + r; }\n"
   2515        "  return r;\n",
   2516        {factory->NewStringFromStaticChars("raboof")}},
   2517       {"  var a = [1, 2, 3];\n"
   2518        "  a.name = 4;\n"
   2519        "  var r = 0;\n"
   2520        "  for (var x of a) { r += x; }\n"
   2521        "  return r;\n",
   2522        {handle(Smi::FromInt(6), isolate)}},
   2523       {"  var r = '';\n"
   2524        "  var data = [1, 2, 3]; \n"
   2525        "  for (a of data) { delete data[0]; r += a; } return r;",
   2526        {factory->NewStringFromStaticChars("123")}},
   2527       {"  var r = '';\n"
   2528        "  var data = [1, 2, 3]; \n"
   2529        "  for (a of data) { delete data[2]; r += a; } return r;",
   2530        {factory->NewStringFromStaticChars("12undefined")}},
   2531       {"  var r = '';\n"
   2532        "  var data = [1, 2, 3]; \n"
   2533        "  for (a of data) { delete data; r += a; } return r;",
   2534        {factory->NewStringFromStaticChars("123")}},
   2535       {"  var r = '';\n"
   2536        "  var input = 'foobar';\n"
   2537        "  for (var a of input) {\n"
   2538        "    if (a == 'b') break;\n"
   2539        "    r += a;\n"
   2540        "  }\n"
   2541        "  return r;\n",
   2542        {factory->NewStringFromStaticChars("foo")}},
   2543       {"  var r = '';\n"
   2544        "  var input = 'foobar';\n"
   2545        "  for (var a of input) {\n"
   2546        "    if (a == 'b') continue;\n"
   2547        "    r += a;\n"
   2548        "  }\n"
   2549        "  return r;\n",
   2550        {factory->NewStringFromStaticChars("fooar")}},
   2551       {"  var r = '';\n"
   2552        "  var data = [1, 2, 3, 4]; \n"
   2553        "  for (a of data) { data[2] = 567; r += a; }\n"
   2554        "  return r;\n",
   2555        {factory->NewStringFromStaticChars("125674")}},
   2556       {"  var r = '';\n"
   2557        "  var data = [1, 2, 3, 4]; \n"
   2558        "  for (a of data) { data[4] = 567; r += a; }\n"
   2559        "  return r;\n",
   2560        {factory->NewStringFromStaticChars("1234567")}},
   2561       {"  var r = '';\n"
   2562        "  var data = [1, 2, 3, 4]; \n"
   2563        "  for (a of data) { data[5] = 567; r += a; }\n"
   2564        "  return r;\n",
   2565        {factory->NewStringFromStaticChars("1234undefined567")}},
   2566       {"  var r = '';\n"
   2567        "  var obj = new Object();\n"
   2568        "  obj[Symbol.iterator] = function() { return {\n"
   2569        "    index: 3,\n"
   2570        "    data: ['a', 'b', 'c', 'd'],"
   2571        "    next: function() {"
   2572        "      return {"
   2573        "        done: this.index == -1,\n"
   2574        "        value: this.index < 0 ? undefined : this.data[this.index--]\n"
   2575        "      }\n"
   2576        "    }\n"
   2577        "    }}\n"
   2578        "  for (a of obj) { r += a }\n"
   2579        "  return r;\n",
   2580        {factory->NewStringFromStaticChars("dcba")}},
   2581   };
   2582 
   2583   for (size_t i = 0; i < arraysize(snippets); i++) {
   2584     ScopedVector<char> script(1024);
   2585     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2586              snippets[i].code_snippet, kFunctionName);
   2587 
   2588     BytecodeGraphTester tester(isolate, zone, script.start());
   2589     auto callable = tester.GetCallable<>();
   2590     Handle<Object> return_value = callable().ToHandleChecked();
   2591     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2592   }
   2593 }
   2594 
   2595 void TestJumpWithConstantsAndWideConstants(size_t shard) {
   2596   const int kStep = 46;
   2597   int start = static_cast<int>(7 + 17 * shard);
   2598   for (int constants = start; constants < 300; constants += kStep) {
   2599     std::stringstream filler_os;
   2600     // Generate a string that consumes constant pool entries and
   2601     // spread out branch distances in script below.
   2602     for (int i = 0; i < constants; i++) {
   2603       filler_os << "var x_ = 'x_" << i << "';\n";
   2604     }
   2605     std::string filler(filler_os.str());
   2606 
   2607     std::stringstream script_os;
   2608     script_os << "function " << kFunctionName << "(a) {\n";
   2609     script_os << "  " << filler;
   2610     script_os << "  for (var i = a; i < 2; i++) {\n";
   2611     script_os << "  " << filler;
   2612     script_os << "    if (i == 0) { " << filler << "i = 10; continue; }\n";
   2613     script_os << "    else if (i == a) { " << filler << "i = 12; break; }\n";
   2614     script_os << "    else { " << filler << " }\n";
   2615     script_os << "  }\n";
   2616     script_os << "  return i;\n";
   2617     script_os << "}\n";
   2618     script_os << kFunctionName << "(0);\n";
   2619     std::string script(script_os.str());
   2620 
   2621     HandleAndZoneScope scope;
   2622     auto isolate = scope.main_isolate();
   2623     auto factory = isolate->factory();
   2624     auto zone = scope.main_zone();
   2625     BytecodeGraphTester tester(isolate, zone, script.c_str());
   2626     auto callable = tester.GetCallable<Handle<Object>>();
   2627     for (int a = 0; a < 3; a++) {
   2628       Handle<Object> return_val =
   2629           callable(factory->NewNumberFromInt(a)).ToHandleChecked();
   2630       static const int results[] = {11, 12, 2};
   2631       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
   2632     }
   2633   }
   2634 }
   2635 
   2636 SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
   2637 
   2638 TEST(BytecodeGraphBuilderDoExpressions) {
   2639   bool old_flag = FLAG_harmony_do_expressions;
   2640   FLAG_harmony_do_expressions = true;
   2641   HandleAndZoneScope scope;
   2642   Isolate* isolate = scope.main_isolate();
   2643   Zone* zone = scope.main_zone();
   2644   Factory* factory = isolate->factory();
   2645   ExpectedSnippet<0> snippets[] = {
   2646       {"var a = do {}; return a;", {factory->undefined_value()}},
   2647       {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
   2648       {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
   2649       {"var a = do { var x = 100; x++; }; return a;",
   2650        {handle(Smi::FromInt(100), isolate)}},
   2651       {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
   2652        "return i;",
   2653        {handle(Smi::FromInt(3), isolate)}},
   2654   };
   2655 
   2656   for (size_t i = 0; i < arraysize(snippets); i++) {
   2657     ScopedVector<char> script(1024);
   2658     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2659              snippets[i].code_snippet, kFunctionName);
   2660 
   2661     BytecodeGraphTester tester(isolate, zone, script.start());
   2662     auto callable = tester.GetCallable<>();
   2663     Handle<Object> return_value = callable().ToHandleChecked();
   2664     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2665   }
   2666 
   2667   FLAG_harmony_do_expressions = old_flag;
   2668 }
   2669 
   2670 TEST(BytecodeGraphBuilderWithStatement) {
   2671   HandleAndZoneScope scope;
   2672   Isolate* isolate = scope.main_isolate();
   2673   Zone* zone = scope.main_zone();
   2674 
   2675   ExpectedSnippet<0> snippets[] = {
   2676       {"with({x:42}) return x;", {handle(Smi::FromInt(42), isolate)}},
   2677       {"with({}) { var y = 10; return y;}",
   2678        {handle(Smi::FromInt(10), isolate)}},
   2679       {"var y = {x:42};"
   2680        " function inner() {"
   2681        "   var x = 20;"
   2682        "   with(y) return x;"
   2683        "}"
   2684        "return inner();",
   2685        {handle(Smi::FromInt(42), isolate)}},
   2686       {"var y = {x:42};"
   2687        " function inner(o) {"
   2688        "   var x = 20;"
   2689        "   with(o) return x;"
   2690        "}"
   2691        "return inner(y);",
   2692        {handle(Smi::FromInt(42), isolate)}},
   2693   };
   2694 
   2695   for (size_t i = 0; i < arraysize(snippets); i++) {
   2696     ScopedVector<char> script(1024);
   2697     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2698              snippets[i].code_snippet, kFunctionName);
   2699 
   2700     BytecodeGraphTester tester(isolate, zone, script.start());
   2701     auto callable = tester.GetCallable<>();
   2702     Handle<Object> return_value = callable().ToHandleChecked();
   2703     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2704   }
   2705 }
   2706 
   2707 TEST(BytecodeGraphBuilderConstDeclaration) {
   2708   HandleAndZoneScope scope;
   2709   Isolate* isolate = scope.main_isolate();
   2710   Zone* zone = scope.main_zone();
   2711   Factory* factory = isolate->factory();
   2712 
   2713   ExpectedSnippet<0> snippets[] = {
   2714       {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}},
   2715       {"let x = 10; x = x + 20; return x;",
   2716        {handle(Smi::FromInt(30), isolate)}},
   2717       {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
   2718       {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
   2719       {"let x; return x;", {factory->undefined_value()}},
   2720       {"var x = 10; { let x = 30; } return x;",
   2721        {handle(Smi::FromInt(10), isolate)}},
   2722       {"let x = 10; { let x = 20; } return x;",
   2723        {handle(Smi::FromInt(10), isolate)}},
   2724       {"var x = 10; eval('let x = 20;'); return x;",
   2725        {handle(Smi::FromInt(10), isolate)}},
   2726       {"var x = 10; eval('const x = 20;'); return x;",
   2727        {handle(Smi::FromInt(10), isolate)}},
   2728       {"var x = 10; { const x = 20; } return x;",
   2729        {handle(Smi::FromInt(10), isolate)}},
   2730       {"var x = 10; { const x = 20; return x;} return -1;",
   2731        {handle(Smi::FromInt(20), isolate)}},
   2732       {"var a = 10;\n"
   2733        "for (var i = 0; i < 10; ++i) {\n"
   2734        " const x = i;\n"  // const declarations are block scoped.
   2735        " a = a + x;\n"
   2736        "}\n"
   2737        "return a;\n",
   2738        {handle(Smi::FromInt(55), isolate)}},
   2739   };
   2740 
   2741   // Tests for sloppy mode.
   2742   for (size_t i = 0; i < arraysize(snippets); i++) {
   2743     ScopedVector<char> script(1024);
   2744     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2745              snippets[i].code_snippet, kFunctionName);
   2746 
   2747     BytecodeGraphTester tester(isolate, zone, script.start());
   2748     auto callable = tester.GetCallable<>();
   2749     Handle<Object> return_value = callable().ToHandleChecked();
   2750     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2751   }
   2752 
   2753   // Tests for strict mode.
   2754   for (size_t i = 0; i < arraysize(snippets); i++) {
   2755     ScopedVector<char> script(1024);
   2756     SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
   2757              snippets[i].code_snippet, kFunctionName);
   2758 
   2759     BytecodeGraphTester tester(isolate, zone, script.start());
   2760     auto callable = tester.GetCallable<>();
   2761     Handle<Object> return_value = callable().ToHandleChecked();
   2762     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2763   }
   2764 }
   2765 
   2766 TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) {
   2767   HandleAndZoneScope scope;
   2768   Isolate* isolate = scope.main_isolate();
   2769   Zone* zone = scope.main_zone();
   2770   Factory* factory = isolate->factory();
   2771 
   2772   ExpectedSnippet<0> snippets[] = {
   2773       {"const x = 3; function f1() {return x;}; return x;",
   2774        {handle(Smi::FromInt(3), isolate)}},
   2775       {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
   2776        {handle(Smi::FromInt(30), isolate)}},
   2777       {"let x; x = 20; function f1() {return x;}; return x;",
   2778        {handle(Smi::FromInt(20), isolate)}},
   2779       {"let x; function f1() {return x;}; return x;",
   2780        {factory->undefined_value()}},
   2781   };
   2782 
   2783   // Tests for sloppy mode.
   2784   for (size_t i = 0; i < arraysize(snippets); i++) {
   2785     ScopedVector<char> script(1024);
   2786     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2787              snippets[i].code_snippet, kFunctionName);
   2788 
   2789     BytecodeGraphTester tester(isolate, zone, script.start());
   2790     auto callable = tester.GetCallable<>();
   2791     Handle<Object> return_value = callable().ToHandleChecked();
   2792     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2793   }
   2794 
   2795   // Tests for strict mode.
   2796   for (size_t i = 0; i < arraysize(snippets); i++) {
   2797     ScopedVector<char> script(1024);
   2798     SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
   2799              snippets[i].code_snippet, kFunctionName);
   2800 
   2801     BytecodeGraphTester tester(isolate, zone, script.start());
   2802     auto callable = tester.GetCallable<>();
   2803     Handle<Object> return_value = callable().ToHandleChecked();
   2804     CHECK(return_value->SameValue(*snippets[i].return_value()));
   2805   }
   2806 }
   2807 
   2808 TEST(BytecodeGraphBuilderConstInLookupContextChain) {
   2809   HandleAndZoneScope scope;
   2810   Isolate* isolate = scope.main_isolate();
   2811   Zone* zone = scope.main_zone();
   2812 
   2813   const char* prologue =
   2814       "function OuterMost() {\n"
   2815       "  const outerConst = 10;\n"
   2816       "  let outerLet = 20;\n"
   2817       "  function Outer() {\n"
   2818       "    function Inner() {\n"
   2819       "      this.innerFunc = function() { ";
   2820   const char* epilogue =
   2821       "      }\n"
   2822       "    }\n"
   2823       "    this.getInnerFunc ="
   2824       "         function() {return new Inner().innerFunc;}\n"
   2825       "  }\n"
   2826       "  this.getOuterFunc ="
   2827       "     function() {return new Outer().getInnerFunc();}"
   2828       "}\n"
   2829       "var f = new OuterMost().getOuterFunc();\n"
   2830       "f();\n";
   2831 
   2832   // Tests for let / constant.
   2833   ExpectedSnippet<0> const_decl[] = {
   2834       {"return outerConst;", {handle(Smi::FromInt(10), isolate)}},
   2835       {"return outerLet;", {handle(Smi::FromInt(20), isolate)}},
   2836       {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}},
   2837       {"var outerLet = 40; return outerLet;",
   2838        {handle(Smi::FromInt(40), isolate)}},
   2839       {"var outerConst = 50; return outerConst;",
   2840        {handle(Smi::FromInt(50), isolate)}},
   2841       {"try { outerConst = 30 } catch(e) { return -1; }",
   2842        {handle(Smi::FromInt(-1), isolate)}}};
   2843 
   2844   for (size_t i = 0; i < arraysize(const_decl); i++) {
   2845     ScopedVector<char> script(1024);
   2846     SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet,
   2847              epilogue);
   2848 
   2849     BytecodeGraphTester tester(isolate, zone, script.start(), "*");
   2850     auto callable = tester.GetCallable<>();
   2851     Handle<Object> return_value = callable().ToHandleChecked();
   2852     CHECK(return_value->SameValue(*const_decl[i].return_value()));
   2853   }
   2854 }
   2855 
   2856 TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
   2857   HandleAndZoneScope scope;
   2858   Isolate* isolate = scope.main_isolate();
   2859   Zone* zone = scope.main_zone();
   2860 
   2861   ExpectedSnippet<0, const char*> illegal_const_decl[] = {
   2862       {"const x = x = 10 + 3; return x;",
   2863        {"Uncaught ReferenceError: x is not defined"}},
   2864       {"const x = 10; x = 20; return x;",
   2865        {"Uncaught TypeError: Assignment to constant variable."}},
   2866       {"const x = 10; { x = 20; } return x;",
   2867        {"Uncaught TypeError: Assignment to constant variable."}},
   2868       {"const x = 10; eval('x = 20;'); return x;",
   2869        {"Uncaught TypeError: Assignment to constant variable."}},
   2870       {"let x = x + 10; return x;",
   2871        {"Uncaught ReferenceError: x is not defined"}},
   2872       {"'use strict'; (function f1() { f1 = 123; })() ",
   2873        {"Uncaught TypeError: Assignment to constant variable."}},
   2874   };
   2875 
   2876   // Tests for sloppy mode.
   2877   for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
   2878     ScopedVector<char> script(1024);
   2879     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2880              illegal_const_decl[i].code_snippet, kFunctionName);
   2881 
   2882     BytecodeGraphTester tester(isolate, zone, script.start());
   2883     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   2884     v8::Local<v8::String> expected_string =
   2885         v8_str(illegal_const_decl[i].return_value());
   2886     CHECK(
   2887         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   2888             .FromJust());
   2889   }
   2890 
   2891   // Tests for strict mode.
   2892   for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
   2893     ScopedVector<char> script(1024);
   2894     SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
   2895              illegal_const_decl[i].code_snippet, kFunctionName);
   2896 
   2897     BytecodeGraphTester tester(isolate, zone, script.start());
   2898     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   2899     v8::Local<v8::String> expected_string =
   2900         v8_str(illegal_const_decl[i].return_value());
   2901     CHECK(
   2902         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   2903             .FromJust());
   2904   }
   2905 }
   2906 
   2907 TEST(BytecodeGraphBuilderDebuggerStatement) {
   2908   FLAG_expose_debug_as = "debug";
   2909   HandleAndZoneScope scope;
   2910   Isolate* isolate = scope.main_isolate();
   2911   Zone* zone = scope.main_zone();
   2912 
   2913   ExpectedSnippet<0> snippet = {
   2914       "var Debug = debug.Debug;"
   2915       "var count = 0;"
   2916       "function f() {"
   2917       "  debugger;"
   2918       "}"
   2919       "function listener(event) {"
   2920       "  if (event == Debug.DebugEvent.Break) count++;"
   2921       "}"
   2922       "Debug.setListener(listener);"
   2923       "f();"
   2924       "Debug.setListener(null);"
   2925       "return count;",
   2926       {handle(Smi::FromInt(1), isolate)}};
   2927 
   2928   ScopedVector<char> script(1024);
   2929   SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
   2930            snippet.code_snippet, kFunctionName);
   2931 
   2932   BytecodeGraphTester tester(isolate, zone, script.start());
   2933   auto callable = tester.GetCallable<>();
   2934   Handle<Object> return_value = callable().ToHandleChecked();
   2935   CHECK(return_value->SameValue(*snippet.return_value()));
   2936 }
   2937 
   2938 }  // namespace compiler
   2939 }  // namespace internal
   2940 }  // namespace v8
   2941