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