LCOV - code coverage report
Current view: top level - test/cctest/compiler - test-run-bytecode-graph-builder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 668 670 99.7 %
Date: 2019-04-18 Functions: 88 98 89.8 %

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

Generated by: LCOV version 1.10