Home | History | Annotate | Download | only in interpreter
      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 "src/v8.h"
      6 
      7 #include "src/execution.h"
      8 #include "src/handles.h"
      9 #include "src/interpreter/bytecode-array-builder.h"
     10 #include "src/interpreter/bytecode-array-iterator.h"
     11 #include "src/interpreter/bytecode-label.h"
     12 #include "src/interpreter/interpreter.h"
     13 #include "test/cctest/cctest.h"
     14 #include "test/cctest/interpreter/interpreter-tester.h"
     15 #include "test/cctest/test-feedback-vector.h"
     16 
     17 namespace v8 {
     18 namespace internal {
     19 namespace interpreter {
     20 
     21 
     22 TEST(InterpreterReturn) {
     23   HandleAndZoneScope handles;
     24   Handle<Object> undefined_value =
     25       handles.main_isolate()->factory()->undefined_value();
     26 
     27   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
     28                                0, 0);
     29   builder.Return();
     30   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
     31 
     32   InterpreterTester tester(handles.main_isolate(), bytecode_array);
     33   auto callable = tester.GetCallable<>();
     34   Handle<Object> return_val = callable().ToHandleChecked();
     35   CHECK(return_val.is_identical_to(undefined_value));
     36 }
     37 
     38 
     39 TEST(InterpreterLoadUndefined) {
     40   HandleAndZoneScope handles;
     41   Handle<Object> undefined_value =
     42       handles.main_isolate()->factory()->undefined_value();
     43 
     44   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
     45                                0, 0);
     46   builder.LoadUndefined().Return();
     47   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
     48 
     49   InterpreterTester tester(handles.main_isolate(), bytecode_array);
     50   auto callable = tester.GetCallable<>();
     51   Handle<Object> return_val = callable().ToHandleChecked();
     52   CHECK(return_val.is_identical_to(undefined_value));
     53 }
     54 
     55 
     56 TEST(InterpreterLoadNull) {
     57   HandleAndZoneScope handles;
     58   Handle<Object> null_value = handles.main_isolate()->factory()->null_value();
     59 
     60   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
     61                                0, 0);
     62   builder.LoadNull().Return();
     63   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
     64 
     65   InterpreterTester tester(handles.main_isolate(), bytecode_array);
     66   auto callable = tester.GetCallable<>();
     67   Handle<Object> return_val = callable().ToHandleChecked();
     68   CHECK(return_val.is_identical_to(null_value));
     69 }
     70 
     71 
     72 TEST(InterpreterLoadTheHole) {
     73   HandleAndZoneScope handles;
     74   Handle<Object> the_hole_value =
     75       handles.main_isolate()->factory()->the_hole_value();
     76 
     77   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
     78                                0, 0);
     79   builder.LoadTheHole().Return();
     80   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
     81 
     82   InterpreterTester tester(handles.main_isolate(), bytecode_array);
     83   auto callable = tester.GetCallable<>();
     84   Handle<Object> return_val = callable().ToHandleChecked();
     85   CHECK(return_val.is_identical_to(the_hole_value));
     86 }
     87 
     88 
     89 TEST(InterpreterLoadTrue) {
     90   HandleAndZoneScope handles;
     91   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
     92 
     93   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
     94                                0, 0);
     95   builder.LoadTrue().Return();
     96   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
     97 
     98   InterpreterTester tester(handles.main_isolate(), bytecode_array);
     99   auto callable = tester.GetCallable<>();
    100   Handle<Object> return_val = callable().ToHandleChecked();
    101   CHECK(return_val.is_identical_to(true_value));
    102 }
    103 
    104 
    105 TEST(InterpreterLoadFalse) {
    106   HandleAndZoneScope handles;
    107   Handle<Object> false_value = handles.main_isolate()->factory()->false_value();
    108 
    109   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    110                                0, 0);
    111   builder.LoadFalse().Return();
    112   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    113 
    114   InterpreterTester tester(handles.main_isolate(), bytecode_array);
    115   auto callable = tester.GetCallable<>();
    116   Handle<Object> return_val = callable().ToHandleChecked();
    117   CHECK(return_val.is_identical_to(false_value));
    118 }
    119 
    120 
    121 TEST(InterpreterLoadLiteral) {
    122   HandleAndZoneScope handles;
    123   i::Factory* factory = handles.main_isolate()->factory();
    124 
    125   // Small Smis.
    126   for (int i = -128; i < 128; i++) {
    127     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    128                                  0, 0);
    129     builder.LoadLiteral(Smi::FromInt(i)).Return();
    130     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    131 
    132     InterpreterTester tester(handles.main_isolate(), bytecode_array);
    133     auto callable = tester.GetCallable<>();
    134     Handle<Object> return_val = callable().ToHandleChecked();
    135     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(i));
    136   }
    137 
    138   // Large Smis.
    139   {
    140     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    141                                  0, 0);
    142 
    143     builder.LoadLiteral(Smi::FromInt(0x12345678)).Return();
    144     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    145 
    146     InterpreterTester tester(handles.main_isolate(), bytecode_array);
    147     auto callable = tester.GetCallable<>();
    148     Handle<Object> return_val = callable().ToHandleChecked();
    149     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x12345678));
    150   }
    151 
    152   // Heap numbers.
    153   {
    154     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    155                                  0, 0);
    156 
    157     builder.LoadLiteral(factory->NewHeapNumber(-2.1e19)).Return();
    158     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    159 
    160     InterpreterTester tester(handles.main_isolate(), bytecode_array);
    161     auto callable = tester.GetCallable<>();
    162     Handle<Object> return_val = callable().ToHandleChecked();
    163     CHECK_EQ(i::HeapNumber::cast(*return_val)->value(), -2.1e19);
    164   }
    165 
    166   // Strings.
    167   {
    168     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    169                                  0, 0);
    170 
    171     Handle<i::String> string = factory->NewStringFromAsciiChecked("String");
    172     builder.LoadLiteral(string).Return();
    173     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    174 
    175     InterpreterTester tester(handles.main_isolate(), bytecode_array);
    176     auto callable = tester.GetCallable<>();
    177     Handle<Object> return_val = callable().ToHandleChecked();
    178     CHECK(i::String::cast(*return_val)->Equals(*string));
    179   }
    180 }
    181 
    182 
    183 TEST(InterpreterLoadStoreRegisters) {
    184   HandleAndZoneScope handles;
    185   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
    186   for (int i = 0; i <= kMaxInt8; i++) {
    187     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    188                                  0, i + 1);
    189 
    190     Register reg(i);
    191     builder.LoadTrue()
    192         .StoreAccumulatorInRegister(reg)
    193         .LoadFalse()
    194         .LoadAccumulatorWithRegister(reg)
    195         .Return();
    196     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    197 
    198     InterpreterTester tester(handles.main_isolate(), bytecode_array);
    199     auto callable = tester.GetCallable<>();
    200     Handle<Object> return_val = callable().ToHandleChecked();
    201     CHECK(return_val.is_identical_to(true_value));
    202   }
    203 }
    204 
    205 
    206 static const Token::Value kShiftOperators[] = {
    207     Token::Value::SHL, Token::Value::SAR, Token::Value::SHR};
    208 
    209 
    210 static const Token::Value kArithmeticOperators[] = {
    211     Token::Value::BIT_OR, Token::Value::BIT_XOR, Token::Value::BIT_AND,
    212     Token::Value::SHL,    Token::Value::SAR,     Token::Value::SHR,
    213     Token::Value::ADD,    Token::Value::SUB,     Token::Value::MUL,
    214     Token::Value::DIV,    Token::Value::MOD};
    215 
    216 
    217 static double BinaryOpC(Token::Value op, double lhs, double rhs) {
    218   switch (op) {
    219     case Token::Value::ADD:
    220       return lhs + rhs;
    221     case Token::Value::SUB:
    222       return lhs - rhs;
    223     case Token::Value::MUL:
    224       return lhs * rhs;
    225     case Token::Value::DIV:
    226       return lhs / rhs;
    227     case Token::Value::MOD:
    228       return std::fmod(lhs, rhs);
    229     case Token::Value::BIT_OR:
    230       return (v8::internal::DoubleToInt32(lhs) |
    231               v8::internal::DoubleToInt32(rhs));
    232     case Token::Value::BIT_XOR:
    233       return (v8::internal::DoubleToInt32(lhs) ^
    234               v8::internal::DoubleToInt32(rhs));
    235     case Token::Value::BIT_AND:
    236       return (v8::internal::DoubleToInt32(lhs) &
    237               v8::internal::DoubleToInt32(rhs));
    238     case Token::Value::SHL: {
    239       int32_t val = v8::internal::DoubleToInt32(lhs);
    240       uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F;
    241       int32_t result = val << count;
    242       return result;
    243     }
    244     case Token::Value::SAR: {
    245       int32_t val = v8::internal::DoubleToInt32(lhs);
    246       uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F;
    247       int32_t result = val >> count;
    248       return result;
    249     }
    250     case Token::Value::SHR: {
    251       uint32_t val = v8::internal::DoubleToUint32(lhs);
    252       uint32_t count = v8::internal::DoubleToUint32(rhs) & 0x1F;
    253       uint32_t result = val >> count;
    254       return result;
    255     }
    256     default:
    257       UNREACHABLE();
    258       return std::numeric_limits<double>::min();
    259   }
    260 }
    261 
    262 
    263 TEST(InterpreterShiftOpsSmi) {
    264   int lhs_inputs[] = {0, -17, -182, 1073741823, -1};
    265   int rhs_inputs[] = {5, 2, 1, -1, -2, 0, 31, 32, -32, 64, 37};
    266   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
    267     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
    268       for (size_t o = 0; o < arraysize(kShiftOperators); o++) {
    269         HandleAndZoneScope handles;
    270         i::Factory* factory = handles.main_isolate()->factory();
    271         BytecodeArrayBuilder builder(handles.main_isolate(),
    272                                      handles.main_zone(), 1, 0, 1);
    273         Register reg(0);
    274         int lhs = lhs_inputs[l];
    275         int rhs = rhs_inputs[r];
    276         builder.LoadLiteral(Smi::FromInt(lhs))
    277             .StoreAccumulatorInRegister(reg)
    278             .LoadLiteral(Smi::FromInt(rhs))
    279             .BinaryOperation(kShiftOperators[o], reg)
    280             .Return();
    281         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    282 
    283         InterpreterTester tester(handles.main_isolate(), bytecode_array);
    284         auto callable = tester.GetCallable<>();
    285         Handle<Object> return_value = callable().ToHandleChecked();
    286         Handle<Object> expected_value =
    287             factory->NewNumber(BinaryOpC(kShiftOperators[o], lhs, rhs));
    288         CHECK(return_value->SameValue(*expected_value));
    289       }
    290     }
    291   }
    292 }
    293 
    294 
    295 TEST(InterpreterBinaryOpsSmi) {
    296   int lhs_inputs[] = {3266, 1024, 0, -17, -18000};
    297   int rhs_inputs[] = {3266, 5, 4, 3, 2, 1, -1, -2};
    298   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
    299     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
    300       for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
    301         HandleAndZoneScope handles;
    302         i::Factory* factory = handles.main_isolate()->factory();
    303         BytecodeArrayBuilder builder(handles.main_isolate(),
    304                                      handles.main_zone(), 1, 0, 1);
    305 
    306         Register reg(0);
    307         int lhs = lhs_inputs[l];
    308         int rhs = rhs_inputs[r];
    309         builder.LoadLiteral(Smi::FromInt(lhs))
    310             .StoreAccumulatorInRegister(reg)
    311             .LoadLiteral(Smi::FromInt(rhs))
    312             .BinaryOperation(kArithmeticOperators[o], reg)
    313             .Return();
    314         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    315 
    316         InterpreterTester tester(handles.main_isolate(), bytecode_array);
    317         auto callable = tester.GetCallable<>();
    318         Handle<Object> return_value = callable().ToHandleChecked();
    319         Handle<Object> expected_value =
    320             factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
    321         CHECK(return_value->SameValue(*expected_value));
    322       }
    323     }
    324   }
    325 }
    326 
    327 
    328 TEST(InterpreterBinaryOpsHeapNumber) {
    329   double lhs_inputs[] = {3266.101, 1024.12, 0.01, -17.99, -18000.833, 9.1e17};
    330   double rhs_inputs[] = {3266.101, 5.999, 4.778, 3.331,  2.643,
    331                          1.1,      -1.8,  -2.9,  8.3e-27};
    332   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
    333     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
    334       for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
    335         HandleAndZoneScope handles;
    336         i::Factory* factory = handles.main_isolate()->factory();
    337         BytecodeArrayBuilder builder(handles.main_isolate(),
    338                                      handles.main_zone(), 1, 0, 1);
    339         Register reg(0);
    340         double lhs = lhs_inputs[l];
    341         double rhs = rhs_inputs[r];
    342         builder.LoadLiteral(factory->NewNumber(lhs))
    343             .StoreAccumulatorInRegister(reg)
    344             .LoadLiteral(factory->NewNumber(rhs))
    345             .BinaryOperation(kArithmeticOperators[o], reg)
    346             .Return();
    347         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    348 
    349         InterpreterTester tester(handles.main_isolate(), bytecode_array);
    350         auto callable = tester.GetCallable<>();
    351         Handle<Object> return_value = callable().ToHandleChecked();
    352         Handle<Object> expected_value =
    353             factory->NewNumber(BinaryOpC(kArithmeticOperators[o], lhs, rhs));
    354         CHECK(return_value->SameValue(*expected_value));
    355       }
    356     }
    357   }
    358 }
    359 
    360 
    361 TEST(InterpreterStringAdd) {
    362   HandleAndZoneScope handles;
    363   i::Factory* factory = handles.main_isolate()->factory();
    364 
    365   struct TestCase {
    366     Handle<Object> lhs;
    367     Handle<Object> rhs;
    368     Handle<Object> expected_value;
    369   } test_cases[] = {
    370       {factory->NewStringFromStaticChars("a"),
    371        factory->NewStringFromStaticChars("b"),
    372        factory->NewStringFromStaticChars("ab")},
    373       {factory->NewStringFromStaticChars("aaaaaa"),
    374        factory->NewStringFromStaticChars("b"),
    375        factory->NewStringFromStaticChars("aaaaaab")},
    376       {factory->NewStringFromStaticChars("aaa"),
    377        factory->NewStringFromStaticChars("bbbbb"),
    378        factory->NewStringFromStaticChars("aaabbbbb")},
    379       {factory->NewStringFromStaticChars(""),
    380        factory->NewStringFromStaticChars("b"),
    381        factory->NewStringFromStaticChars("b")},
    382       {factory->NewStringFromStaticChars("a"),
    383        factory->NewStringFromStaticChars(""),
    384        factory->NewStringFromStaticChars("a")},
    385       {factory->NewStringFromStaticChars("1.11"), factory->NewHeapNumber(2.5),
    386        factory->NewStringFromStaticChars("1.112.5")},
    387       {factory->NewStringFromStaticChars("-1.11"), factory->NewHeapNumber(2.56),
    388        factory->NewStringFromStaticChars("-1.112.56")},
    389       {factory->NewStringFromStaticChars(""), factory->NewHeapNumber(2.5),
    390        factory->NewStringFromStaticChars("2.5")},
    391   };
    392 
    393   for (size_t i = 0; i < arraysize(test_cases); i++) {
    394     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    395                                  0, 1);
    396 
    397     Register reg(0);
    398     builder.LoadLiteral(test_cases[i].lhs)
    399         .StoreAccumulatorInRegister(reg)
    400         .LoadLiteral(test_cases[i].rhs)
    401         .BinaryOperation(Token::Value::ADD, reg)
    402         .Return();
    403     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    404 
    405     InterpreterTester tester(handles.main_isolate(), bytecode_array);
    406     auto callable = tester.GetCallable<>();
    407     Handle<Object> return_value = callable().ToHandleChecked();
    408     CHECK(return_value->SameValue(*test_cases[i].expected_value));
    409   }
    410 }
    411 
    412 
    413 TEST(InterpreterParameter1) {
    414   HandleAndZoneScope handles;
    415   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    416                                0, 0);
    417 
    418   builder.LoadAccumulatorWithRegister(builder.Parameter(0)).Return();
    419   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    420 
    421   InterpreterTester tester(handles.main_isolate(), bytecode_array);
    422   auto callable = tester.GetCallable<Handle<Object>>();
    423 
    424   // Check for heap objects.
    425   Handle<Object> true_value = handles.main_isolate()->factory()->true_value();
    426   Handle<Object> return_val = callable(true_value).ToHandleChecked();
    427   CHECK(return_val.is_identical_to(true_value));
    428 
    429   // Check for Smis.
    430   return_val = callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
    431                    .ToHandleChecked();
    432   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
    433 }
    434 
    435 
    436 TEST(InterpreterParameter8) {
    437   HandleAndZoneScope handles;
    438   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 8,
    439                                0, 0);
    440 
    441   builder.LoadAccumulatorWithRegister(builder.Parameter(0))
    442       .BinaryOperation(Token::Value::ADD, builder.Parameter(1))
    443       .BinaryOperation(Token::Value::ADD, builder.Parameter(2))
    444       .BinaryOperation(Token::Value::ADD, builder.Parameter(3))
    445       .BinaryOperation(Token::Value::ADD, builder.Parameter(4))
    446       .BinaryOperation(Token::Value::ADD, builder.Parameter(5))
    447       .BinaryOperation(Token::Value::ADD, builder.Parameter(6))
    448       .BinaryOperation(Token::Value::ADD, builder.Parameter(7))
    449       .Return();
    450   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    451 
    452   InterpreterTester tester(handles.main_isolate(), bytecode_array);
    453   typedef Handle<Object> H;
    454   auto callable = tester.GetCallable<H, H, H, H, H, H, H, H>();
    455 
    456   Handle<Smi> arg1 = Handle<Smi>(Smi::FromInt(1), handles.main_isolate());
    457   Handle<Smi> arg2 = Handle<Smi>(Smi::FromInt(2), handles.main_isolate());
    458   Handle<Smi> arg3 = Handle<Smi>(Smi::FromInt(3), handles.main_isolate());
    459   Handle<Smi> arg4 = Handle<Smi>(Smi::FromInt(4), handles.main_isolate());
    460   Handle<Smi> arg5 = Handle<Smi>(Smi::FromInt(5), handles.main_isolate());
    461   Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate());
    462   Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate());
    463   Handle<Smi> arg8 = Handle<Smi>(Smi::FromInt(8), handles.main_isolate());
    464   // Check for Smis.
    465   Handle<Object> return_val =
    466       callable(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8)
    467           .ToHandleChecked();
    468   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36));
    469 }
    470 
    471 
    472 TEST(InterpreterParameter1Assign) {
    473   HandleAndZoneScope handles;
    474   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    475                                0, 0);
    476 
    477   builder.LoadLiteral(Smi::FromInt(5))
    478       .StoreAccumulatorInRegister(builder.Parameter(0))
    479       .LoadAccumulatorWithRegister(builder.Parameter(0))
    480       .Return();
    481   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    482 
    483   InterpreterTester tester(handles.main_isolate(), bytecode_array);
    484   auto callable = tester.GetCallable<Handle<Object>>();
    485 
    486   Handle<Object> return_val =
    487       callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
    488           .ToHandleChecked();
    489   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
    490 }
    491 
    492 
    493 TEST(InterpreterLoadGlobal) {
    494   HandleAndZoneScope handles;
    495 
    496   // Test loading a global.
    497   std::string source(
    498       "var global = 321;\n"
    499       "function " + InterpreterTester::function_name() + "() {\n"
    500       "  return global;\n"
    501       "}");
    502   InterpreterTester tester(handles.main_isolate(), source.c_str());
    503   auto callable = tester.GetCallable<>();
    504 
    505   Handle<Object> return_val = callable().ToHandleChecked();
    506   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(321));
    507 }
    508 
    509 
    510 TEST(InterpreterStoreGlobal) {
    511   HandleAndZoneScope handles;
    512   i::Isolate* isolate = handles.main_isolate();
    513   i::Factory* factory = isolate->factory();
    514 
    515   // Test storing to a global.
    516   std::string source(
    517       "var global = 321;\n"
    518       "function " + InterpreterTester::function_name() + "() {\n"
    519       "  global = 999;\n"
    520       "}");
    521   InterpreterTester tester(handles.main_isolate(), source.c_str());
    522   auto callable = tester.GetCallable<>();
    523 
    524   callable().ToHandleChecked();
    525   Handle<i::String> name = factory->InternalizeUtf8String("global");
    526   Handle<i::Object> global_obj =
    527       Object::GetProperty(isolate->global_object(), name).ToHandleChecked();
    528   CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999));
    529 }
    530 
    531 
    532 TEST(InterpreterCallGlobal) {
    533   HandleAndZoneScope handles;
    534 
    535   // Test calling a global function.
    536   std::string source(
    537       "function g_add(a, b) { return a + b; }\n"
    538       "function " + InterpreterTester::function_name() + "() {\n"
    539       "  return g_add(5, 10);\n"
    540       "}");
    541   InterpreterTester tester(handles.main_isolate(), source.c_str());
    542   auto callable = tester.GetCallable<>();
    543 
    544   Handle<Object> return_val = callable().ToHandleChecked();
    545   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
    546 }
    547 
    548 
    549 TEST(InterpreterLoadUnallocated) {
    550   HandleAndZoneScope handles;
    551 
    552   // Test loading an unallocated global.
    553   std::string source(
    554       "unallocated = 123;\n"
    555       "function " + InterpreterTester::function_name() + "() {\n"
    556       "  return unallocated;\n"
    557       "}");
    558   InterpreterTester tester(handles.main_isolate(), source.c_str());
    559   auto callable = tester.GetCallable<>();
    560 
    561   Handle<Object> return_val = callable().ToHandleChecked();
    562   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    563 }
    564 
    565 
    566 TEST(InterpreterStoreUnallocated) {
    567   HandleAndZoneScope handles;
    568   i::Isolate* isolate = handles.main_isolate();
    569   i::Factory* factory = isolate->factory();
    570 
    571   // Test storing to an unallocated global.
    572   std::string source(
    573       "unallocated = 321;\n"
    574       "function " + InterpreterTester::function_name() + "() {\n"
    575       "  unallocated = 999;\n"
    576       "}");
    577   InterpreterTester tester(handles.main_isolate(), source.c_str());
    578   auto callable = tester.GetCallable<>();
    579 
    580   callable().ToHandleChecked();
    581   Handle<i::String> name = factory->InternalizeUtf8String("unallocated");
    582   Handle<i::Object> global_obj =
    583       Object::GetProperty(isolate->global_object(), name).ToHandleChecked();
    584   CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999));
    585 }
    586 
    587 
    588 TEST(InterpreterLoadNamedProperty) {
    589   HandleAndZoneScope handles;
    590   i::Isolate* isolate = handles.main_isolate();
    591   i::Factory* factory = isolate->factory();
    592   i::Zone zone(isolate->allocator());
    593 
    594   i::FeedbackVectorSpec feedback_spec(&zone);
    595   i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
    596 
    597   Handle<i::TypeFeedbackVector> vector =
    598       i::NewTypeFeedbackVector(isolate, &feedback_spec);
    599 
    600   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
    601   name = factory->string_table()->LookupString(isolate, name);
    602 
    603   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    604                                0, 0);
    605 
    606   builder.LoadNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot))
    607       .Return();
    608   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    609 
    610   InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
    611   auto callable = tester.GetCallable<Handle<Object>>();
    612 
    613   Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })");
    614   // Test IC miss.
    615   Handle<Object> return_val = callable(object).ToHandleChecked();
    616   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    617 
    618   // Test transition to monomorphic IC.
    619   return_val = callable(object).ToHandleChecked();
    620   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    621 
    622   // Test transition to polymorphic IC.
    623   Handle<Object> object2 =
    624       InterpreterTester::NewObject("({ val : 456, other : 123 })");
    625   return_val = callable(object2).ToHandleChecked();
    626   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(456));
    627 
    628   // Test transition to megamorphic IC.
    629   Handle<Object> object3 =
    630       InterpreterTester::NewObject("({ val : 789, val2 : 123 })");
    631   callable(object3).ToHandleChecked();
    632   Handle<Object> object4 =
    633       InterpreterTester::NewObject("({ val : 789, val3 : 123 })");
    634   callable(object4).ToHandleChecked();
    635   Handle<Object> object5 =
    636       InterpreterTester::NewObject("({ val : 789, val4 : 123 })");
    637   return_val = callable(object5).ToHandleChecked();
    638   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789));
    639 }
    640 
    641 
    642 TEST(InterpreterLoadKeyedProperty) {
    643   HandleAndZoneScope handles;
    644   i::Isolate* isolate = handles.main_isolate();
    645   i::Factory* factory = isolate->factory();
    646   i::Zone zone(isolate->allocator());
    647 
    648   i::FeedbackVectorSpec feedback_spec(&zone);
    649   i::FeedbackVectorSlot slot = feedback_spec.AddKeyedLoadICSlot();
    650 
    651   Handle<i::TypeFeedbackVector> vector =
    652       i::NewTypeFeedbackVector(isolate, &feedback_spec);
    653 
    654   Handle<i::String> key = factory->NewStringFromAsciiChecked("key");
    655   key = factory->string_table()->LookupString(isolate, key);
    656 
    657   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    658                                0, 1);
    659 
    660   builder.LoadLiteral(key)
    661       .LoadKeyedProperty(builder.Parameter(0), vector->GetIndex(slot))
    662       .Return();
    663   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    664 
    665   InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
    666   auto callable = tester.GetCallable<Handle<Object>>();
    667 
    668   Handle<Object> object = InterpreterTester::NewObject("({ key : 123 })");
    669   // Test IC miss.
    670   Handle<Object> return_val = callable(object).ToHandleChecked();
    671   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    672 
    673   // Test transition to monomorphic IC.
    674   return_val = callable(object).ToHandleChecked();
    675   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    676 
    677   // Test transition to megamorphic IC.
    678   Handle<Object> object3 =
    679       InterpreterTester::NewObject("({ key : 789, val2 : 123 })");
    680   return_val = callable(object3).ToHandleChecked();
    681   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789));
    682 }
    683 
    684 
    685 TEST(InterpreterStoreNamedProperty) {
    686   HandleAndZoneScope handles;
    687   i::Isolate* isolate = handles.main_isolate();
    688   i::Factory* factory = isolate->factory();
    689   i::Zone zone(isolate->allocator());
    690 
    691   i::FeedbackVectorSpec feedback_spec(&zone);
    692   i::FeedbackVectorSlot slot = feedback_spec.AddStoreICSlot();
    693 
    694   Handle<i::TypeFeedbackVector> vector =
    695       i::NewTypeFeedbackVector(isolate, &feedback_spec);
    696 
    697   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
    698   name = factory->string_table()->LookupString(isolate, name);
    699 
    700   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    701                                0, 0);
    702 
    703   builder.LoadLiteral(Smi::FromInt(999))
    704       .StoreNamedProperty(builder.Parameter(0), name, vector->GetIndex(slot),
    705                           i::STRICT)
    706       .Return();
    707   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    708 
    709   InterpreterTester tester(isolate, bytecode_array, vector);
    710   auto callable = tester.GetCallable<Handle<Object>>();
    711   Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })");
    712   // Test IC miss.
    713   Handle<Object> result;
    714   callable(object).ToHandleChecked();
    715   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
    716   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    717 
    718   // Test transition to monomorphic IC.
    719   callable(object).ToHandleChecked();
    720   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
    721   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    722 
    723   // Test transition to polymorphic IC.
    724   Handle<Object> object2 =
    725       InterpreterTester::NewObject("({ val : 456, other : 123 })");
    726   callable(object2).ToHandleChecked();
    727   CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result));
    728   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    729 
    730   // Test transition to megamorphic IC.
    731   Handle<Object> object3 =
    732       InterpreterTester::NewObject("({ val : 789, val2 : 123 })");
    733   callable(object3).ToHandleChecked();
    734   Handle<Object> object4 =
    735       InterpreterTester::NewObject("({ val : 789, val3 : 123 })");
    736   callable(object4).ToHandleChecked();
    737   Handle<Object> object5 =
    738       InterpreterTester::NewObject("({ val : 789, val4 : 123 })");
    739   callable(object5).ToHandleChecked();
    740   CHECK(Runtime::GetObjectProperty(isolate, object5, name).ToHandle(&result));
    741   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    742 }
    743 
    744 
    745 TEST(InterpreterStoreKeyedProperty) {
    746   HandleAndZoneScope handles;
    747   i::Isolate* isolate = handles.main_isolate();
    748   i::Factory* factory = isolate->factory();
    749   i::Zone zone(isolate->allocator());
    750 
    751   i::FeedbackVectorSpec feedback_spec(&zone);
    752   i::FeedbackVectorSlot slot = feedback_spec.AddKeyedStoreICSlot();
    753 
    754   Handle<i::TypeFeedbackVector> vector =
    755       i::NewTypeFeedbackVector(isolate, &feedback_spec);
    756 
    757   Handle<i::String> name = factory->NewStringFromAsciiChecked("val");
    758   name = factory->string_table()->LookupString(isolate, name);
    759 
    760   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    761                                0, 1);
    762 
    763   builder.LoadLiteral(name)
    764       .StoreAccumulatorInRegister(Register(0))
    765       .LoadLiteral(Smi::FromInt(999))
    766       .StoreKeyedProperty(builder.Parameter(0), Register(0),
    767                           vector->GetIndex(slot), i::SLOPPY)
    768       .Return();
    769   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    770 
    771   InterpreterTester tester(isolate, bytecode_array, vector);
    772   auto callable = tester.GetCallable<Handle<Object>>();
    773   Handle<Object> object = InterpreterTester::NewObject("({ val : 123 })");
    774   // Test IC miss.
    775   Handle<Object> result;
    776   callable(object).ToHandleChecked();
    777   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
    778   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    779 
    780   // Test transition to monomorphic IC.
    781   callable(object).ToHandleChecked();
    782   CHECK(Runtime::GetObjectProperty(isolate, object, name).ToHandle(&result));
    783   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    784 
    785   // Test transition to megamorphic IC.
    786   Handle<Object> object2 =
    787       InterpreterTester::NewObject("({ val : 456, other : 123 })");
    788   callable(object2).ToHandleChecked();
    789   CHECK(Runtime::GetObjectProperty(isolate, object2, name).ToHandle(&result));
    790   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    791 }
    792 
    793 static void TestInterpreterCall(TailCallMode tail_call_mode) {
    794   HandleAndZoneScope handles;
    795   i::Isolate* isolate = handles.main_isolate();
    796   i::Factory* factory = isolate->factory();
    797   i::Zone zone(isolate->allocator());
    798 
    799   i::FeedbackVectorSpec feedback_spec(&zone);
    800   i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
    801 
    802   Handle<i::TypeFeedbackVector> vector =
    803       i::NewTypeFeedbackVector(isolate, &feedback_spec);
    804   int slot_index = vector->GetIndex(slot);
    805 
    806   Handle<i::String> name = factory->NewStringFromAsciiChecked("func");
    807   name = factory->string_table()->LookupString(isolate, name);
    808 
    809   // Check with no args.
    810   {
    811     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    812                                  0, 1);
    813 
    814     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
    815         .StoreAccumulatorInRegister(Register(0))
    816         .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
    817         .Return();
    818     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    819 
    820     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
    821     auto callable = tester.GetCallable<Handle<Object>>();
    822 
    823     Handle<Object> object = InterpreterTester::NewObject(
    824         "new (function Obj() { this.func = function() { return 0x265; }})()");
    825     Handle<Object> return_val = callable(object).ToHandleChecked();
    826     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265));
    827   }
    828 
    829   // Check that receiver is passed properly.
    830   {
    831     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    832                                  0, 1);
    833 
    834     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
    835         .StoreAccumulatorInRegister(Register(0))
    836         .Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
    837         .Return();
    838     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    839 
    840     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
    841     auto callable = tester.GetCallable<Handle<Object>>();
    842 
    843     Handle<Object> object = InterpreterTester::NewObject(
    844         "new (function Obj() {"
    845         "  this.val = 1234;"
    846         "  this.func = function() { return this.val; };"
    847         "})()");
    848     Handle<Object> return_val = callable(object).ToHandleChecked();
    849     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234));
    850   }
    851 
    852   // Check with two parameters (+ receiver).
    853   {
    854     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    855                                  0, 4);
    856 
    857     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
    858         .StoreAccumulatorInRegister(Register(0))
    859         .LoadAccumulatorWithRegister(builder.Parameter(0))
    860         .StoreAccumulatorInRegister(Register(1))
    861         .LoadLiteral(Smi::FromInt(51))
    862         .StoreAccumulatorInRegister(Register(2))
    863         .LoadLiteral(Smi::FromInt(11))
    864         .StoreAccumulatorInRegister(Register(3))
    865         .Call(Register(0), Register(1), 3, 0, tail_call_mode)
    866         .Return();
    867     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    868 
    869     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
    870     auto callable = tester.GetCallable<Handle<Object>>();
    871 
    872     Handle<Object> object = InterpreterTester::NewObject(
    873         "new (function Obj() { "
    874         "  this.func = function(a, b) { return a - b; }"
    875         "})()");
    876     Handle<Object> return_val = callable(object).ToHandleChecked();
    877     CHECK(return_val->SameValue(Smi::FromInt(40)));
    878   }
    879 
    880   // Check with 10 parameters (+ receiver).
    881   {
    882     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
    883                                  0, 12);
    884 
    885     builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
    886         .StoreAccumulatorInRegister(Register(0))
    887         .LoadAccumulatorWithRegister(builder.Parameter(0))
    888         .StoreAccumulatorInRegister(Register(1))
    889         .LoadLiteral(factory->NewStringFromAsciiChecked("a"))
    890         .StoreAccumulatorInRegister(Register(2))
    891         .LoadLiteral(factory->NewStringFromAsciiChecked("b"))
    892         .StoreAccumulatorInRegister(Register(3))
    893         .LoadLiteral(factory->NewStringFromAsciiChecked("c"))
    894         .StoreAccumulatorInRegister(Register(4))
    895         .LoadLiteral(factory->NewStringFromAsciiChecked("d"))
    896         .StoreAccumulatorInRegister(Register(5))
    897         .LoadLiteral(factory->NewStringFromAsciiChecked("e"))
    898         .StoreAccumulatorInRegister(Register(6))
    899         .LoadLiteral(factory->NewStringFromAsciiChecked("f"))
    900         .StoreAccumulatorInRegister(Register(7))
    901         .LoadLiteral(factory->NewStringFromAsciiChecked("g"))
    902         .StoreAccumulatorInRegister(Register(8))
    903         .LoadLiteral(factory->NewStringFromAsciiChecked("h"))
    904         .StoreAccumulatorInRegister(Register(9))
    905         .LoadLiteral(factory->NewStringFromAsciiChecked("i"))
    906         .StoreAccumulatorInRegister(Register(10))
    907         .LoadLiteral(factory->NewStringFromAsciiChecked("j"))
    908         .StoreAccumulatorInRegister(Register(11))
    909         .Call(Register(0), Register(1), 11, 0, tail_call_mode)
    910         .Return();
    911     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    912 
    913     InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
    914     auto callable = tester.GetCallable<Handle<Object>>();
    915 
    916     Handle<Object> object = InterpreterTester::NewObject(
    917         "new (function Obj() { "
    918         "  this.prefix = \"prefix_\";"
    919         "  this.func = function(a, b, c, d, e, f, g, h, i, j) {"
    920         "      return this.prefix + a + b + c + d + e + f + g + h + i + j;"
    921         "  }"
    922         "})()");
    923     Handle<Object> return_val = callable(object).ToHandleChecked();
    924     Handle<i::String> expected =
    925         factory->NewStringFromAsciiChecked("prefix_abcdefghij");
    926     CHECK(i::String::cast(*return_val)->Equals(*expected));
    927   }
    928 }
    929 
    930 TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); }
    931 
    932 TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); }
    933 
    934 static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder,
    935                                          Register reg, int value,
    936                                          Register scratch) {
    937   return builder.StoreAccumulatorInRegister(scratch)
    938       .LoadLiteral(Smi::FromInt(value))
    939       .StoreAccumulatorInRegister(reg)
    940       .LoadAccumulatorWithRegister(scratch);
    941 }
    942 
    943 
    944 static BytecodeArrayBuilder& IncrementRegister(BytecodeArrayBuilder& builder,
    945                                                Register reg, int value,
    946                                                Register scratch) {
    947   return builder.StoreAccumulatorInRegister(scratch)
    948       .LoadLiteral(Smi::FromInt(value))
    949       .BinaryOperation(Token::Value::ADD, reg)
    950       .StoreAccumulatorInRegister(reg)
    951       .LoadAccumulatorWithRegister(scratch);
    952 }
    953 
    954 
    955 TEST(InterpreterJumps) {
    956   HandleAndZoneScope handles;
    957   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
    958                                0, 2);
    959 
    960   Register reg(0), scratch(1);
    961   BytecodeLabel label[3];
    962 
    963   builder.LoadLiteral(Smi::FromInt(0))
    964       .StoreAccumulatorInRegister(reg)
    965       .Jump(&label[1]);
    966   SetRegister(builder, reg, 1024, scratch).Bind(&label[0]);
    967   IncrementRegister(builder, reg, 1, scratch).Jump(&label[2]);
    968   SetRegister(builder, reg, 2048, scratch).Bind(&label[1]);
    969   IncrementRegister(builder, reg, 2, scratch).Jump(&label[0]);
    970   SetRegister(builder, reg, 4096, scratch).Bind(&label[2]);
    971   IncrementRegister(builder, reg, 4, scratch)
    972       .LoadAccumulatorWithRegister(reg)
    973       .Return();
    974 
    975   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
    976   InterpreterTester tester(handles.main_isolate(), bytecode_array);
    977   auto callable = tester.GetCallable<>();
    978   Handle<Object> return_value = callable().ToHandleChecked();
    979   CHECK_EQ(Smi::cast(*return_value)->value(), 7);
    980 }
    981 
    982 
    983 TEST(InterpreterConditionalJumps) {
    984   HandleAndZoneScope handles;
    985   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
    986                                0, 2);
    987 
    988   Register reg(0), scratch(1);
    989   BytecodeLabel label[2];
    990   BytecodeLabel done, done1;
    991 
    992   builder.LoadLiteral(Smi::FromInt(0))
    993       .StoreAccumulatorInRegister(reg)
    994       .LoadFalse()
    995       .JumpIfFalse(&label[0]);
    996   IncrementRegister(builder, reg, 1024, scratch)
    997       .Bind(&label[0])
    998       .LoadTrue()
    999       .JumpIfFalse(&done);
   1000   IncrementRegister(builder, reg, 1, scratch).LoadTrue().JumpIfTrue(&label[1]);
   1001   IncrementRegister(builder, reg, 2048, scratch).Bind(&label[1]);
   1002   IncrementRegister(builder, reg, 2, scratch).LoadFalse().JumpIfTrue(&done1);
   1003   IncrementRegister(builder, reg, 4, scratch)
   1004       .LoadAccumulatorWithRegister(reg)
   1005       .Bind(&done)
   1006       .Bind(&done1)
   1007       .Return();
   1008 
   1009   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1010   InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1011   auto callable = tester.GetCallable<>();
   1012   Handle<Object> return_value = callable().ToHandleChecked();
   1013   CHECK_EQ(Smi::cast(*return_value)->value(), 7);
   1014 }
   1015 
   1016 TEST(InterpreterConditionalJumps2) {
   1017   // TODO(oth): Add tests for all conditional jumps near and far.
   1018   HandleAndZoneScope handles;
   1019   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
   1020                                0, 2);
   1021 
   1022   Register reg(0), scratch(1);
   1023   BytecodeLabel label[2];
   1024   BytecodeLabel done, done1;
   1025 
   1026   builder.LoadLiteral(Smi::FromInt(0))
   1027       .StoreAccumulatorInRegister(reg)
   1028       .LoadFalse()
   1029       .JumpIfFalse(&label[0]);
   1030   IncrementRegister(builder, reg, 1024, scratch)
   1031       .Bind(&label[0])
   1032       .LoadTrue()
   1033       .JumpIfFalse(&done);
   1034   IncrementRegister(builder, reg, 1, scratch).LoadTrue().JumpIfTrue(&label[1]);
   1035   IncrementRegister(builder, reg, 2048, scratch).Bind(&label[1]);
   1036   IncrementRegister(builder, reg, 2, scratch).LoadFalse().JumpIfTrue(&done1);
   1037   IncrementRegister(builder, reg, 4, scratch)
   1038       .LoadAccumulatorWithRegister(reg)
   1039       .Bind(&done)
   1040       .Bind(&done1)
   1041       .Return();
   1042 
   1043   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1044   InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1045   auto callable = tester.GetCallable<>();
   1046   Handle<Object> return_value = callable().ToHandleChecked();
   1047   CHECK_EQ(Smi::cast(*return_value)->value(), 7);
   1048 }
   1049 
   1050 TEST(InterpreterJumpConstantWith16BitOperand) {
   1051   HandleAndZoneScope handles;
   1052   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
   1053                                0, 257);
   1054 
   1055   Register reg(0), scratch(256);
   1056   BytecodeLabel done, fake;
   1057 
   1058   builder.LoadLiteral(Smi::FromInt(0));
   1059   builder.StoreAccumulatorInRegister(reg);
   1060   // Consume all 8-bit operands
   1061   for (int i = 1; i <= 256; i++) {
   1062     builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i));
   1063     builder.BinaryOperation(Token::Value::ADD, reg);
   1064     builder.StoreAccumulatorInRegister(reg);
   1065   }
   1066   builder.Jump(&done);
   1067 
   1068   // Emit more than 16-bit immediate operands worth of code to jump over.
   1069   builder.Bind(&fake);
   1070   for (int i = 0; i < 6600; i++) {
   1071     builder.LoadLiteral(Smi::FromInt(0));                 // 1-byte
   1072     builder.BinaryOperation(Token::Value::ADD, scratch);  // 4-bytes
   1073     builder.StoreAccumulatorInRegister(scratch);          // 4-bytes
   1074     builder.MoveRegister(scratch, reg);                   // 6-bytes
   1075   }
   1076   builder.Bind(&done);
   1077   builder.LoadAccumulatorWithRegister(reg);
   1078   builder.Return();
   1079 
   1080   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1081   BytecodeArrayIterator iterator(bytecode_array);
   1082 
   1083   bool found_16bit_constant_jump = false;
   1084   while (!iterator.done()) {
   1085     if (iterator.current_bytecode() == Bytecode::kJumpConstant &&
   1086         iterator.current_operand_scale() == OperandScale::kDouble) {
   1087       found_16bit_constant_jump = true;
   1088       break;
   1089     }
   1090     iterator.Advance();
   1091   }
   1092   CHECK(found_16bit_constant_jump);
   1093 
   1094   InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1095   auto callable = tester.GetCallable<>();
   1096   Handle<Object> return_value = callable().ToHandleChecked();
   1097   CHECK_EQ(Smi::cast(*return_value)->value(), 256.0 / 2 * (1 + 256));
   1098 }
   1099 
   1100 TEST(InterpreterJumpWith32BitOperand) {
   1101   HandleAndZoneScope handles;
   1102   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
   1103                                0, 1);
   1104   Register reg(0);
   1105   BytecodeLabel done;
   1106 
   1107   builder.LoadLiteral(Smi::FromInt(0));
   1108   builder.StoreAccumulatorInRegister(reg);
   1109   // Consume all 16-bit constant pool entries
   1110   for (int i = 1; i <= 65536; i++) {
   1111     builder.LoadLiteral(handles.main_isolate()->factory()->NewNumber(i));
   1112   }
   1113   builder.Jump(&done);
   1114   builder.LoadLiteral(Smi::FromInt(0));
   1115   builder.Bind(&done);
   1116   builder.Return();
   1117 
   1118   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1119   BytecodeArrayIterator iterator(bytecode_array);
   1120 
   1121   bool found_32bit_jump = false;
   1122   while (!iterator.done()) {
   1123     if (iterator.current_bytecode() == Bytecode::kJump &&
   1124         iterator.current_operand_scale() == OperandScale::kQuadruple) {
   1125       found_32bit_jump = true;
   1126       break;
   1127     }
   1128     iterator.Advance();
   1129   }
   1130   CHECK(found_32bit_jump);
   1131 
   1132   InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1133   auto callable = tester.GetCallable<>();
   1134   Handle<Object> return_value = callable().ToHandleChecked();
   1135   CHECK_EQ(Smi::cast(*return_value)->value(), 65536.0);
   1136 }
   1137 
   1138 static const Token::Value kComparisonTypes[] = {
   1139     Token::Value::EQ, Token::Value::NE,  Token::Value::EQ_STRICT,
   1140     Token::Value::LT, Token::Value::LTE, Token::Value::GT,
   1141     Token::Value::GTE};
   1142 
   1143 template <typename T>
   1144 bool CompareC(Token::Value op, T lhs, T rhs, bool types_differed = false) {
   1145   switch (op) {
   1146     case Token::Value::EQ:
   1147       return lhs == rhs;
   1148     case Token::Value::NE:
   1149       return lhs != rhs;
   1150     case Token::Value::EQ_STRICT:
   1151       return (lhs == rhs) && !types_differed;
   1152     case Token::Value::NE_STRICT:
   1153       return (lhs != rhs) || types_differed;
   1154     case Token::Value::LT:
   1155       return lhs < rhs;
   1156     case Token::Value::LTE:
   1157       return lhs <= rhs;
   1158     case Token::Value::GT:
   1159       return lhs > rhs;
   1160     case Token::Value::GTE:
   1161       return lhs >= rhs;
   1162     default:
   1163       UNREACHABLE();
   1164       return false;
   1165   }
   1166 }
   1167 
   1168 
   1169 TEST(InterpreterSmiComparisons) {
   1170   // NB Constants cover 31-bit space.
   1171   int inputs[] = {v8::internal::kMinInt / 2,
   1172                   v8::internal::kMinInt / 4,
   1173                   -108733832,
   1174                   -999,
   1175                   -42,
   1176                   -2,
   1177                   -1,
   1178                   0,
   1179                   +1,
   1180                   +2,
   1181                   42,
   1182                   12345678,
   1183                   v8::internal::kMaxInt / 4,
   1184                   v8::internal::kMaxInt / 2};
   1185 
   1186   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
   1187     Token::Value comparison = kComparisonTypes[c];
   1188     for (size_t i = 0; i < arraysize(inputs); i++) {
   1189       for (size_t j = 0; j < arraysize(inputs); j++) {
   1190         HandleAndZoneScope handles;
   1191         BytecodeArrayBuilder builder(handles.main_isolate(),
   1192                                      handles.main_zone(), 0, 0, 1);
   1193 
   1194         Register r0(0);
   1195         builder.LoadLiteral(Smi::FromInt(inputs[i]))
   1196             .StoreAccumulatorInRegister(r0)
   1197             .LoadLiteral(Smi::FromInt(inputs[j]))
   1198             .CompareOperation(comparison, r0)
   1199             .Return();
   1200 
   1201         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1202         InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1203         auto callable = tester.GetCallable<>();
   1204         Handle<Object> return_value = callable().ToHandleChecked();
   1205         CHECK(return_value->IsBoolean());
   1206         CHECK_EQ(return_value->BooleanValue(),
   1207                  CompareC(comparison, inputs[i], inputs[j]));
   1208       }
   1209     }
   1210   }
   1211 }
   1212 
   1213 
   1214 TEST(InterpreterHeapNumberComparisons) {
   1215   double inputs[] = {std::numeric_limits<double>::min(),
   1216                      std::numeric_limits<double>::max(),
   1217                      -0.001,
   1218                      0.01,
   1219                      0.1000001,
   1220                      1e99,
   1221                      -1e-99};
   1222   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
   1223     Token::Value comparison = kComparisonTypes[c];
   1224     for (size_t i = 0; i < arraysize(inputs); i++) {
   1225       for (size_t j = 0; j < arraysize(inputs); j++) {
   1226         HandleAndZoneScope handles;
   1227         i::Factory* factory = handles.main_isolate()->factory();
   1228         BytecodeArrayBuilder builder(handles.main_isolate(),
   1229                                      handles.main_zone(), 0, 0, 1);
   1230 
   1231         Register r0(0);
   1232         builder.LoadLiteral(factory->NewHeapNumber(inputs[i]))
   1233             .StoreAccumulatorInRegister(r0)
   1234             .LoadLiteral(factory->NewHeapNumber(inputs[j]))
   1235             .CompareOperation(comparison, r0)
   1236             .Return();
   1237 
   1238         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1239         InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1240         auto callable = tester.GetCallable<>();
   1241         Handle<Object> return_value = callable().ToHandleChecked();
   1242         CHECK(return_value->IsBoolean());
   1243         CHECK_EQ(return_value->BooleanValue(),
   1244                  CompareC(comparison, inputs[i], inputs[j]));
   1245       }
   1246     }
   1247   }
   1248 }
   1249 
   1250 
   1251 TEST(InterpreterStringComparisons) {
   1252   std::string inputs[] = {"A", "abc", "z", "", "Foo!", "Foo"};
   1253 
   1254   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
   1255     Token::Value comparison = kComparisonTypes[c];
   1256     for (size_t i = 0; i < arraysize(inputs); i++) {
   1257       for (size_t j = 0; j < arraysize(inputs); j++) {
   1258         const char* lhs = inputs[i].c_str();
   1259         const char* rhs = inputs[j].c_str();
   1260         HandleAndZoneScope handles;
   1261         i::Factory* factory = handles.main_isolate()->factory();
   1262         BytecodeArrayBuilder builder(handles.main_isolate(),
   1263                                      handles.main_zone(), 0, 0, 1);
   1264 
   1265         Register r0(0);
   1266         builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs))
   1267             .StoreAccumulatorInRegister(r0)
   1268             .LoadLiteral(factory->NewStringFromAsciiChecked(rhs))
   1269             .CompareOperation(comparison, r0)
   1270             .Return();
   1271 
   1272         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1273         InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1274         auto callable = tester.GetCallable<>();
   1275         Handle<Object> return_value = callable().ToHandleChecked();
   1276         CHECK(return_value->IsBoolean());
   1277         CHECK_EQ(return_value->BooleanValue(),
   1278                  CompareC(comparison, inputs[i], inputs[j]));
   1279       }
   1280     }
   1281   }
   1282 }
   1283 
   1284 
   1285 TEST(InterpreterMixedComparisons) {
   1286   // This test compares a HeapNumber with a String. The latter is
   1287   // convertible to a HeapNumber so comparison will be between numeric
   1288   // values except for the strict comparisons where no conversion is
   1289   // performed.
   1290   const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"};
   1291 
   1292   i::UnicodeCache unicode_cache;
   1293 
   1294   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
   1295     Token::Value comparison = kComparisonTypes[c];
   1296     for (size_t i = 0; i < arraysize(inputs); i++) {
   1297       for (size_t j = 0; j < arraysize(inputs); j++) {
   1298         for (int pass = 0; pass < 2; pass++) {
   1299           const char* lhs_cstr = inputs[i];
   1300           const char* rhs_cstr = inputs[j];
   1301           double lhs = StringToDouble(&unicode_cache, lhs_cstr,
   1302                                       i::ConversionFlags::NO_FLAGS);
   1303           double rhs = StringToDouble(&unicode_cache, rhs_cstr,
   1304                                       i::ConversionFlags::NO_FLAGS);
   1305           HandleAndZoneScope handles;
   1306           i::Factory* factory = handles.main_isolate()->factory();
   1307           BytecodeArrayBuilder builder(handles.main_isolate(),
   1308                                        handles.main_zone(), 0, 0, 1);
   1309 
   1310           Register r0(0);
   1311           if (pass == 0) {
   1312             // Comparison with HeapNumber on the lhs and String on the rhs
   1313             builder.LoadLiteral(factory->NewNumber(lhs))
   1314                 .StoreAccumulatorInRegister(r0)
   1315                 .LoadLiteral(factory->NewStringFromAsciiChecked(rhs_cstr))
   1316                 .CompareOperation(comparison, r0)
   1317                 .Return();
   1318           } else {
   1319             // Comparison with HeapNumber on the rhs and String on the lhs
   1320             builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs_cstr))
   1321                 .StoreAccumulatorInRegister(r0)
   1322                 .LoadLiteral(factory->NewNumber(rhs))
   1323                 .CompareOperation(comparison, r0)
   1324                 .Return();
   1325           }
   1326 
   1327           Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1328           InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1329           auto callable = tester.GetCallable<>();
   1330           Handle<Object> return_value = callable().ToHandleChecked();
   1331           CHECK(return_value->IsBoolean());
   1332           CHECK_EQ(return_value->BooleanValue(),
   1333                    CompareC(comparison, lhs, rhs, true));
   1334         }
   1335       }
   1336     }
   1337   }
   1338 }
   1339 
   1340 TEST(InterpreterStrictNotEqual) {
   1341   HandleAndZoneScope handles;
   1342   i::Factory* factory = handles.main_isolate()->factory();
   1343   const char* code_snippet =
   1344       "function f(lhs, rhs) {\n"
   1345       "  return lhs !== rhs;\n"
   1346       "}\n"
   1347       "f(0, 0);\n";
   1348   InterpreterTester tester(handles.main_isolate(), code_snippet);
   1349   auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
   1350 
   1351   // Test passing different types.
   1352   const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"};
   1353   i::UnicodeCache unicode_cache;
   1354   for (size_t i = 0; i < arraysize(inputs); i++) {
   1355     for (size_t j = 0; j < arraysize(inputs); j++) {
   1356       double lhs = StringToDouble(&unicode_cache, inputs[i],
   1357                                   i::ConversionFlags::NO_FLAGS);
   1358       double rhs = StringToDouble(&unicode_cache, inputs[j],
   1359                                   i::ConversionFlags::NO_FLAGS);
   1360       Handle<Object> lhs_obj = factory->NewNumber(lhs);
   1361       Handle<Object> rhs_obj = factory->NewStringFromAsciiChecked(inputs[j]);
   1362 
   1363       Handle<Object> return_value =
   1364           callable(lhs_obj, rhs_obj).ToHandleChecked();
   1365       CHECK(return_value->IsBoolean());
   1366       CHECK_EQ(return_value->BooleanValue(),
   1367                CompareC(Token::Value::NE_STRICT, lhs, rhs, true));
   1368     }
   1369   }
   1370 
   1371   // Test passing string types.
   1372   const char* inputs_str[] = {"A", "abc", "z", "", "Foo!", "Foo"};
   1373   for (size_t i = 0; i < arraysize(inputs_str); i++) {
   1374     for (size_t j = 0; j < arraysize(inputs_str); j++) {
   1375       Handle<Object> lhs_obj =
   1376           factory->NewStringFromAsciiChecked(inputs_str[i]);
   1377       Handle<Object> rhs_obj =
   1378           factory->NewStringFromAsciiChecked(inputs_str[j]);
   1379 
   1380       Handle<Object> return_value =
   1381           callable(lhs_obj, rhs_obj).ToHandleChecked();
   1382       CHECK(return_value->IsBoolean());
   1383       CHECK_EQ(return_value->BooleanValue(),
   1384                CompareC(Token::Value::NE_STRICT, inputs_str[i], inputs_str[j]));
   1385     }
   1386   }
   1387 
   1388   // Test passing doubles.
   1389   double inputs_number[] = {std::numeric_limits<double>::min(),
   1390                             std::numeric_limits<double>::max(),
   1391                             -0.001,
   1392                             0.01,
   1393                             0.1000001,
   1394                             1e99,
   1395                             -1e-99};
   1396   for (size_t i = 0; i < arraysize(inputs_number); i++) {
   1397     for (size_t j = 0; j < arraysize(inputs_number); j++) {
   1398       Handle<Object> lhs_obj = factory->NewNumber(inputs_number[i]);
   1399       Handle<Object> rhs_obj = factory->NewNumber(inputs_number[j]);
   1400 
   1401       Handle<Object> return_value =
   1402           callable(lhs_obj, rhs_obj).ToHandleChecked();
   1403       CHECK(return_value->IsBoolean());
   1404       CHECK_EQ(return_value->BooleanValue(),
   1405                CompareC(Token::Value::NE_STRICT, inputs_number[i],
   1406                         inputs_number[j]));
   1407     }
   1408   }
   1409 }
   1410 
   1411 TEST(InterpreterInstanceOf) {
   1412   HandleAndZoneScope handles;
   1413   i::Factory* factory = handles.main_isolate()->factory();
   1414   Handle<i::String> name = factory->NewStringFromAsciiChecked("cons");
   1415   Handle<i::JSFunction> func = factory->NewFunction(name);
   1416   Handle<i::JSObject> instance = factory->NewJSObject(func);
   1417   Handle<i::Object> other = factory->NewNumber(3.3333);
   1418   Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
   1419   for (size_t i = 0; i < arraysize(cases); i++) {
   1420     bool expected_value = (i == 0);
   1421     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
   1422                                  0, 1);
   1423 
   1424     Register r0(0);
   1425     builder.LoadLiteral(cases[i]);
   1426     builder.StoreAccumulatorInRegister(r0)
   1427         .LoadLiteral(func)
   1428         .CompareOperation(Token::Value::INSTANCEOF, r0)
   1429         .Return();
   1430 
   1431     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1432     InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1433     auto callable = tester.GetCallable<>();
   1434     Handle<Object> return_value = callable().ToHandleChecked();
   1435     CHECK(return_value->IsBoolean());
   1436     CHECK_EQ(return_value->BooleanValue(), expected_value);
   1437   }
   1438 }
   1439 
   1440 
   1441 TEST(InterpreterTestIn) {
   1442   HandleAndZoneScope handles;
   1443   i::Factory* factory = handles.main_isolate()->factory();
   1444   // Allocate an array
   1445   Handle<i::JSArray> array =
   1446       factory->NewJSArray(0, i::ElementsKind::FAST_SMI_ELEMENTS);
   1447   // Check for these properties on the array object
   1448   const char* properties[] = {"length", "fuzzle", "x", "0"};
   1449   for (size_t i = 0; i < arraysize(properties); i++) {
   1450     bool expected_value = (i == 0);
   1451     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
   1452                                  0, 1);
   1453 
   1454     Register r0(0);
   1455     builder.LoadLiteral(factory->NewStringFromAsciiChecked(properties[i]))
   1456         .StoreAccumulatorInRegister(r0)
   1457         .LoadLiteral(Handle<Object>::cast(array))
   1458         .CompareOperation(Token::Value::IN, r0)
   1459         .Return();
   1460 
   1461     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1462     InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1463     auto callable = tester.GetCallable<>();
   1464     Handle<Object> return_value = callable().ToHandleChecked();
   1465     CHECK(return_value->IsBoolean());
   1466     CHECK_EQ(return_value->BooleanValue(), expected_value);
   1467   }
   1468 }
   1469 
   1470 
   1471 TEST(InterpreterUnaryNot) {
   1472   HandleAndZoneScope handles;
   1473   for (size_t i = 1; i < 10; i++) {
   1474     bool expected_value = ((i & 1) == 1);
   1475     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
   1476                                  0, 0);
   1477 
   1478     Register r0(0);
   1479     builder.LoadFalse();
   1480     for (size_t j = 0; j < i; j++) {
   1481       builder.LogicalNot();
   1482     }
   1483     builder.Return();
   1484     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1485     InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1486     auto callable = tester.GetCallable<>();
   1487     Handle<Object> return_value = callable().ToHandleChecked();
   1488     CHECK(return_value->IsBoolean());
   1489     CHECK_EQ(return_value->BooleanValue(), expected_value);
   1490   }
   1491 }
   1492 
   1493 
   1494 static void LoadAny(BytecodeArrayBuilder* builder,
   1495                     v8::internal::Factory* factory, Handle<Object> obj) {
   1496   if (obj->IsOddball()) {
   1497     if (obj->SameValue(*factory->true_value())) {
   1498       builder->LoadTrue();
   1499     } else if (obj->SameValue(*factory->false_value())) {
   1500       builder->LoadFalse();
   1501     } else if (obj->SameValue(*factory->the_hole_value())) {
   1502       builder->LoadTheHole();
   1503     } else if (obj->SameValue(*factory->null_value())) {
   1504       builder->LoadNull();
   1505     } else if (obj->SameValue(*factory->undefined_value())) {
   1506       builder->LoadUndefined();
   1507     } else {
   1508       UNREACHABLE();
   1509     }
   1510   } else if (obj->IsSmi()) {
   1511     builder->LoadLiteral(*Handle<Smi>::cast(obj));
   1512   } else {
   1513     builder->LoadLiteral(obj);
   1514   }
   1515 }
   1516 
   1517 
   1518 TEST(InterpreterUnaryNotNonBoolean) {
   1519   HandleAndZoneScope handles;
   1520   i::Factory* factory = handles.main_isolate()->factory();
   1521 
   1522   std::pair<Handle<Object>, bool> object_type_tuples[] = {
   1523       std::make_pair(factory->undefined_value(), true),
   1524       std::make_pair(factory->null_value(), true),
   1525       std::make_pair(factory->false_value(), true),
   1526       std::make_pair(factory->true_value(), false),
   1527       std::make_pair(factory->NewNumber(9.1), false),
   1528       std::make_pair(factory->NewNumberFromInt(0), true),
   1529       std::make_pair(
   1530           Handle<Object>::cast(factory->NewStringFromStaticChars("hello")),
   1531           false),
   1532       std::make_pair(
   1533           Handle<Object>::cast(factory->NewStringFromStaticChars("")), true),
   1534   };
   1535 
   1536   for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
   1537     BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 0,
   1538                                  0, 0);
   1539 
   1540     Register r0(0);
   1541     LoadAny(&builder, factory, object_type_tuples[i].first);
   1542     builder.LogicalNot();
   1543     builder.Return();
   1544     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1545     InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1546     auto callable = tester.GetCallable<>();
   1547     Handle<Object> return_value = callable().ToHandleChecked();
   1548     CHECK(return_value->IsBoolean());
   1549     CHECK_EQ(return_value->BooleanValue(), object_type_tuples[i].second);
   1550   }
   1551 }
   1552 
   1553 
   1554 TEST(InterpreterTypeof) {
   1555   HandleAndZoneScope handles;
   1556 
   1557   std::pair<const char*, const char*> typeof_vals[] = {
   1558       std::make_pair("return typeof undefined;", "undefined"),
   1559       std::make_pair("return typeof null;", "object"),
   1560       std::make_pair("return typeof true;", "boolean"),
   1561       std::make_pair("return typeof false;", "boolean"),
   1562       std::make_pair("return typeof 9.1;", "number"),
   1563       std::make_pair("return typeof 7771;", "number"),
   1564       std::make_pair("return typeof 'hello';", "string"),
   1565       std::make_pair("return typeof global_unallocated;", "undefined"),
   1566   };
   1567 
   1568   for (size_t i = 0; i < arraysize(typeof_vals); i++) {
   1569     std::string source(InterpreterTester::SourceForBody(typeof_vals[i].first));
   1570     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1571 
   1572     auto callable = tester.GetCallable<>();
   1573     Handle<v8::internal::String> return_value =
   1574         Handle<v8::internal::String>::cast(callable().ToHandleChecked());
   1575     auto actual = return_value->ToCString();
   1576     CHECK_EQ(strcmp(&actual[0], typeof_vals[i].second), 0);
   1577   }
   1578 }
   1579 
   1580 
   1581 TEST(InterpreterCallRuntime) {
   1582   HandleAndZoneScope handles;
   1583 
   1584   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
   1585                                0, 2);
   1586 
   1587   builder.LoadLiteral(Smi::FromInt(15))
   1588       .StoreAccumulatorInRegister(Register(0))
   1589       .LoadLiteral(Smi::FromInt(40))
   1590       .StoreAccumulatorInRegister(Register(1))
   1591       .CallRuntime(Runtime::kAdd, Register(0), 2)
   1592       .Return();
   1593   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1594 
   1595   InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1596   auto callable = tester.GetCallable<>();
   1597 
   1598   Handle<Object> return_val = callable().ToHandleChecked();
   1599   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(55));
   1600 }
   1601 
   1602 TEST(InterpreterInvokeIntrinsic) {
   1603   HandleAndZoneScope handles;
   1604 
   1605   BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
   1606                                0, 2);
   1607 
   1608   builder.LoadLiteral(Smi::FromInt(15))
   1609       .StoreAccumulatorInRegister(Register(0))
   1610       .CallRuntime(Runtime::kInlineIsArray, Register(0), 1)
   1611       .Return();
   1612   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
   1613 
   1614   InterpreterTester tester(handles.main_isolate(), bytecode_array);
   1615   auto callable = tester.GetCallable<>();
   1616 
   1617   Handle<Object> return_val = callable().ToHandleChecked();
   1618   CHECK(return_val->IsBoolean());
   1619   CHECK_EQ(return_val->BooleanValue(), false);
   1620 }
   1621 
   1622 TEST(InterpreterFunctionLiteral) {
   1623   HandleAndZoneScope handles;
   1624 
   1625   // Test calling a function literal.
   1626   std::string source(
   1627       "function " + InterpreterTester::function_name() + "(a) {\n"
   1628       "  return (function(x){ return x + 2; })(a);\n"
   1629       "}");
   1630   InterpreterTester tester(handles.main_isolate(), source.c_str());
   1631   auto callable = tester.GetCallable<Handle<Object>>();
   1632 
   1633   Handle<i::Object> return_val = callable(
   1634       Handle<Smi>(Smi::FromInt(3), handles.main_isolate())).ToHandleChecked();
   1635   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
   1636 }
   1637 
   1638 
   1639 TEST(InterpreterRegExpLiterals) {
   1640   HandleAndZoneScope handles;
   1641   i::Isolate* isolate = handles.main_isolate();
   1642   i::Factory* factory = isolate->factory();
   1643 
   1644   std::pair<const char*, Handle<Object>> literals[] = {
   1645       std::make_pair("return /abd/.exec('cccabbdd');\n",
   1646                      factory->null_value()),
   1647       std::make_pair("return /ab+d/.exec('cccabbdd')[0];\n",
   1648                      factory->NewStringFromStaticChars("abbd")),
   1649       std::make_pair("return /AbC/i.exec('ssaBC')[0];\n",
   1650                      factory->NewStringFromStaticChars("aBC")),
   1651       std::make_pair("return 'ssaBC'.match(/AbC/i)[0];\n",
   1652                      factory->NewStringFromStaticChars("aBC")),
   1653       std::make_pair("return 'ssaBCtAbC'.match(/(AbC)/gi)[1];\n",
   1654                      factory->NewStringFromStaticChars("AbC")),
   1655   };
   1656 
   1657   for (size_t i = 0; i < arraysize(literals); i++) {
   1658     std::string source(InterpreterTester::SourceForBody(literals[i].first));
   1659     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1660     auto callable = tester.GetCallable<>();
   1661 
   1662     Handle<i::Object> return_value = callable().ToHandleChecked();
   1663     CHECK(return_value->SameValue(*literals[i].second));
   1664   }
   1665 }
   1666 
   1667 
   1668 TEST(InterpreterArrayLiterals) {
   1669   HandleAndZoneScope handles;
   1670   i::Isolate* isolate = handles.main_isolate();
   1671   i::Factory* factory = isolate->factory();
   1672 
   1673   std::pair<const char*, Handle<Object>> literals[] = {
   1674       std::make_pair("return [][0];\n",
   1675                      factory->undefined_value()),
   1676       std::make_pair("return [1, 3, 2][1];\n",
   1677                      handle(Smi::FromInt(3), isolate)),
   1678       std::make_pair("return ['a', 'b', 'c'][2];\n",
   1679                      factory->NewStringFromStaticChars("c")),
   1680       std::make_pair("var a = 100; return [a, a + 1, a + 2, a + 3][2];\n",
   1681                      handle(Smi::FromInt(102), isolate)),
   1682       std::make_pair("return [[1, 2, 3], ['a', 'b', 'c']][1][0];\n",
   1683                      factory->NewStringFromStaticChars("a")),
   1684       std::make_pair("var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];\n",
   1685                      factory->NewStringFromStaticChars("test"))
   1686   };
   1687 
   1688   for (size_t i = 0; i < arraysize(literals); i++) {
   1689     std::string source(InterpreterTester::SourceForBody(literals[i].first));
   1690     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1691     auto callable = tester.GetCallable<>();
   1692 
   1693     Handle<i::Object> return_value = callable().ToHandleChecked();
   1694     CHECK(return_value->SameValue(*literals[i].second));
   1695   }
   1696 }
   1697 
   1698 
   1699 TEST(InterpreterObjectLiterals) {
   1700   HandleAndZoneScope handles;
   1701   i::Isolate* isolate = handles.main_isolate();
   1702   i::Factory* factory = isolate->factory();
   1703 
   1704   std::pair<const char*, Handle<Object>> literals[] = {
   1705       std::make_pair("return { }.name;",
   1706                      factory->undefined_value()),
   1707       std::make_pair("return { name: 'string', val: 9.2 }.name;",
   1708                      factory->NewStringFromStaticChars("string")),
   1709       std::make_pair("var a = 15; return { name: 'string', val: a }.val;",
   1710                      handle(Smi::FromInt(15), isolate)),
   1711       std::make_pair("var a = 5; return { val: a, val: a + 1 }.val;",
   1712                      handle(Smi::FromInt(6), isolate)),
   1713       std::make_pair("return { func: function() { return 'test' } }.func();",
   1714                      factory->NewStringFromStaticChars("test")),
   1715       std::make_pair("return { func(a) { return a + 'st'; } }.func('te');",
   1716                      factory->NewStringFromStaticChars("test")),
   1717       std::make_pair("return { get a() { return 22; } }.a;",
   1718                      handle(Smi::FromInt(22), isolate)),
   1719       std::make_pair("var a = { get b() { return this.x + 't'; },\n"
   1720                      "          set b(val) { this.x = val + 's' } };\n"
   1721                      "a.b = 'te';\n"
   1722                      "return a.b;",
   1723                      factory->NewStringFromStaticChars("test")),
   1724       std::make_pair("var a = 123; return { 1: a }[1];",
   1725                      handle(Smi::FromInt(123), isolate)),
   1726       std::make_pair("return Object.getPrototypeOf({ __proto__: null });",
   1727                      factory->null_value()),
   1728       std::make_pair("var a = 'test'; return { [a]: 1 }.test;",
   1729                      handle(Smi::FromInt(1), isolate)),
   1730       std::make_pair("var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
   1731                      factory->NewStringFromStaticChars("testing")),
   1732       std::make_pair("var a = 'proto_str';\n"
   1733                      "var b = { [a]: 1, __proto__: { var : a } };\n"
   1734                      "return Object.getPrototypeOf(b).var",
   1735                      factory->NewStringFromStaticChars("proto_str")),
   1736       std::make_pair("var n = 'name';\n"
   1737                      "return { [n]: 'val', get a() { return 987 } }['a'];",
   1738                      handle(Smi::FromInt(987), isolate)),
   1739   };
   1740 
   1741   for (size_t i = 0; i < arraysize(literals); i++) {
   1742     std::string source(InterpreterTester::SourceForBody(literals[i].first));
   1743     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1744     auto callable = tester.GetCallable<>();
   1745 
   1746     Handle<i::Object> return_value = callable().ToHandleChecked();
   1747     CHECK(return_value->SameValue(*literals[i].second));
   1748   }
   1749 }
   1750 
   1751 
   1752 TEST(InterpreterConstruct) {
   1753   HandleAndZoneScope handles;
   1754 
   1755   std::string source(
   1756       "function counter() { this.count = 0; }\n"
   1757       "function " +
   1758       InterpreterTester::function_name() +
   1759       "() {\n"
   1760       "  var c = new counter();\n"
   1761       "  return c.count;\n"
   1762       "}");
   1763   InterpreterTester tester(handles.main_isolate(), source.c_str());
   1764   auto callable = tester.GetCallable<>();
   1765 
   1766   Handle<Object> return_val = callable().ToHandleChecked();
   1767   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0));
   1768 }
   1769 
   1770 
   1771 TEST(InterpreterConstructWithArgument) {
   1772   HandleAndZoneScope handles;
   1773 
   1774   std::string source(
   1775       "function counter(arg0) { this.count = 17; this.x = arg0; }\n"
   1776       "function " +
   1777       InterpreterTester::function_name() +
   1778       "() {\n"
   1779       "  var c = new counter(3);\n"
   1780       "  return c.x;\n"
   1781       "}");
   1782   InterpreterTester tester(handles.main_isolate(), source.c_str());
   1783   auto callable = tester.GetCallable<>();
   1784 
   1785   Handle<Object> return_val = callable().ToHandleChecked();
   1786   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
   1787 }
   1788 
   1789 
   1790 TEST(InterpreterConstructWithArguments) {
   1791   HandleAndZoneScope handles;
   1792 
   1793   std::string source(
   1794       "function counter(arg0, arg1) {\n"
   1795       "  this.count = 7; this.x = arg0; this.y = arg1;\n"
   1796       "}\n"
   1797       "function " +
   1798       InterpreterTester::function_name() +
   1799       "() {\n"
   1800       "  var c = new counter(3, 5);\n"
   1801       "  return c.count + c.x + c.y;\n"
   1802       "}");
   1803   InterpreterTester tester(handles.main_isolate(), source.c_str());
   1804   auto callable = tester.GetCallable<>();
   1805 
   1806   Handle<Object> return_val = callable().ToHandleChecked();
   1807   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
   1808 }
   1809 
   1810 
   1811 TEST(InterpreterContextVariables) {
   1812   HandleAndZoneScope handles;
   1813   i::Isolate* isolate = handles.main_isolate();
   1814 
   1815   std::ostringstream unique_vars;
   1816   for (int i = 0; i < 250; i++) {
   1817     unique_vars << "var a" << i << " = 0;";
   1818   }
   1819   std::pair<std::string, Handle<Object>> context_vars[] = {
   1820       std::make_pair("var a; (function() { a = 1; })(); return a;",
   1821                      handle(Smi::FromInt(1), isolate)),
   1822       std::make_pair("var a = 10; (function() { a; })(); return a;",
   1823                      handle(Smi::FromInt(10), isolate)),
   1824       std::make_pair("var a = 20; var b = 30;\n"
   1825                      "return (function() { return a + b; })();",
   1826                      handle(Smi::FromInt(50), isolate)),
   1827       std::make_pair("'use strict'; let a = 1;\n"
   1828                      "{ let b = 2; return (function() { return a + b; })(); }",
   1829                      handle(Smi::FromInt(3), isolate)),
   1830       std::make_pair("'use strict'; let a = 10;\n"
   1831                      "{ let b = 20; var c = function() { [a, b] };\n"
   1832                      "  return a + b; }",
   1833                      handle(Smi::FromInt(30), isolate)),
   1834       std::make_pair("'use strict';" + unique_vars.str() +
   1835                      "eval(); var b = 100; return b;",
   1836                      handle(Smi::FromInt(100), isolate)),
   1837   };
   1838 
   1839   for (size_t i = 0; i < arraysize(context_vars); i++) {
   1840     std::string source(
   1841         InterpreterTester::SourceForBody(context_vars[i].first.c_str()));
   1842     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1843     auto callable = tester.GetCallable<>();
   1844 
   1845     Handle<i::Object> return_value = callable().ToHandleChecked();
   1846     CHECK(return_value->SameValue(*context_vars[i].second));
   1847   }
   1848 }
   1849 
   1850 
   1851 TEST(InterpreterContextParameters) {
   1852   HandleAndZoneScope handles;
   1853   i::Isolate* isolate = handles.main_isolate();
   1854 
   1855   std::pair<const char*, Handle<Object>> context_params[] = {
   1856       std::make_pair("return (function() { return arg1; })();",
   1857                      handle(Smi::FromInt(1), isolate)),
   1858       std::make_pair("(function() { arg1 = 4; })(); return arg1;",
   1859                      handle(Smi::FromInt(4), isolate)),
   1860       std::make_pair("(function() { arg3 = arg2 - arg1; })(); return arg3;",
   1861                      handle(Smi::FromInt(1), isolate)),
   1862   };
   1863 
   1864   for (size_t i = 0; i < arraysize(context_params); i++) {
   1865     std::string source = "function " + InterpreterTester::function_name() +
   1866                          "(arg1, arg2, arg3) {" + context_params[i].first + "}";
   1867     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1868     auto callable =
   1869         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
   1870 
   1871     Handle<Object> a1 = handle(Smi::FromInt(1), isolate);
   1872     Handle<Object> a2 = handle(Smi::FromInt(2), isolate);
   1873     Handle<Object> a3 = handle(Smi::FromInt(3), isolate);
   1874     Handle<i::Object> return_value = callable(a1, a2, a3).ToHandleChecked();
   1875     CHECK(return_value->SameValue(*context_params[i].second));
   1876   }
   1877 }
   1878 
   1879 
   1880 TEST(InterpreterOuterContextVariables) {
   1881   HandleAndZoneScope handles;
   1882   i::Isolate* isolate = handles.main_isolate();
   1883 
   1884   std::pair<const char*, Handle<Object>> context_vars[] = {
   1885       std::make_pair("return outerVar * innerArg;",
   1886                      handle(Smi::FromInt(200), isolate)),
   1887       std::make_pair("outerVar = innerArg; return outerVar",
   1888                      handle(Smi::FromInt(20), isolate)),
   1889   };
   1890 
   1891   std::string header(
   1892       "function Outer() {"
   1893       "  var outerVar = 10;"
   1894       "  function Inner(innerArg) {"
   1895       "    this.innerFunc = function() { ");
   1896   std::string footer(
   1897       "  }}"
   1898       "  this.getInnerFunc = function() { return new Inner(20).innerFunc; }"
   1899       "}"
   1900       "var f = new Outer().getInnerFunc();");
   1901 
   1902   for (size_t i = 0; i < arraysize(context_vars); i++) {
   1903     std::string source = header + context_vars[i].first + footer;
   1904     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
   1905     auto callable = tester.GetCallable<>();
   1906 
   1907     Handle<i::Object> return_value = callable().ToHandleChecked();
   1908     CHECK(return_value->SameValue(*context_vars[i].second));
   1909   }
   1910 }
   1911 
   1912 
   1913 TEST(InterpreterComma) {
   1914   HandleAndZoneScope handles;
   1915   i::Isolate* isolate = handles.main_isolate();
   1916   i::Factory* factory = isolate->factory();
   1917 
   1918   std::pair<const char*, Handle<Object>> literals[] = {
   1919       std::make_pair("var a; return 0, a;\n", factory->undefined_value()),
   1920       std::make_pair("return 'a', 2.2, 3;\n",
   1921                      handle(Smi::FromInt(3), isolate)),
   1922       std::make_pair("return 'a', 'b', 'c';\n",
   1923                      factory->NewStringFromStaticChars("c")),
   1924       std::make_pair("return 3.2, 2.3, 4.5;\n", factory->NewNumber(4.5)),
   1925       std::make_pair("var a = 10; return b = a, b = b+1;\n",
   1926                      handle(Smi::FromInt(11), isolate)),
   1927       std::make_pair("var a = 10; return b = a, b = b+1, b + 10;\n",
   1928                      handle(Smi::FromInt(21), isolate))};
   1929 
   1930   for (size_t i = 0; i < arraysize(literals); i++) {
   1931     std::string source(InterpreterTester::SourceForBody(literals[i].first));
   1932     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1933     auto callable = tester.GetCallable<>();
   1934 
   1935     Handle<i::Object> return_value = callable().ToHandleChecked();
   1936     CHECK(return_value->SameValue(*literals[i].second));
   1937   }
   1938 }
   1939 
   1940 
   1941 TEST(InterpreterLogicalOr) {
   1942   HandleAndZoneScope handles;
   1943   i::Isolate* isolate = handles.main_isolate();
   1944   i::Factory* factory = isolate->factory();
   1945 
   1946   std::pair<const char*, Handle<Object>> literals[] = {
   1947       std::make_pair("var a, b; return a || b;\n", factory->undefined_value()),
   1948       std::make_pair("var a, b = 10; return a || b;\n",
   1949                      handle(Smi::FromInt(10), isolate)),
   1950       std::make_pair("var a = '0', b = 10; return a || b;\n",
   1951                      factory->NewStringFromStaticChars("0")),
   1952       std::make_pair("return 0 || 3.2;\n", factory->NewNumber(3.2)),
   1953       std::make_pair("return 'a' || 0;\n",
   1954                      factory->NewStringFromStaticChars("a")),
   1955       std::make_pair("var a = '0', b = 10; return (a == 0) || b;\n",
   1956                      factory->true_value())};
   1957 
   1958   for (size_t i = 0; i < arraysize(literals); i++) {
   1959     std::string source(InterpreterTester::SourceForBody(literals[i].first));
   1960     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1961     auto callable = tester.GetCallable<>();
   1962 
   1963     Handle<i::Object> return_value = callable().ToHandleChecked();
   1964     CHECK(return_value->SameValue(*literals[i].second));
   1965   }
   1966 }
   1967 
   1968 
   1969 TEST(InterpreterLogicalAnd) {
   1970   HandleAndZoneScope handles;
   1971   i::Isolate* isolate = handles.main_isolate();
   1972   i::Factory* factory = isolate->factory();
   1973 
   1974   std::pair<const char*, Handle<Object>> literals[] = {
   1975       std::make_pair("var a, b = 10; return a && b;\n",
   1976                      factory->undefined_value()),
   1977       std::make_pair("var a = 0, b = 10; return a && b / a;\n",
   1978                      handle(Smi::FromInt(0), isolate)),
   1979       std::make_pair("var a = '0', b = 10; return a && b;\n",
   1980                      handle(Smi::FromInt(10), isolate)),
   1981       std::make_pair("return 0.0 && 3.2;\n", handle(Smi::FromInt(0), isolate)),
   1982       std::make_pair("return 'a' && 'b';\n",
   1983                      factory->NewStringFromStaticChars("b")),
   1984       std::make_pair("return 'a' && 0 || 'b', 'c';\n",
   1985                      factory->NewStringFromStaticChars("c")),
   1986       std::make_pair("var x = 1, y = 3; return x && 0 + 1 || y;\n",
   1987                      handle(Smi::FromInt(1), isolate)),
   1988       std::make_pair("var x = 1, y = 3; return (x == 1) && (3 == 3) || y;\n",
   1989                      factory->true_value())};
   1990 
   1991   for (size_t i = 0; i < arraysize(literals); i++) {
   1992     std::string source(InterpreterTester::SourceForBody(literals[i].first));
   1993     InterpreterTester tester(handles.main_isolate(), source.c_str());
   1994     auto callable = tester.GetCallable<>();
   1995 
   1996     Handle<i::Object> return_value = callable().ToHandleChecked();
   1997     CHECK(return_value->SameValue(*literals[i].second));
   1998   }
   1999 }
   2000 
   2001 
   2002 TEST(InterpreterTryCatch) {
   2003   HandleAndZoneScope handles;
   2004   i::Isolate* isolate = handles.main_isolate();
   2005 
   2006   std::pair<const char*, Handle<Object>> catches[] = {
   2007       std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
   2008                      handle(Smi::FromInt(2), isolate)),
   2009       std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;",
   2010                      handle(Smi::FromInt(2), isolate)),
   2011       std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
   2012                      handle(Smi::FromInt(3), isolate)),
   2013       std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };"
   2014                      "       try { throw a } catch(e) { a = e + 3 }; return a;",
   2015                      handle(Smi::FromInt(6), isolate)),
   2016   };
   2017 
   2018   for (size_t i = 0; i < arraysize(catches); i++) {
   2019     std::string source(InterpreterTester::SourceForBody(catches[i].first));
   2020     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2021     auto callable = tester.GetCallable<>();
   2022 
   2023     Handle<i::Object> return_value = callable().ToHandleChecked();
   2024     CHECK(return_value->SameValue(*catches[i].second));
   2025   }
   2026 }
   2027 
   2028 
   2029 TEST(InterpreterTryFinally) {
   2030   HandleAndZoneScope handles;
   2031   i::Isolate* isolate = handles.main_isolate();
   2032   i::Factory* factory = isolate->factory();
   2033 
   2034   std::pair<const char*, Handle<Object>> finallies[] = {
   2035       std::make_pair(
   2036           "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
   2037           factory->NewStringFromStaticChars("R4")),
   2038       std::make_pair(
   2039           "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
   2040           factory->NewStringFromStaticChars("R23")),
   2041       std::make_pair(
   2042           "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
   2043           factory->NewStringFromStaticChars("E23")),
   2044       std::make_pair(
   2045           "var a = 1; try { a = 2; throw 23; } finally { return a; };",
   2046           factory->NewStringFromStaticChars("R2")),
   2047       std::make_pair(
   2048           "var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
   2049           factory->NewStringFromStaticChars("E42")),
   2050       std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
   2051                      "  try { a = 2; break; } finally { a = 3; }"
   2052                      "} return a + i;",
   2053                      factory->NewStringFromStaticChars("R13")),
   2054       std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
   2055                      "  try { a = 2; continue; } finally { a = 3; }"
   2056                      "} return a + i;",
   2057                      factory->NewStringFromStaticChars("R23")),
   2058       std::make_pair("var a = 1; try { a = 2;"
   2059                      "  try { a = 3; throw 23; } finally { a = 4; }"
   2060                      "} catch(e) { a = a + e; } return a;",
   2061                      factory->NewStringFromStaticChars("R27")),
   2062       std::make_pair("var func_name;"
   2063                      "function tcf2(a) {"
   2064                      "  try { throw new Error('boom');} "
   2065                      "  catch(e) {return 153; } "
   2066                      "  finally {func_name = tcf2.name;}"
   2067                      "}"
   2068                      "tcf2();"
   2069                      "return func_name;",
   2070                      factory->NewStringFromStaticChars("Rtcf2")),
   2071   };
   2072 
   2073   const char* try_wrapper =
   2074       "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()";
   2075 
   2076   for (size_t i = 0; i < arraysize(finallies); i++) {
   2077     std::string source(InterpreterTester::SourceForBody(finallies[i].first));
   2078     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2079     tester.GetCallable<>();
   2080     Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
   2081     CHECK(wrapped->SameValue(*finallies[i].second));
   2082   }
   2083 }
   2084 
   2085 
   2086 TEST(InterpreterThrow) {
   2087   HandleAndZoneScope handles;
   2088   i::Isolate* isolate = handles.main_isolate();
   2089   i::Factory* factory = isolate->factory();
   2090 
   2091   std::pair<const char*, Handle<Object>> throws[] = {
   2092       std::make_pair("throw undefined;\n",
   2093                      factory->undefined_value()),
   2094       std::make_pair("throw 1;\n",
   2095                      handle(Smi::FromInt(1), isolate)),
   2096       std::make_pair("throw 'Error';\n",
   2097                      factory->NewStringFromStaticChars("Error")),
   2098       std::make_pair("var a = true; if (a) { throw 'Error'; }\n",
   2099                      factory->NewStringFromStaticChars("Error")),
   2100       std::make_pair("var a = false; if (a) { throw 'Error'; }\n",
   2101                      factory->undefined_value()),
   2102       std::make_pair("throw 'Error1'; throw 'Error2'\n",
   2103                      factory->NewStringFromStaticChars("Error1")),
   2104   };
   2105 
   2106   const char* try_wrapper =
   2107       "(function() { try { f(); } catch(e) { return e; }})()";
   2108 
   2109   for (size_t i = 0; i < arraysize(throws); i++) {
   2110     std::string source(InterpreterTester::SourceForBody(throws[i].first));
   2111     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2112     tester.GetCallable<>();
   2113     Handle<Object> thrown_obj = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
   2114     CHECK(thrown_obj->SameValue(*throws[i].second));
   2115   }
   2116 }
   2117 
   2118 
   2119 TEST(InterpreterCountOperators) {
   2120   HandleAndZoneScope handles;
   2121   i::Isolate* isolate = handles.main_isolate();
   2122   i::Factory* factory = isolate->factory();
   2123 
   2124   std::pair<const char*, Handle<Object>> count_ops[] = {
   2125       std::make_pair("var a = 1; return ++a;",
   2126                      handle(Smi::FromInt(2), isolate)),
   2127       std::make_pair("var a = 1; return a++;",
   2128                      handle(Smi::FromInt(1), isolate)),
   2129       std::make_pair("var a = 5; return --a;",
   2130                      handle(Smi::FromInt(4), isolate)),
   2131       std::make_pair("var a = 5; return a--;",
   2132                      handle(Smi::FromInt(5), isolate)),
   2133       std::make_pair("var a = 5.2; return --a;",
   2134                      factory->NewHeapNumber(4.2)),
   2135       std::make_pair("var a = 'string'; return ++a;",
   2136                      factory->nan_value()),
   2137       std::make_pair("var a = 'string'; return a--;",
   2138                      factory->nan_value()),
   2139       std::make_pair("var a = true; return ++a;",
   2140                      handle(Smi::FromInt(2), isolate)),
   2141       std::make_pair("var a = false; return a--;",
   2142                      handle(Smi::FromInt(0), isolate)),
   2143       std::make_pair("var a = { val: 11 }; return ++a.val;",
   2144                      handle(Smi::FromInt(12), isolate)),
   2145       std::make_pair("var a = { val: 11 }; return a.val--;",
   2146                      handle(Smi::FromInt(11), isolate)),
   2147       std::make_pair("var a = { val: 11 }; return ++a.val;",
   2148                      handle(Smi::FromInt(12), isolate)),
   2149       std::make_pair("var name = 'val'; var a = { val: 22 }; return --a[name];",
   2150                      handle(Smi::FromInt(21), isolate)),
   2151       std::make_pair("var name = 'val'; var a = { val: 22 }; return a[name]++;",
   2152                      handle(Smi::FromInt(22), isolate)),
   2153       std::make_pair("var a = 1; (function() { a = 2 })(); return ++a;",
   2154                      handle(Smi::FromInt(3), isolate)),
   2155       std::make_pair("var a = 1; (function() { a = 2 })(); return a--;",
   2156                      handle(Smi::FromInt(2), isolate)),
   2157       std::make_pair("var i = 5; while(i--) {}; return i;",
   2158                      handle(Smi::FromInt(-1), isolate)),
   2159       std::make_pair("var i = 1; if(i--) { return 1; } else { return 2; };",
   2160                      handle(Smi::FromInt(1), isolate)),
   2161       std::make_pair("var i = -2; do {} while(i++) {}; return i;",
   2162                       handle(Smi::FromInt(1), isolate)),
   2163       std::make_pair("var i = -1; for(; i++; ) {}; return i",
   2164                       handle(Smi::FromInt(1), isolate)),
   2165       std::make_pair("var i = 20; switch(i++) {\n"
   2166                      "  case 20: return 1;\n"
   2167                      "  default: return 2;\n"
   2168                      "}",
   2169                      handle(Smi::FromInt(1), isolate)),
   2170   };
   2171 
   2172   for (size_t i = 0; i < arraysize(count_ops); i++) {
   2173     std::string source(InterpreterTester::SourceForBody(count_ops[i].first));
   2174     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2175     auto callable = tester.GetCallable<>();
   2176 
   2177     Handle<i::Object> return_value = callable().ToHandleChecked();
   2178     CHECK(return_value->SameValue(*count_ops[i].second));
   2179   }
   2180 }
   2181 
   2182 
   2183 TEST(InterpreterGlobalCountOperators) {
   2184   HandleAndZoneScope handles;
   2185   i::Isolate* isolate = handles.main_isolate();
   2186 
   2187   std::pair<const char*, Handle<Object>> count_ops[] = {
   2188       std::make_pair("var global = 100;function f(){ return ++global; }",
   2189                      handle(Smi::FromInt(101), isolate)),
   2190       std::make_pair("var global = 100; function f(){ return --global; }",
   2191                      handle(Smi::FromInt(99), isolate)),
   2192       std::make_pair("var global = 100; function f(){ return global++; }",
   2193                      handle(Smi::FromInt(100), isolate)),
   2194       std::make_pair("unallocated = 200; function f(){ return ++unallocated; }",
   2195                      handle(Smi::FromInt(201), isolate)),
   2196       std::make_pair("unallocated = 200; function f(){ return --unallocated; }",
   2197                      handle(Smi::FromInt(199), isolate)),
   2198       std::make_pair("unallocated = 200; function f(){ return unallocated++; }",
   2199                      handle(Smi::FromInt(200), isolate)),
   2200   };
   2201 
   2202   for (size_t i = 0; i < arraysize(count_ops); i++) {
   2203     InterpreterTester tester(handles.main_isolate(), count_ops[i].first);
   2204     auto callable = tester.GetCallable<>();
   2205 
   2206     Handle<i::Object> return_value = callable().ToHandleChecked();
   2207     CHECK(return_value->SameValue(*count_ops[i].second));
   2208   }
   2209 }
   2210 
   2211 
   2212 TEST(InterpreterCompoundExpressions) {
   2213   HandleAndZoneScope handles;
   2214   i::Isolate* isolate = handles.main_isolate();
   2215   i::Factory* factory = isolate->factory();
   2216 
   2217   std::pair<const char*, Handle<Object>> compound_expr[] = {
   2218       std::make_pair("var a = 1; a += 2; return a;",
   2219                      Handle<Object>(Smi::FromInt(3), isolate)),
   2220       std::make_pair("var a = 10; a /= 2; return a;",
   2221                      Handle<Object>(Smi::FromInt(5), isolate)),
   2222       std::make_pair("var a = 'test'; a += 'ing'; return a;",
   2223                      factory->NewStringFromStaticChars("testing")),
   2224       std::make_pair("var a = { val: 2 }; a.val *= 2; return a.val;",
   2225                      Handle<Object>(Smi::FromInt(4), isolate)),
   2226       std::make_pair("var a = 1; (function f() { a = 2; })(); a += 24;"
   2227                      "return a;",
   2228                      Handle<Object>(Smi::FromInt(26), isolate)),
   2229   };
   2230 
   2231   for (size_t i = 0; i < arraysize(compound_expr); i++) {
   2232     std::string source(
   2233         InterpreterTester::SourceForBody(compound_expr[i].first));
   2234     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2235     auto callable = tester.GetCallable<>();
   2236 
   2237     Handle<i::Object> return_value = callable().ToHandleChecked();
   2238     CHECK(return_value->SameValue(*compound_expr[i].second));
   2239   }
   2240 }
   2241 
   2242 
   2243 TEST(InterpreterGlobalCompoundExpressions) {
   2244   HandleAndZoneScope handles;
   2245   i::Isolate* isolate = handles.main_isolate();
   2246 
   2247   std::pair<const char*, Handle<Object>> compound_expr[2] = {
   2248       std::make_pair("var global = 100;"
   2249                      "function f() { global += 20; return global; }",
   2250                      Handle<Object>(Smi::FromInt(120), isolate)),
   2251       std::make_pair("unallocated = 100;"
   2252                      "function f() { unallocated -= 20; return unallocated; }",
   2253                      Handle<Object>(Smi::FromInt(80), isolate)),
   2254   };
   2255 
   2256   for (size_t i = 0; i < arraysize(compound_expr); i++) {
   2257     InterpreterTester tester(handles.main_isolate(), compound_expr[i].first);
   2258     auto callable = tester.GetCallable<>();
   2259 
   2260     Handle<i::Object> return_value = callable().ToHandleChecked();
   2261     CHECK(return_value->SameValue(*compound_expr[i].second));
   2262   }
   2263 }
   2264 
   2265 
   2266 TEST(InterpreterCreateArguments) {
   2267   HandleAndZoneScope handles;
   2268   i::Isolate* isolate = handles.main_isolate();
   2269   i::Factory* factory = isolate->factory();
   2270 
   2271   std::pair<const char*, int> create_args[] = {
   2272       std::make_pair("function f() { return arguments[0]; }", 0),
   2273       std::make_pair("function f(a) { return arguments[0]; }", 0),
   2274       std::make_pair("function f() { return arguments[2]; }", 2),
   2275       std::make_pair("function f(a) { return arguments[2]; }", 2),
   2276       std::make_pair("function f(a, b, c, d) { return arguments[2]; }", 2),
   2277       std::make_pair("function f(a) {"
   2278                      "'use strict'; return arguments[0]; }",
   2279                      0),
   2280       std::make_pair("function f(a, b, c, d) {"
   2281                      "'use strict'; return arguments[2]; }",
   2282                      2),
   2283       // Check arguments are mapped in sloppy mode and unmapped in strict.
   2284       std::make_pair("function f(a, b, c, d) {"
   2285                      "  c = b; return arguments[2]; }",
   2286                      1),
   2287       std::make_pair("function f(a, b, c, d) {"
   2288                      "  'use strict'; c = b; return arguments[2]; }",
   2289                      2),
   2290       // Check arguments for duplicate parameters in sloppy mode.
   2291       std::make_pair("function f(a, a, b) { return arguments[1]; }", 1),
   2292       // check rest parameters
   2293       std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
   2294       std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
   2295       std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0),
   2296       std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1),
   2297       std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2),
   2298       std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1),
   2299       std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }",
   2300                      2),
   2301   };
   2302 
   2303   // Test passing no arguments.
   2304   for (size_t i = 0; i < arraysize(create_args); i++) {
   2305     InterpreterTester tester(handles.main_isolate(), create_args[i].first);
   2306     auto callable = tester.GetCallable<>();
   2307     Handle<Object> return_val = callable().ToHandleChecked();
   2308     CHECK(return_val.is_identical_to(factory->undefined_value()));
   2309   }
   2310 
   2311   // Test passing one argument.
   2312   for (size_t i = 0; i < arraysize(create_args); i++) {
   2313     InterpreterTester tester(handles.main_isolate(), create_args[i].first);
   2314     auto callable = tester.GetCallable<Handle<Object>>();
   2315     Handle<Object> return_val =
   2316         callable(handle(Smi::FromInt(40), isolate)).ToHandleChecked();
   2317     if (create_args[i].second == 0) {
   2318       CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(40));
   2319     } else {
   2320       CHECK(return_val.is_identical_to(factory->undefined_value()));
   2321     }
   2322   }
   2323 
   2324   // Test passing three argument.
   2325   for (size_t i = 0; i < arraysize(create_args); i++) {
   2326     Handle<Object> args[3] = {
   2327         handle(Smi::FromInt(40), isolate),
   2328         handle(Smi::FromInt(60), isolate),
   2329         handle(Smi::FromInt(80), isolate),
   2330     };
   2331 
   2332     InterpreterTester tester(handles.main_isolate(), create_args[i].first);
   2333     auto callable =
   2334         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
   2335     Handle<Object> return_val =
   2336         callable(args[0], args[1], args[2]).ToHandleChecked();
   2337     CHECK(return_val->SameValue(*args[create_args[i].second]));
   2338   }
   2339 }
   2340 
   2341 
   2342 TEST(InterpreterConditional) {
   2343   HandleAndZoneScope handles;
   2344   i::Isolate* isolate = handles.main_isolate();
   2345 
   2346   std::pair<const char*, Handle<Object>> conditional[] = {
   2347       std::make_pair("return true ? 2 : 3;",
   2348                      handle(Smi::FromInt(2), isolate)),
   2349       std::make_pair("return false ? 2 : 3;",
   2350                      handle(Smi::FromInt(3), isolate)),
   2351       std::make_pair("var a = 1; return a ? 20 : 30;",
   2352                      handle(Smi::FromInt(20), isolate)),
   2353       std::make_pair("var a = 1; return a ? 20 : 30;",
   2354                      handle(Smi::FromInt(20), isolate)),
   2355       std::make_pair("var a = 'string'; return a ? 20 : 30;",
   2356                      handle(Smi::FromInt(20), isolate)),
   2357       std::make_pair("var a = undefined; return a ? 20 : 30;",
   2358                      handle(Smi::FromInt(30), isolate)),
   2359       std::make_pair("return 1 ? 2 ? 3 : 4 : 5;",
   2360                      handle(Smi::FromInt(3), isolate)),
   2361       std::make_pair("return 0 ? 2 ? 3 : 4 : 5;",
   2362                      handle(Smi::FromInt(5), isolate)),
   2363   };
   2364 
   2365   for (size_t i = 0; i < arraysize(conditional); i++) {
   2366     std::string source(InterpreterTester::SourceForBody(conditional[i].first));
   2367     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2368     auto callable = tester.GetCallable<>();
   2369 
   2370     Handle<i::Object> return_value = callable().ToHandleChecked();
   2371     CHECK(return_value->SameValue(*conditional[i].second));
   2372   }
   2373 }
   2374 
   2375 
   2376 TEST(InterpreterDelete) {
   2377   HandleAndZoneScope handles;
   2378   i::Isolate* isolate = handles.main_isolate();
   2379   i::Factory* factory = isolate->factory();
   2380 
   2381   // Tests for delete for local variables that work both in strict
   2382   // and sloppy modes
   2383   std::pair<const char*, Handle<Object>> test_delete[] = {
   2384       std::make_pair(
   2385           "var a = { x:10, y:'abc', z:30.2}; delete a.x; return a.x;\n",
   2386           factory->undefined_value()),
   2387       std::make_pair(
   2388           "var b = { x:10, y:'abc', z:30.2}; delete b.x; return b.y;\n",
   2389           factory->NewStringFromStaticChars("abc")),
   2390       std::make_pair("var c = { x:10, y:'abc', z:30.2}; var d = c; delete d.x; "
   2391                      "return c.x;\n",
   2392                      factory->undefined_value()),
   2393       std::make_pair("var e = { x:10, y:'abc', z:30.2}; var g = e; delete g.x; "
   2394                      "return e.y;\n",
   2395                      factory->NewStringFromStaticChars("abc")),
   2396       std::make_pair("var a = { x:10, y:'abc', z:30.2};\n"
   2397                      "var b = a;"
   2398                      "delete b.x;"
   2399                      "return b.x;\n",
   2400                      factory->undefined_value()),
   2401       std::make_pair("var a = {1:10};\n"
   2402                      "(function f1() {return a;});"
   2403                      "return delete a[1];",
   2404                      factory->ToBoolean(true)),
   2405       std::make_pair("return delete this;", factory->ToBoolean(true)),
   2406       std::make_pair("return delete 'test';", factory->ToBoolean(true))};
   2407 
   2408   // Test delete in sloppy mode
   2409   for (size_t i = 0; i < arraysize(test_delete); i++) {
   2410     std::string source(InterpreterTester::SourceForBody(test_delete[i].first));
   2411     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2412     auto callable = tester.GetCallable<>();
   2413 
   2414     Handle<i::Object> return_value = callable().ToHandleChecked();
   2415     CHECK(return_value->SameValue(*test_delete[i].second));
   2416   }
   2417 
   2418   // Test delete in strict mode
   2419   for (size_t i = 0; i < arraysize(test_delete); i++) {
   2420     std::string strict_test =
   2421         "'use strict'; " + std::string(test_delete[i].first);
   2422     std::string source(InterpreterTester::SourceForBody(strict_test.c_str()));
   2423     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2424     auto callable = tester.GetCallable<>();
   2425 
   2426     Handle<i::Object> return_value = callable().ToHandleChecked();
   2427     CHECK(return_value->SameValue(*test_delete[i].second));
   2428   }
   2429 }
   2430 
   2431 
   2432 TEST(InterpreterDeleteSloppyUnqualifiedIdentifier) {
   2433   HandleAndZoneScope handles;
   2434   i::Isolate* isolate = handles.main_isolate();
   2435   i::Factory* factory = isolate->factory();
   2436 
   2437   // These tests generate a syntax error for strict mode. We don't
   2438   // test for it here.
   2439   std::pair<const char*, Handle<Object>> test_delete[] = {
   2440       std::make_pair("var sloppy_a = { x:10, y:'abc'};\n"
   2441                      "var sloppy_b = delete sloppy_a;\n"
   2442                      "if (delete sloppy_a) {\n"
   2443                      "  return undefined;\n"
   2444                      "} else {\n"
   2445                      "  return sloppy_a.x;\n"
   2446                      "}\n",
   2447                      Handle<Object>(Smi::FromInt(10), isolate)),
   2448       // TODO(mythria) When try-catch is implemented change the tests to check
   2449       // if delete actually deletes
   2450       std::make_pair("sloppy_a = { x:10, y:'abc'};\n"
   2451                      "var sloppy_b = delete sloppy_a;\n"
   2452                      // "try{return a.x;} catch(e) {return b;}\n"
   2453                      "return sloppy_b;",
   2454                      factory->ToBoolean(true)),
   2455       std::make_pair("sloppy_a = { x:10, y:'abc'};\n"
   2456                      "var sloppy_b = delete sloppy_c;\n"
   2457                      "return sloppy_b;",
   2458                      factory->ToBoolean(true))};
   2459 
   2460   for (size_t i = 0; i < arraysize(test_delete); i++) {
   2461     std::string source(InterpreterTester::SourceForBody(test_delete[i].first));
   2462     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2463     auto callable = tester.GetCallable<>();
   2464 
   2465     Handle<i::Object> return_value = callable().ToHandleChecked();
   2466     CHECK(return_value->SameValue(*test_delete[i].second));
   2467   }
   2468 }
   2469 
   2470 
   2471 TEST(InterpreterGlobalDelete) {
   2472   HandleAndZoneScope handles;
   2473   i::Isolate* isolate = handles.main_isolate();
   2474   i::Factory* factory = isolate->factory();
   2475 
   2476   std::pair<const char*, Handle<Object>> test_global_delete[] = {
   2477       std::make_pair("var a = { x:10, y:'abc', z:30.2 };\n"
   2478                      "function f() {\n"
   2479                      "  delete a.x;\n"
   2480                      "  return a.x;\n"
   2481                      "}\n"
   2482                      "f();\n",
   2483                      factory->undefined_value()),
   2484       std::make_pair("var b = {1:10, 2:'abc', 3:30.2 };\n"
   2485                      "function f() {\n"
   2486                      "  delete b[2];\n"
   2487                      "  return b[1];\n"
   2488                      " }\n"
   2489                      "f();\n",
   2490                      Handle<Object>(Smi::FromInt(10), isolate)),
   2491       std::make_pair("var c = { x:10, y:'abc', z:30.2 };\n"
   2492                      "function f() {\n"
   2493                      "   var d = c;\n"
   2494                      "   delete d.y;\n"
   2495                      "   return d.x;\n"
   2496                      "}\n"
   2497                      "f();\n",
   2498                      Handle<Object>(Smi::FromInt(10), isolate)),
   2499       std::make_pair("e = { x:10, y:'abc' };\n"
   2500                      "function f() {\n"
   2501                      "  return delete e;\n"
   2502                      "}\n"
   2503                      "f();\n",
   2504                      factory->ToBoolean(true)),
   2505       std::make_pair("var g = { x:10, y:'abc' };\n"
   2506                      "function f() {\n"
   2507                      "  return delete g;\n"
   2508                      "}\n"
   2509                      "f();\n",
   2510                      factory->ToBoolean(false)),
   2511       std::make_pair("function f() {\n"
   2512                      "  var obj = {h:10, f1() {return delete this;}};\n"
   2513                      "  return obj.f1();\n"
   2514                      "}\n"
   2515                      "f();",
   2516                      factory->ToBoolean(true)),
   2517       std::make_pair("function f() {\n"
   2518                      "  var obj = {h:10,\n"
   2519                      "             f1() {\n"
   2520                      "              'use strict';\n"
   2521                      "              return delete this.h;}};\n"
   2522                      "  return obj.f1();\n"
   2523                      "}\n"
   2524                      "f();",
   2525                      factory->ToBoolean(true))};
   2526 
   2527   for (size_t i = 0; i < arraysize(test_global_delete); i++) {
   2528     InterpreterTester tester(handles.main_isolate(),
   2529                              test_global_delete[i].first);
   2530     auto callable = tester.GetCallable<>();
   2531 
   2532     Handle<i::Object> return_value = callable().ToHandleChecked();
   2533     CHECK(return_value->SameValue(*test_global_delete[i].second));
   2534   }
   2535 }
   2536 
   2537 
   2538 TEST(InterpreterBasicLoops) {
   2539   HandleAndZoneScope handles;
   2540   i::Isolate* isolate = handles.main_isolate();
   2541   i::Factory* factory = isolate->factory();
   2542 
   2543   std::pair<const char*, Handle<Object>> loops[] = {
   2544       std::make_pair("var a = 10; var b = 1;\n"
   2545                      "while (a) {\n"
   2546                      "  b = b * 2;\n"
   2547                      "  a = a - 1;\n"
   2548                      "};\n"
   2549                      "return b;\n",
   2550                      factory->NewHeapNumber(1024)),
   2551       std::make_pair("var a = 1; var b = 1;\n"
   2552                      "do {\n"
   2553                      "  b = b * 2;\n"
   2554                      "  --a;\n"
   2555                      "} while(a);\n"
   2556                      "return b;\n",
   2557                      handle(Smi::FromInt(2), isolate)),
   2558       std::make_pair("var b = 1;\n"
   2559                      "for ( var a = 10; a; a--) {\n"
   2560                      "  b *= 2;\n"
   2561                      "}\n"
   2562                      "return b;",
   2563                      factory->NewHeapNumber(1024)),
   2564       std::make_pair("var a = 10; var b = 1;\n"
   2565                      "while (a > 0) {\n"
   2566                      "  b = b * 2;\n"
   2567                      "  a = a - 1;\n"
   2568                      "};\n"
   2569                      "return b;\n",
   2570                      factory->NewHeapNumber(1024)),
   2571       std::make_pair("var a = 1; var b = 1;\n"
   2572                      "do {\n"
   2573                      "  b = b * 2;\n"
   2574                      "  --a;\n"
   2575                      "} while(a);\n"
   2576                      "return b;\n",
   2577                      handle(Smi::FromInt(2), isolate)),
   2578       std::make_pair("var b = 1;\n"
   2579                      "for ( var a = 10; a > 0; a--) {\n"
   2580                      "  b *= 2;\n"
   2581                      "}\n"
   2582                      "return b;",
   2583                      factory->NewHeapNumber(1024)),
   2584       std::make_pair("var a = 10; var b = 1;\n"
   2585                      "while (false) {\n"
   2586                      "  b = b * 2;\n"
   2587                      "  a = a - 1;\n"
   2588                      "}\n"
   2589                      "return b;\n",
   2590                      Handle<Object>(Smi::FromInt(1), isolate)),
   2591       std::make_pair("var a = 10; var b = 1;\n"
   2592                      "while (true) {\n"
   2593                      "  b = b * 2;\n"
   2594                      "  a = a - 1;\n"
   2595                      "  if (a == 0) break;"
   2596                      "  continue;"
   2597                      "}\n"
   2598                      "return b;\n",
   2599                      factory->NewHeapNumber(1024)),
   2600       std::make_pair("var a = 10; var b = 1;\n"
   2601                      "do {\n"
   2602                      "  b = b * 2;\n"
   2603                      "  a = a - 1;\n"
   2604                      "  if (a == 0) break;"
   2605                      "} while(true);\n"
   2606                      "return b;\n",
   2607                      factory->NewHeapNumber(1024)),
   2608       std::make_pair("var a = 10; var b = 1;\n"
   2609                      "do {\n"
   2610                      "  b = b * 2;\n"
   2611                      "  a = a - 1;\n"
   2612                      "  if (a == 0) break;"
   2613                      "} while(false);\n"
   2614                      "return b;\n",
   2615                      Handle<Object>(Smi::FromInt(2), isolate)),
   2616       std::make_pair("var a = 10; var b = 1;\n"
   2617                      "for ( a = 1, b = 30; false; ) {\n"
   2618                      "  b = b * 2;\n"
   2619                      "}\n"
   2620                      "return b;\n",
   2621                      Handle<Object>(Smi::FromInt(30), isolate))};
   2622 
   2623   for (size_t i = 0; i < arraysize(loops); i++) {
   2624     std::string source(InterpreterTester::SourceForBody(loops[i].first));
   2625     InterpreterTester tester(handles.main_isolate(), source.c_str());
   2626     auto callable = tester.GetCallable<>();
   2627 
   2628     Handle<i::Object> return_value = callable().ToHandleChecked();
   2629     CHECK(return_value->SameValue(*loops[i].second));
   2630   }
   2631 }
   2632 
   2633 
   2634 TEST(InterpreterForIn) {
   2635   std::pair<const char*, int> for_in_samples[] = {
   2636       {"var r = -1;\n"
   2637        "for (var a in null) { r = a; }\n"
   2638        "return r;\n",
   2639        -1},
   2640       {"var r = -1;\n"
   2641        "for (var a in undefined) { r = a; }\n"
   2642        "return r;\n",
   2643        -1},
   2644       {"var r = 0;\n"
   2645        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
   2646        "return r;\n",
   2647        0xf},
   2648       {"var r = 0;\n"
   2649        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
   2650        "var r = 0;\n"
   2651        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
   2652        "return r;\n",
   2653        0xf},
   2654       {"var r = 0;\n"
   2655        "for (var a in 'foobar') { r = r + (1 << a); }\n"
   2656        "return r;\n",
   2657        0x3f},
   2658       {"var r = 0;\n"
   2659        "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\n"
   2660        "  r = r + Number(a);\n"
   2661        " }\n"
   2662        " return r;\n",
   2663        1111},
   2664       {"var r = 0;\n"
   2665        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
   2666        "for (var a in data) {\n"
   2667        "  if (a == 1) delete data[1];\n"
   2668        "  r = r + Number(a);\n"
   2669        " }\n"
   2670        " return r;\n",
   2671        1111},
   2672       {"var r = 0;\n"
   2673        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
   2674        "for (var a in data) {\n"
   2675        "  if (a == 10) delete data[100];\n"
   2676        "  r = r + Number(a);\n"
   2677        " }\n"
   2678        " return r;\n",
   2679        1011},
   2680       {"var r = 0;\n"
   2681        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
   2682        "for (var a in data) {\n"
   2683        "  if (a == 10) data[10000] = 4;\n"
   2684        "  r = r + Number(a);\n"
   2685        " }\n"
   2686        " return r;\n",
   2687        1111},
   2688       {"var r = 0;\n"
   2689        "var input = 'foobar';\n"
   2690        "for (var a in input) {\n"
   2691        "  if (input[a] == 'b') break;\n"
   2692        "  r = r + (1 << a);\n"
   2693        "}\n"
   2694        "return r;\n",
   2695        0x7},
   2696       {"var r = 0;\n"
   2697        "var input = 'foobar';\n"
   2698        "for (var a in input) {\n"
   2699        " if (input[a] == 'b') continue;\n"
   2700        " r = r + (1 << a);\n"
   2701        "}\n"
   2702        "return r;\n",
   2703        0x37},
   2704       {"var r = 0;\n"
   2705        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
   2706        "for (var a in data) {\n"
   2707        "  if (a == 10) {\n"
   2708        "     data[10000] = 4;\n"
   2709        "  }\n"
   2710        "  r = r + Number(a);\n"
   2711        "}\n"
   2712        "return r;\n",
   2713        1111},
   2714       {"var r = [ 3 ];\n"
   2715        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
   2716        "for (r[10] in data) {\n"
   2717        "}\n"
   2718        "return Number(r[10]);\n",
   2719        1000},
   2720       {"var r = [ 3 ];\n"
   2721        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
   2722        "for (r['100'] in data) {\n"
   2723        "}\n"
   2724        "return Number(r['100']);\n",
   2725        1000},
   2726       {"var obj = {}\n"
   2727        "var descObj = new Boolean(false);\n"
   2728        "var accessed = 0;\n"
   2729        "descObj.enumerable = true;\n"
   2730        "Object.defineProperties(obj, { prop:descObj });\n"
   2731        "for (var p in obj) {\n"
   2732        "  if (p === 'prop') { accessed = 1; }\n"
   2733        "}\n"
   2734        "return accessed;",
   2735        1},
   2736       {"var appointment = {};\n"
   2737        "Object.defineProperty(appointment, 'startTime', {\n"
   2738        "    value: 1001,\n"
   2739        "    writable: false,\n"
   2740        "    enumerable: false,\n"
   2741        "    configurable: true\n"
   2742        "});\n"
   2743        "Object.defineProperty(appointment, 'name', {\n"
   2744        "    value: 'NAME',\n"
   2745        "    writable: false,\n"
   2746        "    enumerable: false,\n"
   2747        "    configurable: true\n"
   2748        "});\n"
   2749        "var meeting = Object.create(appointment);\n"
   2750        "Object.defineProperty(meeting, 'conferenceCall', {\n"
   2751        "    value: 'In-person meeting',\n"
   2752        "    writable: false,\n"
   2753        "    enumerable: false,\n"
   2754        "    configurable: true\n"
   2755        "});\n"
   2756        "\n"
   2757        "var teamMeeting = Object.create(meeting);\n"
   2758        "\n"
   2759        "var flags = 0;\n"
   2760        "for (var p in teamMeeting) {\n"
   2761        "    if (p === 'startTime') {\n"
   2762        "        flags |= 1;\n"
   2763        "    }\n"
   2764        "    if (p === 'name') {\n"
   2765        "        flags |= 2;\n"
   2766        "    }\n"
   2767        "    if (p === 'conferenceCall') {\n"
   2768        "        flags |= 4;\n"
   2769        "    }\n"
   2770        "}\n"
   2771        "\n"
   2772        "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
   2773        "    !teamMeeting.hasOwnProperty('startTime') &&\n"
   2774        "    !teamMeeting.hasOwnProperty('conferenceCall');\n"
   2775        "if (!hasOwnProperty) {\n"
   2776        "    flags |= 8;\n"
   2777        "}\n"
   2778        "return flags;\n",
   2779        0},
   2780       {"var data = {x:23, y:34};\n"
   2781        " var result = 0;\n"
   2782        "var o = {};\n"
   2783        "var arr = [o];\n"
   2784        "for (arr[0].p in data)\n"       // This is to test if value is loaded
   2785        "  result += data[arr[0].p];\n"  // back from accumulator before storing
   2786        "return result;\n",              // named properties.
   2787        57},
   2788       {"var data = {x:23, y:34};\n"
   2789        "var result = 0;\n"
   2790        "var o = {};\n"
   2791        "var i = 0;\n"
   2792        "for (o[i++] in data)\n"       // This is to test if value is loaded
   2793        "  result += data[o[i-1]];\n"  // back from accumulator before
   2794        "return result;\n",            // storing keyed properties.
   2795        57}};
   2796 
   2797   // Two passes are made for this test. On the first, 8-bit register
   2798   // operands are employed, and on the 16-bit register operands are
   2799   // used.
   2800   for (int pass = 0; pass < 2; pass++) {
   2801     HandleAndZoneScope handles;
   2802     std::ostringstream wide_os;
   2803     if (pass == 1) {
   2804       for (int i = 0; i < 200; i++) {
   2805         wide_os << "var local" << i << " = 0;\n";
   2806       }
   2807     }
   2808 
   2809     for (size_t i = 0; i < arraysize(for_in_samples); i++) {
   2810       std::ostringstream body_os;
   2811       body_os << wide_os.str() << for_in_samples[i].first;
   2812       std::string body(body_os.str());
   2813       std::string function = InterpreterTester::SourceForBody(body.c_str());
   2814       InterpreterTester tester(handles.main_isolate(), function.c_str());
   2815       auto callable = tester.GetCallable<>();
   2816       Handle<Object> return_val = callable().ToHandleChecked();
   2817       CHECK_EQ(Handle<Smi>::cast(return_val)->value(),
   2818                for_in_samples[i].second);
   2819     }
   2820   }
   2821 }
   2822 
   2823 
   2824 TEST(InterpreterForOf) {
   2825   HandleAndZoneScope handles;
   2826   i::Isolate* isolate = handles.main_isolate();
   2827   i::Factory* factory = isolate->factory();
   2828 
   2829   std::pair<const char*, Handle<Object>> for_of[] = {
   2830       {"function f() {\n"
   2831        "  var r = 0;\n"
   2832        "  for (var a of [0,6,7,9]) { r += a; }\n"
   2833        "  return r;\n"
   2834        "}",
   2835        handle(Smi::FromInt(22), isolate)},
   2836       {"function f() {\n"
   2837        "  var r = '';\n"
   2838        "  for (var a of 'foobar') { r = a + r; }\n"
   2839        "  return r;\n"
   2840        "}",
   2841        factory->NewStringFromStaticChars("raboof")},
   2842       {"function f() {\n"
   2843        "  var a = [1, 2, 3];\n"
   2844        "  a.name = 4;\n"
   2845        "  var r = 0;\n"
   2846        "  for (var x of a) { r += x; }\n"
   2847        "  return r;\n"
   2848        "}",
   2849        handle(Smi::FromInt(6), isolate)},
   2850       {"function f() {\n"
   2851        "  var r = '';\n"
   2852        "  var data = [1, 2, 3]; \n"
   2853        "  for (a of data) { delete data[0]; r += a; } return r; }",
   2854        factory->NewStringFromStaticChars("123")},
   2855       {"function f() {\n"
   2856        "  var r = '';\n"
   2857        "  var data = [1, 2, 3]; \n"
   2858        "  for (a of data) { delete data[2]; r += a; } return r; }",
   2859        factory->NewStringFromStaticChars("12undefined")},
   2860       {"function f() {\n"
   2861        "  var r = '';\n"
   2862        "  var data = [1, 2, 3]; \n"
   2863        "  for (a of data) { delete data; r += a; } return r; }",
   2864        factory->NewStringFromStaticChars("123")},
   2865       {"function f() {\n"
   2866        "  var r = '';\n"
   2867        "  var input = 'foobar';\n"
   2868        "  for (var a of input) {\n"
   2869        "    if (a == 'b') break;\n"
   2870        "    r += a;\n"
   2871        "  }\n"
   2872        "  return r;\n"
   2873        "}",
   2874        factory->NewStringFromStaticChars("foo")},
   2875       {"function f() {\n"
   2876        "  var r = '';\n"
   2877        "  var input = 'foobar';\n"
   2878        "  for (var a of input) {\n"
   2879        "    if (a == 'b') continue;\n"
   2880        "    r += a;\n"
   2881        "  }\n"
   2882        "  return r;\n"
   2883        "}",
   2884        factory->NewStringFromStaticChars("fooar")},
   2885       {"function f() {\n"
   2886        "  var r = '';\n"
   2887        "  var data = [1, 2, 3, 4]; \n"
   2888        "  for (a of data) { data[2] = 567; r += a; }\n"
   2889        "  return r;\n"
   2890        "}",
   2891        factory->NewStringFromStaticChars("125674")},
   2892       {"function f() {\n"
   2893        "  var r = '';\n"
   2894        "  var data = [1, 2, 3, 4]; \n"
   2895        "  for (a of data) { data[4] = 567; r += a; }\n"
   2896        "  return r;\n"
   2897        "}",
   2898        factory->NewStringFromStaticChars("1234567")},
   2899       {"function f() {\n"
   2900        "  var r = '';\n"
   2901        "  var data = [1, 2, 3, 4]; \n"
   2902        "  for (a of data) { data[5] = 567; r += a; }\n"
   2903        "  return r;\n"
   2904        "}",
   2905        factory->NewStringFromStaticChars("1234undefined567")},
   2906       {"function f() {\n"
   2907        "  var r = '';\n"
   2908        "  var obj = new Object();\n"
   2909        "  obj[Symbol.iterator] = function() { return {\n"
   2910        "    index: 3,\n"
   2911        "    data: ['a', 'b', 'c', 'd'],"
   2912        "    next: function() {"
   2913        "      return {"
   2914        "        done: this.index == -1,\n"
   2915        "        value: this.index < 0 ? undefined : this.data[this.index--]\n"
   2916        "      }\n"
   2917        "    }\n"
   2918        "    }}\n"
   2919        "  for (a of obj) { r += a }\n"
   2920        "  return r;\n"
   2921        "}",
   2922        factory->NewStringFromStaticChars("dcba")},
   2923   };
   2924 
   2925   for (size_t i = 0; i < arraysize(for_of); i++) {
   2926     InterpreterTester tester(handles.main_isolate(), for_of[i].first);
   2927     auto callable = tester.GetCallable<>();
   2928     Handle<Object> return_val = callable().ToHandleChecked();
   2929     CHECK(return_val->SameValue(*for_of[i].second));
   2930   }
   2931 }
   2932 
   2933 
   2934 TEST(InterpreterSwitch) {
   2935   HandleAndZoneScope handles;
   2936   i::Isolate* isolate = handles.main_isolate();
   2937   i::Factory* factory = isolate->factory();
   2938 
   2939   std::pair<const char*, Handle<Object>> switch_ops[] = {
   2940       std::make_pair("var a = 1;\n"
   2941                      "switch(a) {\n"
   2942                      " case 1: return 2;\n"
   2943                      " case 2: return 3;\n"
   2944                      "}\n",
   2945                      handle(Smi::FromInt(2), isolate)),
   2946       std::make_pair("var a = 1;\n"
   2947                      "switch(a) {\n"
   2948                      " case 2: a = 2; break;\n"
   2949                      " case 1: a = 3; break;\n"
   2950                      "}\n"
   2951                      "return a;",
   2952                      handle(Smi::FromInt(3), isolate)),
   2953       std::make_pair("var a = 1;\n"
   2954                      "switch(a) {\n"
   2955                      " case 1: a = 2; // fall-through\n"
   2956                      " case 2: a = 3; break;\n"
   2957                      "}\n"
   2958                      "return a;",
   2959                      handle(Smi::FromInt(3), isolate)),
   2960       std::make_pair("var a = 100;\n"
   2961                      "switch(a) {\n"
   2962                      " case 1: return 100;\n"
   2963                      " case 2: return 200;\n"
   2964                      "}\n"
   2965                      "return undefined;",
   2966                      factory->undefined_value()),
   2967       std::make_pair("var a = 100;\n"
   2968                      "switch(a) {\n"
   2969                      " case 1: return 100;\n"
   2970                      " case 2: return 200;\n"
   2971                      " default: return 300;\n"
   2972                      "}\n"
   2973                      "return undefined;",
   2974                      handle(Smi::FromInt(300), isolate)),
   2975       std::make_pair("var a = 100;\n"
   2976                      "switch(typeof(a)) {\n"
   2977                      " case 'string': return 1;\n"
   2978                      " case 'number': return 2;\n"
   2979                      " default: return 3;\n"
   2980                      "}\n",
   2981                      handle(Smi::FromInt(2), isolate)),
   2982       std::make_pair("var a = 100;\n"
   2983                      "switch(a) {\n"
   2984                      " case a += 20: return 1;\n"
   2985                      " case a -= 10: return 2;\n"
   2986                      " case a -= 10: return 3;\n"
   2987                      " default: return 3;\n"
   2988                      "}\n",
   2989                      handle(Smi::FromInt(3), isolate)),
   2990       std::make_pair("var a = 1;\n"
   2991                      "switch(a) {\n"
   2992                      " case 1: \n"
   2993                      "   switch(a + 1) {\n"
   2994                      "      case 2 : a += 1; break;\n"
   2995                      "      default : a += 2; break;\n"
   2996                      "   }  // fall-through\n"
   2997                      " case 2: a += 3;\n"
   2998                      "}\n"
   2999                      "return a;",
   3000                      handle(Smi::FromInt(5), isolate)),
   3001   };
   3002 
   3003   for (size_t i = 0; i < arraysize(switch_ops); i++) {
   3004     std::string source(InterpreterTester::SourceForBody(switch_ops[i].first));
   3005     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3006     auto callable = tester.GetCallable<>();
   3007 
   3008     Handle<i::Object> return_value = callable().ToHandleChecked();
   3009     CHECK(return_value->SameValue(*switch_ops[i].second));
   3010   }
   3011 }
   3012 
   3013 
   3014 TEST(InterpreterSloppyThis) {
   3015   HandleAndZoneScope handles;
   3016   i::Isolate* isolate = handles.main_isolate();
   3017   i::Factory* factory = isolate->factory();
   3018 
   3019   std::pair<const char*, Handle<Object>> sloppy_this[] = {
   3020       std::make_pair("var global_val = 100;\n"
   3021                      "function f() { return this.global_val; }\n",
   3022                      handle(Smi::FromInt(100), isolate)),
   3023       std::make_pair("var global_val = 110;\n"
   3024                      "function g() { return this.global_val; };"
   3025                      "function f() { return g(); }\n",
   3026                      handle(Smi::FromInt(110), isolate)),
   3027       std::make_pair("var global_val = 110;\n"
   3028                      "function g() { return this.global_val };"
   3029                      "function f() { 'use strict'; return g(); }\n",
   3030                      handle(Smi::FromInt(110), isolate)),
   3031       std::make_pair("function f() { 'use strict'; return this; }\n",
   3032                      factory->undefined_value()),
   3033       std::make_pair("function g() { 'use strict'; return this; };"
   3034                      "function f() { return g(); }\n",
   3035                      factory->undefined_value()),
   3036   };
   3037 
   3038   for (size_t i = 0; i < arraysize(sloppy_this); i++) {
   3039     InterpreterTester tester(handles.main_isolate(), sloppy_this[i].first);
   3040     auto callable = tester.GetCallable<>();
   3041 
   3042     Handle<i::Object> return_value = callable().ToHandleChecked();
   3043     CHECK(return_value->SameValue(*sloppy_this[i].second));
   3044   }
   3045 }
   3046 
   3047 
   3048 TEST(InterpreterThisFunction) {
   3049   HandleAndZoneScope handles;
   3050   i::Isolate* isolate = handles.main_isolate();
   3051   i::Factory* factory = isolate->factory();
   3052 
   3053   InterpreterTester tester(handles.main_isolate(),
   3054                            "var f;\n f = function f() { return f.name; }");
   3055   auto callable = tester.GetCallable<>();
   3056 
   3057   Handle<i::Object> return_value = callable().ToHandleChecked();
   3058   CHECK(return_value->SameValue(*factory->NewStringFromStaticChars("f")));
   3059 }
   3060 
   3061 
   3062 TEST(InterpreterNewTarget) {
   3063   HandleAndZoneScope handles;
   3064   i::Isolate* isolate = handles.main_isolate();
   3065   i::Factory* factory = isolate->factory();
   3066 
   3067   // TODO(rmcilroy): Add tests that we get the original constructor for
   3068   // superclass constructors once we have class support.
   3069   InterpreterTester tester(handles.main_isolate(),
   3070                            "function f() { this.a = new.target; }");
   3071   auto callable = tester.GetCallable<>();
   3072   callable().ToHandleChecked();
   3073 
   3074   Handle<Object> new_target_name = v8::Utils::OpenHandle(
   3075       *CompileRun("(function() { return (new f()).a.name; })();"));
   3076   CHECK(new_target_name->SameValue(*factory->NewStringFromStaticChars("f")));
   3077 }
   3078 
   3079 
   3080 TEST(InterpreterAssignmentInExpressions) {
   3081   HandleAndZoneScope handles;
   3082 
   3083   std::pair<const char*, int> samples[] = {
   3084       {"function f() {\n"
   3085        "  var x = 7;\n"
   3086        "  var y = x + (x = 1) + (x = 2);\n"
   3087        "  return y;\n"
   3088        "}",
   3089        10},
   3090       {"function f() {\n"
   3091        "  var x = 7;\n"
   3092        "  var y = x + (x = 1) + (x = 2);\n"
   3093        "  return x;\n"
   3094        "}",
   3095        2},
   3096       {"function f() {\n"
   3097        "  var x = 55;\n"
   3098        "  x = x + (x = 100) + (x = 101);\n"
   3099        "  return x;\n"
   3100        "}",
   3101        256},
   3102       {"function f() {\n"
   3103        "  var x = 7;\n"
   3104        "  return ++x + x + x++;\n"
   3105        "}",
   3106        24},
   3107       {"function f() {\n"
   3108        "  var x = 7;\n"
   3109        "  var y = 1 + ++x + x + x++;\n"
   3110        "  return x;\n"
   3111        "}",
   3112        9},
   3113       {"function f() {\n"
   3114        "  var x = 7;\n"
   3115        "  var y = ++x + x + x++;\n"
   3116        "  return x;\n"
   3117        "}",
   3118        9},
   3119       {"function f() {\n"
   3120        "  var x = 7, y = 100, z = 1000;\n"
   3121        "  return x + (x += 3) + y + (y *= 10) + (z *= 7) + z;\n"
   3122        "}",
   3123        15117},
   3124       {"function f() {\n"
   3125        "  var inner = function (x) { return x + (x = 2) + (x = 4) + x; };\n"
   3126        "  return inner(1);\n"
   3127        "}",
   3128        11},
   3129       {"function f() {\n"
   3130        "  var x = 1, y = 2;\n"
   3131        "  x = x + (x = 3) + y + (y = 4), y = y + (y = 5) + y + x;\n"
   3132        "  return x + y;\n"
   3133        "}",
   3134        10 + 24},
   3135       {"function f() {\n"
   3136        "  var x = 0;\n"
   3137        "  var y = x | (x = 1) | (x = 2);\n"
   3138        "  return x;\n"
   3139        "}",
   3140        2},
   3141       {"function f() {\n"
   3142        "  var x = 0;\n"
   3143        "  var y = x || (x = 1);\n"
   3144        "  return x;\n"
   3145        "}",
   3146        1},
   3147       {"function f() {\n"
   3148        "  var x = 1;\n"
   3149        "  var y = x && (x = 2) && (x = 3);\n"
   3150        "  return x;\n"
   3151        "}",
   3152        3},
   3153       {"function f() {\n"
   3154        "  var x = 1;\n"
   3155        "  var y = x || (x = 2);\n"
   3156        "  return x;\n"
   3157        "}",
   3158        1},
   3159       {"function f() {\n"
   3160        "  var x = 1;\n"
   3161        "  x = (x << (x = 3)) | (x = 16);\n"
   3162        "  return x;\n"
   3163        "}",
   3164        24},
   3165       {"function f() {\n"
   3166        "  var r = 7;\n"
   3167        "  var s = 11;\n"
   3168        "  var t = 13;\n"
   3169        "  var u = r + s + t + (r = 10) + (s = 20) +"
   3170        "          (t = (r + s)) + r + s + t;\n"
   3171        "  return r + s + t + u;\n"
   3172        "}",
   3173        211},
   3174       {"function f() {\n"
   3175        "  var r = 7;\n"
   3176        "  var s = 11;\n"
   3177        "  var t = 13;\n"
   3178        "  return r > (3 * s * (s = 1)) ? (t + (t += 1)) : (r + (r = 4));\n"
   3179        "}",
   3180        11},
   3181       {"function f() {\n"
   3182        "  var r = 7;\n"
   3183        "  var s = 11;\n"
   3184        "  var t = 13;\n"
   3185        "  return r > (3 * s * (s = 0)) ? (t + (t += 1)) : (r + (r = 4));\n"
   3186        "}",
   3187        27},
   3188       {"function f() {\n"
   3189        "  var r = 7;\n"
   3190        "  var s = 11;\n"
   3191        "  var t = 13;\n"
   3192        "  return (r + (r = 5)) > s ? r : t;\n"
   3193        "}",
   3194        5},
   3195       {"function f(a) {\n"
   3196        "  return a + (arguments[0] = 10);\n"
   3197        "}",
   3198        50},
   3199       {"function f(a) {\n"
   3200        "  return a + (arguments[0] = 10) + a;\n"
   3201        "}",
   3202        60},
   3203       {"function f(a) {\n"
   3204        "  return a + (arguments[0] = 10) + arguments[0];\n"
   3205        "}",
   3206        60},
   3207   };
   3208 
   3209   const int arg_value = 40;
   3210   for (size_t i = 0; i < arraysize(samples); i++) {
   3211     InterpreterTester tester(handles.main_isolate(), samples[i].first);
   3212     auto callable = tester.GetCallable<Handle<Object>>();
   3213     Handle<Object> return_val =
   3214         callable(handle(Smi::FromInt(arg_value), handles.main_isolate()))
   3215             .ToHandleChecked();
   3216     CHECK_EQ(Handle<Smi>::cast(return_val)->value(), samples[i].second);
   3217   }
   3218 }
   3219 
   3220 
   3221 TEST(InterpreterToName) {
   3222   HandleAndZoneScope handles;
   3223   i::Isolate* isolate = handles.main_isolate();
   3224   i::Factory* factory = isolate->factory();
   3225 
   3226   std::pair<const char*, Handle<Object>> to_name_tests[] = {
   3227       {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
   3228        factory->NewNumberFromInt(10)},
   3229       {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
   3230        factory->NewNumberFromInt(10)},
   3231       {"var a = 20; var obj = {[a] : 10}; return obj[20];",
   3232        factory->NewNumberFromInt(10)},
   3233       {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
   3234        factory->NewNumberFromInt(10)},
   3235       {"var a = {val:23}; var obj = {[a] : 10};\n"
   3236        "return obj['[object Object]'];",
   3237        factory->NewNumberFromInt(10)},
   3238       {"var a = {toString : function() { return 'x'}};\n"
   3239        "var obj = {[a] : 10};\n"
   3240        "return obj.x;",
   3241        factory->NewNumberFromInt(10)},
   3242       {"var a = {valueOf : function() { return 'x'}};\n"
   3243        "var obj = {[a] : 10};\n"
   3244        "return obj.x;",
   3245        factory->undefined_value()},
   3246       {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
   3247        "var obj = {[a] : 10};\n"
   3248        "return obj.x;",
   3249        factory->NewNumberFromInt(10)},
   3250   };
   3251 
   3252   for (size_t i = 0; i < arraysize(to_name_tests); i++) {
   3253     std::string source(
   3254         InterpreterTester::SourceForBody(to_name_tests[i].first));
   3255     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3256     auto callable = tester.GetCallable<>();
   3257 
   3258     Handle<i::Object> return_value = callable().ToHandleChecked();
   3259     CHECK(return_value->SameValue(*to_name_tests[i].second));
   3260   }
   3261 }
   3262 
   3263 
   3264 TEST(TemporaryRegisterAllocation) {
   3265   HandleAndZoneScope handles;
   3266   i::Isolate* isolate = handles.main_isolate();
   3267   i::Factory* factory = isolate->factory();
   3268 
   3269   std::pair<const char*, Handle<Object>> reg_tests[] = {
   3270       {"function add(a, b, c) {"
   3271        "   return a + b + c;"
   3272        "}"
   3273        "function f() {"
   3274        "  var a = 10, b = 10;"
   3275        "   return add(a, b++, b);"
   3276        "}",
   3277        factory->NewNumberFromInt(31)},
   3278       {"function add(a, b, c, d) {"
   3279        "  return a + b + c + d;"
   3280        "}"
   3281        "function f() {"
   3282        "  var x = 10, y = 20, z = 30;"
   3283        "  return x + add(x, (y= x++), x, z);"
   3284        "}",
   3285        factory->NewNumberFromInt(71)},
   3286   };
   3287 
   3288   for (size_t i = 0; i < arraysize(reg_tests); i++) {
   3289     InterpreterTester tester(handles.main_isolate(), reg_tests[i].first);
   3290     auto callable = tester.GetCallable<>();
   3291 
   3292     Handle<i::Object> return_value = callable().ToHandleChecked();
   3293     CHECK(return_value->SameValue(*reg_tests[i].second));
   3294   }
   3295 }
   3296 
   3297 
   3298 TEST(InterpreterLookupSlot) {
   3299   HandleAndZoneScope handles;
   3300   i::Isolate* isolate = handles.main_isolate();
   3301   i::Factory* factory = isolate->factory();
   3302 
   3303   // TODO(mythria): Add more tests when we have support for eval/with.
   3304   const char* function_prologue = "var f;"
   3305                                   "var x = 1;"
   3306                                   "function f1() {"
   3307                                   "  eval(\"function t() {";
   3308   const char* function_epilogue = "        }; f = t;\");"
   3309                                   "}"
   3310                                   "f1();";
   3311 
   3312 
   3313   std::pair<const char*, Handle<Object>> lookup_slot[] = {
   3314       {"return x;", handle(Smi::FromInt(1), isolate)},
   3315       {"return typeof x;", factory->NewStringFromStaticChars("number")},
   3316       {"return typeof dummy;", factory->NewStringFromStaticChars("undefined")},
   3317       {"x = 10; return x;", handle(Smi::FromInt(10), isolate)},
   3318       {"'use strict'; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
   3319   };
   3320 
   3321   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
   3322     std::string script = std::string(function_prologue) +
   3323                          std::string(lookup_slot[i].first) +
   3324                          std::string(function_epilogue);
   3325 
   3326     InterpreterTester tester(handles.main_isolate(), script.c_str(), "t");
   3327     auto callable = tester.GetCallable<>();
   3328 
   3329     Handle<i::Object> return_value = callable().ToHandleChecked();
   3330     CHECK(return_value->SameValue(*lookup_slot[i].second));
   3331   }
   3332 }
   3333 
   3334 
   3335 TEST(InterpreterCallLookupSlot) {
   3336   HandleAndZoneScope handles;
   3337   i::Isolate* isolate = handles.main_isolate();
   3338 
   3339   std::pair<const char*, Handle<Object>> call_lookup[] = {
   3340       {"g = function(){ return 2 }; eval(''); return g();",
   3341        handle(Smi::FromInt(2), isolate)},
   3342       {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
   3343        "return g();",
   3344        handle(Smi::FromInt(3), isolate)},
   3345       {"g = { x: function(){ return this.y }, y: 20 };\n"
   3346        "eval('g = { x: g.x, y: 30 }');\n"
   3347        "return g.x();",
   3348        handle(Smi::FromInt(30), isolate)},
   3349   };
   3350 
   3351   for (size_t i = 0; i < arraysize(call_lookup); i++) {
   3352     std::string source(InterpreterTester::SourceForBody(call_lookup[i].first));
   3353     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3354     auto callable = tester.GetCallable<>();
   3355 
   3356     Handle<i::Object> return_value = callable().ToHandleChecked();
   3357     CHECK(return_value->SameValue(*call_lookup[i].second));
   3358   }
   3359 }
   3360 
   3361 
   3362 TEST(InterpreterLookupSlotWide) {
   3363   HandleAndZoneScope handles;
   3364   i::Isolate* isolate = handles.main_isolate();
   3365   i::Factory* factory = isolate->factory();
   3366 
   3367   const char* function_prologue =
   3368       "var f;"
   3369       "var x = 1;"
   3370       "function f1() {"
   3371       "  eval(\"function t() {";
   3372   const char* function_epilogue =
   3373       "        }; f = t;\");"
   3374       "}"
   3375       "f1();";
   3376   std::ostringstream str;
   3377   str << "var y = 2.3;";
   3378   for (int i = 1; i < 256; i++) {
   3379     str << "y = " << 2.3 + i << ";";
   3380   }
   3381   std::string init_function_body = str.str();
   3382 
   3383   std::pair<std::string, Handle<Object>> lookup_slot[] = {
   3384       {init_function_body + "return x;", handle(Smi::FromInt(1), isolate)},
   3385       {init_function_body + "return typeof x;",
   3386        factory->NewStringFromStaticChars("number")},
   3387       {init_function_body + "return x = 10;",
   3388        handle(Smi::FromInt(10), isolate)},
   3389       {"'use strict';" + init_function_body + "x = 20; return x;",
   3390        handle(Smi::FromInt(20), isolate)},
   3391   };
   3392 
   3393   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
   3394     std::string script = std::string(function_prologue) + lookup_slot[i].first +
   3395                          std::string(function_epilogue);
   3396 
   3397     InterpreterTester tester(handles.main_isolate(), script.c_str(), "t");
   3398     auto callable = tester.GetCallable<>();
   3399 
   3400     Handle<i::Object> return_value = callable().ToHandleChecked();
   3401     CHECK(return_value->SameValue(*lookup_slot[i].second));
   3402   }
   3403 }
   3404 
   3405 
   3406 TEST(InterpreterDeleteLookupSlot) {
   3407   HandleAndZoneScope handles;
   3408   i::Isolate* isolate = handles.main_isolate();
   3409   i::Factory* factory = isolate->factory();
   3410 
   3411   // TODO(mythria): Add more tests when we have support for eval/with.
   3412   const char* function_prologue = "var f;"
   3413                                   "var x = 1;"
   3414                                   "y = 10;"
   3415                                   "var obj = {val:10};"
   3416                                   "var z = 30;"
   3417                                   "function f1() {"
   3418                                   "  var z = 20;"
   3419                                   "  eval(\"function t() {";
   3420   const char* function_epilogue = "        }; f = t;\");"
   3421                                   "}"
   3422                                   "f1();";
   3423 
   3424 
   3425   std::pair<const char*, Handle<Object>> delete_lookup_slot[] = {
   3426       {"return delete x;", factory->false_value()},
   3427       {"return delete y;", factory->true_value()},
   3428       {"return delete z;", factory->false_value()},
   3429       {"return delete obj.val;", factory->true_value()},
   3430       {"'use strict'; return delete obj.val;", factory->true_value()},
   3431   };
   3432 
   3433   for (size_t i = 0; i < arraysize(delete_lookup_slot); i++) {
   3434     std::string script = std::string(function_prologue) +
   3435                          std::string(delete_lookup_slot[i].first) +
   3436                          std::string(function_epilogue);
   3437 
   3438     InterpreterTester tester(handles.main_isolate(), script.c_str(), "t");
   3439     auto callable = tester.GetCallable<>();
   3440 
   3441     Handle<i::Object> return_value = callable().ToHandleChecked();
   3442     CHECK(return_value->SameValue(*delete_lookup_slot[i].second));
   3443   }
   3444 }
   3445 
   3446 
   3447 TEST(JumpWithConstantsAndWideConstants) {
   3448   HandleAndZoneScope handles;
   3449   const int kStep = 13;
   3450   for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
   3451     auto isolate = handles.main_isolate();
   3452     auto factory = isolate->factory();
   3453     std::ostringstream filler_os;
   3454     // Generate a string that consumes constant pool entries and
   3455     // spread out branch distances in script below.
   3456     for (int i = 0; i < constants; i++) {
   3457       filler_os << "var x_ = 'x_" << i << "';\n";
   3458     }
   3459     std::string filler(filler_os.str());
   3460     std::ostringstream script_os;
   3461     script_os << "function " << InterpreterTester::function_name() << "(a) {\n";
   3462     script_os << "  " << filler;
   3463     script_os << "  for (var i = a; i < 2; i++) {\n";
   3464     script_os << "  " << filler;
   3465     script_os << "    if (i == 0) { " << filler << "i = 10; continue; }\n";
   3466     script_os << "    else if (i == a) { " << filler << "i = 12; break; }\n";
   3467     script_os << "    else { " << filler << " }\n";
   3468     script_os << "  }\n";
   3469     script_os << "  return i;\n";
   3470     script_os << "}\n";
   3471     std::string script(script_os.str());
   3472     for (int a = 0; a < 3; a++) {
   3473       InterpreterTester tester(handles.main_isolate(), script.c_str());
   3474       auto callable = tester.GetCallable<Handle<Object>>();
   3475       Handle<Object> argument = factory->NewNumberFromInt(a);
   3476       Handle<Object> return_val = callable(argument).ToHandleChecked();
   3477       static const int results[] = {11, 12, 2};
   3478       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
   3479     }
   3480   }
   3481 }
   3482 
   3483 
   3484 TEST(InterpreterEval) {
   3485   HandleAndZoneScope handles;
   3486   i::Isolate* isolate = handles.main_isolate();
   3487   i::Factory* factory = isolate->factory();
   3488 
   3489   std::pair<const char*, Handle<Object>> eval[] = {
   3490       {"return eval('1;');", handle(Smi::FromInt(1), isolate)},
   3491       {"return eval('100 * 20;');", handle(Smi::FromInt(2000), isolate)},
   3492       {"var x = 10; return eval('x + 20;');",
   3493        handle(Smi::FromInt(30), isolate)},
   3494       {"var x = 10; eval('x = 33;'); return x;",
   3495        handle(Smi::FromInt(33), isolate)},
   3496       {"'use strict'; var x = 20; var z = 0;\n"
   3497        "eval('var x = 33; z = x;'); return x + z;",
   3498        handle(Smi::FromInt(53), isolate)},
   3499       {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
   3500        handle(Smi::FromInt(86), isolate)},
   3501       {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
   3502        handle(Smi::FromInt(11), isolate)},
   3503       {"var x = 10; eval('var x = 20;'); return x;",
   3504        handle(Smi::FromInt(20), isolate)},
   3505       {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
   3506        handle(Smi::FromInt(1), isolate)},
   3507       {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
   3508        handle(Smi::FromInt(1), isolate)},
   3509       {"var x = 10; eval('x + 20;'); return typeof x;",
   3510        factory->NewStringFromStaticChars("number")},
   3511       {"eval('var y = 10;'); return typeof unallocated;",
   3512        factory->NewStringFromStaticChars("undefined")},
   3513       {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
   3514        factory->NewStringFromStaticChars("undefined")},
   3515       {"eval('var x = 10;'); return typeof x;",
   3516        factory->NewStringFromStaticChars("number")},
   3517       {"var x = {}; eval('var x = 10;'); return typeof x;",
   3518        factory->NewStringFromStaticChars("number")},
   3519       {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
   3520        factory->NewStringFromStaticChars("object")},
   3521   };
   3522 
   3523   for (size_t i = 0; i < arraysize(eval); i++) {
   3524     std::string source(InterpreterTester::SourceForBody(eval[i].first));
   3525     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3526     auto callable = tester.GetCallable<>();
   3527     Handle<i::Object> return_value = callable().ToHandleChecked();
   3528     CHECK(return_value->SameValue(*eval[i].second));
   3529   }
   3530 }
   3531 
   3532 
   3533 TEST(InterpreterEvalParams) {
   3534   HandleAndZoneScope handles;
   3535   i::Isolate* isolate = handles.main_isolate();
   3536 
   3537   std::pair<const char*, Handle<Object>> eval_params[] = {
   3538       {"var x = 10; return eval('x + p1;');",
   3539        handle(Smi::FromInt(30), isolate)},
   3540       {"var x = 10; eval('p1 = x;'); return p1;",
   3541        handle(Smi::FromInt(10), isolate)},
   3542       {"var a = 10;"
   3543        "function inner() { return eval('a + p1;');}"
   3544        "return inner();",
   3545        handle(Smi::FromInt(30), isolate)},
   3546   };
   3547 
   3548   for (size_t i = 0; i < arraysize(eval_params); i++) {
   3549     std::string source = "function " + InterpreterTester::function_name() +
   3550                          "(p1) {" + eval_params[i].first + "}";
   3551     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3552     auto callable = tester.GetCallable<Handle<Object>>();
   3553 
   3554     Handle<i::Object> return_value =
   3555         callable(handle(Smi::FromInt(20), isolate)).ToHandleChecked();
   3556     CHECK(return_value->SameValue(*eval_params[i].second));
   3557   }
   3558 }
   3559 
   3560 
   3561 TEST(InterpreterEvalGlobal) {
   3562   HandleAndZoneScope handles;
   3563   i::Isolate* isolate = handles.main_isolate();
   3564   i::Factory* factory = isolate->factory();
   3565 
   3566   std::pair<const char*, Handle<Object>> eval_global[] = {
   3567       {"function add_global() { eval('function test() { z = 33; }; test()'); };"
   3568        "function f() { add_global(); return z; }; f();",
   3569        handle(Smi::FromInt(33), isolate)},
   3570       {"function add_global() {\n"
   3571        " eval('\"use strict\"; function test() { y = 33; };"
   3572        "      try { test() } catch(e) {}');\n"
   3573        "}\n"
   3574        "function f() { add_global(); return typeof y; } f();",
   3575        factory->NewStringFromStaticChars("undefined")},
   3576   };
   3577 
   3578   for (size_t i = 0; i < arraysize(eval_global); i++) {
   3579     InterpreterTester tester(handles.main_isolate(), eval_global[i].first,
   3580                              "test");
   3581     auto callable = tester.GetCallable<>();
   3582 
   3583     Handle<i::Object> return_value = callable().ToHandleChecked();
   3584     CHECK(return_value->SameValue(*eval_global[i].second));
   3585   }
   3586 }
   3587 
   3588 
   3589 TEST(InterpreterEvalVariableDecl) {
   3590   HandleAndZoneScope handles;
   3591   i::Isolate* isolate = handles.main_isolate();
   3592   i::Factory* factory = isolate->factory();
   3593 
   3594   std::pair<const char*, Handle<Object>> eval_global[] = {
   3595       {"function f() { eval('var x = 10; x++;'); return x; }",
   3596        handle(Smi::FromInt(11), isolate)},
   3597       {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
   3598        handle(Smi::FromInt(11), isolate)},
   3599       {"function f() {"
   3600        " var x = 20;"
   3601        " eval('\"use strict\"; var x = 10; x++;');"
   3602        " return x; }",
   3603        handle(Smi::FromInt(20), isolate)},
   3604       {"function f() {"
   3605        " var y = 30;"
   3606        " eval('var x = {1:20}; x[2]=y;');"
   3607        " return x[2]; }",
   3608        handle(Smi::FromInt(30), isolate)},
   3609       {"function f() {"
   3610        " eval('var x = {name:\"test\"};');"
   3611        " return x.name; }",
   3612        factory->NewStringFromStaticChars("test")},
   3613       {"function f() {"
   3614        "  eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
   3615        "  return x[1].type+x[0].name; }",
   3616        factory->NewStringFromStaticChars("cctest")},
   3617       {"function f() {\n"
   3618        " var x = 3;\n"
   3619        " var get_eval_x;\n"
   3620        " eval('\"use strict\"; "
   3621        "      var x = 20; "
   3622        "      get_eval_x = function func() {return x;};');\n"
   3623        " return get_eval_x() + x;\n"
   3624        "}",
   3625        handle(Smi::FromInt(23), isolate)},
   3626       // TODO(mythria): Add tests with const declarations.
   3627   };
   3628 
   3629   for (size_t i = 0; i < arraysize(eval_global); i++) {
   3630     InterpreterTester tester(handles.main_isolate(), eval_global[i].first, "*");
   3631     auto callable = tester.GetCallable<>();
   3632 
   3633     Handle<i::Object> return_value = callable().ToHandleChecked();
   3634     CHECK(return_value->SameValue(*eval_global[i].second));
   3635   }
   3636 }
   3637 
   3638 
   3639 TEST(InterpreterEvalFunctionDecl) {
   3640   HandleAndZoneScope handles;
   3641   i::Isolate* isolate = handles.main_isolate();
   3642 
   3643   std::pair<const char*, Handle<Object>> eval_func_decl[] = {
   3644       {"function f() {\n"
   3645        " var x = 3;\n"
   3646        " eval('var x = 20;"
   3647        "       function get_x() {return x;};');\n"
   3648        " return get_x() + x;\n"
   3649        "}",
   3650        handle(Smi::FromInt(40), isolate)},
   3651   };
   3652 
   3653   for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
   3654     InterpreterTester tester(handles.main_isolate(), eval_func_decl[i].first,
   3655                              "*");
   3656     auto callable = tester.GetCallable<>();
   3657 
   3658     Handle<i::Object> return_value = callable().ToHandleChecked();
   3659     CHECK(return_value->SameValue(*eval_func_decl[i].second));
   3660   }
   3661 }
   3662 
   3663 TEST(InterpreterWideRegisterArithmetic) {
   3664   HandleAndZoneScope handles;
   3665   i::Isolate* isolate = handles.main_isolate();
   3666 
   3667   static const size_t kMaxRegisterForTest = 150;
   3668   std::ostringstream os;
   3669   os << "function " << InterpreterTester::function_name() << "(arg) {\n";
   3670   os << "  var retval = -77;\n";
   3671   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
   3672     os << "  var x" << i << " = " << i << ";\n";
   3673   }
   3674   for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
   3675     size_t j = kMaxRegisterForTest - i - 1;
   3676     os << "  var tmp = x" << j << ";\n";
   3677     os << "  var x" << j << " = x" << i << ";\n";
   3678     os << "  var x" << i << " = tmp;\n";
   3679   }
   3680   for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
   3681     size_t j = kMaxRegisterForTest - i - 1;
   3682     os << "  var tmp = x" << j << ";\n";
   3683     os << "  var x" << j << " = x" << i << ";\n";
   3684     os << "  var x" << i << " = tmp;\n";
   3685   }
   3686   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
   3687     os << "  if (arg == " << i << ") {\n"  //
   3688        << "    retval = x" << i << ";\n"   //
   3689        << "  }\n";                         //
   3690   }
   3691   os << "  return retval;\n";
   3692   os << "}\n";
   3693 
   3694   std::string source = os.str();
   3695   InterpreterTester tester(handles.main_isolate(), source.c_str());
   3696   auto callable = tester.GetCallable<Handle<Object>>();
   3697   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
   3698     Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate);
   3699     Handle<Object> return_value = callable(arg).ToHandleChecked();
   3700     CHECK(return_value->SameValue(*arg));
   3701   }
   3702 }
   3703 
   3704 TEST(InterpreterCallWideRegisters) {
   3705   static const int kPeriod = 25;
   3706   static const int kLength = 512;
   3707   static const int kStartChar = 65;
   3708 
   3709   for (int pass = 0; pass < 3; pass += 1) {
   3710     std::ostringstream os;
   3711     for (int i = 0; i < pass * 97; i += 1) {
   3712       os << "var x" << i << " = " << i << "\n";
   3713     }
   3714     os << "return String.fromCharCode(";
   3715     os << kStartChar;
   3716     for (int i = 1; i < kLength; i += 1) {
   3717       os << "," << kStartChar + (i % kPeriod);
   3718     }
   3719     os << ");";
   3720     std::string source = InterpreterTester::SourceForBody(os.str().c_str());
   3721     HandleAndZoneScope handles;
   3722     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3723     auto callable = tester.GetCallable();
   3724     Handle<Object> return_val = callable().ToHandleChecked();
   3725     Handle<String> return_string = Handle<String>::cast(return_val);
   3726     CHECK_EQ(return_string->length(), kLength);
   3727     for (int i = 0; i < kLength; i += 1) {
   3728       CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod));
   3729     }
   3730   }
   3731 }
   3732 
   3733 TEST(InterpreterWideParametersPickOne) {
   3734   static const int kParameterCount = 130;
   3735   for (int parameter = 0; parameter < 10; parameter++) {
   3736     HandleAndZoneScope handles;
   3737     i::Isolate* isolate = handles.main_isolate();
   3738     std::ostringstream os;
   3739     os << "function " << InterpreterTester::function_name() << "(arg) {\n";
   3740     os << "  function selector(i";
   3741     for (int i = 0; i < kParameterCount; i++) {
   3742       os << ","
   3743          << "a" << i;
   3744     }
   3745     os << ") {\n";
   3746     os << "  return a" << parameter << ";\n";
   3747     os << "  };\n";
   3748     os << "  return selector(arg";
   3749     for (int i = 0; i < kParameterCount; i++) {
   3750       os << "," << i;
   3751     }
   3752     os << ");";
   3753     os << "}\n";
   3754 
   3755     std::string source = os.str();
   3756     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
   3757     auto callable = tester.GetCallable<Handle<Object>>();
   3758     Handle<Object> arg = handle(Smi::FromInt(0xaa55), isolate);
   3759     Handle<Object> return_value = callable(arg).ToHandleChecked();
   3760     Handle<Smi> actual = Handle<Smi>::cast(return_value);
   3761     CHECK_EQ(actual->value(), parameter);
   3762   }
   3763 }
   3764 
   3765 TEST(InterpreterWideParametersSummation) {
   3766   static int kParameterCount = 200;
   3767   static int kBaseValue = 17000;
   3768   HandleAndZoneScope handles;
   3769   i::Isolate* isolate = handles.main_isolate();
   3770   std::ostringstream os;
   3771   os << "function " << InterpreterTester::function_name() << "(arg) {\n";
   3772   os << "  function summation(i";
   3773   for (int i = 0; i < kParameterCount; i++) {
   3774     os << ","
   3775        << "a" << i;
   3776   }
   3777   os << ") {\n";
   3778   os << "    var sum = " << kBaseValue << ";\n";
   3779   os << "    switch(i) {\n";
   3780   for (int i = 0; i < kParameterCount; i++) {
   3781     int j = kParameterCount - i - 1;
   3782     os << "      case " << j << ": sum += a" << j << ";\n";
   3783   }
   3784   os << "  }\n";
   3785   os << "    return sum;\n";
   3786   os << "  };\n";
   3787   os << "  return summation(arg";
   3788   for (int i = 0; i < kParameterCount; i++) {
   3789     os << "," << i;
   3790   }
   3791   os << ");";
   3792   os << "}\n";
   3793 
   3794   std::string source = os.str();
   3795   InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
   3796   auto callable = tester.GetCallable<Handle<Object>>();
   3797   for (int i = 0; i < kParameterCount; i++) {
   3798     Handle<Object> arg = handle(Smi::FromInt(i), isolate);
   3799     Handle<Object> return_value = callable(arg).ToHandleChecked();
   3800     int expected = kBaseValue + i * (i + 1) / 2;
   3801     Handle<Smi> actual = Handle<Smi>::cast(return_value);
   3802     CHECK_EQ(actual->value(), expected);
   3803   }
   3804 }
   3805 
   3806 TEST(InterpreterDoExpression) {
   3807   bool old_flag = FLAG_harmony_do_expressions;
   3808   FLAG_harmony_do_expressions = true;
   3809 
   3810   HandleAndZoneScope handles;
   3811   i::Isolate* isolate = handles.main_isolate();
   3812   Factory* factory = isolate->factory();
   3813 
   3814   std::pair<const char*, Handle<Object>> do_expr[] = {
   3815       {"var a = do {}; return a;", factory->undefined_value()},
   3816       {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
   3817       {"var a = do { var x = 100; }; return a;", factory->undefined_value()},
   3818       {"var a = do { var x = 100; x++; }; return a;",
   3819        handle(Smi::FromInt(100), isolate)},
   3820       {"var i = 0; for (; i < 5;) { i = do { if (i == 3) { break; }; i + 1; }};"
   3821        "return i;",
   3822        handle(Smi::FromInt(3), isolate)},
   3823   };
   3824 
   3825   for (size_t i = 0; i < arraysize(do_expr); i++) {
   3826     std::string source(InterpreterTester::SourceForBody(do_expr[i].first));
   3827     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3828     auto callable = tester.GetCallable<>();
   3829 
   3830     Handle<i::Object> return_value = callable().ToHandleChecked();
   3831     CHECK(return_value->SameValue(*do_expr[i].second));
   3832   }
   3833 
   3834   FLAG_harmony_do_expressions = old_flag;
   3835 }
   3836 
   3837 TEST(InterpreterWithStatement) {
   3838   HandleAndZoneScope handles;
   3839   i::Isolate* isolate = handles.main_isolate();
   3840 
   3841   std::pair<const char*, Handle<Object>> with_stmt[] = {
   3842       {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)},
   3843       {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)},
   3844       {"var y = {x:42};"
   3845        " function inner() {"
   3846        "   var x = 20;"
   3847        "   with(y) return x;"
   3848        "}"
   3849        "return inner();",
   3850        handle(Smi::FromInt(42), isolate)},
   3851       {"var y = {x:42};"
   3852        " function inner(o) {"
   3853        "   var x = 20;"
   3854        "   with(o) return x;"
   3855        "}"
   3856        "return inner(y);",
   3857        handle(Smi::FromInt(42), isolate)},
   3858   };
   3859 
   3860   for (size_t i = 0; i < arraysize(with_stmt); i++) {
   3861     std::string source(InterpreterTester::SourceForBody(with_stmt[i].first));
   3862     InterpreterTester tester(handles.main_isolate(), source.c_str());
   3863     auto callable = tester.GetCallable<>();
   3864 
   3865     Handle<i::Object> return_value = callable().ToHandleChecked();
   3866     CHECK(return_value->SameValue(*with_stmt[i].second));
   3867   }
   3868 }
   3869 
   3870 TEST(InterpreterClassLiterals) {
   3871   HandleAndZoneScope handles;
   3872   i::Isolate* isolate = handles.main_isolate();
   3873   std::pair<const char*, Handle<Object>> examples[] = {
   3874       {"class C {\n"
   3875        "  constructor(x) { this.x_ = x; }\n"
   3876        "  method() { return this.x_; }\n"
   3877        "}\n"
   3878        "return new C(99).method();",
   3879        handle(Smi::FromInt(99), isolate)},
   3880       {"class C {\n"
   3881        "  constructor(x) { this.x_ = x; }\n"
   3882        "  static static_method(x) { return x; }\n"
   3883        "}\n"
   3884        "return C.static_method(101);",
   3885        handle(Smi::FromInt(101), isolate)},
   3886       {"class C {\n"
   3887        "  get x() { return 102; }\n"
   3888        "}\n"
   3889        "return new C().x",
   3890        handle(Smi::FromInt(102), isolate)},
   3891       {"class C {\n"
   3892        "  static get x() { return 103; }\n"
   3893        "}\n"
   3894        "return C.x",
   3895        handle(Smi::FromInt(103), isolate)},
   3896       {"class C {\n"
   3897        "  constructor() { this.x_ = 0; }"
   3898        "  set x(value) { this.x_ = value; }\n"
   3899        "  get x() { return this.x_; }\n"
   3900        "}\n"
   3901        "var c = new C();"
   3902        "c.x = 104;"
   3903        "return c.x;",
   3904        handle(Smi::FromInt(104), isolate)},
   3905       {"var x = 0;"
   3906        "class C {\n"
   3907        "  static set x(value) { x = value; }\n"
   3908        "  static get x() { return x; }\n"
   3909        "}\n"
   3910        "C.x = 105;"
   3911        "return C.x;",
   3912        handle(Smi::FromInt(105), isolate)},
   3913       {"var method = 'f';"
   3914        "class C {\n"
   3915        "  [method]() { return 106; }\n"
   3916        "}\n"
   3917        "return new C().f();",
   3918        handle(Smi::FromInt(106), isolate)},
   3919   };
   3920 
   3921   for (size_t i = 0; i < arraysize(examples); ++i) {
   3922     std::string source(InterpreterTester::SourceForBody(examples[i].first));
   3923     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
   3924     auto callable = tester.GetCallable<>();
   3925 
   3926     Handle<i::Object> return_value = callable().ToHandleChecked();
   3927     CHECK(return_value->SameValue(*examples[i].second));
   3928   }
   3929 }
   3930 
   3931 TEST(InterpreterClassAndSuperClass) {
   3932   HandleAndZoneScope handles;
   3933   i::Isolate* isolate = handles.main_isolate();
   3934   std::pair<const char*, Handle<Object>> examples[] = {
   3935       {"class A {\n"
   3936        "  constructor(x) { this.x_ = x; }\n"
   3937        "  method() { return this.x_; }\n"
   3938        "}\n"
   3939        "class B extends A {\n"
   3940        "   constructor(x, y) { super(x); this.y_ = y; }\n"
   3941        "   method() { return super.method() + 1; }\n"
   3942        "}\n"
   3943        "return new B(998, 0).method();\n",
   3944        handle(Smi::FromInt(999), isolate)},
   3945       {"class A {\n"
   3946        "  constructor() { this.x_ = 2; this.y_ = 3; }\n"
   3947        "}\n"
   3948        "class B extends A {\n"
   3949        "  constructor() { super(); }"
   3950        "  method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
   3951        "}\n"
   3952        "return new B().method();\n",
   3953        handle(Smi::FromInt(7), isolate)},
   3954       {"var calls = 0;\n"
   3955        "class B {}\n"
   3956        "B.prototype.x = 42;\n"
   3957        "class C extends B {\n"
   3958        "  constructor() {\n"
   3959        "    super();\n"
   3960        "    calls++;\n"
   3961        "  }\n"
   3962        "}\n"
   3963        "new C;\n"
   3964        "return calls;\n",
   3965        handle(Smi::FromInt(1), isolate)},
   3966       {"class A {\n"
   3967        "  method() { return 1; }\n"
   3968        "  get x() { return 2; }\n"
   3969        "}\n"
   3970        "class B extends A {\n"
   3971        "  method() { return super.x === 2 ? super.method() : -1; }\n"
   3972        "}\n"
   3973        "return new B().method();\n",
   3974        handle(Smi::FromInt(1), isolate)},
   3975       {"var object = { setY(v) { super.y = v; }};\n"
   3976        "object.setY(10);\n"
   3977        "return object.y;\n",
   3978        handle(Smi::FromInt(10), isolate)},
   3979   };
   3980 
   3981   for (size_t i = 0; i < arraysize(examples); ++i) {
   3982     std::string source(InterpreterTester::SourceForBody(examples[i].first));
   3983     InterpreterTester tester(handles.main_isolate(), source.c_str(), "*");
   3984     auto callable = tester.GetCallable<>();
   3985     Handle<i::Object> return_value = callable().ToHandleChecked();
   3986     CHECK(return_value->SameValue(*examples[i].second));
   3987   }
   3988 }
   3989 
   3990 TEST(InterpreterConstDeclaration) {
   3991   HandleAndZoneScope handles;
   3992   i::Isolate* isolate = handles.main_isolate();
   3993   i::Factory* factory = isolate->factory();
   3994 
   3995   std::pair<const char*, Handle<Object>> const_decl[] = {
   3996       {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
   3997       {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
   3998       {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
   3999       {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
   4000       {"let x; return x;", factory->undefined_value()},
   4001       {"var x = 10; { let x = 30; } return x;",
   4002        handle(Smi::FromInt(10), isolate)},
   4003       {"let x = 10; { let x = 20; } return x;",
   4004        handle(Smi::FromInt(10), isolate)},
   4005       {"var x = 10; eval('let x = 20;'); return x;",
   4006        handle(Smi::FromInt(10), isolate)},
   4007       {"var x = 10; eval('const x = 20;'); return x;",
   4008        handle(Smi::FromInt(10), isolate)},
   4009       {"var x = 10; { const x = 20; } return x;",
   4010        handle(Smi::FromInt(10), isolate)},
   4011       {"var x = 10; { const x = 20; return x;} return -1;",
   4012        handle(Smi::FromInt(20), isolate)},
   4013       {"var a = 10;\n"
   4014        "for (var i = 0; i < 10; ++i) {\n"
   4015        " const x = i;\n"  // const declarations are block scoped.
   4016        " a = a + x;\n"
   4017        "}\n"
   4018        "return a;\n",
   4019        handle(Smi::FromInt(55), isolate)},
   4020   };
   4021 
   4022   // Tests for sloppy mode.
   4023   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4024     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
   4025     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4026     auto callable = tester.GetCallable<>();
   4027 
   4028     Handle<i::Object> return_value = callable().ToHandleChecked();
   4029     CHECK(return_value->SameValue(*const_decl[i].second));
   4030   }
   4031 
   4032   // Tests for strict mode.
   4033   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4034     std::string strict_body =
   4035         "'use strict'; " + std::string(const_decl[i].first);
   4036     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
   4037     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4038     auto callable = tester.GetCallable<>();
   4039 
   4040     Handle<i::Object> return_value = callable().ToHandleChecked();
   4041     CHECK(return_value->SameValue(*const_decl[i].second));
   4042   }
   4043 }
   4044 
   4045 TEST(InterpreterConstDeclarationLookupSlots) {
   4046   HandleAndZoneScope handles;
   4047   i::Isolate* isolate = handles.main_isolate();
   4048   i::Factory* factory = isolate->factory();
   4049 
   4050   std::pair<const char*, Handle<Object>> const_decl[] = {
   4051       {"const x = 3; function f1() {return x;}; return x;",
   4052        handle(Smi::FromInt(3), isolate)},
   4053       {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
   4054        handle(Smi::FromInt(30), isolate)},
   4055       {"let x; x = 20; function f1() {return x;}; return x;",
   4056        handle(Smi::FromInt(20), isolate)},
   4057       {"let x; function f1() {return x;}; return x;",
   4058        factory->undefined_value()},
   4059   };
   4060 
   4061   // Tests for sloppy mode.
   4062   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4063     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
   4064     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4065     auto callable = tester.GetCallable<>();
   4066 
   4067     Handle<i::Object> return_value = callable().ToHandleChecked();
   4068     CHECK(return_value->SameValue(*const_decl[i].second));
   4069   }
   4070 
   4071   // Tests for strict mode.
   4072   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4073     std::string strict_body =
   4074         "'use strict'; " + std::string(const_decl[i].first);
   4075     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
   4076     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4077     auto callable = tester.GetCallable<>();
   4078 
   4079     Handle<i::Object> return_value = callable().ToHandleChecked();
   4080     CHECK(return_value->SameValue(*const_decl[i].second));
   4081   }
   4082 }
   4083 
   4084 TEST(InterpreterConstInLookupContextChain) {
   4085   HandleAndZoneScope handles;
   4086   i::Isolate* isolate = handles.main_isolate();
   4087 
   4088   const char* prologue =
   4089       "function OuterMost() {\n"
   4090       "  const outerConst = 10;\n"
   4091       "  let outerLet = 20;\n"
   4092       "  function Outer() {\n"
   4093       "    function Inner() {\n"
   4094       "      this.innerFunc = function() { ";
   4095   const char* epilogue =
   4096       "      }\n"
   4097       "    }\n"
   4098       "    this.getInnerFunc ="
   4099       "         function() {return new Inner().innerFunc;}\n"
   4100       "  }\n"
   4101       "  this.getOuterFunc ="
   4102       "     function() {return new Outer().getInnerFunc();}"
   4103       "}\n"
   4104       "var f = new OuterMost().getOuterFunc();\n"
   4105       "f();\n";
   4106   std::pair<const char*, Handle<Object>> const_decl[] = {
   4107       {"return outerConst;", handle(Smi::FromInt(10), isolate)},
   4108       {"return outerLet;", handle(Smi::FromInt(20), isolate)},
   4109       {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
   4110       {"var outerLet = 40; return outerLet;",
   4111        handle(Smi::FromInt(40), isolate)},
   4112       {"var outerConst = 50; return outerConst;",
   4113        handle(Smi::FromInt(50), isolate)},
   4114       {"try { outerConst = 30 } catch(e) { return -1; }",
   4115        handle(Smi::FromInt(-1), isolate)}};
   4116 
   4117   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4118     std::string script = std::string(prologue) +
   4119                          std::string(const_decl[i].first) +
   4120                          std::string(epilogue);
   4121     InterpreterTester tester(handles.main_isolate(), script.c_str(), "*");
   4122     auto callable = tester.GetCallable<>();
   4123 
   4124     Handle<i::Object> return_value = callable().ToHandleChecked();
   4125     CHECK(return_value->SameValue(*const_decl[i].second));
   4126   }
   4127 }
   4128 
   4129 TEST(InterpreterIllegalConstDeclaration) {
   4130   HandleAndZoneScope handles;
   4131 
   4132   std::pair<const char*, const char*> const_decl[] = {
   4133       {"const x = x = 10 + 3; return x;",
   4134        "Uncaught ReferenceError: x is not defined"},
   4135       {"const x = 10; x = 20; return x;",
   4136        "Uncaught TypeError: Assignment to constant variable."},
   4137       {"const x = 10; { x = 20; } return x;",
   4138        "Uncaught TypeError: Assignment to constant variable."},
   4139       {"const x = 10; eval('x = 20;'); return x;",
   4140        "Uncaught TypeError: Assignment to constant variable."},
   4141       {"let x = x + 10; return x;",
   4142        "Uncaught ReferenceError: x is not defined"},
   4143       {"'use strict'; (function f1() { f1 = 123; })() ",
   4144        "Uncaught TypeError: Assignment to constant variable."},
   4145   };
   4146 
   4147   // Tests for sloppy mode.
   4148   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4149     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
   4150     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4151     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   4152     v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
   4153     CHECK(
   4154         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   4155             .FromJust());
   4156   }
   4157 
   4158   // Tests for strict mode.
   4159   for (size_t i = 0; i < arraysize(const_decl); i++) {
   4160     std::string strict_body =
   4161         "'use strict'; " + std::string(const_decl[i].first);
   4162     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
   4163     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4164     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
   4165     v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
   4166     CHECK(
   4167         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
   4168             .FromJust());
   4169   }
   4170 }
   4171 
   4172 TEST(InterpreterGenerators) {
   4173   bool old_flag = FLAG_ignition_generators;
   4174   FLAG_ignition_generators = true;
   4175 
   4176   HandleAndZoneScope handles;
   4177   i::Isolate* isolate = handles.main_isolate();
   4178   i::Factory* factory = isolate->factory();
   4179 
   4180   std::pair<const char*, Handle<Object>> tests[] = {
   4181       {"function* f() { }; return f().next().value",
   4182        factory->undefined_value()},
   4183       {"function* f() { yield 42 }; return f().next().value",
   4184        factory->NewNumberFromInt(42)},
   4185       {"function* f() { for (let x of [42]) yield x}; return f().next().value",
   4186        factory->NewNumberFromInt(42)},
   4187   };
   4188 
   4189   for (size_t i = 0; i < arraysize(tests); i++) {
   4190     std::string source(InterpreterTester::SourceForBody(tests[i].first));
   4191     InterpreterTester tester(handles.main_isolate(), source.c_str());
   4192     auto callable = tester.GetCallable<>();
   4193 
   4194     Handle<i::Object> return_value = callable().ToHandleChecked();
   4195     CHECK(return_value->SameValue(*tests[i].second));
   4196   }
   4197 
   4198   FLAG_ignition_generators = old_flag;
   4199 }
   4200 
   4201 }  // namespace interpreter
   4202 }  // namespace internal
   4203 }  // namespace v8
   4204