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

Generated by: LCOV version 1.10