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

Generated by: LCOV version 1.10