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: 748 751 99.6 %
Date: 2017-10-20 Functions: 89 101 88.1 %

          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.h"
       8             : #include "src/compilation-info.h"
       9             : #include "src/compiler/pipeline.h"
      10             : #include "src/debug/debug-interface.h"
      11             : #include "src/execution.h"
      12             : #include "src/handles.h"
      13             : #include "src/interpreter/bytecode-array-builder.h"
      14             : #include "src/interpreter/interpreter.h"
      15             : #include "src/objects-inl.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        1584 :                          isolate->factory()->undefined_value(), 0, nullptr);
      46             : }
      47             : 
      48             : template <class... A>
      49        3108 : static MaybeHandle<Object> CallFunction(Isolate* isolate,
      50             :                                         Handle<JSFunction> function,
      51             :                                         A... args) {
      52        3108 :   Handle<Object> argv[] = {args...};
      53             :   return Execution::Call(isolate, function,
      54             :                          isolate->factory()->undefined_value(), sizeof...(args),
      55        3108 :                          argv);
      56             : }
      57             : 
      58             : template <class... A>
      59             : class BytecodeGraphCallable {
      60             :  public:
      61             :   BytecodeGraphCallable(Isolate* isolate, Handle<JSFunction> function)
      62        2760 :       : isolate_(isolate), function_(function) {}
      63        1584 :   virtual ~BytecodeGraphCallable() {}
      64             : 
      65        1584 :   MaybeHandle<Object> operator()(A... args) {
      66        6276 :     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        2760 :       : isolate_(isolate), script_(script) {
      79        2760 :     i::FLAG_always_opt = false;
      80        2760 :     i::FLAG_allow_natives_syntax = true;
      81             :   }
      82        2760 :   virtual ~BytecodeGraphTester() {}
      83             : 
      84             :   template <class... A>
      85             :   BytecodeGraphCallable<A...> GetCallable(
      86             :       const char* functionName = kFunctionName) {
      87        2760 :     return BytecodeGraphCallable<A...>(isolate_, GetFunction(functionName));
      88             :   }
      89             : 
      90         114 :   Local<Message> CheckThrowsReturnMessage() {
      91         114 :     TryCatch try_catch(reinterpret_cast<v8::Isolate*>(isolate_));
      92             :     auto callable = GetCallable<>();
      93         114 :     MaybeHandle<Object> no_result = callable();
      94         114 :     CHECK(isolate_->has_pending_exception());
      95         114 :     CHECK(try_catch.HasCaught());
      96         114 :     CHECK(no_result.is_null());
      97         114 :     isolate_->OptionalRescheduleException(true);
      98         228 :     CHECK(!try_catch.Message().IsEmpty());
      99         228 :     return try_catch.Message();
     100             :   }
     101             : 
     102         444 :   static Handle<Object> NewObject(const char* script) {
     103         444 :     return v8::Utils::OpenHandle(*CompileRun(script));
     104             :   }
     105             : 
     106             :  private:
     107             :   Isolate* isolate_;
     108             :   const char* script_;
     109             : 
     110        2760 :   Handle<JSFunction> GetFunction(const char* functionName) {
     111        2760 :     CompileRun(script_);
     112             :     Local<Function> api_function = Local<Function>::Cast(
     113             :         CcTest::global()
     114        8280 :             ->Get(CcTest::isolate()->GetCurrentContext(), v8_str(functionName))
     115        2760 :             .ToLocalChecked());
     116             :     Handle<JSFunction> function =
     117             :         Handle<JSFunction>::cast(v8::Utils::OpenHandle(*api_function));
     118        2760 :     CHECK(function->shared()->HasBytecodeArray());
     119             : 
     120        2760 :     Zone zone(function->GetIsolate()->allocator(), ZONE_NAME);
     121             :     Handle<SharedFunctionInfo> shared(function->shared());
     122             :     CompilationInfo compilation_info(&zone, function->GetIsolate(), shared,
     123        5520 :                                      function);
     124             : 
     125             :     // Compiler relies on canonicalized handles, let's create
     126             :     // a canonicalized scope and migrate existing handles there.
     127        5520 :     CanonicalHandleScope canonical(isolate_);
     128        2760 :     compilation_info.ReopenHandlesInNewHandleScope();
     129             : 
     130        2760 :     Handle<Code> code = Pipeline::GenerateCodeForTesting(&compilation_info);
     131        2760 :     function->set_code(*code);
     132             : 
     133        5520 :     return function;
     134             :   }
     135             : 
     136             :   DISALLOW_COPY_AND_ASSIGN(BytecodeGraphTester);
     137             : };
     138             : 
     139             : #define SPACE()
     140             : 
     141             : #define REPEAT_2(SEP, ...) __VA_ARGS__ SEP() __VA_ARGS__
     142             : #define REPEAT_4(SEP, ...) \
     143             :   REPEAT_2(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__)
     144             : #define REPEAT_8(SEP, ...) \
     145             :   REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_4(SEP, __VA_ARGS__)
     146             : #define REPEAT_16(SEP, ...) \
     147             :   REPEAT_8(SEP, __VA_ARGS__) SEP() REPEAT_8(SEP, __VA_ARGS__)
     148             : #define REPEAT_32(SEP, ...) \
     149             :   REPEAT_16(SEP, __VA_ARGS__) SEP() REPEAT_16(SEP, __VA_ARGS__)
     150             : #define REPEAT_64(SEP, ...) \
     151             :   REPEAT_32(SEP, __VA_ARGS__) SEP() REPEAT_32(SEP, __VA_ARGS__)
     152             : #define REPEAT_128(SEP, ...) \
     153             :   REPEAT_64(SEP, __VA_ARGS__) SEP() REPEAT_64(SEP, __VA_ARGS__)
     154             : #define REPEAT_256(SEP, ...) \
     155             :   REPEAT_128(SEP, __VA_ARGS__) SEP() REPEAT_128(SEP, __VA_ARGS__)
     156             : 
     157             : #define REPEAT_127(SEP, ...)  \
     158             :   REPEAT_64(SEP, __VA_ARGS__) \
     159             :   SEP()                       \
     160             :   REPEAT_32(SEP, __VA_ARGS__) \
     161             :   SEP()                       \
     162             :   REPEAT_16(SEP, __VA_ARGS__) \
     163             :   SEP()                       \
     164             :   REPEAT_8(SEP, __VA_ARGS__)  \
     165             :   SEP()                       \
     166             :   REPEAT_4(SEP, __VA_ARGS__) SEP() REPEAT_2(SEP, __VA_ARGS__) SEP() __VA_ARGS__
     167             : 
     168             : template <int N, typename T = Handle<Object>>
     169             : struct ExpectedSnippet {
     170             :   const char* code_snippet;
     171             :   T return_value_and_parameters[N + 1];
     172             : 
     173             :   inline T return_value() const { return return_value_and_parameters[0]; }
     174             : 
     175        1344 :   inline T parameter(int i) const {
     176        1344 :     CHECK_GE(i, 0);
     177        1344 :     CHECK_LT(i, N);
     178        1344 :     return return_value_and_parameters[1 + i];
     179             :   }
     180             : };
     181             : 
     182       23724 : TEST(BytecodeGraphBuilderReturnStatements) {
     183           6 :   HandleAndZoneScope scope;
     184           6 :   Isolate* isolate = scope.main_isolate();
     185             :   Factory* factory = isolate->factory();
     186             : 
     187             :   ExpectedSnippet<0> snippets[] = {
     188             :       {"return;", {factory->undefined_value()}},
     189             :       {"return null;", {factory->null_value()}},
     190             :       {"return true;", {factory->true_value()}},
     191             :       {"return false;", {factory->false_value()}},
     192             :       {"return 0;", {factory->NewNumberFromInt(0)}},
     193             :       {"return +1;", {factory->NewNumberFromInt(1)}},
     194             :       {"return -1;", {factory->NewNumberFromInt(-1)}},
     195             :       {"return +127;", {factory->NewNumberFromInt(127)}},
     196             :       {"return -128;", {factory->NewNumberFromInt(-128)}},
     197             :       {"return 0.001;", {factory->NewNumber(0.001)}},
     198             :       {"return 3.7e-60;", {factory->NewNumber(3.7e-60)}},
     199             :       {"return -3.7e60;", {factory->NewNumber(-3.7e60)}},
     200             :       {"return '';", {factory->NewStringFromStaticChars("")}},
     201             :       {"return 'catfood';", {factory->NewStringFromStaticChars("catfood")}},
     202          42 :       {"return NaN;", {factory->nan_value()}}};
     203             : 
     204          96 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     205             :     ScopedVector<char> script(1024);
     206             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
     207          90 :              snippets[i].code_snippet, kFunctionName);
     208             : 
     209             :     BytecodeGraphTester tester(isolate, script.start());
     210             :     auto callable = tester.GetCallable<>();
     211         180 :     Handle<Object> return_value = callable().ToHandleChecked();
     212         180 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     213           6 :   }
     214           6 : }
     215             : 
     216       23724 : TEST(BytecodeGraphBuilderPrimitiveExpressions) {
     217           6 :   HandleAndZoneScope scope;
     218           6 :   Isolate* isolate = scope.main_isolate();
     219             :   Factory* factory = isolate->factory();
     220             : 
     221             :   ExpectedSnippet<0> snippets[] = {
     222             :       {"return 1 + 1;", {factory->NewNumberFromInt(2)}},
     223             :       {"return 20 - 30;", {factory->NewNumberFromInt(-10)}},
     224             :       {"return 4 * 100;", {factory->NewNumberFromInt(400)}},
     225             :       {"return 100 / 5;", {factory->NewNumberFromInt(20)}},
     226             :       {"return 25 % 7;", {factory->NewNumberFromInt(4)}},
     227           6 :   };
     228             : 
     229          36 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     230             :     ScopedVector<char> script(1024);
     231             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
     232          30 :              snippets[i].code_snippet, kFunctionName);
     233             : 
     234             :     BytecodeGraphTester tester(isolate, script.start());
     235             :     auto callable = tester.GetCallable<>();
     236          60 :     Handle<Object> return_value = callable().ToHandleChecked();
     237          60 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     238           6 :   }
     239           6 : }
     240             : 
     241       23724 : TEST(BytecodeGraphBuilderTwoParameterTests) {
     242           6 :   HandleAndZoneScope scope;
     243           6 :   Isolate* isolate = scope.main_isolate();
     244             :   Factory* factory = isolate->factory();
     245             : 
     246             :   ExpectedSnippet<2> snippets[] = {
     247             :       // Integers
     248             :       {"return p1 + p2;",
     249             :        {factory->NewNumberFromInt(-70), factory->NewNumberFromInt(3),
     250             :         factory->NewNumberFromInt(-73)}},
     251             :       {"return p1 + p2 + 3;",
     252             :        {factory->NewNumberFromInt(1139044), factory->NewNumberFromInt(300),
     253             :         factory->NewNumberFromInt(1138741)}},
     254             :       {"return p1 - p2;",
     255             :        {factory->NewNumberFromInt(1100), factory->NewNumberFromInt(1000),
     256             :         factory->NewNumberFromInt(-100)}},
     257             :       {"return p1 * p2;",
     258             :        {factory->NewNumberFromInt(-100000), factory->NewNumberFromInt(1000),
     259             :         factory->NewNumberFromInt(-100)}},
     260             :       {"return p1 / p2;",
     261             :        {factory->NewNumberFromInt(-10), factory->NewNumberFromInt(1000),
     262             :         factory->NewNumberFromInt(-100)}},
     263             :       {"return p1 % p2;",
     264             :        {factory->NewNumberFromInt(5), factory->NewNumberFromInt(373),
     265             :         factory->NewNumberFromInt(16)}},
     266             :       // Doubles
     267             :       {"return p1 + p2;",
     268             :        {factory->NewHeapNumber(9.999), factory->NewHeapNumber(3.333),
     269             :         factory->NewHeapNumber(6.666)}},
     270             :       {"return p1 - p2;",
     271             :        {factory->NewHeapNumber(-3.333), factory->NewHeapNumber(3.333),
     272             :         factory->NewHeapNumber(6.666)}},
     273             :       {"return p1 * p2;",
     274             :        {factory->NewHeapNumber(3.333 * 6.666), factory->NewHeapNumber(3.333),
     275             :         factory->NewHeapNumber(6.666)}},
     276             :       {"return p1 / p2;",
     277             :        {factory->NewHeapNumber(2.25), factory->NewHeapNumber(9),
     278             :         factory->NewHeapNumber(4)}},
     279             :       // Strings
     280             :       {"return p1 + p2;",
     281             :        {factory->NewStringFromStaticChars("abcdef"),
     282             :         factory->NewStringFromStaticChars("abc"),
     283          42 :         factory->NewStringFromStaticChars("def")}}};
     284             : 
     285          72 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     286             :     ScopedVector<char> script(1024);
     287             :     SNPrintF(script, "function %s(p1, p2) { %s }\n%s(0, 0);", kFunctionName,
     288          66 :              snippets[i].code_snippet, kFunctionName);
     289             : 
     290             :     BytecodeGraphTester tester(isolate, script.start());
     291             :     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
     292             :     Handle<Object> return_value =
     293          66 :         callable(snippets[i].parameter(0), snippets[i].parameter(1))
     294             :             .ToHandleChecked();
     295          66 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     296           6 :   }
     297           6 : }
     298             : 
     299             : 
     300       23724 : TEST(BytecodeGraphBuilderNamedLoad) {
     301           6 :   HandleAndZoneScope scope;
     302           6 :   Isolate* isolate = scope.main_isolate();
     303             :   Factory* factory = isolate->factory();
     304             : 
     305             :   ExpectedSnippet<1> snippets[] = {
     306             :       {"return p1.val;",
     307             :        {factory->NewNumberFromInt(10),
     308             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     309             :       {"return p1[\"name\"];",
     310             :        {factory->NewStringFromStaticChars("abc"),
     311             :         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
     312             :       {"'use strict'; return p1.val;",
     313             :        {factory->NewNumberFromInt(10),
     314             :         BytecodeGraphTester::NewObject("({val : 10 })")}},
     315             :       {"'use strict'; return p1[\"val\"];",
     316             :        {factory->NewNumberFromInt(10),
     317             :         BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
     318             :       {"var b;\n" REPEAT_127(SPACE, " b = p1.name; ") " return p1.name;\n",
     319             :        {factory->NewStringFromStaticChars("abc"),
     320             :         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
     321             :       {"'use strict'; var b;\n"
     322             :        REPEAT_127(SPACE, " b = p1.name; ")
     323             :        "return p1.name;\n",
     324             :        {factory->NewStringFromStaticChars("abc"),
     325             :         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
     326          24 :   };
     327             : 
     328          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     329             :     ScopedVector<char> script(2048);
     330             :     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
     331          36 :              snippets[i].code_snippet, kFunctionName);
     332             : 
     333             :     BytecodeGraphTester tester(isolate, script.start());
     334             :     auto callable = tester.GetCallable<Handle<Object>>();
     335             :     Handle<Object> return_value =
     336          36 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     337          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     338           6 :   }
     339           6 : }
     340             : 
     341       23724 : TEST(BytecodeGraphBuilderKeyedLoad) {
     342           6 :   HandleAndZoneScope scope;
     343           6 :   Isolate* isolate = scope.main_isolate();
     344             :   Factory* factory = isolate->factory();
     345             : 
     346             :   ExpectedSnippet<2> snippets[] = {
     347             :       {"return p1[p2];",
     348             :        {factory->NewNumberFromInt(10),
     349             :         BytecodeGraphTester::NewObject("({val : 10})"),
     350             :         factory->NewStringFromStaticChars("val")}},
     351             :       {"return p1[100];",
     352             :        {factory->NewStringFromStaticChars("abc"),
     353             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     354             :         factory->NewNumberFromInt(0)}},
     355             :       {"var b = 100; return p1[b];",
     356             :        {factory->NewStringFromStaticChars("abc"),
     357             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     358             :         factory->NewNumberFromInt(0)}},
     359             :       {"'use strict'; return p1[p2];",
     360             :        {factory->NewNumberFromInt(10),
     361             :         BytecodeGraphTester::NewObject("({val : 10 })"),
     362             :         factory->NewStringFromStaticChars("val")}},
     363             :       {"'use strict'; return p1[100];",
     364             :        {factory->NewNumberFromInt(10),
     365             :         BytecodeGraphTester::NewObject("({100 : 10})"),
     366             :         factory->NewNumberFromInt(0)}},
     367             :       {"'use strict'; var b = p2; return p1[b];",
     368             :        {factory->NewStringFromStaticChars("abc"),
     369             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     370             :         factory->NewNumberFromInt(100)}},
     371             :       {"var b;\n" REPEAT_127(SPACE, " b = p1[p2]; ") " return p1[p2];\n",
     372             :        {factory->NewStringFromStaticChars("abc"),
     373             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     374             :         factory->NewNumberFromInt(100)}},
     375             :       {"'use strict'; var b;\n" REPEAT_127(SPACE,
     376             :                                            " b = p1[p2]; ") "return p1[p2];\n",
     377             :        {factory->NewStringFromStaticChars("abc"),
     378             :         BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
     379             :         factory->NewNumberFromInt(100)}},
     380          48 :   };
     381             : 
     382          54 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     383             :     ScopedVector<char> script(2048);
     384             :     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0);", kFunctionName,
     385          48 :              snippets[i].code_snippet, kFunctionName);
     386             : 
     387             :     BytecodeGraphTester tester(isolate, script.start());
     388             :     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
     389             :     Handle<Object> return_value =
     390          48 :         callable(snippets[i].parameter(0), snippets[i].parameter(1))
     391             :             .ToHandleChecked();
     392          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     393           6 :   }
     394           6 : }
     395             : 
     396          12 : void TestBytecodeGraphBuilderNamedStore(size_t shard) {
     397          12 :   HandleAndZoneScope scope;
     398          12 :   Isolate* isolate = scope.main_isolate();
     399             :   Factory* factory = isolate->factory();
     400             : 
     401             :   ExpectedSnippet<1> snippets[] = {
     402             :       {"return p1.val = 20;",
     403             :        {factory->NewNumberFromInt(20),
     404             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     405             :       {"p1.type = 'int'; return p1.type;",
     406             :        {factory->NewStringFromStaticChars("int"),
     407             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     408             :       {"p1.name = 'def'; return p1[\"name\"];",
     409             :        {factory->NewStringFromStaticChars("def"),
     410             :         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
     411             :       {"'use strict'; p1.val = 20; return p1.val;",
     412             :        {factory->NewNumberFromInt(20),
     413             :         BytecodeGraphTester::NewObject("({val : 10 })")}},
     414             :       {"'use strict'; return p1.type = 'int';",
     415             :        {factory->NewStringFromStaticChars("int"),
     416             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     417             :       {"'use strict'; p1.val = 20; return p1[\"val\"];",
     418             :        {factory->NewNumberFromInt(20),
     419             :         BytecodeGraphTester::NewObject("({val : 10, name : 'abc'})")}},
     420             :       {"var b = 'abc';\n" REPEAT_127(
     421             :            SPACE, " p1.name = b; ") " p1.name = 'def'; return p1.name;\n",
     422             :        {factory->NewStringFromStaticChars("def"),
     423             :         BytecodeGraphTester::NewObject("({name : 'abc'})")}},
     424             :       {"'use strict'; var b = 'def';\n" REPEAT_127(
     425             :            SPACE, " p1.name = 'abc'; ") "p1.name = b; return p1.name;\n",
     426             :        {factory->NewStringFromStaticChars("def"),
     427             :         BytecodeGraphTester::NewObject("({ name : 'abc'})")}},
     428          72 :   };
     429             : 
     430         108 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     431         144 :     if ((i % 2) != shard) continue;
     432             :     ScopedVector<char> script(3072);
     433             :     SNPrintF(script, "function %s(p1) { %s };\n%s({});", kFunctionName,
     434          48 :              snippets[i].code_snippet, kFunctionName);
     435             : 
     436             :     BytecodeGraphTester tester(isolate, script.start());
     437             :     auto callable = tester.GetCallable<Handle<Object>>();
     438             :     Handle<Object> return_value =
     439          48 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     440          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     441          12 :   }
     442          12 : }
     443             : 
     444       23730 : SHARD_TEST_BY_2(BytecodeGraphBuilderNamedStore)
     445             : 
     446          12 : void TestBytecodeGraphBuilderKeyedStore(size_t shard) {
     447          12 :   HandleAndZoneScope scope;
     448          12 :   Isolate* isolate = scope.main_isolate();
     449             :   Factory* factory = isolate->factory();
     450             : 
     451             :   ExpectedSnippet<2> snippets[] = {
     452             :       {"p1[p2] = 20; return p1[p2];",
     453             :        {factory->NewNumberFromInt(20),
     454             :         BytecodeGraphTester::NewObject("({val : 10})"),
     455             :         factory->NewStringFromStaticChars("val")}},
     456             :       {"return p1[100] = 'def';",
     457             :        {factory->NewStringFromStaticChars("def"),
     458             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     459             :         factory->NewNumberFromInt(0)}},
     460             :       {"var b = 100; p1[b] = 'def'; return p1[b];",
     461             :        {factory->NewStringFromStaticChars("def"),
     462             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     463             :         factory->NewNumberFromInt(0)}},
     464             :       {"'use strict'; p1[p2] = 20; return p1[p2];",
     465             :        {factory->NewNumberFromInt(20),
     466             :         BytecodeGraphTester::NewObject("({val : 10 })"),
     467             :         factory->NewStringFromStaticChars("val")}},
     468             :       {"'use strict'; return p1[100] = 20;",
     469             :        {factory->NewNumberFromInt(20),
     470             :         BytecodeGraphTester::NewObject("({100 : 10})"),
     471             :         factory->NewNumberFromInt(0)}},
     472             :       {"'use strict'; var b = p2; p1[b] = 'def'; return p1[b];",
     473             :        {factory->NewStringFromStaticChars("def"),
     474             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     475             :         factory->NewNumberFromInt(100)}},
     476             :       {"var b;\n" REPEAT_127(
     477             :            SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
     478             :        {factory->NewStringFromStaticChars("def"),
     479             :         BytecodeGraphTester::NewObject("({100 : 'abc'})"),
     480             :         factory->NewNumberFromInt(100)}},
     481             :       {"'use strict'; var b;\n" REPEAT_127(
     482             :            SPACE, " b = p1[p2]; ") " p1[p2] = 'def'; return p1[p2];\n",
     483             :        {factory->NewStringFromStaticChars("def"),
     484             :         BytecodeGraphTester::NewObject("({ 100 : 'abc'})"),
     485             :         factory->NewNumberFromInt(100)}},
     486          96 :   };
     487             : 
     488         108 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     489         144 :     if ((i % 2) != shard) continue;
     490             :     ScopedVector<char> script(2048);
     491             :     SNPrintF(script, "function %s(p1, p2) { %s };\n%s({});", kFunctionName,
     492          48 :              snippets[i].code_snippet, kFunctionName);
     493             : 
     494             :     BytecodeGraphTester tester(isolate, script.start());
     495             :     auto callable = tester.GetCallable<Handle<Object>>();
     496             :     Handle<Object> return_value =
     497          48 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     498          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     499          12 :   }
     500          12 : }
     501             : 
     502       23730 : SHARD_TEST_BY_2(BytecodeGraphBuilderKeyedStore)
     503             : 
     504       23724 : TEST(BytecodeGraphBuilderPropertyCall) {
     505           6 :   HandleAndZoneScope scope;
     506           6 :   Isolate* isolate = scope.main_isolate();
     507             :   Factory* factory = isolate->factory();
     508             : 
     509             :   ExpectedSnippet<1> snippets[] = {
     510             :       {"return p1.func();",
     511             :        {factory->NewNumberFromInt(25),
     512             :         BytecodeGraphTester::NewObject("({func() { return 25; }})")}},
     513             :       {"return p1.func('abc');",
     514             :        {factory->NewStringFromStaticChars("abc"),
     515             :         BytecodeGraphTester::NewObject("({func(a) { return a; }})")}},
     516             :       {"return p1.func(1, 2, 3, 4, 5, 6, 7, 8);",
     517             :        {factory->NewNumberFromInt(36),
     518             :         BytecodeGraphTester::NewObject(
     519             :             "({func(a, b, c, d, e, f, g, h) {\n"
     520             :             "  return a + b + c + d + e + f + g + h;}})")}},
     521          12 :   };
     522             : 
     523          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     524             :     ScopedVector<char> script(2048);
     525             :     SNPrintF(script, "function %s(p1) { %s };\n%s({func() {}});", kFunctionName,
     526          18 :              snippets[i].code_snippet, kFunctionName);
     527             : 
     528             :     BytecodeGraphTester tester(isolate, script.start());
     529             :     auto callable = tester.GetCallable<Handle<Object>>();
     530             :     Handle<Object> return_value =
     531          18 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     532          18 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     533           6 :   }
     534           6 : }
     535             : 
     536       23724 : TEST(BytecodeGraphBuilderCallNew) {
     537           6 :   HandleAndZoneScope scope;
     538           6 :   Isolate* isolate = scope.main_isolate();
     539             :   Factory* factory = isolate->factory();
     540             : 
     541             :   ExpectedSnippet<0> snippets[] = {
     542             :       {"function counter() { this.count = 20; }\n"
     543             :        "function f() {\n"
     544             :        "  var c = new counter();\n"
     545             :        "  return c.count;\n"
     546             :        "}; f()",
     547             :        {factory->NewNumberFromInt(20)}},
     548             :       {"function counter(arg0) { this.count = 17; this.x = arg0; }\n"
     549             :        "function f() {\n"
     550             :        "  var c = new counter(6);\n"
     551             :        "  return c.count + c.x;\n"
     552             :        "}; f()",
     553             :        {factory->NewNumberFromInt(23)}},
     554             :       {"function counter(arg0, arg1) {\n"
     555             :        "  this.count = 17; this.x = arg0; this.y = arg1;\n"
     556             :        "}\n"
     557             :        "function f() {\n"
     558             :        "  var c = new counter(3, 5);\n"
     559             :        "  return c.count + c.x + c.y;\n"
     560             :        "}; f()",
     561             :        {factory->NewNumberFromInt(25)}},
     562           6 :   };
     563             : 
     564          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     565          18 :     BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
     566             :     auto callable = tester.GetCallable<>();
     567          36 :     Handle<Object> return_value = callable().ToHandleChecked();
     568          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     569           6 :   }
     570           6 : }
     571             : 
     572       23724 : TEST(BytecodeGraphBuilderCreateClosure) {
     573           6 :   HandleAndZoneScope scope;
     574           6 :   Isolate* isolate = scope.main_isolate();
     575             :   Factory* factory = isolate->factory();
     576             : 
     577             :   ExpectedSnippet<0> snippets[] = {
     578             :       {"function f() {\n"
     579             :        "  function counter() { this.count = 20; }\n"
     580             :        "  var c = new counter();\n"
     581             :        "  return c.count;\n"
     582             :        "}; f()",
     583             :        {factory->NewNumberFromInt(20)}},
     584             :       {"function f() {\n"
     585             :        "  function counter(arg0) { this.count = 17; this.x = arg0; }\n"
     586             :        "  var c = new counter(6);\n"
     587             :        "  return c.count + c.x;\n"
     588             :        "}; f()",
     589             :        {factory->NewNumberFromInt(23)}},
     590             :       {"function f() {\n"
     591             :        "  function counter(arg0, arg1) {\n"
     592             :        "    this.count = 17; this.x = arg0; this.y = arg1;\n"
     593             :        "  }\n"
     594             :        "  var c = new counter(3, 5);\n"
     595             :        "  return c.count + c.x + c.y;\n"
     596             :        "}; f()",
     597             :        {factory->NewNumberFromInt(25)}},
     598           6 :   };
     599             : 
     600          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     601          18 :     BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
     602             :     auto callable = tester.GetCallable<>();
     603          36 :     Handle<Object> return_value = callable().ToHandleChecked();
     604          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     605           6 :   }
     606           6 : }
     607             : 
     608       23724 : TEST(BytecodeGraphBuilderCallRuntime) {
     609           6 :   HandleAndZoneScope scope;
     610           6 :   Isolate* isolate = scope.main_isolate();
     611             :   Factory* factory = isolate->factory();
     612             : 
     613             :   ExpectedSnippet<1> snippets[] = {
     614             :       {"function f(arg0) { return %MaxSmi(); }\nf()",
     615             :        {factory->NewNumberFromInt(Smi::kMaxValue), factory->undefined_value()}},
     616             :       {"function f(arg0) { return %IsArray(arg0) }\nf(undefined)",
     617             :        {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
     618             :       {"function f(arg0) { return %Add(arg0, 2) }\nf(1)",
     619             :        {factory->NewNumberFromInt(5), factory->NewNumberFromInt(3)}},
     620             :       {"function f(arg0) { return %spread_arguments(arg0).length }\nf([])",
     621             :        {factory->NewNumberFromInt(3),
     622             :         BytecodeGraphTester::NewObject("[1, 2, 3]")}},
     623          18 :   };
     624             : 
     625          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     626          24 :     BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
     627             :     auto callable = tester.GetCallable<Handle<Object>>();
     628             :     Handle<Object> return_value =
     629          24 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     630          24 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     631           6 :   }
     632           6 : }
     633             : 
     634       23724 : TEST(BytecodeGraphBuilderInvokeIntrinsic) {
     635           6 :   HandleAndZoneScope scope;
     636           6 :   Isolate* isolate = scope.main_isolate();
     637             :   Factory* factory = isolate->factory();
     638             : 
     639             :   ExpectedSnippet<1> snippets[] = {
     640             :       {"function f(arg0) { return %_IsJSReceiver(arg0); }\nf()",
     641             :        {factory->false_value(), factory->NewNumberFromInt(1)}},
     642             :       {"function f(arg0) { return %_IsArray(arg0) }\nf(undefined)",
     643             :        {factory->true_value(), BytecodeGraphTester::NewObject("[1, 2, 3]")}},
     644          18 :   };
     645             : 
     646          18 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     647          12 :     BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
     648             :     auto callable = tester.GetCallable<Handle<Object>>();
     649             :     Handle<Object> return_value =
     650          12 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     651          12 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     652           6 :   }
     653           6 : }
     654             : 
     655          12 : void TestBytecodeGraphBuilderGlobals(size_t shard) {
     656          12 :   HandleAndZoneScope scope;
     657          12 :   Isolate* isolate = scope.main_isolate();
     658             :   Factory* factory = isolate->factory();
     659             : 
     660             :   ExpectedSnippet<0> snippets[] = {
     661             :       {"var global = 321;\n function f() { return global; };\n f();",
     662             :        {factory->NewNumberFromInt(321)}},
     663             :       {"var global = 321;\n"
     664             :        "function f() { global = 123; return global };\n f();",
     665             :        {factory->NewNumberFromInt(123)}},
     666             :       {"var global = function() { return 'abc'};\n"
     667             :        "function f() { return global(); };\n f();",
     668             :        {factory->NewStringFromStaticChars("abc")}},
     669             :       {"var global = 456;\n"
     670             :        "function f() { 'use strict'; return global; };\n f();",
     671             :        {factory->NewNumberFromInt(456)}},
     672             :       {"var global = 987;\n"
     673             :        "function f() { 'use strict'; global = 789; return global };\n f();",
     674             :        {factory->NewNumberFromInt(789)}},
     675             :       {"var global = function() { return 'xyz'};\n"
     676             :        "function f() { 'use strict'; return global(); };\n f();",
     677             :        {factory->NewStringFromStaticChars("xyz")}},
     678             :       {"var global = 'abc'; var global_obj = {val:123};\n"
     679             :        "function f() {\n" REPEAT_127(
     680             :            SPACE, " var b = global_obj.name;\n") "return global; };\n f();\n",
     681             :        {factory->NewStringFromStaticChars("abc")}},
     682             :       {"var global = 'abc'; var global_obj = {val:123};\n"
     683             :        "function f() { 'use strict';\n" REPEAT_127(
     684             :            SPACE, " var b = global_obj.name;\n") "global = 'xyz'; return "
     685             :                                                  "global };\n f();\n",
     686             :        {factory->NewStringFromStaticChars("xyz")}},
     687             :       {"function f() { return typeof(undeclared_var); }\n; f();\n",
     688             :        {factory->NewStringFromStaticChars("undefined")}},
     689             :       {"var defined_var = 10; function f() { return typeof(defined_var); }\n; "
     690             :        "f();\n",
     691             :        {factory->NewStringFromStaticChars("number")}},
     692          72 :   };
     693             : 
     694         132 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     695         180 :     if ((i % 2) != shard) continue;
     696          60 :     BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
     697             :     auto callable = tester.GetCallable<>();
     698         120 :     Handle<Object> return_value = callable().ToHandleChecked();
     699         120 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     700          12 :   }
     701          12 : }
     702             : 
     703       23730 : SHARD_TEST_BY_2(BytecodeGraphBuilderGlobals)
     704             : 
     705       23724 : TEST(BytecodeGraphBuilderToObject) {
     706             :   // TODO(mythria): tests for ToObject. Needs ForIn.
     707           6 : }
     708             : 
     709       23724 : TEST(BytecodeGraphBuilderToName) {
     710           6 :   HandleAndZoneScope scope;
     711           6 :   Isolate* isolate = scope.main_isolate();
     712             :   Factory* factory = isolate->factory();
     713             : 
     714             :   ExpectedSnippet<0> snippets[] = {
     715             :       {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
     716             :        {factory->NewNumberFromInt(10)}},
     717             :       {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
     718             :        {factory->NewNumberFromInt(10)}},
     719             :       {"var a = 20; var obj = {[a] : 10}; return obj[20];",
     720             :        {factory->NewNumberFromInt(10)}},
     721             :       {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
     722             :        {factory->NewNumberFromInt(10)}},
     723             :       {"var a = {val:23}; var obj = {[a] : 10}; return obj['[object Object]'];",
     724             :        {factory->NewNumberFromInt(10)}},
     725             :       {"var a = {toString : function() { return 'x'}};\n"
     726             :        "var obj = {[a] : 10};\n"
     727             :        "return obj.x;",
     728             :        {factory->NewNumberFromInt(10)}},
     729             :       {"var a = {valueOf : function() { return 'x'}};\n"
     730             :        "var obj = {[a] : 10};\n"
     731             :        "return obj.x;",
     732             :        {factory->undefined_value()}},
     733             :       {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
     734             :        "var obj = {[a] : 10};\n"
     735             :        "return obj.x;",
     736             :        {factory->NewNumberFromInt(10)}},
     737          12 :   };
     738             : 
     739          54 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     740             :     ScopedVector<char> script(1024);
     741             :     SNPrintF(script, "function %s() { %s }\n%s({});", kFunctionName,
     742          48 :              snippets[i].code_snippet, kFunctionName);
     743             : 
     744             :     BytecodeGraphTester tester(isolate, script.start());
     745             :     auto callable = tester.GetCallable<>();
     746          96 :     Handle<Object> return_value = callable().ToHandleChecked();
     747          96 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     748           6 :   }
     749           6 : }
     750             : 
     751       23724 : TEST(BytecodeGraphBuilderLogicalNot) {
     752           6 :   HandleAndZoneScope scope;
     753           6 :   Isolate* isolate = scope.main_isolate();
     754             :   Factory* factory = isolate->factory();
     755             : 
     756             :   ExpectedSnippet<1> snippets[] = {
     757             :       {"return !p1;",
     758             :        {factory->false_value(),
     759             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     760             :       {"return !p1;", {factory->true_value(), factory->NewNumberFromInt(0)}},
     761             :       {"return !p1;", {factory->true_value(), factory->undefined_value()}},
     762             :       {"return !p1;", {factory->false_value(), factory->NewNumberFromInt(10)}},
     763             :       {"return !p1;", {factory->false_value(), factory->true_value()}},
     764             :       {"return !p1;",
     765             :        {factory->false_value(), factory->NewStringFromStaticChars("abc")}},
     766          42 :   };
     767             : 
     768          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     769             :     ScopedVector<char> script(1024);
     770             :     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
     771          36 :              snippets[i].code_snippet, kFunctionName);
     772             : 
     773             :     BytecodeGraphTester tester(isolate, script.start());
     774             :     auto callable = tester.GetCallable<Handle<Object>>();
     775             :     Handle<Object> return_value =
     776          36 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     777          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     778           6 :   }
     779           6 : }
     780             : 
     781       23724 : TEST(BytecodeGraphBuilderTypeOf) {
     782           6 :   HandleAndZoneScope scope;
     783           6 :   Isolate* isolate = scope.main_isolate();
     784             :   Factory* factory = isolate->factory();
     785             : 
     786             :   ExpectedSnippet<1> snippets[] = {
     787             :       {"return typeof p1;",
     788             :        {factory->NewStringFromStaticChars("object"),
     789             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     790             :       {"return typeof p1;",
     791             :        {factory->NewStringFromStaticChars("undefined"),
     792             :         factory->undefined_value()}},
     793             :       {"return typeof p1;",
     794             :        {factory->NewStringFromStaticChars("number"),
     795             :         factory->NewNumberFromInt(10)}},
     796             :       {"return typeof p1;",
     797             :        {factory->NewStringFromStaticChars("boolean"), factory->true_value()}},
     798             :       {"return typeof p1;",
     799             :        {factory->NewStringFromStaticChars("string"),
     800             :         factory->NewStringFromStaticChars("abc")}},
     801          36 :   };
     802             : 
     803          36 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     804             :     ScopedVector<char> script(1024);
     805             :     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
     806          30 :              snippets[i].code_snippet, kFunctionName);
     807             : 
     808             :     BytecodeGraphTester tester(isolate, script.start());
     809             :     auto callable = tester.GetCallable<Handle<Object>>();
     810             :     Handle<Object> return_value =
     811          30 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     812          30 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     813           6 :   }
     814           6 : }
     815             : 
     816       23724 : TEST(BytecodeGraphBuilderCompareTypeOf) {
     817           6 :   HandleAndZoneScope scope;
     818           6 :   Isolate* isolate = scope.main_isolate();
     819             :   Factory* factory = isolate->factory();
     820             : 
     821             :   ExpectedSnippet<1> snippets[] = {
     822             :       {"return typeof p1 === 'number';",
     823             :        {factory->true_value(), factory->NewNumber(1.1)}},
     824             :       {"return typeof p1 === 'string';",
     825             :        {factory->false_value(), factory->NewNumber(1.1)}},
     826             :       {"return typeof p1 === 'string';",
     827             :        {factory->true_value(), factory->NewStringFromStaticChars("string")}},
     828             :       {"return typeof p1 === 'string';",
     829             :        {factory->false_value(), factory->undefined_value()}},
     830             :       {"return typeof p1 === 'undefined';",
     831             :        {factory->true_value(), factory->undefined_value()}},
     832             :       {"return typeof p1 === 'object';",
     833             :        {factory->true_value(), factory->null_value()}},
     834             :       {"return typeof p1 === 'object';",
     835             :        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
     836             :       {"return typeof p1 === 'function';",
     837             :        {factory->false_value(),
     838             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     839             :       {"return typeof p1 === 'symbol';",
     840             :        {factory->true_value(), factory->NewSymbol()}},
     841             :       {"return typeof p1 === 'symbol';",
     842             :        {factory->false_value(), factory->NewStringFromStaticChars("string")}},
     843             :       {"return typeof p1 === 'other';",
     844             :        {factory->false_value(), factory->NewNumber(1.1)}},
     845          90 :   };
     846             : 
     847          72 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     848             :     ScopedVector<char> script(1024);
     849             :     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
     850          66 :              snippets[i].code_snippet, kFunctionName);
     851             : 
     852             :     BytecodeGraphTester tester(isolate, script.start());
     853             :     auto callable = tester.GetCallable<Handle<Object>>();
     854             :     Handle<Object> return_value =
     855          66 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     856          66 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     857           6 :   }
     858           6 : }
     859             : 
     860       23724 : TEST(BytecodeGraphBuilderCountOperation) {
     861           6 :   HandleAndZoneScope scope;
     862           6 :   Isolate* isolate = scope.main_isolate();
     863             :   Factory* factory = isolate->factory();
     864             : 
     865             :   ExpectedSnippet<1> snippets[] = {
     866             :       {"return ++p1;",
     867             :        {factory->NewNumberFromInt(11), factory->NewNumberFromInt(10)}},
     868             :       {"return p1++;",
     869             :        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
     870             :       {"return p1++ + 10;",
     871             :        {factory->NewHeapNumber(15.23), factory->NewHeapNumber(5.23)}},
     872             :       {"return 20 + ++p1;",
     873             :        {factory->NewHeapNumber(27.23), factory->NewHeapNumber(6.23)}},
     874             :       {"return --p1;",
     875             :        {factory->NewHeapNumber(9.8), factory->NewHeapNumber(10.8)}},
     876             :       {"return p1--;",
     877             :        {factory->NewHeapNumber(10.8), factory->NewHeapNumber(10.8)}},
     878             :       {"return p1-- + 10;",
     879             :        {factory->NewNumberFromInt(20), factory->NewNumberFromInt(10)}},
     880             :       {"return 20 + --p1;",
     881             :        {factory->NewNumberFromInt(29), factory->NewNumberFromInt(10)}},
     882             :       {"return p1.val--;",
     883             :        {factory->NewNumberFromInt(10),
     884             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     885             :       {"return ++p1['val'];",
     886             :        {factory->NewNumberFromInt(11),
     887             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     888             :       {"return ++p1[1];",
     889             :        {factory->NewNumberFromInt(11),
     890             :         BytecodeGraphTester::NewObject("({1 : 10})")}},
     891             :       {" function inner() { return p1 } return --p1;",
     892             :        {factory->NewNumberFromInt(9), factory->NewNumberFromInt(10)}},
     893             :       {" function inner() { return p1 } return p1--;",
     894             :        {factory->NewNumberFromInt(10), factory->NewNumberFromInt(10)}},
     895             :       {"return ++p1;",
     896             :        {factory->nan_value(), factory->NewStringFromStaticChars("String")}},
     897          36 :   };
     898             : 
     899          90 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     900             :     ScopedVector<char> script(1024);
     901             :     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
     902          84 :              snippets[i].code_snippet, kFunctionName);
     903             : 
     904             :     BytecodeGraphTester tester(isolate, script.start());
     905             :     auto callable = tester.GetCallable<Handle<Object>>();
     906             :     Handle<Object> return_value =
     907          84 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     908          84 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     909           6 :   }
     910           6 : }
     911             : 
     912       23724 : TEST(BytecodeGraphBuilderDelete) {
     913           6 :   HandleAndZoneScope scope;
     914           6 :   Isolate* isolate = scope.main_isolate();
     915             :   Factory* factory = isolate->factory();
     916             : 
     917             :   ExpectedSnippet<1> snippets[] = {
     918             :       {"return delete p1.val;",
     919             :        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
     920             :       {"delete p1.val; return p1.val;",
     921             :        {factory->undefined_value(),
     922             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     923             :       {"delete p1.name; return p1.val;",
     924             :        {factory->NewNumberFromInt(10),
     925             :         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
     926             :       {"'use strict'; return delete p1.val;",
     927             :        {factory->true_value(), BytecodeGraphTester::NewObject("({val : 10})")}},
     928             :       {"'use strict'; delete p1.val; return p1.val;",
     929             :        {factory->undefined_value(),
     930             :         BytecodeGraphTester::NewObject("({val : 10})")}},
     931             :       {"'use strict'; delete p1.name; return p1.val;",
     932             :        {factory->NewNumberFromInt(10),
     933             :         BytecodeGraphTester::NewObject("({val : 10, name:'abc'})")}},
     934          30 :   };
     935             : 
     936          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     937             :     ScopedVector<char> script(1024);
     938             :     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
     939          36 :              snippets[i].code_snippet, kFunctionName);
     940             : 
     941             :     BytecodeGraphTester tester(isolate, script.start());
     942             :     auto callable = tester.GetCallable<Handle<Object>>();
     943             :     Handle<Object> return_value =
     944          36 :         callable(snippets[i].parameter(0)).ToHandleChecked();
     945          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     946           6 :   }
     947           6 : }
     948             : 
     949       23724 : TEST(BytecodeGraphBuilderDeleteGlobal) {
     950           6 :   HandleAndZoneScope scope;
     951           6 :   Isolate* isolate = scope.main_isolate();
     952             :   Factory* factory = isolate->factory();
     953             : 
     954             :   ExpectedSnippet<0> snippets[] = {
     955             :       {"var obj = {val : 10, type : 'int'};"
     956             :        "function f() {return delete obj;};",
     957             :        {factory->false_value()}},
     958             :       {"function f() {return delete this;};", {factory->true_value()}},
     959             :       {"var obj = {val : 10, type : 'int'};"
     960             :        "function f() {return delete obj.val;};",
     961             :        {factory->true_value()}},
     962             :       {"var obj = {val : 10, type : 'int'};"
     963             :        "function f() {'use strict'; return delete obj.val;};",
     964             :        {factory->true_value()}},
     965             :       {"var obj = {val : 10, type : 'int'};"
     966             :        "function f() {delete obj.val; return obj.val;};",
     967             :        {factory->undefined_value()}},
     968             :       {"var obj = {val : 10, type : 'int'};"
     969             :        "function f() {'use strict'; delete obj.val; return obj.val;};",
     970             :        {factory->undefined_value()}},
     971             :       {"var obj = {1 : 10, 2 : 20};"
     972             :        "function f() { return delete obj[1]; };",
     973             :        {factory->true_value()}},
     974             :       {"var obj = {1 : 10, 2 : 20};"
     975             :        "function f() { 'use strict';  return delete obj[1];};",
     976             :        {factory->true_value()}},
     977             :       {"obj = {1 : 10, 2 : 20};"
     978             :        "function f() { delete obj[1]; return obj[2];};",
     979             :        {factory->NewNumberFromInt(20)}},
     980             :       {"function f() {"
     981             :        "  var obj = {1 : 10, 2 : 20};"
     982             :        "  function inner() { return obj[1]; };"
     983             :        "  return delete obj[1];"
     984             :        "}",
     985             :        {factory->true_value()}},
     986          54 :   };
     987             : 
     988          66 :   for (size_t i = 0; i < arraysize(snippets); i++) {
     989             :     ScopedVector<char> script(1024);
     990          60 :     SNPrintF(script, "%s %s({});", snippets[i].code_snippet, kFunctionName);
     991             : 
     992             :     BytecodeGraphTester tester(isolate, script.start());
     993             :     auto callable = tester.GetCallable<>();
     994         120 :     Handle<Object> return_value = callable().ToHandleChecked();
     995         120 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
     996           6 :   }
     997           6 : }
     998             : 
     999       23724 : TEST(BytecodeGraphBuilderDeleteLookupSlot) {
    1000           6 :   HandleAndZoneScope scope;
    1001           6 :   Isolate* isolate = scope.main_isolate();
    1002             :   Factory* factory = isolate->factory();
    1003             : 
    1004             :   // TODO(mythria): Add more tests when we have support for LdaLookupSlot.
    1005             :   const char* function_prologue = "var f;"
    1006             :                                   "var x = 1;"
    1007             :                                   "y = 10;"
    1008             :                                   "var obj = {val:10};"
    1009             :                                   "var z = 30;"
    1010             :                                   "function f1() {"
    1011             :                                   "  var z = 20;"
    1012             :                                   "  eval(\"function t() {";
    1013             :   const char* function_epilogue = "        }; f = t; t();\");"
    1014             :                                   "}"
    1015             :                                   "f1();";
    1016             : 
    1017             :   ExpectedSnippet<0> snippets[] = {
    1018             :       {"return delete y;", {factory->true_value()}},
    1019             :       {"return delete z;", {factory->false_value()}},
    1020          12 :   };
    1021             : 
    1022          18 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1023             :     ScopedVector<char> script(1024);
    1024             :     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
    1025          12 :              function_epilogue);
    1026             : 
    1027             :     BytecodeGraphTester tester(isolate, script.start(), "t");
    1028             :     auto callable = tester.GetCallable<>();
    1029          24 :     Handle<Object> return_value = callable().ToHandleChecked();
    1030          24 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1031           6 :   }
    1032           6 : }
    1033             : 
    1034       23724 : TEST(BytecodeGraphBuilderLookupSlot) {
    1035           6 :   HandleAndZoneScope scope;
    1036           6 :   Isolate* isolate = scope.main_isolate();
    1037             :   Factory* factory = isolate->factory();
    1038             : 
    1039             :   const char* function_prologue = "var f;"
    1040             :                                   "var x = 12;"
    1041             :                                   "y = 10;"
    1042             :                                   "var obj = {val:3.1414};"
    1043             :                                   "var z = 30;"
    1044             :                                   "function f1() {"
    1045             :                                   "  var z = 20;"
    1046             :                                   "  eval(\"function t() {";
    1047             :   const char* function_epilogue = "        }; f = t; t();\");"
    1048             :                                   "}"
    1049             :                                   "f1();";
    1050             : 
    1051             :   ExpectedSnippet<0> snippets[] = {
    1052             :       {"return x;", {factory->NewNumber(12)}},
    1053             :       {"return obj.val;", {factory->NewNumber(3.1414)}},
    1054             :       {"return typeof x;", {factory->NewStringFromStaticChars("number")}},
    1055             :       {"return typeof dummy;",
    1056             :        {factory->NewStringFromStaticChars("undefined")}},
    1057             :       {"x = 23; return x;", {factory->NewNumber(23)}},
    1058             :       {"'use strict'; obj.val = 23.456; return obj.val;",
    1059          18 :        {factory->NewNumber(23.456)}}};
    1060             : 
    1061          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1062             :     ScopedVector<char> script(1024);
    1063             :     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
    1064          36 :              function_epilogue);
    1065             : 
    1066             :     BytecodeGraphTester tester(isolate, script.start(), "t");
    1067             :     auto callable = tester.GetCallable<>();
    1068          72 :     Handle<Object> return_value = callable().ToHandleChecked();
    1069          72 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1070           6 :   }
    1071           6 : }
    1072             : 
    1073       23724 : TEST(BytecodeGraphBuilderLookupContextSlot) {
    1074           6 :   HandleAndZoneScope scope;
    1075           6 :   Isolate* isolate = scope.main_isolate();
    1076             :   Factory* factory = isolate->factory();
    1077             : 
    1078             :   // Testing with eval called in the current context.
    1079             :   const char* inner_eval_prologue = "var x = 0; function inner() {";
    1080             :   const char* inner_eval_epilogue = "}; return inner();";
    1081             : 
    1082             :   ExpectedSnippet<0> inner_eval_snippets[] = {
    1083             :       {"eval(''); return x;", {factory->NewNumber(0)}},
    1084             :       {"eval('var x = 1'); return x;", {factory->NewNumber(1)}},
    1085           6 :       {"'use strict'; eval('var x = 1'); return x;", {factory->NewNumber(0)}}};
    1086             : 
    1087          24 :   for (size_t i = 0; i < arraysize(inner_eval_snippets); i++) {
    1088             :     ScopedVector<char> script(1024);
    1089             :     SNPrintF(script, "function %s(p1) { %s %s %s } ; %s() ;", kFunctionName,
    1090             :              inner_eval_prologue, inner_eval_snippets[i].code_snippet,
    1091          18 :              inner_eval_epilogue, kFunctionName);
    1092             : 
    1093             :     BytecodeGraphTester tester(isolate, script.start());
    1094             :     auto callable = tester.GetCallable<>();
    1095          36 :     Handle<Object> return_value = callable().ToHandleChecked();
    1096          36 :     CHECK(return_value->SameValue(*inner_eval_snippets[i].return_value()));
    1097             :   }
    1098             : 
    1099             :   // Testing with eval called in a parent context.
    1100             :   const char* outer_eval_prologue = "";
    1101             :   const char* outer_eval_epilogue =
    1102             :       "function inner() { return x; }; return inner();";
    1103             : 
    1104             :   ExpectedSnippet<0> outer_eval_snippets[] = {
    1105             :       {"var x = 0; eval('');", {factory->NewNumber(0)}},
    1106             :       {"var x = 0; eval('var x = 1');", {factory->NewNumber(1)}},
    1107           6 :       {"'use strict'; var x = 0; eval('var x = 1');", {factory->NewNumber(0)}}};
    1108             : 
    1109          24 :   for (size_t i = 0; i < arraysize(outer_eval_snippets); i++) {
    1110             :     ScopedVector<char> script(1024);
    1111             :     SNPrintF(script, "function %s() { %s %s %s } ; %s() ;", kFunctionName,
    1112             :              outer_eval_prologue, outer_eval_snippets[i].code_snippet,
    1113          18 :              outer_eval_epilogue, kFunctionName);
    1114             : 
    1115             :     BytecodeGraphTester tester(isolate, script.start());
    1116             :     auto callable = tester.GetCallable<>();
    1117          36 :     Handle<Object> return_value = callable().ToHandleChecked();
    1118          36 :     CHECK(return_value->SameValue(*outer_eval_snippets[i].return_value()));
    1119           6 :   }
    1120           6 : }
    1121             : 
    1122       23724 : TEST(BytecodeGraphBuilderLookupGlobalSlot) {
    1123           6 :   HandleAndZoneScope scope;
    1124           6 :   Isolate* isolate = scope.main_isolate();
    1125             :   Factory* factory = isolate->factory();
    1126             : 
    1127             :   // Testing with eval called in the current context.
    1128             :   const char* inner_eval_prologue = "x = 0; function inner() {";
    1129             :   const char* inner_eval_epilogue = "}; return inner();";
    1130             : 
    1131             :   ExpectedSnippet<0> inner_eval_snippets[] = {
    1132             :       {"eval(''); return x;", {factory->NewNumber(0)}},
    1133             :       {"eval('var x = 1'); return x;", {factory->NewNumber(1)}},
    1134           6 :       {"'use strict'; eval('var x = 1'); return x;", {factory->NewNumber(0)}}};
    1135             : 
    1136          24 :   for (size_t i = 0; i < arraysize(inner_eval_snippets); i++) {
    1137             :     ScopedVector<char> script(1024);
    1138             :     SNPrintF(script, "function %s(p1) { %s %s %s } ; %s() ;", kFunctionName,
    1139             :              inner_eval_prologue, inner_eval_snippets[i].code_snippet,
    1140          18 :              inner_eval_epilogue, kFunctionName);
    1141             : 
    1142             :     BytecodeGraphTester tester(isolate, script.start());
    1143             :     auto callable = tester.GetCallable<>();
    1144          36 :     Handle<Object> return_value = callable().ToHandleChecked();
    1145          36 :     CHECK(return_value->SameValue(*inner_eval_snippets[i].return_value()));
    1146             :   }
    1147             : 
    1148             :   // Testing with eval called in a parent context.
    1149             :   const char* outer_eval_prologue = "";
    1150             :   const char* outer_eval_epilogue =
    1151             :       "function inner() { return x; }; return inner();";
    1152             : 
    1153             :   ExpectedSnippet<0> outer_eval_snippets[] = {
    1154             :       {"x = 0; eval('');", {factory->NewNumber(0)}},
    1155             :       {"x = 0; eval('var x = 1');", {factory->NewNumber(1)}},
    1156           6 :       {"'use strict'; x = 0; eval('var x = 1');", {factory->NewNumber(0)}}};
    1157             : 
    1158          24 :   for (size_t i = 0; i < arraysize(outer_eval_snippets); i++) {
    1159             :     ScopedVector<char> script(1024);
    1160             :     SNPrintF(script, "function %s() { %s %s %s } ; %s() ;", kFunctionName,
    1161             :              outer_eval_prologue, outer_eval_snippets[i].code_snippet,
    1162          18 :              outer_eval_epilogue, kFunctionName);
    1163             : 
    1164             :     BytecodeGraphTester tester(isolate, script.start());
    1165             :     auto callable = tester.GetCallable<>();
    1166          36 :     Handle<Object> return_value = callable().ToHandleChecked();
    1167          36 :     CHECK(return_value->SameValue(*outer_eval_snippets[i].return_value()));
    1168           6 :   }
    1169           6 : }
    1170             : 
    1171       23724 : TEST(BytecodeGraphBuilderLookupSlotWide) {
    1172           6 :   HandleAndZoneScope scope;
    1173           6 :   Isolate* isolate = scope.main_isolate();
    1174             :   Factory* factory = isolate->factory();
    1175             : 
    1176             :   const char* function_prologue =
    1177             :       "var f;"
    1178             :       "var x = 12;"
    1179             :       "y = 10;"
    1180             :       "var obj = {val:3.1414};"
    1181             :       "var z = 30;"
    1182             :       "function f1() {"
    1183             :       "  var z = 20;"
    1184             :       "  eval(\"function t() {";
    1185             :   const char* function_epilogue =
    1186             :       "        }; f = t; t();\");"
    1187             :       "}"
    1188             :       "f1();";
    1189             : 
    1190             :   ExpectedSnippet<0> snippets[] = {
    1191             :       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x;",
    1192             :        {factory->NewNumber(12)}},
    1193             :       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return typeof x;",
    1194             :        {factory->NewStringFromStaticChars("number")}},
    1195             :       {"var y = 2.3;" REPEAT_256(SPACE, "y = 2.3;") "return x = 23;",
    1196             :        {factory->NewNumber(23)}},
    1197             :       {"'use strict';" REPEAT_256(SPACE, "y = 2.3;") "return obj.val = 23.456;",
    1198          12 :        {factory->NewNumber(23.456)}}};
    1199             : 
    1200          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1201             :     ScopedVector<char> script(3072);
    1202             :     SNPrintF(script, "%s %s %s", function_prologue, snippets[i].code_snippet,
    1203          24 :              function_epilogue);
    1204             : 
    1205             :     BytecodeGraphTester tester(isolate, script.start(), "t");
    1206             :     auto callable = tester.GetCallable<>();
    1207          48 :     Handle<Object> return_value = callable().ToHandleChecked();
    1208          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1209           6 :   }
    1210           6 : }
    1211             : 
    1212       23724 : TEST(BytecodeGraphBuilderCallLookupSlot) {
    1213           6 :   HandleAndZoneScope scope;
    1214           6 :   Isolate* isolate = scope.main_isolate();
    1215             : 
    1216             :   ExpectedSnippet<0> snippets[] = {
    1217             :       {"g = function(){ return 2 }; eval(''); return g();",
    1218             :        {handle(Smi::FromInt(2), isolate)}},
    1219             :       {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
    1220             :        "return g();",
    1221             :        {handle(Smi::FromInt(3), isolate)}},
    1222             :       {"g = { x: function(){ return this.y }, y: 20 };\n"
    1223             :        "eval('g = { x: g.x, y: 30 }');\n"
    1224             :        "return g.x();",
    1225             :        {handle(Smi::FromInt(30), isolate)}},
    1226          18 :   };
    1227             : 
    1228          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1229             :     ScopedVector<char> script(1024);
    1230             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1231          18 :              snippets[i].code_snippet, kFunctionName);
    1232             :     BytecodeGraphTester tester(isolate, script.start());
    1233             :     auto callable = tester.GetCallable<>();
    1234          36 :     Handle<Object> return_value = callable().ToHandleChecked();
    1235          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1236           6 :   }
    1237           6 : }
    1238             : 
    1239       23724 : TEST(BytecodeGraphBuilderEval) {
    1240           6 :   HandleAndZoneScope scope;
    1241           6 :   Isolate* isolate = scope.main_isolate();
    1242             :   Factory* factory = isolate->factory();
    1243             : 
    1244             :   ExpectedSnippet<0> snippets[] = {
    1245             :       {"return eval('1;');", {handle(Smi::FromInt(1), isolate)}},
    1246             :       {"return eval('100 * 20;');", {handle(Smi::FromInt(2000), isolate)}},
    1247             :       {"var x = 10; return eval('x + 20;');",
    1248             :        {handle(Smi::FromInt(30), isolate)}},
    1249             :       {"var x = 10; eval('x = 33;'); return x;",
    1250             :        {handle(Smi::FromInt(33), isolate)}},
    1251             :       {"'use strict'; var x = 20; var z = 0;\n"
    1252             :        "eval('var x = 33; z = x;'); return x + z;",
    1253             :        {handle(Smi::FromInt(53), isolate)}},
    1254             :       {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
    1255             :        {handle(Smi::FromInt(86), isolate)}},
    1256             :       {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
    1257             :        {handle(Smi::FromInt(11), isolate)}},
    1258             :       {"var x = 10; eval('var x = 20;'); return x;",
    1259             :        {handle(Smi::FromInt(20), isolate)}},
    1260             :       {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
    1261             :        {handle(Smi::FromInt(1), isolate)}},
    1262             :       {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
    1263             :        {handle(Smi::FromInt(1), isolate)}},
    1264             :       {"var x = 10; eval('x + 20;'); return typeof x;",
    1265             :        {factory->NewStringFromStaticChars("number")}},
    1266             :       {"eval('var y = 10;'); return typeof unallocated;",
    1267             :        {factory->NewStringFromStaticChars("undefined")}},
    1268             :       {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
    1269             :        {factory->NewStringFromStaticChars("undefined")}},
    1270             :       {"eval('var x = 10;'); return typeof x;",
    1271             :        {factory->NewStringFromStaticChars("number")}},
    1272             :       {"var x = {}; eval('var x = 10;'); return typeof x;",
    1273             :        {factory->NewStringFromStaticChars("number")}},
    1274             :       {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
    1275             :        {factory->NewStringFromStaticChars("object")}},
    1276          96 :   };
    1277             : 
    1278         102 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1279             :     ScopedVector<char> script(1024);
    1280             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1281          96 :              snippets[i].code_snippet, kFunctionName);
    1282             :     BytecodeGraphTester tester(isolate, script.start());
    1283             :     auto callable = tester.GetCallable<>();
    1284         192 :     Handle<Object> return_value = callable().ToHandleChecked();
    1285         192 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1286           6 :   }
    1287           6 : }
    1288             : 
    1289       23724 : TEST(BytecodeGraphBuilderEvalParams) {
    1290           6 :   HandleAndZoneScope scope;
    1291           6 :   Isolate* isolate = scope.main_isolate();
    1292             : 
    1293             :   ExpectedSnippet<1> snippets[] = {
    1294             :       {"var x = 10; return eval('x + p1;');",
    1295             :        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
    1296             :       {"var x = 10; eval('p1 = x;'); return p1;",
    1297             :        {handle(Smi::FromInt(10), isolate), handle(Smi::FromInt(20), isolate)}},
    1298             :       {"var a = 10;"
    1299             :        "function inner() { return eval('a + p1;');}"
    1300             :        "return inner();",
    1301             :        {handle(Smi::FromInt(30), isolate), handle(Smi::FromInt(20), isolate)}},
    1302          18 :   };
    1303             : 
    1304          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1305             :     ScopedVector<char> script(1024);
    1306             :     SNPrintF(script, "function %s(p1) { %s }\n%s(0);", kFunctionName,
    1307          18 :              snippets[i].code_snippet, kFunctionName);
    1308             :     BytecodeGraphTester tester(isolate, script.start());
    1309             :     auto callable = tester.GetCallable<Handle<Object>>();
    1310             :     Handle<Object> return_value =
    1311          18 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    1312          18 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1313           6 :   }
    1314           6 : }
    1315             : 
    1316       23724 : TEST(BytecodeGraphBuilderEvalGlobal) {
    1317           6 :   HandleAndZoneScope scope;
    1318           6 :   Isolate* isolate = scope.main_isolate();
    1319             :   Factory* factory = isolate->factory();
    1320             : 
    1321             :   ExpectedSnippet<0> snippets[] = {
    1322             :       {"function add_global() { eval('function f() { z = 33; }; f()'); };"
    1323             :        "function f() { add_global(); return z; }; f();",
    1324             :        {handle(Smi::FromInt(33), isolate)}},
    1325             :       {"function add_global() {\n"
    1326             :        " eval('\"use strict\"; function f() { y = 33; };"
    1327             :        "      try { f() } catch(e) {}');\n"
    1328             :        "}\n"
    1329             :        "function f() { add_global(); return typeof y; } f();",
    1330             :        {factory->NewStringFromStaticChars("undefined")}},
    1331          12 :   };
    1332             : 
    1333          18 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1334          12 :     BytecodeGraphTester tester(isolate, snippets[i].code_snippet);
    1335             :     auto callable = tester.GetCallable<>();
    1336          24 :     Handle<Object> return_value = callable().ToHandleChecked();
    1337          24 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1338           6 :   }
    1339           6 : }
    1340             : 
    1341        1680 : bool get_compare_result(Token::Value opcode, Handle<Object> lhs_value,
    1342             :                         Handle<Object> rhs_value) {
    1343        1680 :   switch (opcode) {
    1344             :     case Token::Value::EQ:
    1345         420 :       return Object::Equals(lhs_value, rhs_value).FromJust();
    1346             :     case Token::Value::NE:
    1347         420 :       return !Object::Equals(lhs_value, rhs_value).FromJust();
    1348             :     case Token::Value::EQ_STRICT:
    1349         210 :       return lhs_value->StrictEquals(*rhs_value);
    1350             :     case Token::Value::NE_STRICT:
    1351         210 :       return !lhs_value->StrictEquals(*rhs_value);
    1352             :     case Token::Value::LT:
    1353         420 :       return Object::LessThan(lhs_value, rhs_value).FromJust();
    1354             :     case Token::Value::LTE:
    1355         420 :       return Object::LessThanOrEqual(lhs_value, rhs_value).FromJust();
    1356             :     case Token::Value::GT:
    1357         420 :       return Object::GreaterThan(lhs_value, rhs_value).FromJust();
    1358             :     case Token::Value::GTE:
    1359         420 :       return Object::GreaterThanOrEqual(lhs_value, rhs_value).FromJust();
    1360             :     default:
    1361           0 :       UNREACHABLE();
    1362             :   }
    1363             : }
    1364             : 
    1365          48 : const char* get_code_snippet(Token::Value opcode) {
    1366          48 :   switch (opcode) {
    1367             :     case Token::Value::EQ:
    1368             :       return "return p1 == p2;";
    1369             :     case Token::Value::NE:
    1370           6 :       return "return p1 != p2;";
    1371             :     case Token::Value::EQ_STRICT:
    1372           6 :       return "return p1 === p2;";
    1373             :     case Token::Value::NE_STRICT:
    1374           6 :       return "return p1 !== p2;";
    1375             :     case Token::Value::LT:
    1376           6 :       return "return p1 < p2;";
    1377             :     case Token::Value::LTE:
    1378           6 :       return "return p1 <= p2;";
    1379             :     case Token::Value::GT:
    1380           6 :       return "return p1 > p2;";
    1381             :     case Token::Value::GTE:
    1382           6 :       return "return p1 >= p2;";
    1383             :     default:
    1384           0 :       UNREACHABLE();
    1385             :   }
    1386             : }
    1387             : 
    1388       23724 : TEST(BytecodeGraphBuilderCompare) {
    1389           6 :   HandleAndZoneScope scope;
    1390           6 :   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          18 :       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          18 :                                  factory->NewNumberFromInt(SMI_MIN)};
    1403             : 
    1404          54 :   for (size_t i = 0; i < arraysize(kCompareOperators); i++) {
    1405             :     ScopedVector<char> script(1024);
    1406             :     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
    1407          48 :              get_code_snippet(kCompareOperators[i]), kFunctionName);
    1408             : 
    1409             :     BytecodeGraphTester tester(isolate, script.start());
    1410             :     auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
    1411         288 :     for (size_t j = 0; j < arraysize(lhs_values); j++) {
    1412        1680 :       for (size_t k = 0; k < arraysize(rhs_values); k++) {
    1413             :         Handle<Object> return_value =
    1414             :             callable(lhs_values[j], rhs_values[k]).ToHandleChecked();
    1415             :         bool result = get_compare_result(kCompareOperators[i], lhs_values[j],
    1416        1680 :                                          rhs_values[k]);
    1417        3360 :         CHECK(return_value->SameValue(*factory->ToBoolean(result)));
    1418             :       }
    1419             :     }
    1420           6 :   }
    1421           6 : }
    1422             : 
    1423       23724 : TEST(BytecodeGraphBuilderTestIn) {
    1424           6 :   HandleAndZoneScope scope;
    1425           6 :   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          84 :   };
    1455             : 
    1456          54 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1457             :     ScopedVector<char> script(1024);
    1458             :     SNPrintF(script, "function %s(p1, p2) { %s }\n%s({}, {});", kFunctionName,
    1459          48 :              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          48 :         callable(snippets[i].parameter(0), snippets[i].parameter(1))
    1465             :             .ToHandleChecked();
    1466          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1467           6 :   }
    1468           6 : }
    1469             : 
    1470       23724 : TEST(BytecodeGraphBuilderTestInstanceOf) {
    1471           6 :   HandleAndZoneScope scope;
    1472           6 :   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          24 :   };
    1485             : 
    1486          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1487             :     ScopedVector<char> script(1024);
    1488             :     SNPrintF(script, "function %s(p1) { %s }\n%s({});", kFunctionName,
    1489          18 :              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          18 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    1495          18 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1496           6 :   }
    1497           6 : }
    1498             : 
    1499       23724 : TEST(BytecodeGraphBuilderTryCatch) {
    1500           6 :   HandleAndZoneScope scope;
    1501           6 :   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          24 :   };
    1514             : 
    1515          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1516             :     ScopedVector<char> script(1024);
    1517             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1518          24 :              snippets[i].code_snippet, kFunctionName);
    1519             : 
    1520             :     BytecodeGraphTester tester(isolate, script.start());
    1521             :     auto callable = tester.GetCallable<>();
    1522          48 :     Handle<Object> return_value = callable().ToHandleChecked();
    1523          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1524           6 :   }
    1525           6 : }
    1526             : 
    1527       23724 : TEST(BytecodeGraphBuilderTryFinally1) {
    1528           6 :   HandleAndZoneScope scope;
    1529           6 :   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          36 :   };
    1551             : 
    1552          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1553             :     ScopedVector<char> script(1024);
    1554             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1555          36 :              snippets[i].code_snippet, kFunctionName);
    1556             : 
    1557             :     BytecodeGraphTester tester(isolate, script.start());
    1558             :     auto callable = tester.GetCallable<>();
    1559          72 :     Handle<Object> return_value = callable().ToHandleChecked();
    1560          72 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1561           6 :   }
    1562           6 : }
    1563             : 
    1564       23724 : TEST(BytecodeGraphBuilderTryFinally2) {
    1565           6 :   HandleAndZoneScope scope;
    1566           6 :   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           6 :   };
    1574             : 
    1575          18 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1576             :     ScopedVector<char> script(1024);
    1577             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1578          12 :              snippets[i].code_snippet, kFunctionName);
    1579             : 
    1580             :     BytecodeGraphTester tester(isolate, script.start());
    1581          24 :     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
    1582          12 :     v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
    1583          36 :     CHECK(
    1584             :         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
    1585             :             .FromJust());
    1586           6 :   }
    1587           6 : }
    1588             : 
    1589       23724 : TEST(BytecodeGraphBuilderThrow) {
    1590           6 :   HandleAndZoneScope scope;
    1591           6 :   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           6 :   };
    1602             : 
    1603          36 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1604             :     ScopedVector<char> script(1024);
    1605             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1606          30 :              snippets[i].code_snippet, kFunctionName);
    1607             : 
    1608             :     BytecodeGraphTester tester(isolate, script.start());
    1609          60 :     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
    1610          30 :     v8::Local<v8::String> expected_string = v8_str(snippets[i].return_value());
    1611          90 :     CHECK(
    1612             :         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
    1613             :             .FromJust());
    1614           6 :   }
    1615           6 : }
    1616             : 
    1617       23724 : TEST(BytecodeGraphBuilderContext) {
    1618           6 :   HandleAndZoneScope scope;
    1619           6 :   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          18 :   };
    1662             : 
    1663          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1664             :     ScopedVector<char> script(1024);
    1665          18 :     SNPrintF(script, "%s", snippets[i].code_snippet);
    1666             : 
    1667             :     BytecodeGraphTester tester(isolate, script.start(), "f");
    1668             :     auto callable = tester.GetCallable<>("f");
    1669          36 :     Handle<Object> return_value = callable().ToHandleChecked();
    1670          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1671           6 :   }
    1672           6 : }
    1673             : 
    1674       23724 : TEST(BytecodeGraphBuilderLoadContext) {
    1675           6 :   HandleAndZoneScope scope;
    1676           6 :   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          18 :        {factory->NewNumberFromInt(24), factory->NewNumberFromInt(4)}}};
    1725             : 
    1726          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1727             :     ScopedVector<char> script(1024);
    1728          24 :     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          24 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    1734          24 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1735           6 :   }
    1736           6 : }
    1737             : 
    1738       23724 : TEST(BytecodeGraphBuilderCreateArgumentsNoParameters) {
    1739           6 :   HandleAndZoneScope scope;
    1740           6 :   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          36 :   };
    1755             : 
    1756          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1757             :     ScopedVector<char> script(1024);
    1758          36 :     SNPrintF(script, "%s\n%s();", snippets[i].code_snippet, kFunctionName);
    1759             : 
    1760             :     BytecodeGraphTester tester(isolate, script.start());
    1761             :     auto callable = tester.GetCallable<>();
    1762          72 :     Handle<Object> return_value = callable().ToHandleChecked();
    1763          72 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1764           6 :   }
    1765           6 : }
    1766             : 
    1767       23724 : TEST(BytecodeGraphBuilderCreateArguments) {
    1768           6 :   HandleAndZoneScope scope;
    1769           6 :   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          18 :   };
    1796             : 
    1797          48 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1798             :     ScopedVector<char> script(1024);
    1799          42 :     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          42 :                  snippets[i].parameter(2))
    1807             :             .ToHandleChecked();
    1808          42 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1809           6 :   }
    1810           6 : }
    1811             : 
    1812       23724 : TEST(BytecodeGraphBuilderCreateRestArguments) {
    1813           6 :   HandleAndZoneScope scope;
    1814           6 :   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          12 :   };
    1838             : 
    1839          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1840             :     ScopedVector<char> script(1024);
    1841          36 :     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          36 :                  snippets[i].parameter(2))
    1849             :             .ToHandleChecked();
    1850          36 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1851           6 :   }
    1852           6 : }
    1853             : 
    1854       23724 : TEST(BytecodeGraphBuilderRegExpLiterals) {
    1855           6 :   HandleAndZoneScope scope;
    1856           6 :   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          42 :   };
    1875             : 
    1876          48 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1877             :     ScopedVector<char> script(4096);
    1878             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1879          42 :              snippets[i].code_snippet, kFunctionName);
    1880             : 
    1881             :     BytecodeGraphTester tester(isolate, script.start());
    1882             :     auto callable = tester.GetCallable<>();
    1883          84 :     Handle<Object> return_value = callable().ToHandleChecked();
    1884          84 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1885           6 :   }
    1886           6 : }
    1887             : 
    1888       23724 : TEST(BytecodeGraphBuilderArrayLiterals) {
    1889           6 :   HandleAndZoneScope scope;
    1890           6 :   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          36 :        {factory->NewStringFromStaticChars("1t")}}};
    1913             : 
    1914          66 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1915             :     ScopedVector<char> script(4096);
    1916             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1917          60 :              snippets[i].code_snippet, kFunctionName);
    1918             : 
    1919             :     BytecodeGraphTester tester(isolate, script.start());
    1920             :     auto callable = tester.GetCallable<>();
    1921         120 :     Handle<Object> return_value = callable().ToHandleChecked();
    1922         120 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1923           6 :   }
    1924           6 : }
    1925             : 
    1926       23724 : TEST(BytecodeGraphBuilderObjectLiterals) {
    1927           6 :   HandleAndZoneScope scope;
    1928           6 :   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          72 :   };
    1976             : 
    1977         114 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    1978             :     ScopedVector<char> script(4096);
    1979             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    1980         108 :              snippets[i].code_snippet, kFunctionName);
    1981             :     BytecodeGraphTester tester(isolate, script.start());
    1982             :     auto callable = tester.GetCallable<>();
    1983         216 :     Handle<Object> return_value = callable().ToHandleChecked();
    1984         216 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    1985           6 :   }
    1986           6 : }
    1987             : 
    1988       23724 : TEST(BytecodeGraphBuilderIf) {
    1989           6 :   HandleAndZoneScope scope;
    1990           6 :   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           6 :   };
    2082             : 
    2083          90 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2084             :     ScopedVector<char> script(2048);
    2085             :     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
    2086          84 :              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          84 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    2092          84 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2093           6 :   }
    2094           6 : }
    2095             : 
    2096       23724 : TEST(BytecodeGraphBuilderConditionalOperator) {
    2097           6 :   HandleAndZoneScope scope;
    2098           6 :   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           6 :   };
    2111             : 
    2112          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2113             :     ScopedVector<char> script(2048);
    2114             :     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
    2115          24 :              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          24 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    2121          24 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2122           6 :   }
    2123           6 : }
    2124             : 
    2125       23724 : TEST(BytecodeGraphBuilderSwitch) {
    2126           6 :   HandleAndZoneScope scope;
    2127           6 :   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           6 :   };
    2157             : 
    2158          48 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2159             :     ScopedVector<char> script(2048);
    2160             :     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
    2161          42 :              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          42 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    2167          42 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2168           6 :   }
    2169           6 : }
    2170             : 
    2171       23724 : TEST(BytecodeGraphBuilderSwitchMerge) {
    2172           6 :   HandleAndZoneScope scope;
    2173           6 :   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           6 :   };
    2205             : 
    2206          48 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2207             :     ScopedVector<char> script(2048);
    2208             :     SNPrintF(script, "function %s(p1) { %s };\n%s(0);", kFunctionName,
    2209          42 :              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          42 :         callable(snippets[i].parameter(0)).ToHandleChecked();
    2215          42 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2216           6 :   }
    2217           6 : }
    2218             : 
    2219       23724 : TEST(BytecodeGraphBuilderNestedSwitch) {
    2220           6 :   HandleAndZoneScope scope;
    2221           6 :   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           6 :   };
    2263             : 
    2264          54 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2265             :     ScopedVector<char> script(2048);
    2266             :     SNPrintF(script, "function %s(p1, p2) { %s };\n%s(0, 0);", kFunctionName,
    2267          48 :              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          48 :         callable(snippets[i].parameter(0), snippets[i].parameter(1))
    2273             :             .ToHandleChecked();
    2274          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2275           6 :   }
    2276           6 : }
    2277             : 
    2278       23724 : TEST(BytecodeGraphBuilderBreakableBlocks) {
    2279           6 :   HandleAndZoneScope scope;
    2280           6 :   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           6 :   };
    2304             : 
    2305          18 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2306             :     ScopedVector<char> script(1024);
    2307             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2308          12 :              snippets[i].code_snippet, kFunctionName);
    2309             : 
    2310             :     BytecodeGraphTester tester(isolate, script.start());
    2311             :     auto callable = tester.GetCallable<>();
    2312          24 :     Handle<Object> return_value = callable().ToHandleChecked();
    2313          24 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2314           6 :   }
    2315           6 : }
    2316             : 
    2317       23724 : TEST(BytecodeGraphBuilderWhile) {
    2318           6 :   HandleAndZoneScope scope;
    2319           6 :   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           6 :        {factory->NewNumberFromInt(16)}}};
    2351             : 
    2352          42 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2353             :     ScopedVector<char> script(1024);
    2354             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2355          36 :              snippets[i].code_snippet, kFunctionName);
    2356             : 
    2357             :     BytecodeGraphTester tester(isolate, script.start());
    2358             :     auto callable = tester.GetCallable<>();
    2359          72 :     Handle<Object> return_value = callable().ToHandleChecked();
    2360          72 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2361           6 :   }
    2362           6 : }
    2363             : 
    2364       23724 : TEST(BytecodeGraphBuilderDo) {
    2365           6 :   HandleAndZoneScope scope;
    2366           6 :   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           6 :        {factory->NewNumber(3)}}};
    2398             : 
    2399          36 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2400             :     ScopedVector<char> script(1024);
    2401             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2402          30 :              snippets[i].code_snippet, kFunctionName);
    2403             : 
    2404             :     BytecodeGraphTester tester(isolate, script.start());
    2405             :     auto callable = tester.GetCallable<>();
    2406          60 :     Handle<Object> return_value = callable().ToHandleChecked();
    2407          60 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2408           6 :   }
    2409           6 : }
    2410             : 
    2411       23724 : TEST(BytecodeGraphBuilderFor) {
    2412           6 :   HandleAndZoneScope scope;
    2413           6 :   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           6 :   };
    2490             : 
    2491          72 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2492             :     ScopedVector<char> script(1024);
    2493             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2494          66 :              snippets[i].code_snippet, kFunctionName);
    2495             : 
    2496             :     BytecodeGraphTester tester(isolate, script.start());
    2497             :     auto callable = tester.GetCallable<>();
    2498         132 :     Handle<Object> return_value = callable().ToHandleChecked();
    2499         132 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2500           6 :   }
    2501           6 : }
    2502             : 
    2503       23724 : TEST(BytecodeGraphBuilderForIn) {
    2504           6 :   HandleAndZoneScope scope;
    2505           6 :   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           6 :   };
    2560             : 
    2561          54 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2562             :     ScopedVector<char> script(1024);
    2563             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2564          48 :              snippets[i].code_snippet, kFunctionName);
    2565             : 
    2566             :     BytecodeGraphTester tester(isolate, script.start());
    2567             :     auto callable = tester.GetCallable<>();
    2568          96 :     Handle<Object> return_value = callable().ToHandleChecked();
    2569          96 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2570           6 :   }
    2571           6 : }
    2572             : 
    2573       23724 : TEST(BytecodeGraphBuilderForOf) {
    2574           6 :   HandleAndZoneScope scope;
    2575           6 :   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          72 :   };
    2651             : 
    2652          78 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2653             :     ScopedVector<char> script(1024);
    2654             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2655          72 :              snippets[i].code_snippet, kFunctionName);
    2656             : 
    2657             :     BytecodeGraphTester tester(isolate, script.start());
    2658             :     auto callable = tester.GetCallable<>();
    2659         144 :     Handle<Object> return_value = callable().ToHandleChecked();
    2660         144 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2661           6 :   }
    2662           6 : }
    2663             : 
    2664          24 : void TestJumpWithConstantsAndWideConstants(size_t shard) {
    2665             :   const int kStep = 46;
    2666          24 :   int start = static_cast<int>(7 + 17 * shard);
    2667         174 :   for (int constants = start; constants < 300; constants += kStep) {
    2668         150 :     std::stringstream filler_os;
    2669             :     // Generate a string that consumes constant pool entries and
    2670             :     // spread out branch distances in script below.
    2671       23088 :     for (int i = 0; i < constants; i++) {
    2672       22938 :       filler_os << "var x_ = 'x_" << i << "';\n";
    2673             :     }
    2674             :     std::string filler(filler_os.str());
    2675             : 
    2676         300 :     std::stringstream script_os;
    2677         150 :     script_os << "function " << kFunctionName << "(a) {\n";
    2678         150 :     script_os << "  " << filler;
    2679         150 :     script_os << "  for (var i = a; i < 2; i++) {\n";
    2680         150 :     script_os << "  " << filler;
    2681         300 :     script_os << "    if (i == 0) { " << filler << "i = 10; continue; }\n";
    2682         300 :     script_os << "    else if (i == a) { " << filler << "i = 12; break; }\n";
    2683         300 :     script_os << "    else { " << filler << " }\n";
    2684         150 :     script_os << "  }\n";
    2685         150 :     script_os << "  return i;\n";
    2686         150 :     script_os << "}\n";
    2687         150 :     script_os << kFunctionName << "(0);\n";
    2688             :     std::string script(script_os.str());
    2689             : 
    2690         300 :     HandleAndZoneScope scope;
    2691         150 :     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         600 :     for (int a = 0; a < 3; a++) {
    2696             :       Handle<Object> return_val =
    2697         450 :           callable(factory->NewNumberFromInt(a)).ToHandleChecked();
    2698             :       static const int results[] = {11, 12, 2};
    2699         900 :       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
    2700             :     }
    2701         150 :   }
    2702          24 : }
    2703             : 
    2704       23742 : SHARD_TEST_BY_4(JumpWithConstantsAndWideConstants)
    2705             : 
    2706       23724 : TEST(BytecodeGraphBuilderDoExpressions) {
    2707           6 :   bool old_flag = FLAG_harmony_do_expressions;
    2708           6 :   FLAG_harmony_do_expressions = true;
    2709           6 :   HandleAndZoneScope scope;
    2710           6 :   Isolate* isolate = scope.main_isolate();
    2711             :   Factory* factory = isolate->factory();
    2712             :   ExpectedSnippet<0> snippets[] = {
    2713             :       {"var a = do {}; return a;", {factory->undefined_value()}},
    2714             :       {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
    2715             :       {"var a = do { var x = 100; }; return a;", {factory->undefined_value()}},
    2716             :       {"var a = do { var x = 100; x++; }; return a;",
    2717             :        {handle(Smi::FromInt(100), isolate)}},
    2718             :       {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
    2719             :        "return i;",
    2720             :        {handle(Smi::FromInt(3), isolate)}},
    2721          30 :   };
    2722             : 
    2723          36 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2724             :     ScopedVector<char> script(1024);
    2725             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2726          30 :              snippets[i].code_snippet, kFunctionName);
    2727             : 
    2728             :     BytecodeGraphTester tester(isolate, script.start());
    2729             :     auto callable = tester.GetCallable<>();
    2730          60 :     Handle<Object> return_value = callable().ToHandleChecked();
    2731          60 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2732             :   }
    2733             : 
    2734           6 :   FLAG_harmony_do_expressions = old_flag;
    2735           6 : }
    2736             : 
    2737       23724 : TEST(BytecodeGraphBuilderWithStatement) {
    2738           6 :   HandleAndZoneScope scope;
    2739           6 :   Isolate* isolate = scope.main_isolate();
    2740             : 
    2741             :   ExpectedSnippet<0> snippets[] = {
    2742             :       {"with({x:42}) return x;", {handle(Smi::FromInt(42), isolate)}},
    2743             :       {"with({}) { var y = 10; return y;}",
    2744             :        {handle(Smi::FromInt(10), isolate)}},
    2745             :       {"var y = {x:42};"
    2746             :        " function inner() {"
    2747             :        "   var x = 20;"
    2748             :        "   with(y) return x;"
    2749             :        "}"
    2750             :        "return inner();",
    2751             :        {handle(Smi::FromInt(42), isolate)}},
    2752             :       {"var y = {x:42};"
    2753             :        " function inner(o) {"
    2754             :        "   var x = 20;"
    2755             :        "   with(o) return x;"
    2756             :        "}"
    2757             :        "return inner(y);",
    2758             :        {handle(Smi::FromInt(42), isolate)}},
    2759          24 :   };
    2760             : 
    2761          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2762             :     ScopedVector<char> script(1024);
    2763             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2764          24 :              snippets[i].code_snippet, kFunctionName);
    2765             : 
    2766             :     BytecodeGraphTester tester(isolate, script.start());
    2767             :     auto callable = tester.GetCallable<>();
    2768          48 :     Handle<Object> return_value = callable().ToHandleChecked();
    2769          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2770           6 :   }
    2771           6 : }
    2772             : 
    2773       23724 : TEST(BytecodeGraphBuilderConstDeclaration) {
    2774           6 :   HandleAndZoneScope scope;
    2775           6 :   Isolate* isolate = scope.main_isolate();
    2776             :   Factory* factory = isolate->factory();
    2777             : 
    2778             :   ExpectedSnippet<0> snippets[] = {
    2779             :       {"const x = 3; return x;", {handle(Smi::FromInt(3), isolate)}},
    2780             :       {"let x = 10; x = x + 20; return x;",
    2781             :        {handle(Smi::FromInt(30), isolate)}},
    2782             :       {"let x = 10; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
    2783             :       {"let x; x = 20; return x;", {handle(Smi::FromInt(20), isolate)}},
    2784             :       {"let x; return x;", {factory->undefined_value()}},
    2785             :       {"var x = 10; { let x = 30; } return x;",
    2786             :        {handle(Smi::FromInt(10), isolate)}},
    2787             :       {"let x = 10; { let x = 20; } return x;",
    2788             :        {handle(Smi::FromInt(10), isolate)}},
    2789             :       {"var x = 10; eval('let x = 20;'); return x;",
    2790             :        {handle(Smi::FromInt(10), isolate)}},
    2791             :       {"var x = 10; eval('const x = 20;'); return x;",
    2792             :        {handle(Smi::FromInt(10), isolate)}},
    2793             :       {"var x = 10; { const x = 20; } return x;",
    2794             :        {handle(Smi::FromInt(10), isolate)}},
    2795             :       {"var x = 10; { const x = 20; return x;} return -1;",
    2796             :        {handle(Smi::FromInt(20), isolate)}},
    2797             :       {"var a = 10;\n"
    2798             :        "for (var i = 0; i < 10; ++i) {\n"
    2799             :        " const x = i;\n"  // const declarations are block scoped.
    2800             :        " a = a + x;\n"
    2801             :        "}\n"
    2802             :        "return a;\n",
    2803             :        {handle(Smi::FromInt(55), isolate)}},
    2804          72 :   };
    2805             : 
    2806             :   // Tests for sloppy mode.
    2807          78 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2808             :     ScopedVector<char> script(1024);
    2809             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2810          72 :              snippets[i].code_snippet, kFunctionName);
    2811             : 
    2812             :     BytecodeGraphTester tester(isolate, script.start());
    2813             :     auto callable = tester.GetCallable<>();
    2814         144 :     Handle<Object> return_value = callable().ToHandleChecked();
    2815         144 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2816             :   }
    2817             : 
    2818             :   // Tests for strict mode.
    2819          72 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2820             :     ScopedVector<char> script(1024);
    2821             :     SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
    2822          72 :              snippets[i].code_snippet, kFunctionName);
    2823             : 
    2824             :     BytecodeGraphTester tester(isolate, script.start());
    2825             :     auto callable = tester.GetCallable<>();
    2826         144 :     Handle<Object> return_value = callable().ToHandleChecked();
    2827         144 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2828           6 :   }
    2829           6 : }
    2830             : 
    2831       23724 : TEST(BytecodeGraphBuilderConstDeclarationLookupSlots) {
    2832           6 :   HandleAndZoneScope scope;
    2833           6 :   Isolate* isolate = scope.main_isolate();
    2834             :   Factory* factory = isolate->factory();
    2835             : 
    2836             :   ExpectedSnippet<0> snippets[] = {
    2837             :       {"const x = 3; function f1() {return x;}; return x;",
    2838             :        {handle(Smi::FromInt(3), isolate)}},
    2839             :       {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
    2840             :        {handle(Smi::FromInt(30), isolate)}},
    2841             :       {"let x; x = 20; function f1() {return x;}; return x;",
    2842             :        {handle(Smi::FromInt(20), isolate)}},
    2843             :       {"let x; function f1() {return x;}; return x;",
    2844             :        {factory->undefined_value()}},
    2845          24 :   };
    2846             : 
    2847             :   // Tests for sloppy mode.
    2848          30 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2849             :     ScopedVector<char> script(1024);
    2850             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2851          24 :              snippets[i].code_snippet, kFunctionName);
    2852             : 
    2853             :     BytecodeGraphTester tester(isolate, script.start());
    2854             :     auto callable = tester.GetCallable<>();
    2855          48 :     Handle<Object> return_value = callable().ToHandleChecked();
    2856          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2857             :   }
    2858             : 
    2859             :   // Tests for strict mode.
    2860          24 :   for (size_t i = 0; i < arraysize(snippets); i++) {
    2861             :     ScopedVector<char> script(1024);
    2862             :     SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
    2863          24 :              snippets[i].code_snippet, kFunctionName);
    2864             : 
    2865             :     BytecodeGraphTester tester(isolate, script.start());
    2866             :     auto callable = tester.GetCallable<>();
    2867          48 :     Handle<Object> return_value = callable().ToHandleChecked();
    2868          48 :     CHECK(return_value->SameValue(*snippets[i].return_value()));
    2869           6 :   }
    2870           6 : }
    2871             : 
    2872       23724 : TEST(BytecodeGraphBuilderConstInLookupContextChain) {
    2873           6 :   HandleAndZoneScope scope;
    2874           6 :   Isolate* isolate = scope.main_isolate();
    2875             : 
    2876             :   const char* prologue =
    2877             :       "function OuterMost() {\n"
    2878             :       "  const outerConst = 10;\n"
    2879             :       "  let outerLet = 20;\n"
    2880             :       "  function Outer() {\n"
    2881             :       "    function Inner() {\n"
    2882             :       "      this.innerFunc = function() { ";
    2883             :   const char* epilogue =
    2884             :       "      }\n"
    2885             :       "    }\n"
    2886             :       "    this.getInnerFunc ="
    2887             :       "         function() {return new Inner().innerFunc;}\n"
    2888             :       "  }\n"
    2889             :       "  this.getOuterFunc ="
    2890             :       "     function() {return new Outer().getInnerFunc();}"
    2891             :       "}\n"
    2892             :       "var f = new OuterMost().getOuterFunc();\n"
    2893             :       "f();\n";
    2894             : 
    2895             :   // Tests for let / constant.
    2896             :   ExpectedSnippet<0> const_decl[] = {
    2897             :       {"return outerConst;", {handle(Smi::FromInt(10), isolate)}},
    2898             :       {"return outerLet;", {handle(Smi::FromInt(20), isolate)}},
    2899             :       {"outerLet = 30; return outerLet;", {handle(Smi::FromInt(30), isolate)}},
    2900             :       {"var outerLet = 40; return outerLet;",
    2901             :        {handle(Smi::FromInt(40), isolate)}},
    2902             :       {"var outerConst = 50; return outerConst;",
    2903             :        {handle(Smi::FromInt(50), isolate)}},
    2904             :       {"try { outerConst = 30 } catch(e) { return -1; }",
    2905          36 :        {handle(Smi::FromInt(-1), isolate)}}};
    2906             : 
    2907          42 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    2908             :     ScopedVector<char> script(1024);
    2909             :     SNPrintF(script, "%s %s %s", prologue, const_decl[i].code_snippet,
    2910          36 :              epilogue);
    2911             : 
    2912             :     BytecodeGraphTester tester(isolate, script.start(), "*");
    2913             :     auto callable = tester.GetCallable<>();
    2914          72 :     Handle<Object> return_value = callable().ToHandleChecked();
    2915          72 :     CHECK(return_value->SameValue(*const_decl[i].return_value()));
    2916           6 :   }
    2917           6 : }
    2918             : 
    2919       23724 : TEST(BytecodeGraphBuilderIllegalConstDeclaration) {
    2920           6 :   HandleAndZoneScope scope;
    2921           6 :   Isolate* isolate = scope.main_isolate();
    2922             : 
    2923             :   ExpectedSnippet<0, const char*> illegal_const_decl[] = {
    2924             :       {"const x = x = 10 + 3; return x;",
    2925             :        {"Uncaught ReferenceError: x is not defined"}},
    2926             :       {"const x = 10; x = 20; return x;",
    2927             :        {"Uncaught TypeError: Assignment to constant variable."}},
    2928             :       {"const x = 10; { x = 20; } return x;",
    2929             :        {"Uncaught TypeError: Assignment to constant variable."}},
    2930             :       {"const x = 10; eval('x = 20;'); return x;",
    2931             :        {"Uncaught TypeError: Assignment to constant variable."}},
    2932             :       {"let x = x + 10; return x;",
    2933             :        {"Uncaught ReferenceError: x is not defined"}},
    2934             :       {"'use strict'; (function f1() { f1 = 123; })() ",
    2935             :        {"Uncaught TypeError: Assignment to constant variable."}},
    2936           6 :   };
    2937             : 
    2938             :   // Tests for sloppy mode.
    2939          42 :   for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
    2940             :     ScopedVector<char> script(1024);
    2941             :     SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName,
    2942          36 :              illegal_const_decl[i].code_snippet, kFunctionName);
    2943             : 
    2944             :     BytecodeGraphTester tester(isolate, script.start());
    2945          72 :     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
    2946             :     v8::Local<v8::String> expected_string =
    2947          36 :         v8_str(illegal_const_decl[i].return_value());
    2948         108 :     CHECK(
    2949             :         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
    2950             :             .FromJust());
    2951             :   }
    2952             : 
    2953             :   // Tests for strict mode.
    2954          36 :   for (size_t i = 0; i < arraysize(illegal_const_decl); i++) {
    2955             :     ScopedVector<char> script(1024);
    2956             :     SNPrintF(script, "function %s() {'use strict'; %s }\n%s();", kFunctionName,
    2957          36 :              illegal_const_decl[i].code_snippet, kFunctionName);
    2958             : 
    2959             :     BytecodeGraphTester tester(isolate, script.start());
    2960          72 :     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
    2961             :     v8::Local<v8::String> expected_string =
    2962          36 :         v8_str(illegal_const_decl[i].return_value());
    2963         108 :     CHECK(
    2964             :         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
    2965             :             .FromJust());
    2966           6 :   }
    2967           6 : }
    2968             : 
    2969           0 : class CountBreakDebugDelegate : public v8::debug::DebugDelegate {
    2970             :  public:
    2971          12 :   void BreakProgramRequested(v8::Local<v8::Context> paused_context,
    2972             :                              v8::Local<v8::Object> exec_state,
    2973             :                              v8::Local<v8::Value> break_points_hit,
    2974             :                              const std::vector<int>&) override {
    2975          12 :     debug_break_count++;
    2976          12 :   }
    2977             :   int debug_break_count = 0;
    2978             : };
    2979             : 
    2980       23724 : TEST(BytecodeGraphBuilderDebuggerStatement) {
    2981           6 :   CountBreakDebugDelegate delegate;
    2982          12 :   HandleAndZoneScope scope;
    2983           6 :   Isolate* isolate = scope.main_isolate();
    2984             : 
    2985           6 :   v8::debug::SetDebugDelegate(CcTest::isolate(), &delegate);
    2986             : 
    2987             :   ExpectedSnippet<0> snippet = {
    2988             :       "function f() {"
    2989             :       "  debugger;"
    2990             :       "}"
    2991             :       "f();",
    2992             :       {isolate->factory()->undefined_value()}};
    2993             : 
    2994             :   BytecodeGraphTester tester(isolate, snippet.code_snippet);
    2995             :   auto callable = tester.GetCallable<>();
    2996          12 :   Handle<Object> return_value = callable().ToHandleChecked();
    2997             : 
    2998           6 :   v8::debug::SetDebugDelegate(CcTest::isolate(), nullptr);
    2999           6 :   CHECK(return_value.is_identical_to(snippet.return_value()));
    3000           6 :   CHECK_EQ(2, delegate.debug_break_count);
    3001           6 : }
    3002             : 
    3003             : #undef SHARD_TEST_BY_2
    3004             : #undef SHARD_TEST_BY_4
    3005             : #undef SPACE
    3006             : #undef REPEAT_2
    3007             : #undef REPEAT_4
    3008             : #undef REPEAT_8
    3009             : #undef REPEAT_16
    3010             : #undef REPEAT_32
    3011             : #undef REPEAT_64
    3012             : #undef REPEAT_128
    3013             : #undef REPEAT_256
    3014             : #undef REPEAT_127
    3015             : 
    3016             : }  // namespace compiler
    3017             : }  // namespace internal
    3018       71154 : }  // namespace v8

Generated by: LCOV version 1.10