LCOV - code coverage report
Current view: top level - test/cctest/interpreter - test-interpreter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1835 1840 99.7 %
Date: 2017-10-20 Functions: 117 117 100.0 %

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

Generated by: LCOV version 1.10