LCOV - code coverage report
Current view: top level - test/cctest/interpreter - test-interpreter.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1769 1785 99.1 %
Date: 2019-04-18 Functions: 126 127 99.2 %

          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       26661 : TEST(InterpreterReturn) {
      39          10 :   HandleAndZoneScope handles;
      40             :   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           5 :   CHECK(return_val.is_identical_to(undefined_value));
      52           5 : }
      53             : 
      54       26661 : TEST(InterpreterLoadUndefined) {
      55          10 :   HandleAndZoneScope handles;
      56             :   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           5 :   CHECK(return_val.is_identical_to(undefined_value));
      68           5 : }
      69             : 
      70       26661 : TEST(InterpreterLoadNull) {
      71          10 :   HandleAndZoneScope handles;
      72             :   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           5 :   CHECK(return_val.is_identical_to(null_value));
      84           5 : }
      85             : 
      86       26661 : TEST(InterpreterLoadTheHole) {
      87          10 :   HandleAndZoneScope handles;
      88             :   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           5 :   CHECK(return_val.is_identical_to(the_hole_value));
     100           5 : }
     101             : 
     102       26661 : TEST(InterpreterLoadTrue) {
     103          10 :   HandleAndZoneScope handles;
     104             :   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           5 :   CHECK(return_val.is_identical_to(true_value));
     116           5 : }
     117             : 
     118       26661 : TEST(InterpreterLoadFalse) {
     119          10 :   HandleAndZoneScope handles;
     120             :   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           5 :   CHECK(return_val.is_identical_to(false_value));
     132           5 : }
     133             : 
     134       26661 : TEST(InterpreterLoadLiteral) {
     135          10 :   HandleAndZoneScope handles;
     136             :   Isolate* isolate = handles.main_isolate();
     137             :   Zone* zone = handles.main_zone();
     138             : 
     139             :   // Small Smis.
     140        2565 :   for (int i = -128; i < 128; i++) {
     141        2560 :     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        1280 :     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(i));
     149             :   }
     150             : 
     151             :   // Large Smis.
     152             :   {
     153          10 :     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           5 :     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           5 :                                 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           5 :                                 HashSeed(isolate));
     186             : 
     187          10 :     BytecodeArrayBuilder builder(zone, 1, 0);
     188             : 
     189           5 :     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             :   }
     200           5 : }
     201             : 
     202       26661 : TEST(InterpreterLoadStoreRegisters) {
     203          10 :   HandleAndZoneScope handles;
     204             :   Isolate* isolate = handles.main_isolate();
     205             :   Zone* zone = handles.main_zone();
     206             :   Handle<Object> true_value = isolate->factory()->true_value();
     207        1285 :   for (int i = 0; i <= kMaxInt8; i++) {
     208        1280 :     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             :   }
     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       26661 : 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          55 :   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
     282         575 :     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
     283        1925 :       for (size_t o = 0; o < arraysize(kShiftOperators); o++) {
     284        1650 :         HandleAndZoneScope handles;
     285             :         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             :       }
     312             :     }
     313             :   }
     314           5 : }
     315             : 
     316       26661 : 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          55 :   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
     320         425 :     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
     321        4600 :       for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
     322        4400 :         HandleAndZoneScope handles;
     323             :         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             :       }
     350             :     }
     351             :   }
     352           5 : }
     353             : 
     354       26661 : 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          65 :   for (size_t l = 0; l < arraysize(lhs_inputs); l++) {
     359         570 :     for (size_t r = 0; r < arraysize(rhs_inputs); r++) {
     360        6210 :       for (size_t o = 0; o < arraysize(kArithmeticOperators); o++) {
     361        5940 :         HandleAndZoneScope handles;
     362             :         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             :       }
     389             :     }
     390             :   }
     391           5 : }
     392             : 
     393       26661 : TEST(InterpreterBinaryOpsBigInt) {
     394             :   // This test only checks that the recorded type feedback is kBigInt.
     395             :   AstBigInt inputs[] = {AstBigInt("1"), AstBigInt("-42"), AstBigInt("0xFFFF")};
     396          35 :   for (size_t l = 0; l < arraysize(inputs); l++) {
     397         105 :     for (size_t r = 0; r < arraysize(inputs); r++) {
     398        1035 :       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         900 :         HandleAndZoneScope handles;
     403             :         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         450 :         CHECK(return_value->IsBigInt());
     426         450 :         if (tester.HasFeedbackMetadata()) {
     427             :           MaybeObject feedback = callable.vector()->Get(slot);
     428         450 :           CHECK(feedback->IsSmi());
     429         450 :           CHECK_EQ(BinaryOperationFeedback::kBigInt, feedback->ToSmi().value());
     430             :         }
     431             :       }
     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       26661 : TEST(InterpreterStringAdd) {
     486          10 :   HandleAndZoneScope handles;
     487             :   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           5 :                               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          85 :   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             :       MaybeObject feedback = callable.vector()->Get(slot);
     550          40 :       CHECK(feedback->IsSmi());
     551          40 :       CHECK_EQ(test_cases[i].expected_feedback, feedback->ToSmi().value());
     552             :     }
     553             :   }
     554           5 : }
     555             : 
     556       26661 : TEST(InterpreterParameter1) {
     557          10 :   HandleAndZoneScope handles;
     558             :   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          10 :   Handle<Object> return_val = callable(true_value).ToHandleChecked();
     571           5 :   CHECK(return_val.is_identical_to(true_value));
     572             : 
     573             :   // Check for Smis.
     574          10 :   return_val = callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
     575             :                    .ToHandleChecked();
     576           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
     577           5 : }
     578             : 
     579       26661 : TEST(InterpreterParameter8) {
     580          10 :   HandleAndZoneScope handles;
     581             :   Isolate* isolate = handles.main_isolate();
     582             :   Zone* zone = handles.main_zone();
     583             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
     584           5 :                               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             :   Handle<Smi> arg1 = Handle<Smi>(Smi::FromInt(1), handles.main_isolate());
     616             :   Handle<Smi> arg2 = Handle<Smi>(Smi::FromInt(2), handles.main_isolate());
     617             :   Handle<Smi> arg3 = Handle<Smi>(Smi::FromInt(3), handles.main_isolate());
     618             :   Handle<Smi> arg4 = Handle<Smi>(Smi::FromInt(4), handles.main_isolate());
     619             :   Handle<Smi> arg5 = Handle<Smi>(Smi::FromInt(5), handles.main_isolate());
     620             :   Handle<Smi> arg6 = Handle<Smi>(Smi::FromInt(6), handles.main_isolate());
     621             :   Handle<Smi> arg7 = Handle<Smi>(Smi::FromInt(7), handles.main_isolate());
     622             :   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           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(36));
     628           5 : }
     629             : 
     630       26661 : TEST(InterpreterBinaryOpTypeFeedback) {
     631             :   if (FLAG_lite_mode) return;
     632             : 
     633          10 :   HandleAndZoneScope handles;
     634             :   i::Isolate* isolate = handles.main_isolate();
     635             :   Zone* zone = handles.main_zone();
     636             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
     637           5 :                               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         265 :   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             :     MaybeObject feedback0 = callable.vector()->Get(slot0);
     758         130 :     CHECK(feedback0->IsSmi());
     759         130 :     CHECK_EQ(test_case.feedback, feedback0->ToSmi().value());
     760         260 :     CHECK(Object::Equals(isolate, test_case.result, return_val).ToChecked());
     761             :   }
     762             : }
     763             : 
     764       26661 : TEST(InterpreterBinaryOpSmiTypeFeedback) {
     765             :   if (FLAG_lite_mode) return;
     766             : 
     767          10 :   HandleAndZoneScope handles;
     768             :   i::Isolate* isolate = handles.main_isolate();
     769             :   Zone* zone = handles.main_zone();
     770             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
     771           5 :                               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         205 :   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             :     MaybeObject feedback0 = callable.vector()->Get(slot0);
     866         100 :     CHECK(feedback0->IsSmi());
     867         100 :     CHECK_EQ(test_case.feedback, feedback0->ToSmi().value());
     868         200 :     CHECK(Object::Equals(isolate, test_case.result, return_val).ToChecked());
     869             :   }
     870             : }
     871             : 
     872       26661 : TEST(InterpreterUnaryOpFeedback) {
     873             :   if (FLAG_lite_mode) return;
     874             : 
     875          10 :   HandleAndZoneScope handles;
     876             :   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          35 :   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          30 :         .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             :     MaybeObject feedback0 = callable.vector()->Get(slot0);
     939          15 :     CHECK(feedback0->IsSmi());
     940          15 :     CHECK_EQ(BinaryOperationFeedback::kSignedSmall, feedback0->ToSmi().value());
     941             : 
     942             :     MaybeObject feedback1 = callable.vector()->Get(slot1);
     943          15 :     CHECK(feedback1->IsSmi());
     944          15 :     CHECK_EQ(BinaryOperationFeedback::kNumber, feedback1->ToSmi().value());
     945             : 
     946             :     MaybeObject feedback2 = callable.vector()->Get(slot2);
     947          15 :     CHECK(feedback2->IsSmi());
     948          15 :     CHECK_EQ(BinaryOperationFeedback::kNumber, feedback2->ToSmi().value());
     949             : 
     950             :     MaybeObject feedback3 = callable.vector()->Get(slot3);
     951          15 :     CHECK(feedback3->IsSmi());
     952          15 :     CHECK_EQ(BinaryOperationFeedback::kBigInt, feedback3->ToSmi().value());
     953             : 
     954             :     MaybeObject feedback4 = callable.vector()->Get(slot4);
     955          15 :     CHECK(feedback4->IsSmi());
     956          15 :     CHECK_EQ(BinaryOperationFeedback::kAny, feedback4->ToSmi().value());
     957             :   }
     958             : }
     959             : 
     960       26661 : TEST(InterpreterBitwiseTypeFeedback) {
     961             :   if (FLAG_lite_mode) return;
     962             : 
     963          10 :   HandleAndZoneScope handles;
     964             :   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          65 :   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             :     MaybeObject feedback0 = callable.vector()->Get(slot0);
    1002          30 :     CHECK(feedback0->IsSmi());
    1003          30 :     CHECK_EQ(BinaryOperationFeedback::kSignedSmall, feedback0->ToSmi().value());
    1004             : 
    1005             :     MaybeObject feedback1 = callable.vector()->Get(slot1);
    1006          30 :     CHECK(feedback1->IsSmi());
    1007          30 :     CHECK_EQ(BinaryOperationFeedback::kNumber, feedback1->ToSmi().value());
    1008             : 
    1009             :     MaybeObject feedback2 = callable.vector()->Get(slot2);
    1010          30 :     CHECK(feedback2->IsSmi());
    1011          30 :     CHECK_EQ(BinaryOperationFeedback::kAny, feedback2->ToSmi().value());
    1012             :   }
    1013             : }
    1014             : 
    1015       26661 : TEST(InterpreterParameter1Assign) {
    1016          10 :   HandleAndZoneScope handles;
    1017             :   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          10 :       callable(Handle<Smi>(Smi::FromInt(3), handles.main_isolate()))
    1032             :           .ToHandleChecked();
    1033           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
    1034           5 : }
    1035             : 
    1036       26661 : TEST(InterpreterLoadGlobal) {
    1037          10 :   HandleAndZoneScope handles;
    1038             :   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           5 :       "}");
    1046          10 :   InterpreterTester tester(isolate, source.c_str());
    1047             :   auto callable = tester.GetCallable<>();
    1048             : 
    1049             :   Handle<Object> return_val = callable().ToHandleChecked();
    1050           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(321));
    1051           5 : }
    1052             : 
    1053       26661 : TEST(InterpreterStoreGlobal) {
    1054          10 :   HandleAndZoneScope handles;
    1055             :   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           5 :       "}");
    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          15 :       Object::GetProperty(isolate, isolate->global_object(), name)
    1071             :           .ToHandleChecked();
    1072           5 :   CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999));
    1073           5 : }
    1074             : 
    1075       26661 : TEST(InterpreterCallGlobal) {
    1076          10 :   HandleAndZoneScope handles;
    1077             :   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           5 :       "}");
    1085          10 :   InterpreterTester tester(isolate, source.c_str());
    1086             :   auto callable = tester.GetCallable<>();
    1087             : 
    1088             :   Handle<Object> return_val = callable().ToHandleChecked();
    1089           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
    1090           5 : }
    1091             : 
    1092       26661 : TEST(InterpreterLoadUnallocated) {
    1093          10 :   HandleAndZoneScope handles;
    1094             :   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           5 :       "}");
    1102          10 :   InterpreterTester tester(isolate, source.c_str());
    1103             :   auto callable = tester.GetCallable<>();
    1104             : 
    1105             :   Handle<Object> return_val = callable().ToHandleChecked();
    1106           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    1107           5 : }
    1108             : 
    1109       26661 : TEST(InterpreterStoreUnallocated) {
    1110          10 :   HandleAndZoneScope handles;
    1111             :   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           5 :       "}");
    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          15 :       Object::GetProperty(isolate, isolate->global_object(), name)
    1127             :           .ToHandleChecked();
    1128           5 :   CHECK_EQ(Smi::cast(*global_obj), Smi::FromInt(999));
    1129           5 : }
    1130             : 
    1131       26661 : TEST(InterpreterLoadNamedProperty) {
    1132          10 :   HandleAndZoneScope handles;
    1133             :   Isolate* isolate = handles.main_isolate();
    1134             :   Zone* zone = handles.main_zone();
    1135             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1136           5 :                               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          10 :   Handle<Object> return_val = callable(object).ToHandleChecked();
    1158           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    1159             : 
    1160             :   // Test transition to monomorphic IC.
    1161          10 :   return_val = callable(object).ToHandleChecked();
    1162           5 :   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          10 :   return_val = callable(object2).ToHandleChecked();
    1168           5 :   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          10 :   callable(object3).ToHandleChecked();
    1174             :   Handle<Object> object4 =
    1175           5 :       InterpreterTester::NewObject("({ val : 789, val3 : 123 })");
    1176          10 :   callable(object4).ToHandleChecked();
    1177             :   Handle<Object> object5 =
    1178           5 :       InterpreterTester::NewObject("({ val : 789, val4 : 123 })");
    1179          10 :   return_val = callable(object5).ToHandleChecked();
    1180           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789));
    1181           5 : }
    1182             : 
    1183       26661 : TEST(InterpreterLoadKeyedProperty) {
    1184          10 :   HandleAndZoneScope handles;
    1185             :   Isolate* isolate = handles.main_isolate();
    1186             :   Zone* zone = handles.main_zone();
    1187             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1188           5 :                               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          10 :   Handle<Object> return_val = callable(object).ToHandleChecked();
    1212           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(123));
    1213             : 
    1214             :   // Test transition to monomorphic IC.
    1215          10 :   return_val = callable(object).ToHandleChecked();
    1216           5 :   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          10 :   return_val = callable(object3).ToHandleChecked();
    1222           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(789));
    1223           5 : }
    1224             : 
    1225       26661 : TEST(InterpreterStoreNamedProperty) {
    1226          10 :   HandleAndZoneScope handles;
    1227             :   Isolate* isolate = handles.main_isolate();
    1228             :   Zone* zone = handles.main_zone();
    1229             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1230           5 :                               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           5 :   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          10 :   callable(object).ToHandleChecked();
    1255          10 :   CHECK(Runtime::GetObjectProperty(isolate, object, name->string())
    1256             :             .ToHandle(&result));
    1257           5 :   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    1258             : 
    1259             :   // Test transition to monomorphic IC.
    1260          10 :   callable(object).ToHandleChecked();
    1261          10 :   CHECK(Runtime::GetObjectProperty(isolate, object, name->string())
    1262             :             .ToHandle(&result));
    1263           5 :   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          10 :   callable(object2).ToHandleChecked();
    1269          10 :   CHECK(Runtime::GetObjectProperty(isolate, object2, name->string())
    1270             :             .ToHandle(&result));
    1271           5 :   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          10 :   callable(object3).ToHandleChecked();
    1277             :   Handle<Object> object4 =
    1278           5 :       InterpreterTester::NewObject("({ val : 789, val3 : 123 })");
    1279          10 :   callable(object4).ToHandleChecked();
    1280             :   Handle<Object> object5 =
    1281           5 :       InterpreterTester::NewObject("({ val : 789, val4 : 123 })");
    1282          10 :   callable(object5).ToHandleChecked();
    1283          10 :   CHECK(Runtime::GetObjectProperty(isolate, object5, name->string())
    1284             :             .ToHandle(&result));
    1285           5 :   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    1286           5 : }
    1287             : 
    1288       26661 : TEST(InterpreterStoreKeyedProperty) {
    1289          10 :   HandleAndZoneScope handles;
    1290             :   Isolate* isolate = handles.main_isolate();
    1291             :   Zone* zone = handles.main_zone();
    1292             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1293           5 :                               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           5 :   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          10 :   callable(object).ToHandleChecked();
    1320          10 :   CHECK(Runtime::GetObjectProperty(isolate, object, name->string())
    1321             :             .ToHandle(&result));
    1322           5 :   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    1323             : 
    1324             :   // Test transition to monomorphic IC.
    1325          10 :   callable(object).ToHandleChecked();
    1326          10 :   CHECK(Runtime::GetObjectProperty(isolate, object, name->string())
    1327             :             .ToHandle(&result));
    1328           5 :   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          10 :   callable(object2).ToHandleChecked();
    1334          10 :   CHECK(Runtime::GetObjectProperty(isolate, object2, name->string())
    1335             :             .ToHandle(&result));
    1336           5 :   CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
    1337           5 : }
    1338             : 
    1339       26661 : TEST(InterpreterCall) {
    1340          10 :   HandleAndZoneScope handles;
    1341             :   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           5 :                               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          10 :     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          10 :     Handle<Object> return_val = callable(object).ToHandleChecked();
    1380           5 :     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(0x265));
    1381             :   }
    1382             : 
    1383             :   // Check that receiver is passed properly.
    1384             :   {
    1385          10 :     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          10 :     Handle<Object> return_val = callable(object).ToHandleChecked();
    1405           5 :     CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(1234));
    1406             :   }
    1407             : 
    1408             :   // Check with two parameters (+ receiver).
    1409             :   {
    1410          10 :     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          10 :     Handle<Object> return_val = callable(object).ToHandleChecked();
    1438          10 :     CHECK(return_val->SameValue(Smi::FromInt(40)));
    1439             :   }
    1440             : 
    1441             :   // Check with 10 parameters (+ receiver).
    1442             :   {
    1443          10 :     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          10 :     Handle<Object> return_val = callable(object).ToHandleChecked();
    1490             :     Handle<i::String> expected =
    1491           5 :         factory->NewStringFromAsciiChecked("prefix_abcdefghij");
    1492           5 :     CHECK(i::String::cast(*return_val)->Equals(*expected));
    1493             :   }
    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       26661 : TEST(InterpreterJumps) {
    1517          10 :   HandleAndZoneScope handles;
    1518             :   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             :   BytecodeLoopHeader loop_header;
    1532          25 :   BytecodeLabel label[2];
    1533             : 
    1534           5 :   builder.LoadLiteral(Smi::zero())
    1535           5 :       .StoreAccumulatorInRegister(reg)
    1536           5 :       .Jump(&label[0]);
    1537           5 :   SetRegister(builder, reg, 1024, scratch).Bind(&loop_header);
    1538           5 :   IncrementRegister(builder, reg, 1, scratch, GetIndex(slot)).Jump(&label[1]);
    1539           5 :   SetRegister(builder, reg, 2048, scratch).Bind(&label[0]);
    1540           5 :   IncrementRegister(builder, reg, 2, scratch, GetIndex(slot1))
    1541           5 :       .JumpLoop(&loop_header, 0);
    1542           5 :   SetRegister(builder, reg, 4096, scratch).Bind(&label[1]);
    1543           5 :   IncrementRegister(builder, reg, 4, scratch, GetIndex(slot2))
    1544           5 :       .LoadAccumulatorWithRegister(reg)
    1545           5 :       .Return();
    1546             : 
    1547           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1548          10 :   InterpreterTester tester(isolate, bytecode_array, metadata);
    1549             :   auto callable = tester.GetCallable<>();
    1550             :   Handle<Object> return_value = callable().ToHandleChecked();
    1551           5 :   CHECK_EQ(Smi::ToInt(*return_value), 7);
    1552           5 : }
    1553             : 
    1554       26661 : TEST(InterpreterConditionalJumps) {
    1555          10 :   HandleAndZoneScope handles;
    1556             :   Isolate* isolate = handles.main_isolate();
    1557             :   Zone* zone = handles.main_zone();
    1558             :   FeedbackVectorSpec feedback_spec(zone);
    1559          10 :   BytecodeArrayBuilder builder(zone, 1, 2, &feedback_spec);
    1560             : 
    1561             :   FeedbackSlot slot = feedback_spec.AddBinaryOpICSlot();
    1562             :   FeedbackSlot slot1 = feedback_spec.AddBinaryOpICSlot();
    1563             :   FeedbackSlot slot2 = feedback_spec.AddBinaryOpICSlot();
    1564             :   FeedbackSlot slot3 = feedback_spec.AddBinaryOpICSlot();
    1565             :   FeedbackSlot slot4 = feedback_spec.AddBinaryOpICSlot();
    1566             : 
    1567             :   Handle<i::FeedbackMetadata> metadata =
    1568             :       NewFeedbackMetadata(isolate, &feedback_spec);
    1569             : 
    1570             :   Register reg(0), scratch(1);
    1571          25 :   BytecodeLabel label[2];
    1572             :   BytecodeLabel done, done1;
    1573             : 
    1574           5 :   builder.LoadLiteral(Smi::zero())
    1575           5 :       .StoreAccumulatorInRegister(reg)
    1576           5 :       .LoadFalse()
    1577           5 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &label[0]);
    1578           5 :   IncrementRegister(builder, reg, 1024, scratch, GetIndex(slot))
    1579           5 :       .Bind(&label[0])
    1580           5 :       .LoadTrue()
    1581           5 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done);
    1582           5 :   IncrementRegister(builder, reg, 1, scratch, GetIndex(slot1))
    1583           5 :       .LoadTrue()
    1584           5 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &label[1]);
    1585           5 :   IncrementRegister(builder, reg, 2048, scratch, GetIndex(slot2))
    1586           5 :       .Bind(&label[1]);
    1587           5 :   IncrementRegister(builder, reg, 2, scratch, GetIndex(slot3))
    1588           5 :       .LoadFalse()
    1589           5 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &done1);
    1590           5 :   IncrementRegister(builder, reg, 4, scratch, GetIndex(slot4))
    1591           5 :       .LoadAccumulatorWithRegister(reg)
    1592           5 :       .Bind(&done)
    1593           5 :       .Bind(&done1)
    1594           5 :       .Return();
    1595             : 
    1596           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1597          10 :   InterpreterTester tester(isolate, bytecode_array, metadata);
    1598             :   auto callable = tester.GetCallable<>();
    1599             :   Handle<Object> return_value = callable().ToHandleChecked();
    1600           5 :   CHECK_EQ(Smi::ToInt(*return_value), 7);
    1601           5 : }
    1602             : 
    1603       26661 : TEST(InterpreterConditionalJumps2) {
    1604             :   // TODO(oth): Add tests for all conditional jumps near and far.
    1605          10 :   HandleAndZoneScope handles;
    1606             :   Isolate* isolate = handles.main_isolate();
    1607             :   Zone* zone = handles.main_zone();
    1608             :   FeedbackVectorSpec feedback_spec(zone);
    1609          10 :   BytecodeArrayBuilder builder(zone, 1, 2, &feedback_spec);
    1610             : 
    1611             :   FeedbackSlot slot = feedback_spec.AddBinaryOpICSlot();
    1612             :   FeedbackSlot slot1 = feedback_spec.AddBinaryOpICSlot();
    1613             :   FeedbackSlot slot2 = feedback_spec.AddBinaryOpICSlot();
    1614             :   FeedbackSlot slot3 = feedback_spec.AddBinaryOpICSlot();
    1615             :   FeedbackSlot slot4 = feedback_spec.AddBinaryOpICSlot();
    1616             : 
    1617             :   Handle<i::FeedbackMetadata> metadata =
    1618             :       NewFeedbackMetadata(isolate, &feedback_spec);
    1619             : 
    1620             :   Register reg(0), scratch(1);
    1621          25 :   BytecodeLabel label[2];
    1622             :   BytecodeLabel done, done1;
    1623             : 
    1624           5 :   builder.LoadLiteral(Smi::zero())
    1625           5 :       .StoreAccumulatorInRegister(reg)
    1626           5 :       .LoadFalse()
    1627           5 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &label[0]);
    1628           5 :   IncrementRegister(builder, reg, 1024, scratch, GetIndex(slot))
    1629           5 :       .Bind(&label[0])
    1630           5 :       .LoadTrue()
    1631           5 :       .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &done);
    1632           5 :   IncrementRegister(builder, reg, 1, scratch, GetIndex(slot1))
    1633           5 :       .LoadTrue()
    1634           5 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &label[1]);
    1635           5 :   IncrementRegister(builder, reg, 2048, scratch, GetIndex(slot2))
    1636           5 :       .Bind(&label[1]);
    1637           5 :   IncrementRegister(builder, reg, 2, scratch, GetIndex(slot3))
    1638           5 :       .LoadFalse()
    1639           5 :       .JumpIfTrue(ToBooleanMode::kAlreadyBoolean, &done1);
    1640           5 :   IncrementRegister(builder, reg, 4, scratch, GetIndex(slot4))
    1641           5 :       .LoadAccumulatorWithRegister(reg)
    1642           5 :       .Bind(&done)
    1643           5 :       .Bind(&done1)
    1644           5 :       .Return();
    1645             : 
    1646           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1647          10 :   InterpreterTester tester(isolate, bytecode_array, metadata);
    1648             :   auto callable = tester.GetCallable<>();
    1649             :   Handle<Object> return_value = callable().ToHandleChecked();
    1650           5 :   CHECK_EQ(Smi::ToInt(*return_value), 7);
    1651           5 : }
    1652             : 
    1653       26661 : TEST(InterpreterJumpConstantWith16BitOperand) {
    1654          10 :   HandleAndZoneScope handles;
    1655             :   Isolate* isolate = handles.main_isolate();
    1656             :   Zone* zone = handles.main_zone();
    1657             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1658           5 :                               HashSeed(isolate));
    1659             :   FeedbackVectorSpec feedback_spec(zone);
    1660          10 :   BytecodeArrayBuilder builder(zone, 1, 257, &feedback_spec);
    1661             : 
    1662             :   FeedbackSlot slot = feedback_spec.AddBinaryOpICSlot();
    1663             :   Handle<i::FeedbackMetadata> metadata =
    1664             :       NewFeedbackMetadata(isolate, &feedback_spec);
    1665             : 
    1666             :   Register reg(0), scratch(256);
    1667             :   BytecodeLabel done, fake;
    1668             : 
    1669           5 :   builder.LoadLiteral(Smi::zero());
    1670           5 :   builder.StoreAccumulatorInRegister(reg);
    1671             :   // Conditional jump to the fake label, to force both basic blocks to be live.
    1672           5 :   builder.JumpIfTrue(ToBooleanMode::kConvertToBoolean, &fake);
    1673             :   // Consume all 8-bit operands
    1674        2565 :   for (int i = 1; i <= 256; i++) {
    1675        1280 :     builder.LoadLiteral(i + 0.5);
    1676        1280 :     builder.BinaryOperation(Token::Value::ADD, reg, GetIndex(slot));
    1677        1280 :     builder.StoreAccumulatorInRegister(reg);
    1678             :   }
    1679           5 :   builder.Jump(&done);
    1680             : 
    1681             :   // Emit more than 16-bit immediate operands worth of code to jump over.
    1682           5 :   builder.Bind(&fake);
    1683       66005 :   for (int i = 0; i < 6600; i++) {
    1684       33000 :     builder.LoadLiteral(Smi::zero());  // 1-byte
    1685             :     builder.BinaryOperation(Token::Value::ADD, scratch,
    1686       33000 :                             GetIndex(slot));              // 6-bytes
    1687       33000 :     builder.StoreAccumulatorInRegister(scratch);          // 4-bytes
    1688       33000 :     builder.MoveRegister(scratch, reg);                   // 6-bytes
    1689             :   }
    1690           5 :   builder.Bind(&done);
    1691           5 :   builder.LoadAccumulatorWithRegister(reg);
    1692           5 :   builder.Return();
    1693             : 
    1694           5 :   ast_factory.Internalize(isolate);
    1695           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1696           5 :   BytecodeArrayIterator iterator(bytecode_array);
    1697             : 
    1698             :   bool found_16bit_constant_jump = false;
    1699        7715 :   while (!iterator.done()) {
    1700        3860 :     if (iterator.current_bytecode() == Bytecode::kJumpConstant &&
    1701             :         iterator.current_operand_scale() == OperandScale::kDouble) {
    1702             :       found_16bit_constant_jump = true;
    1703             :       break;
    1704             :     }
    1705        3855 :     iterator.Advance();
    1706             :   }
    1707           5 :   CHECK(found_16bit_constant_jump);
    1708             : 
    1709          10 :   InterpreterTester tester(isolate, bytecode_array, metadata);
    1710             :   auto callable = tester.GetCallable<>();
    1711             :   Handle<Object> return_value = callable().ToHandleChecked();
    1712           5 :   CHECK_EQ(Handle<HeapNumber>::cast(return_value)->value(),
    1713             :            256.0 / 2 * (1.5 + 256.5));
    1714           5 : }
    1715             : 
    1716       26661 : TEST(InterpreterJumpWith32BitOperand) {
    1717          10 :   HandleAndZoneScope handles;
    1718             :   Isolate* isolate = handles.main_isolate();
    1719             :   Zone* zone = handles.main_zone();
    1720             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1721           5 :                               HashSeed(isolate));
    1722          10 :   BytecodeArrayBuilder builder(zone, 1, 1);
    1723             :   Register reg(0);
    1724             :   BytecodeLabel done;
    1725             : 
    1726           5 :   builder.LoadLiteral(Smi::zero());
    1727           5 :   builder.StoreAccumulatorInRegister(reg);
    1728             :   // Consume all 16-bit constant pool entries. Make sure to use doubles so that
    1729             :   // the jump can't re-use an integer.
    1730      655365 :   for (int i = 1; i <= 65536; i++) {
    1731      327680 :     builder.LoadLiteral(i + 0.5);
    1732             :   }
    1733           5 :   builder.Jump(&done);
    1734           5 :   builder.LoadLiteral(Smi::zero());
    1735           5 :   builder.Bind(&done);
    1736           5 :   builder.Return();
    1737             : 
    1738           5 :   ast_factory.Internalize(isolate);
    1739           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1740             : 
    1741           5 :   BytecodeArrayIterator iterator(bytecode_array);
    1742             : 
    1743             :   bool found_32bit_jump = false;
    1744          35 :   while (!iterator.done()) {
    1745          20 :     if (iterator.current_bytecode() == Bytecode::kJump &&
    1746             :         iterator.current_operand_scale() == OperandScale::kQuadruple) {
    1747             :       found_32bit_jump = true;
    1748             :       break;
    1749             :     }
    1750          15 :     iterator.Advance();
    1751             :   }
    1752           5 :   CHECK(found_32bit_jump);
    1753             : 
    1754          10 :   InterpreterTester tester(isolate, bytecode_array);
    1755             :   auto callable = tester.GetCallable<>();
    1756             :   Handle<Object> return_value = callable().ToHandleChecked();
    1757           5 :   CHECK_EQ(Handle<HeapNumber>::cast(return_value)->value(), 65536.5);
    1758           5 : }
    1759             : 
    1760             : static const Token::Value kComparisonTypes[] = {
    1761             :     Token::Value::EQ,  Token::Value::EQ_STRICT, Token::Value::LT,
    1762             :     Token::Value::LTE, Token::Value::GT,        Token::Value::GTE};
    1763             : 
    1764             : template <typename T>
    1765       10480 : bool CompareC(Token::Value op, T lhs, T rhs, bool types_differed = false) {
    1766       10480 :   switch (op) {
    1767             :     case Token::Value::EQ:
    1768        1655 :       return lhs == rhs;
    1769             :     case Token::Value::NE:
    1770           0 :       return lhs != rhs;
    1771             :     case Token::Value::EQ_STRICT:
    1772        1655 :       return (lhs == rhs) && !types_differed;
    1773             :     case Token::Value::NE_STRICT:
    1774         550 :       return (lhs != rhs) || types_differed;
    1775             :     case Token::Value::LT:
    1776        1655 :       return lhs < rhs;
    1777             :     case Token::Value::LTE:
    1778        1655 :       return lhs <= rhs;
    1779             :     case Token::Value::GT:
    1780        1655 :       return lhs > rhs;
    1781             :     case Token::Value::GTE:
    1782        1655 :       return lhs >= rhs;
    1783             :     default:
    1784           0 :       UNREACHABLE();
    1785             :   }
    1786             : }
    1787             : 
    1788       26661 : TEST(InterpreterSmiComparisons) {
    1789             :   // NB Constants cover 31-bit space.
    1790             :   int inputs[] = {v8::internal::kMinInt / 2,
    1791             :                   v8::internal::kMinInt / 4,
    1792             :                   -108733832,
    1793             :                   -999,
    1794             :                   -42,
    1795             :                   -2,
    1796             :                   -1,
    1797             :                   0,
    1798             :                   +1,
    1799             :                   +2,
    1800             :                   42,
    1801             :                   12345678,
    1802             :                   v8::internal::kMaxInt / 4,
    1803           5 :                   v8::internal::kMaxInt / 2};
    1804             : 
    1805          65 :   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
    1806          30 :     Token::Value comparison = kComparisonTypes[c];
    1807         870 :     for (size_t i = 0; i < arraysize(inputs); i++) {
    1808       12180 :       for (size_t j = 0; j < arraysize(inputs); j++) {
    1809       11760 :         HandleAndZoneScope handles;
    1810             :         Isolate* isolate = handles.main_isolate();
    1811             :         Zone* zone = handles.main_zone();
    1812             :         FeedbackVectorSpec feedback_spec(zone);
    1813       11760 :         BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
    1814             : 
    1815             :         FeedbackSlot slot = feedback_spec.AddCompareICSlot();
    1816             :         Handle<i::FeedbackMetadata> metadata =
    1817             :             NewFeedbackMetadata(isolate, &feedback_spec);
    1818             : 
    1819             :         Register r0(0);
    1820       11760 :         builder.LoadLiteral(Smi::FromInt(inputs[i]))
    1821        5880 :             .StoreAccumulatorInRegister(r0)
    1822       11760 :             .LoadLiteral(Smi::FromInt(inputs[j]))
    1823       11760 :             .CompareOperation(comparison, r0, GetIndex(slot))
    1824        5880 :             .Return();
    1825             : 
    1826        5880 :         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1827       11760 :         InterpreterTester tester(isolate, bytecode_array, metadata);
    1828             :         auto callable = tester.GetCallable<>();
    1829             :         Handle<Object> return_value = callable().ToHandleChecked();
    1830        5880 :         CHECK(return_value->IsBoolean());
    1831       11760 :         CHECK_EQ(return_value->BooleanValue(isolate),
    1832             :                  CompareC(comparison, inputs[i], inputs[j]));
    1833        5880 :         if (tester.HasFeedbackMetadata()) {
    1834             :           MaybeObject feedback = callable.vector()->Get(slot);
    1835        5880 :           CHECK(feedback->IsSmi());
    1836        5880 :           CHECK_EQ(CompareOperationFeedback::kSignedSmall,
    1837             :                    feedback->ToSmi().value());
    1838             :         }
    1839             :       }
    1840             :     }
    1841             :   }
    1842           5 : }
    1843             : 
    1844       26661 : TEST(InterpreterHeapNumberComparisons) {
    1845             :   double inputs[] = {std::numeric_limits<double>::min(),
    1846             :                      std::numeric_limits<double>::max(),
    1847             :                      -0.001,
    1848             :                      0.01,
    1849             :                      0.1000001,
    1850             :                      1e99,
    1851           5 :                      -1e-99};
    1852          65 :   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
    1853          30 :     Token::Value comparison = kComparisonTypes[c];
    1854         450 :     for (size_t i = 0; i < arraysize(inputs); i++) {
    1855        3150 :       for (size_t j = 0; j < arraysize(inputs); j++) {
    1856        2940 :         HandleAndZoneScope handles;
    1857             :         Isolate* isolate = handles.main_isolate();
    1858             :         Zone* zone = handles.main_zone();
    1859             :         AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1860        1470 :                                     HashSeed(isolate));
    1861             : 
    1862             :         FeedbackVectorSpec feedback_spec(zone);
    1863        2940 :         BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
    1864             : 
    1865             :         FeedbackSlot slot = feedback_spec.AddCompareICSlot();
    1866             :         Handle<i::FeedbackMetadata> metadata =
    1867             :             NewFeedbackMetadata(isolate, &feedback_spec);
    1868             : 
    1869             :         Register r0(0);
    1870        1470 :         builder.LoadLiteral(inputs[i])
    1871        1470 :             .StoreAccumulatorInRegister(r0)
    1872        2940 :             .LoadLiteral(inputs[j])
    1873        2940 :             .CompareOperation(comparison, r0, GetIndex(slot))
    1874        1470 :             .Return();
    1875             : 
    1876        1470 :         ast_factory.Internalize(isolate);
    1877        1470 :         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1878        2940 :         InterpreterTester tester(isolate, bytecode_array, metadata);
    1879             :         auto callable = tester.GetCallable<>();
    1880             :         Handle<Object> return_value = callable().ToHandleChecked();
    1881        1470 :         CHECK(return_value->IsBoolean());
    1882        2940 :         CHECK_EQ(return_value->BooleanValue(isolate),
    1883             :                  CompareC(comparison, inputs[i], inputs[j]));
    1884        1470 :         if (tester.HasFeedbackMetadata()) {
    1885             :           MaybeObject feedback = callable.vector()->Get(slot);
    1886        1470 :           CHECK(feedback->IsSmi());
    1887        1470 :           CHECK_EQ(CompareOperationFeedback::kNumber,
    1888             :                    feedback->ToSmi().value());
    1889             :         }
    1890             :       }
    1891             :     }
    1892             :   }
    1893           5 : }
    1894             : 
    1895       26661 : TEST(InterpreterBigIntComparisons) {
    1896             :   // This test only checks that the recorded type feedback is kBigInt.
    1897             :   AstBigInt inputs[] = {AstBigInt("0"), AstBigInt("-42"),
    1898             :                         AstBigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")};
    1899          65 :   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
    1900          30 :     Token::Value comparison = kComparisonTypes[c];
    1901         210 :     for (size_t i = 0; i < arraysize(inputs); i++) {
    1902         630 :       for (size_t j = 0; j < arraysize(inputs); j++) {
    1903         540 :         HandleAndZoneScope handles;
    1904             :         Isolate* isolate = handles.main_isolate();
    1905             :         Zone* zone = handles.main_zone();
    1906             :         AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1907         270 :                                     HashSeed(isolate));
    1908             : 
    1909             :         FeedbackVectorSpec feedback_spec(zone);
    1910         540 :         BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
    1911             : 
    1912             :         FeedbackSlot slot = feedback_spec.AddCompareICSlot();
    1913             :         Handle<i::FeedbackMetadata> metadata =
    1914             :             NewFeedbackMetadata(isolate, &feedback_spec);
    1915             : 
    1916             :         Register r0(0);
    1917         270 :         builder.LoadLiteral(inputs[i])
    1918         270 :             .StoreAccumulatorInRegister(r0)
    1919         270 :             .LoadLiteral(inputs[j])
    1920         540 :             .CompareOperation(comparison, r0, GetIndex(slot))
    1921         270 :             .Return();
    1922             : 
    1923         270 :         ast_factory.Internalize(isolate);
    1924         270 :         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1925         540 :         InterpreterTester tester(isolate, bytecode_array, metadata);
    1926             :         auto callable = tester.GetCallable<>();
    1927             :         Handle<Object> return_value = callable().ToHandleChecked();
    1928         270 :         CHECK(return_value->IsBoolean());
    1929         270 :         if (tester.HasFeedbackMetadata()) {
    1930             :           MaybeObject feedback = callable.vector()->Get(slot);
    1931         270 :           CHECK(feedback->IsSmi());
    1932         270 :           CHECK_EQ(CompareOperationFeedback::kBigInt,
    1933             :                    feedback->ToSmi().value());
    1934             :         }
    1935             :       }
    1936             :     }
    1937             :   }
    1938           5 : }
    1939             : 
    1940       26661 : TEST(InterpreterStringComparisons) {
    1941          10 :   HandleAndZoneScope handles;
    1942             :   Isolate* isolate = handles.main_isolate();
    1943             :   Zone* zone = handles.main_zone();
    1944             : 
    1945          40 :   std::string inputs[] = {"A", "abc", "z", "", "Foo!", "Foo"};
    1946             : 
    1947          65 :   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
    1948          30 :     Token::Value comparison = kComparisonTypes[c];
    1949         390 :     for (size_t i = 0; i < arraysize(inputs); i++) {
    1950        2340 :       for (size_t j = 0; j < arraysize(inputs); j++) {
    1951             :         AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    1952        1080 :                                     HashSeed(isolate));
    1953             : 
    1954        2160 :         CanonicalHandleScope canonical(isolate);
    1955        1080 :         const char* lhs = inputs[i].c_str();
    1956        1080 :         const char* rhs = inputs[j].c_str();
    1957             : 
    1958             :         FeedbackVectorSpec feedback_spec(zone);
    1959             :         FeedbackSlot slot = feedback_spec.AddCompareICSlot();
    1960             :         Handle<i::FeedbackMetadata> metadata =
    1961             :             NewFeedbackMetadata(isolate, &feedback_spec);
    1962             : 
    1963        2160 :         BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
    1964             :         Register r0(0);
    1965        1080 :         builder.LoadLiteral(ast_factory.GetOneByteString(lhs))
    1966        1080 :             .StoreAccumulatorInRegister(r0)
    1967        2160 :             .LoadLiteral(ast_factory.GetOneByteString(rhs))
    1968        2160 :             .CompareOperation(comparison, r0, GetIndex(slot))
    1969        1080 :             .Return();
    1970             : 
    1971        1080 :         ast_factory.Internalize(isolate);
    1972        1080 :         Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    1973        2160 :         InterpreterTester tester(isolate, bytecode_array, metadata);
    1974             :         auto callable = tester.GetCallable<>();
    1975             :         Handle<Object> return_value = callable().ToHandleChecked();
    1976        1080 :         CHECK(return_value->IsBoolean());
    1977        4320 :         CHECK_EQ(return_value->BooleanValue(isolate),
    1978             :                  CompareC(comparison, inputs[i], inputs[j]));
    1979        1080 :         if (tester.HasFeedbackMetadata()) {
    1980             :           MaybeObject feedback = callable.vector()->Get(slot);
    1981        1080 :           CHECK(feedback->IsSmi());
    1982             :           int const expected_feedback =
    1983             :               Token::IsOrderedRelationalCompareOp(comparison)
    1984             :                   ? CompareOperationFeedback::kString
    1985        1080 :                   : CompareOperationFeedback::kInternalizedString;
    1986        1080 :           CHECK_EQ(expected_feedback, feedback->ToSmi().value());
    1987             :         }
    1988             :       }
    1989             :     }
    1990             :   }
    1991           5 : }
    1992             : 
    1993         750 : static void LoadStringAndAddSpace(BytecodeArrayBuilder* builder,
    1994             :                                   AstValueFactory* ast_factory,
    1995             :                                   const char* cstr,
    1996             :                                   FeedbackSlot string_add_slot) {
    1997         750 :   Register string_reg = builder->register_allocator()->NewRegister();
    1998             : 
    1999             :   (*builder)
    2000         750 :       .LoadLiteral(ast_factory->GetOneByteString(cstr))
    2001         750 :       .StoreAccumulatorInRegister(string_reg)
    2002        1500 :       .LoadLiteral(ast_factory->GetOneByteString(" "))
    2003             :       .BinaryOperation(Token::Value::ADD, string_reg,
    2004         750 :                        GetIndex(string_add_slot));
    2005         750 : }
    2006             : 
    2007       26661 : TEST(InterpreterMixedComparisons) {
    2008             :   // This test compares a HeapNumber with a String. The latter is
    2009             :   // convertible to a HeapNumber so comparison will be between numeric
    2010             :   // values except for the strict comparisons where no conversion is
    2011             :   // performed.
    2012           5 :   const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e50", "2.01"};
    2013             : 
    2014             :   enum WhichSideString { kLhsIsString, kRhsIsString };
    2015             : 
    2016             :   enum StringType { kInternalizedStringConstant, kComputedString };
    2017             : 
    2018          65 :   for (size_t c = 0; c < arraysize(kComparisonTypes); c++) {
    2019          30 :     Token::Value comparison = kComparisonTypes[c];
    2020         330 :     for (size_t i = 0; i < arraysize(inputs); i++) {
    2021        1650 :       for (size_t j = 0; j < arraysize(inputs); j++) {
    2022             :         // We test the case where either the lhs or the rhs is a string...
    2023        3750 :         for (WhichSideString which_side : {kLhsIsString, kRhsIsString}) {
    2024             :           // ... and the case when the string is internalized or computed.
    2025        4500 :           for (StringType string_type :
    2026        2250 :                {kInternalizedStringConstant, kComputedString}) {
    2027        2250 :             const char* lhs_cstr = inputs[i];
    2028        2250 :             const char* rhs_cstr = inputs[j];
    2029        2250 :             double lhs = StringToDouble(lhs_cstr, ConversionFlags::NO_FLAGS);
    2030        2250 :             double rhs = StringToDouble(rhs_cstr, ConversionFlags::NO_FLAGS);
    2031        3750 :             HandleAndZoneScope handles;
    2032             :             Isolate* isolate = handles.main_isolate();
    2033             :             Zone* zone = handles.main_zone();
    2034             :             AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    2035        2250 :                                         HashSeed(isolate));
    2036             :             FeedbackVectorSpec feedback_spec(zone);
    2037        3750 :             BytecodeArrayBuilder builder(zone, 1, 0, &feedback_spec);
    2038             : 
    2039        2250 :             FeedbackSlot string_add_slot = feedback_spec.AddBinaryOpICSlot();
    2040             :             FeedbackSlot slot = feedback_spec.AddCompareICSlot();
    2041             :             Handle<i::FeedbackMetadata> metadata =
    2042             :                 NewFeedbackMetadata(isolate, &feedback_spec);
    2043             : 
    2044             :             // lhs is in a register, rhs is in the accumulator.
    2045        2250 :             Register lhs_reg = builder.register_allocator()->NewRegister();
    2046             : 
    2047        2250 :             if (which_side == kRhsIsString) {
    2048             :               // Comparison with HeapNumber on the lhs and String on the rhs.
    2049             : 
    2050         750 :               builder.LoadLiteral(lhs).StoreAccumulatorInRegister(lhs_reg);
    2051             : 
    2052         750 :               if (string_type == kInternalizedStringConstant) {
    2053             :                 // rhs string is internalized.
    2054         750 :                 builder.LoadLiteral(ast_factory.GetOneByteString(rhs_cstr));
    2055             :               } else {
    2056           0 :                 CHECK_EQ(string_type, kComputedString);
    2057             :                 // rhs string is not internalized (append a space to the end).
    2058             :                 LoadStringAndAddSpace(&builder, &ast_factory, rhs_cstr,
    2059           0 :                                       string_add_slot);
    2060             :               }
    2061         750 :               break;
    2062             :             } else {
    2063        1500 :               CHECK_EQ(which_side, kLhsIsString);
    2064             :               // Comparison with String on the lhs and HeapNumber on the rhs.
    2065             : 
    2066        1500 :               if (string_type == kInternalizedStringConstant) {
    2067             :                 // lhs string is internalized
    2068         750 :                 builder.LoadLiteral(ast_factory.GetOneByteString(lhs_cstr));
    2069             :               } else {
    2070         750 :                 CHECK_EQ(string_type, kComputedString);
    2071             :                 // lhs string is not internalized (append a space to the end).
    2072             :                 LoadStringAndAddSpace(&builder, &ast_factory, lhs_cstr,
    2073         750 :                                       string_add_slot);
    2074             :               }
    2075        1500 :               builder.StoreAccumulatorInRegister(lhs_reg);
    2076             : 
    2077        1500 :               builder.LoadLiteral(rhs);
    2078             :             }
    2079             : 
    2080        1500 :             builder.CompareOperation(comparison, lhs_reg, GetIndex(slot))
    2081        1500 :                 .Return();
    2082             : 
    2083        1500 :             ast_factory.Internalize(isolate);
    2084             :             Handle<BytecodeArray> bytecode_array =
    2085        1500 :                 builder.ToBytecodeArray(isolate);
    2086        3000 :             InterpreterTester tester(isolate, bytecode_array, metadata);
    2087             :             auto callable = tester.GetCallable<>();
    2088             :             Handle<Object> return_value = callable().ToHandleChecked();
    2089        1500 :             CHECK(return_value->IsBoolean());
    2090        3000 :             CHECK_EQ(return_value->BooleanValue(isolate),
    2091             :                      CompareC(comparison, lhs, rhs, true));
    2092        1500 :             if (tester.HasFeedbackMetadata()) {
    2093             :               MaybeObject feedback = callable.vector()->Get(slot);
    2094        1500 :               CHECK(feedback->IsSmi());
    2095             :               // Comparison with a number and string collects kAny feedback.
    2096        1500 :               CHECK_EQ(CompareOperationFeedback::kAny,
    2097             :                        feedback->ToSmi().value());
    2098             :             }
    2099             :           }
    2100             :         }
    2101             :       }
    2102             :     }
    2103             :   }
    2104           5 : }
    2105             : 
    2106       26661 : TEST(InterpreterStrictNotEqual) {
    2107          10 :   HandleAndZoneScope handles;
    2108             :   Isolate* isolate = handles.main_isolate();
    2109             :   Factory* factory = isolate->factory();
    2110             :   const char* code_snippet =
    2111             :       "function f(lhs, rhs) {\n"
    2112             :       "  return lhs !== rhs;\n"
    2113             :       "}\n"
    2114             :       "f(0, 0);\n";
    2115          10 :   InterpreterTester tester(isolate, code_snippet);
    2116             :   auto callable = tester.GetCallable<Handle<Object>, Handle<Object>>();
    2117             : 
    2118             :   // Test passing different types.
    2119           5 :   const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"};
    2120          55 :   for (size_t i = 0; i < arraysize(inputs); i++) {
    2121         275 :     for (size_t j = 0; j < arraysize(inputs); j++) {
    2122         125 :       double lhs = StringToDouble(inputs[i], ConversionFlags::NO_FLAGS);
    2123         125 :       double rhs = StringToDouble(inputs[j], ConversionFlags::NO_FLAGS);
    2124         125 :       Handle<Object> lhs_obj = factory->NewNumber(lhs);
    2125         125 :       Handle<Object> rhs_obj = factory->NewStringFromAsciiChecked(inputs[j]);
    2126             : 
    2127             :       Handle<Object> return_value =
    2128         250 :           callable(lhs_obj, rhs_obj).ToHandleChecked();
    2129         125 :       CHECK(return_value->IsBoolean());
    2130         250 :       CHECK_EQ(return_value->BooleanValue(isolate),
    2131             :                CompareC(Token::Value::NE_STRICT, lhs, rhs, true));
    2132             :     }
    2133             :   }
    2134             : 
    2135             :   // Test passing string types.
    2136           5 :   const char* inputs_str[] = {"A", "abc", "z", "", "Foo!", "Foo"};
    2137          65 :   for (size_t i = 0; i < arraysize(inputs_str); i++) {
    2138         390 :     for (size_t j = 0; j < arraysize(inputs_str); j++) {
    2139             :       Handle<Object> lhs_obj =
    2140         180 :           factory->NewStringFromAsciiChecked(inputs_str[i]);
    2141             :       Handle<Object> rhs_obj =
    2142         180 :           factory->NewStringFromAsciiChecked(inputs_str[j]);
    2143             : 
    2144             :       Handle<Object> return_value =
    2145         360 :           callable(lhs_obj, rhs_obj).ToHandleChecked();
    2146         180 :       CHECK(return_value->IsBoolean());
    2147         360 :       CHECK_EQ(return_value->BooleanValue(isolate),
    2148             :                CompareC(Token::Value::NE_STRICT, inputs_str[i], inputs_str[j]));
    2149             :     }
    2150             :   }
    2151             : 
    2152             :   // Test passing doubles.
    2153             :   double inputs_number[] = {std::numeric_limits<double>::min(),
    2154             :                             std::numeric_limits<double>::max(),
    2155             :                             -0.001,
    2156             :                             0.01,
    2157             :                             0.1000001,
    2158             :                             1e99,
    2159           5 :                             -1e-99};
    2160          75 :   for (size_t i = 0; i < arraysize(inputs_number); i++) {
    2161         525 :     for (size_t j = 0; j < arraysize(inputs_number); j++) {
    2162         245 :       Handle<Object> lhs_obj = factory->NewNumber(inputs_number[i]);
    2163         245 :       Handle<Object> rhs_obj = factory->NewNumber(inputs_number[j]);
    2164             : 
    2165             :       Handle<Object> return_value =
    2166         490 :           callable(lhs_obj, rhs_obj).ToHandleChecked();
    2167         245 :       CHECK(return_value->IsBoolean());
    2168         490 :       CHECK_EQ(return_value->BooleanValue(isolate),
    2169             :                CompareC(Token::Value::NE_STRICT, inputs_number[i],
    2170             :                         inputs_number[j]));
    2171             :     }
    2172             :   }
    2173           5 : }
    2174             : 
    2175       26661 : TEST(InterpreterCompareTypeOf) {
    2176             :   typedef TestTypeOfFlags::LiteralFlag LiteralFlag;
    2177          10 :   HandleAndZoneScope handles;
    2178             :   Isolate* isolate = handles.main_isolate();
    2179             :   Factory* factory = isolate->factory();
    2180             :   Zone* zone = handles.main_zone();
    2181             :   std::pair<Handle<Object>, LiteralFlag> inputs[] = {
    2182             :       {handle(Smi::FromInt(24), isolate), LiteralFlag::kNumber},
    2183          10 :       {factory->NewNumber(2.5), LiteralFlag::kNumber},
    2184          10 :       {factory->NewStringFromAsciiChecked("foo"), LiteralFlag::kString},
    2185             :       {factory
    2186          10 :            ->NewConsString(factory->NewStringFromAsciiChecked("foo"),
    2187           5 :                            factory->NewStringFromAsciiChecked("bar"))
    2188             :            .ToHandleChecked(),
    2189             :        LiteralFlag::kString},
    2190             :       {factory->prototype_string(), LiteralFlag::kString},
    2191          10 :       {factory->NewSymbol(), LiteralFlag::kSymbol},
    2192             :       {factory->true_value(), LiteralFlag::kBoolean},
    2193             :       {factory->false_value(), LiteralFlag::kBoolean},
    2194             :       {factory->undefined_value(), LiteralFlag::kUndefined},
    2195          10 :       {InterpreterTester::NewObject(
    2196             :            "(function() { return function() {}; })();"),
    2197             :        LiteralFlag::kFunction},
    2198          10 :       {InterpreterTester::NewObject("new Object();"), LiteralFlag::kObject},
    2199             :       {factory->null_value(), LiteralFlag::kObject},
    2200             :   };
    2201             :   const LiteralFlag kLiterals[] = {
    2202             : #define LITERAL_FLAG(name, _) LiteralFlag::k##name,
    2203             :       TYPEOF_LITERAL_LIST(LITERAL_FLAG)
    2204             : #undef LITERAL_FLAG
    2205           5 :   };
    2206             : 
    2207          95 :   for (size_t l = 0; l < arraysize(kLiterals); l++) {
    2208          45 :     LiteralFlag literal_flag = kLiterals[l];
    2209          50 :     if (literal_flag == LiteralFlag::kOther) continue;
    2210             : 
    2211          80 :     BytecodeArrayBuilder builder(zone, 1, 0);
    2212          40 :     builder.LoadAccumulatorWithRegister(builder.Receiver())
    2213          40 :         .CompareTypeOf(kLiterals[l])
    2214          40 :         .Return();
    2215          40 :     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2216          80 :     InterpreterTester tester(isolate, bytecode_array);
    2217             :     auto callable = tester.GetCallable<Handle<Object>>();
    2218             : 
    2219        1000 :     for (size_t i = 0; i < arraysize(inputs); i++) {
    2220         960 :       Handle<Object> return_value = callable(inputs[i].first).ToHandleChecked();
    2221         480 :       CHECK(return_value->IsBoolean());
    2222         960 :       CHECK_EQ(return_value->BooleanValue(isolate),
    2223             :                inputs[i].second == literal_flag);
    2224             :     }
    2225             :   }
    2226           5 : }
    2227             : 
    2228       26661 : TEST(InterpreterInstanceOf) {
    2229          10 :   HandleAndZoneScope handles;
    2230             :   Isolate* isolate = handles.main_isolate();
    2231             :   Zone* zone = handles.main_zone();
    2232             :   Factory* factory = isolate->factory();
    2233           5 :   Handle<i::String> name = factory->NewStringFromAsciiChecked("cons");
    2234           5 :   Handle<i::JSFunction> func = factory->NewFunctionForTest(name);
    2235           5 :   Handle<i::JSObject> instance = factory->NewJSObject(func);
    2236           5 :   Handle<i::Object> other = factory->NewNumber(3.3333);
    2237           5 :   Handle<i::Object> cases[] = {Handle<i::Object>::cast(instance), other};
    2238          25 :   for (size_t i = 0; i < arraysize(cases); i++) {
    2239          10 :     bool expected_value = (i == 0);
    2240             :     FeedbackVectorSpec feedback_spec(zone);
    2241          20 :     BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
    2242             : 
    2243             :     Register r0(0);
    2244          10 :     size_t case_entry = builder.AllocateDeferredConstantPoolEntry();
    2245          10 :     builder.SetDeferredConstantPoolEntry(case_entry, cases[i]);
    2246          10 :     builder.LoadConstantPoolEntry(case_entry).StoreAccumulatorInRegister(r0);
    2247             : 
    2248             :     FeedbackSlot slot = feedback_spec.AddInstanceOfSlot();
    2249             :     Handle<i::FeedbackMetadata> metadata =
    2250             :         NewFeedbackMetadata(isolate, &feedback_spec);
    2251             : 
    2252          10 :     size_t func_entry = builder.AllocateDeferredConstantPoolEntry();
    2253          10 :     builder.SetDeferredConstantPoolEntry(func_entry, func);
    2254          10 :     builder.LoadConstantPoolEntry(func_entry)
    2255          10 :         .CompareOperation(Token::Value::INSTANCEOF, r0, GetIndex(slot))
    2256          10 :         .Return();
    2257             : 
    2258          10 :     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2259          20 :     InterpreterTester tester(isolate, bytecode_array, metadata);
    2260             :     auto callable = tester.GetCallable<>();
    2261             :     Handle<Object> return_value = callable().ToHandleChecked();
    2262          10 :     CHECK(return_value->IsBoolean());
    2263          10 :     CHECK_EQ(return_value->BooleanValue(isolate), expected_value);
    2264             :   }
    2265           5 : }
    2266             : 
    2267       26661 : TEST(InterpreterTestIn) {
    2268          10 :   HandleAndZoneScope handles;
    2269             :   Isolate* isolate = handles.main_isolate();
    2270             :   Zone* zone = handles.main_zone();
    2271             :   Factory* factory = isolate->factory();
    2272             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    2273           5 :                               HashSeed(isolate));
    2274             :   // Allocate an array
    2275             :   Handle<i::JSArray> array =
    2276             :       factory->NewJSArray(0, i::ElementsKind::PACKED_SMI_ELEMENTS);
    2277             :   // Check for these properties on the array object
    2278           5 :   const char* properties[] = {"length", "fuzzle", "x", "0"};
    2279          45 :   for (size_t i = 0; i < arraysize(properties); i++) {
    2280          20 :     bool expected_value = (i == 0);
    2281             :     FeedbackVectorSpec feedback_spec(zone);
    2282          40 :     BytecodeArrayBuilder builder(zone, 1, 1, &feedback_spec);
    2283             : 
    2284             :     Register r0(0);
    2285          20 :     builder.LoadLiteral(ast_factory.GetOneByteString(properties[i]))
    2286          20 :         .StoreAccumulatorInRegister(r0);
    2287             : 
    2288             :     FeedbackSlot slot = feedback_spec.AddKeyedHasICSlot();
    2289             :     Handle<i::FeedbackMetadata> metadata =
    2290             :         NewFeedbackMetadata(isolate, &feedback_spec);
    2291             : 
    2292          20 :     size_t array_entry = builder.AllocateDeferredConstantPoolEntry();
    2293          20 :     builder.SetDeferredConstantPoolEntry(array_entry, array);
    2294          20 :     builder.LoadConstantPoolEntry(array_entry)
    2295          20 :         .CompareOperation(Token::Value::IN, r0, GetIndex(slot))
    2296          20 :         .Return();
    2297             : 
    2298          20 :     ast_factory.Internalize(isolate);
    2299          20 :     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2300          40 :     InterpreterTester tester(isolate, bytecode_array, metadata);
    2301             :     auto callable = tester.GetCallable<>();
    2302             :     Handle<Object> return_value = callable().ToHandleChecked();
    2303          20 :     CHECK(return_value->IsBoolean());
    2304          20 :     CHECK_EQ(return_value->BooleanValue(isolate), expected_value);
    2305             :   }
    2306           5 : }
    2307             : 
    2308       26661 : TEST(InterpreterUnaryNot) {
    2309          10 :   HandleAndZoneScope handles;
    2310             :   Isolate* isolate = handles.main_isolate();
    2311             :   Zone* zone = handles.main_zone();
    2312          95 :   for (size_t i = 1; i < 10; i++) {
    2313          45 :     bool expected_value = ((i & 1) == 1);
    2314          90 :     BytecodeArrayBuilder builder(zone, 1, 0);
    2315             : 
    2316             :     Register r0(0);
    2317          45 :     builder.LoadFalse();
    2318         495 :     for (size_t j = 0; j < i; j++) {
    2319         225 :       builder.LogicalNot(ToBooleanMode::kAlreadyBoolean);
    2320             :     }
    2321          45 :     builder.Return();
    2322          45 :     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2323          90 :     InterpreterTester tester(isolate, bytecode_array);
    2324             :     auto callable = tester.GetCallable<>();
    2325             :     Handle<Object> return_value = callable().ToHandleChecked();
    2326          45 :     CHECK(return_value->IsBoolean());
    2327          45 :     CHECK_EQ(return_value->BooleanValue(isolate), expected_value);
    2328             :   }
    2329           5 : }
    2330             : 
    2331       26661 : TEST(InterpreterUnaryNotNonBoolean) {
    2332          10 :   HandleAndZoneScope handles;
    2333             :   Isolate* isolate = handles.main_isolate();
    2334             :   Zone* zone = handles.main_zone();
    2335             :   AstValueFactory ast_factory(zone, isolate->ast_string_constants(),
    2336           5 :                               HashSeed(isolate));
    2337             : 
    2338             :   std::pair<LiteralForTest, bool> object_type_tuples[] = {
    2339             :       std::make_pair(LiteralForTest(LiteralForTest::kUndefined), true),
    2340             :       std::make_pair(LiteralForTest(LiteralForTest::kNull), true),
    2341             :       std::make_pair(LiteralForTest(LiteralForTest::kFalse), true),
    2342             :       std::make_pair(LiteralForTest(LiteralForTest::kTrue), false),
    2343             :       std::make_pair(LiteralForTest(9.1), false),
    2344             :       std::make_pair(LiteralForTest(0), true),
    2345             :       std::make_pair(LiteralForTest(ast_factory.GetOneByteString("hello")),
    2346           5 :                      false),
    2347           5 :       std::make_pair(LiteralForTest(ast_factory.GetOneByteString("")), true),
    2348             :   };
    2349             : 
    2350          85 :   for (size_t i = 0; i < arraysize(object_type_tuples); i++) {
    2351          80 :     BytecodeArrayBuilder builder(zone, 1, 0);
    2352             : 
    2353             :     Register r0(0);
    2354          40 :     LoadLiteralForTest(&builder, object_type_tuples[i].first);
    2355          40 :     builder.LogicalNot(ToBooleanMode::kConvertToBoolean).Return();
    2356          40 :     ast_factory.Internalize(isolate);
    2357          40 :     Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2358          80 :     InterpreterTester tester(isolate, bytecode_array);
    2359             :     auto callable = tester.GetCallable<>();
    2360             :     Handle<Object> return_value = callable().ToHandleChecked();
    2361          40 :     CHECK(return_value->IsBoolean());
    2362          80 :     CHECK_EQ(return_value->BooleanValue(isolate), object_type_tuples[i].second);
    2363             :   }
    2364           5 : }
    2365             : 
    2366       26661 : TEST(InterpreterTypeof) {
    2367          10 :   HandleAndZoneScope handles;
    2368             :   Isolate* isolate = handles.main_isolate();
    2369             : 
    2370             :   std::pair<const char*, const char*> typeof_vals[] = {
    2371             :       std::make_pair("return typeof undefined;", "undefined"),
    2372             :       std::make_pair("return typeof null;", "object"),
    2373             :       std::make_pair("return typeof true;", "boolean"),
    2374             :       std::make_pair("return typeof false;", "boolean"),
    2375             :       std::make_pair("return typeof 9.1;", "number"),
    2376             :       std::make_pair("return typeof 7771;", "number"),
    2377             :       std::make_pair("return typeof 'hello';", "string"),
    2378             :       std::make_pair("return typeof global_unallocated;", "undefined"),
    2379           5 :   };
    2380             : 
    2381          85 :   for (size_t i = 0; i < arraysize(typeof_vals); i++) {
    2382          40 :     std::string source(InterpreterTester::SourceForBody(typeof_vals[i].first));
    2383          80 :     InterpreterTester tester(isolate, source.c_str());
    2384             : 
    2385             :     auto callable = tester.GetCallable<>();
    2386             :     Handle<v8::internal::String> return_value =
    2387             :         Handle<v8::internal::String>::cast(callable().ToHandleChecked());
    2388          40 :     auto actual = return_value->ToCString();
    2389          80 :     CHECK_EQ(strcmp(&actual[0], typeof_vals[i].second), 0);
    2390             :   }
    2391           5 : }
    2392             : 
    2393       26661 : TEST(InterpreterCallRuntime) {
    2394          10 :   HandleAndZoneScope handles;
    2395             :   Isolate* isolate = handles.main_isolate();
    2396             :   Zone* zone = handles.main_zone();
    2397             : 
    2398          10 :   BytecodeArrayBuilder builder(zone, 1, 2);
    2399           5 :   RegisterList args = builder.register_allocator()->NewRegisterList(2);
    2400             : 
    2401           5 :   builder.LoadLiteral(Smi::FromInt(15))
    2402           5 :       .StoreAccumulatorInRegister(args[0])
    2403           5 :       .LoadLiteral(Smi::FromInt(40))
    2404           5 :       .StoreAccumulatorInRegister(args[1])
    2405           5 :       .CallRuntime(Runtime::kAdd, args)
    2406           5 :       .Return();
    2407           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2408             : 
    2409          10 :   InterpreterTester tester(isolate, bytecode_array);
    2410             :   auto callable = tester.GetCallable<>();
    2411             : 
    2412             :   Handle<Object> return_val = callable().ToHandleChecked();
    2413           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(55));
    2414           5 : }
    2415             : 
    2416       26661 : TEST(InterpreterInvokeIntrinsic) {
    2417          10 :   HandleAndZoneScope handles;
    2418             :   Isolate* isolate = handles.main_isolate();
    2419             :   Zone* zone = handles.main_zone();
    2420             : 
    2421          10 :   BytecodeArrayBuilder builder(zone, 1, 2);
    2422             : 
    2423           5 :   builder.LoadLiteral(Smi::FromInt(15))
    2424          10 :       .StoreAccumulatorInRegister(Register(0))
    2425          10 :       .CallRuntime(Runtime::kInlineIsArray, Register(0))
    2426           5 :       .Return();
    2427           5 :   Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
    2428             : 
    2429          10 :   InterpreterTester tester(isolate, bytecode_array);
    2430             :   auto callable = tester.GetCallable<>();
    2431             : 
    2432             :   Handle<Object> return_val = callable().ToHandleChecked();
    2433           5 :   CHECK(return_val->IsBoolean());
    2434           5 :   CHECK_EQ(return_val->BooleanValue(isolate), false);
    2435           5 : }
    2436             : 
    2437       26661 : TEST(InterpreterFunctionLiteral) {
    2438          10 :   HandleAndZoneScope handles;
    2439             :   Isolate* isolate = handles.main_isolate();
    2440             : 
    2441             :   // Test calling a function literal.
    2442             :   std::string source(
    2443          15 :       "function " + InterpreterTester::function_name() + "(a) {\n"
    2444             :       "  return (function(x){ return x + 2; })(a);\n"
    2445           5 :       "}");
    2446          10 :   InterpreterTester tester(isolate, source.c_str());
    2447             :   auto callable = tester.GetCallable<Handle<Object>>();
    2448             : 
    2449          10 :   Handle<i::Object> return_val = callable(
    2450           5 :       Handle<Smi>(Smi::FromInt(3), handles.main_isolate())).ToHandleChecked();
    2451           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(5));
    2452           5 : }
    2453             : 
    2454       26661 : TEST(InterpreterRegExpLiterals) {
    2455          10 :   HandleAndZoneScope handles;
    2456             :   Isolate* isolate = handles.main_isolate();
    2457             :   Factory* factory = isolate->factory();
    2458             : 
    2459             :   std::pair<const char*, Handle<Object>> literals[] = {
    2460             :       std::make_pair("return /abd/.exec('cccabbdd');\n",
    2461             :                      factory->null_value()),
    2462             :       std::make_pair("return /ab+d/.exec('cccabbdd')[0];\n",
    2463          10 :                      factory->NewStringFromStaticChars("abbd")),
    2464             :       std::make_pair("return /AbC/i.exec('ssaBC')[0];\n",
    2465          10 :                      factory->NewStringFromStaticChars("aBC")),
    2466             :       std::make_pair("return 'ssaBC'.match(/AbC/i)[0];\n",
    2467          10 :                      factory->NewStringFromStaticChars("aBC")),
    2468             :       std::make_pair("return 'ssaBCtAbC'.match(/(AbC)/gi)[1];\n",
    2469          10 :                      factory->NewStringFromStaticChars("AbC")),
    2470             :   };
    2471             : 
    2472          55 :   for (size_t i = 0; i < arraysize(literals); i++) {
    2473          25 :     std::string source(InterpreterTester::SourceForBody(literals[i].first));
    2474          50 :     InterpreterTester tester(isolate, source.c_str());
    2475             :     auto callable = tester.GetCallable<>();
    2476             : 
    2477             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2478          50 :     CHECK(return_value->SameValue(*literals[i].second));
    2479             :   }
    2480           5 : }
    2481             : 
    2482       26661 : TEST(InterpreterArrayLiterals) {
    2483          10 :   HandleAndZoneScope handles;
    2484             :   Isolate* isolate = handles.main_isolate();
    2485             :   Factory* factory = isolate->factory();
    2486             : 
    2487             :   std::pair<const char*, Handle<Object>> literals[] = {
    2488             :       std::make_pair("return [][0];\n",
    2489             :                      factory->undefined_value()),
    2490             :       std::make_pair("return [1, 3, 2][1];\n",
    2491             :                      handle(Smi::FromInt(3), isolate)),
    2492             :       std::make_pair("return ['a', 'b', 'c'][2];\n",
    2493          10 :                      factory->NewStringFromStaticChars("c")),
    2494             :       std::make_pair("var a = 100; return [a, a + 1, a + 2, a + 3][2];\n",
    2495             :                      handle(Smi::FromInt(102), isolate)),
    2496             :       std::make_pair("return [[1, 2, 3], ['a', 'b', 'c']][1][0];\n",
    2497          10 :                      factory->NewStringFromStaticChars("a")),
    2498             :       std::make_pair("var t = 't'; return [[t, t + 'est'], [1 + t]][0][1];\n",
    2499          10 :                      factory->NewStringFromStaticChars("test"))
    2500             :   };
    2501             : 
    2502          65 :   for (size_t i = 0; i < arraysize(literals); i++) {
    2503          30 :     std::string source(InterpreterTester::SourceForBody(literals[i].first));
    2504          60 :     InterpreterTester tester(isolate, source.c_str());
    2505             :     auto callable = tester.GetCallable<>();
    2506             : 
    2507             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2508          60 :     CHECK(return_value->SameValue(*literals[i].second));
    2509             :   }
    2510           5 : }
    2511             : 
    2512       26661 : TEST(InterpreterObjectLiterals) {
    2513          10 :   HandleAndZoneScope handles;
    2514             :   Isolate* isolate = handles.main_isolate();
    2515             :   Factory* factory = isolate->factory();
    2516             : 
    2517             :   std::pair<const char*, Handle<Object>> literals[] = {
    2518             :       std::make_pair("return { }.name;",
    2519             :                      factory->undefined_value()),
    2520             :       std::make_pair("return { name: 'string', val: 9.2 }.name;",
    2521          10 :                      factory->NewStringFromStaticChars("string")),
    2522             :       std::make_pair("var a = 15; return { name: 'string', val: a }.val;",
    2523             :                      handle(Smi::FromInt(15), isolate)),
    2524             :       std::make_pair("var a = 5; return { val: a, val: a + 1 }.val;",
    2525             :                      handle(Smi::FromInt(6), isolate)),
    2526             :       std::make_pair("return { func: function() { return 'test' } }.func();",
    2527          10 :                      factory->NewStringFromStaticChars("test")),
    2528             :       std::make_pair("return { func(a) { return a + 'st'; } }.func('te');",
    2529          10 :                      factory->NewStringFromStaticChars("test")),
    2530             :       std::make_pair("return { get a() { return 22; } }.a;",
    2531             :                      handle(Smi::FromInt(22), isolate)),
    2532             :       std::make_pair("var a = { get b() { return this.x + 't'; },\n"
    2533             :                      "          set b(val) { this.x = val + 's' } };\n"
    2534             :                      "a.b = 'te';\n"
    2535             :                      "return a.b;",
    2536          10 :                      factory->NewStringFromStaticChars("test")),
    2537             :       std::make_pair("var a = 123; return { 1: a }[1];",
    2538             :                      handle(Smi::FromInt(123), isolate)),
    2539             :       std::make_pair("return Object.getPrototypeOf({ __proto__: null });",
    2540             :                      factory->null_value()),
    2541             :       std::make_pair("var a = 'test'; return { [a]: 1 }.test;",
    2542             :                      handle(Smi::FromInt(1), isolate)),
    2543             :       std::make_pair("var a = 'test'; return { b: a, [a]: a + 'ing' }['test']",
    2544          10 :                      factory->NewStringFromStaticChars("testing")),
    2545             :       std::make_pair("var a = 'proto_str';\n"
    2546             :                      "var b = { [a]: 1, __proto__: { var : a } };\n"
    2547             :                      "return Object.getPrototypeOf(b).var",
    2548          10 :                      factory->NewStringFromStaticChars("proto_str")),
    2549             :       std::make_pair("var n = 'name';\n"
    2550             :                      "return { [n]: 'val', get a() { return 987 } }['a'];",
    2551             :                      handle(Smi::FromInt(987), isolate)),
    2552             :   };
    2553             : 
    2554         145 :   for (size_t i = 0; i < arraysize(literals); i++) {
    2555          70 :     std::string source(InterpreterTester::SourceForBody(literals[i].first));
    2556         140 :     InterpreterTester tester(isolate, source.c_str());
    2557             :     auto callable = tester.GetCallable<>();
    2558             : 
    2559             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2560         140 :     CHECK(return_value->SameValue(*literals[i].second));
    2561             :   }
    2562           5 : }
    2563             : 
    2564       26661 : TEST(InterpreterConstruct) {
    2565          10 :   HandleAndZoneScope handles;
    2566             :   Isolate* isolate = handles.main_isolate();
    2567             : 
    2568             :   std::string source(
    2569             :       "function counter() { this.count = 0; }\n"
    2570          10 :       "function " +
    2571          10 :       InterpreterTester::function_name() +
    2572             :       "() {\n"
    2573             :       "  var c = new counter();\n"
    2574             :       "  return c.count;\n"
    2575           5 :       "}");
    2576          10 :   InterpreterTester tester(isolate, source.c_str());
    2577             :   auto callable = tester.GetCallable<>();
    2578             : 
    2579             :   Handle<Object> return_val = callable().ToHandleChecked();
    2580           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::kZero);
    2581           5 : }
    2582             : 
    2583       26661 : TEST(InterpreterConstructWithArgument) {
    2584          10 :   HandleAndZoneScope handles;
    2585             :   Isolate* isolate = handles.main_isolate();
    2586             : 
    2587             :   std::string source(
    2588             :       "function counter(arg0) { this.count = 17; this.x = arg0; }\n"
    2589          10 :       "function " +
    2590          10 :       InterpreterTester::function_name() +
    2591             :       "() {\n"
    2592             :       "  var c = new counter(3);\n"
    2593             :       "  return c.x;\n"
    2594           5 :       "}");
    2595          10 :   InterpreterTester tester(isolate, source.c_str());
    2596             :   auto callable = tester.GetCallable<>();
    2597             : 
    2598             :   Handle<Object> return_val = callable().ToHandleChecked();
    2599           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(3));
    2600           5 : }
    2601             : 
    2602       26661 : TEST(InterpreterConstructWithArguments) {
    2603          10 :   HandleAndZoneScope handles;
    2604             :   Isolate* isolate = handles.main_isolate();
    2605             : 
    2606             :   std::string source(
    2607             :       "function counter(arg0, arg1) {\n"
    2608             :       "  this.count = 7; this.x = arg0; this.y = arg1;\n"
    2609             :       "}\n"
    2610          10 :       "function " +
    2611          10 :       InterpreterTester::function_name() +
    2612             :       "() {\n"
    2613             :       "  var c = new counter(3, 5);\n"
    2614             :       "  return c.count + c.x + c.y;\n"
    2615           5 :       "}");
    2616          10 :   InterpreterTester tester(isolate, source.c_str());
    2617             :   auto callable = tester.GetCallable<>();
    2618             : 
    2619             :   Handle<Object> return_val = callable().ToHandleChecked();
    2620           5 :   CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(15));
    2621           5 : }
    2622             : 
    2623       26661 : TEST(InterpreterContextVariables) {
    2624          10 :   HandleAndZoneScope handles;
    2625             :   Isolate* isolate = handles.main_isolate();
    2626             : 
    2627          10 :   std::ostringstream unique_vars;
    2628        2505 :   for (int i = 0; i < 250; i++) {
    2629        1250 :     unique_vars << "var a" << i << " = 0;";
    2630             :   }
    2631             :   std::pair<std::string, Handle<Object>> context_vars[] = {
    2632             :       std::make_pair("var a; (function() { a = 1; })(); return a;",
    2633             :                      handle(Smi::FromInt(1), isolate)),
    2634             :       std::make_pair("var a = 10; (function() { a; })(); return a;",
    2635             :                      handle(Smi::FromInt(10), isolate)),
    2636             :       std::make_pair("var a = 20; var b = 30;\n"
    2637             :                      "return (function() { return a + b; })();",
    2638             :                      handle(Smi::FromInt(50), isolate)),
    2639             :       std::make_pair("'use strict'; let a = 1;\n"
    2640             :                      "{ let b = 2; return (function() { return a + b; })(); }",
    2641             :                      handle(Smi::FromInt(3), isolate)),
    2642             :       std::make_pair("'use strict'; let a = 10;\n"
    2643             :                      "{ let b = 20; var c = function() { [a, b] };\n"
    2644             :                      "  return a + b; }",
    2645             :                      handle(Smi::FromInt(30), isolate)),
    2646          25 :       std::make_pair("'use strict';" + unique_vars.str() +
    2647             :                      "eval(); var b = 100; return b;",
    2648             :                      handle(Smi::FromInt(100), isolate)),
    2649          35 :   };
    2650             : 
    2651          65 :   for (size_t i = 0; i < arraysize(context_vars); i++) {
    2652             :     std::string source(
    2653          30 :         InterpreterTester::SourceForBody(context_vars[i].first.c_str()));
    2654          60 :     InterpreterTester tester(isolate, source.c_str());
    2655             :     auto callable = tester.GetCallable<>();
    2656             : 
    2657             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2658          60 :     CHECK(return_value->SameValue(*context_vars[i].second));
    2659             :   }
    2660           5 : }
    2661             : 
    2662       26661 : TEST(InterpreterContextParameters) {
    2663          10 :   HandleAndZoneScope handles;
    2664             :   Isolate* isolate = handles.main_isolate();
    2665             : 
    2666             :   std::pair<const char*, Handle<Object>> context_params[] = {
    2667             :       std::make_pair("return (function() { return arg1; })();",
    2668             :                      handle(Smi::FromInt(1), isolate)),
    2669             :       std::make_pair("(function() { arg1 = 4; })(); return arg1;",
    2670             :                      handle(Smi::FromInt(4), isolate)),
    2671             :       std::make_pair("(function() { arg3 = arg2 - arg1; })(); return arg3;",
    2672             :                      handle(Smi::FromInt(1), isolate)),
    2673             :   };
    2674             : 
    2675          35 :   for (size_t i = 0; i < arraysize(context_params); i++) {
    2676          60 :     std::string source = "function " + InterpreterTester::function_name() +
    2677          45 :                          "(arg1, arg2, arg3) {" + context_params[i].first + "}";
    2678          30 :     InterpreterTester tester(isolate, source.c_str());
    2679             :     auto callable =
    2680             :         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
    2681             : 
    2682             :     Handle<Object> a1 = handle(Smi::FromInt(1), isolate);
    2683             :     Handle<Object> a2 = handle(Smi::FromInt(2), isolate);
    2684             :     Handle<Object> a3 = handle(Smi::FromInt(3), isolate);
    2685             :     Handle<i::Object> return_value = callable(a1, a2, a3).ToHandleChecked();
    2686          30 :     CHECK(return_value->SameValue(*context_params[i].second));
    2687             :   }
    2688           5 : }
    2689             : 
    2690       26661 : TEST(InterpreterOuterContextVariables) {
    2691          10 :   HandleAndZoneScope handles;
    2692             :   Isolate* isolate = handles.main_isolate();
    2693             : 
    2694             :   std::pair<const char*, Handle<Object>> context_vars[] = {
    2695             :       std::make_pair("return outerVar * innerArg;",
    2696             :                      handle(Smi::FromInt(200), isolate)),
    2697             :       std::make_pair("outerVar = innerArg; return outerVar",
    2698             :                      handle(Smi::FromInt(20), isolate)),
    2699             :   };
    2700             : 
    2701             :   std::string header(
    2702             :       "function Outer() {"
    2703             :       "  var outerVar = 10;"
    2704             :       "  function Inner(innerArg) {"
    2705           5 :       "    this.innerFunc = function() { ");
    2706             :   std::string footer(
    2707             :       "  }}"
    2708             :       "  this.getInnerFunc = function() { return new Inner(20).innerFunc; }"
    2709             :       "}"
    2710           5 :       "var f = new Outer().getInnerFunc();");
    2711             : 
    2712          25 :   for (size_t i = 0; i < arraysize(context_vars); i++) {
    2713          30 :     std::string source = header + context_vars[i].first + footer;
    2714          20 :     InterpreterTester tester(isolate, source.c_str(), "*");
    2715             :     auto callable = tester.GetCallable<>();
    2716             : 
    2717             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2718          20 :     CHECK(return_value->SameValue(*context_vars[i].second));
    2719             :   }
    2720           5 : }
    2721             : 
    2722       26661 : TEST(InterpreterComma) {
    2723          10 :   HandleAndZoneScope handles;
    2724             :   Isolate* isolate = handles.main_isolate();
    2725             :   Factory* factory = isolate->factory();
    2726             : 
    2727             :   std::pair<const char*, Handle<Object>> literals[] = {
    2728             :       std::make_pair("var a; return 0, a;\n", factory->undefined_value()),
    2729             :       std::make_pair("return 'a', 2.2, 3;\n",
    2730             :                      handle(Smi::FromInt(3), isolate)),
    2731             :       std::make_pair("return 'a', 'b', 'c';\n",
    2732          10 :                      factory->NewStringFromStaticChars("c")),
    2733          10 :       std::make_pair("return 3.2, 2.3, 4.5;\n", factory->NewNumber(4.5)),
    2734             :       std::make_pair("var a = 10; return b = a, b = b+1;\n",
    2735             :                      handle(Smi::FromInt(11), isolate)),
    2736             :       std::make_pair("var a = 10; return b = a, b = b+1, b + 10;\n",
    2737           5 :                      handle(Smi::FromInt(21), isolate))};
    2738             : 
    2739          65 :   for (size_t i = 0; i < arraysize(literals); i++) {
    2740          30 :     std::string source(InterpreterTester::SourceForBody(literals[i].first));
    2741          60 :     InterpreterTester tester(isolate, source.c_str());
    2742             :     auto callable = tester.GetCallable<>();
    2743             : 
    2744             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2745          60 :     CHECK(return_value->SameValue(*literals[i].second));
    2746             :   }
    2747           5 : }
    2748             : 
    2749       26661 : TEST(InterpreterLogicalOr) {
    2750          10 :   HandleAndZoneScope handles;
    2751             :   Isolate* isolate = handles.main_isolate();
    2752             :   Factory* factory = isolate->factory();
    2753             : 
    2754             :   std::pair<const char*, Handle<Object>> literals[] = {
    2755             :       std::make_pair("var a, b; return a || b;\n", factory->undefined_value()),
    2756             :       std::make_pair("var a, b = 10; return a || b;\n",
    2757             :                      handle(Smi::FromInt(10), isolate)),
    2758             :       std::make_pair("var a = '0', b = 10; return a || b;\n",
    2759          10 :                      factory->NewStringFromStaticChars("0")),
    2760          10 :       std::make_pair("return 0 || 3.2;\n", factory->NewNumber(3.2)),
    2761             :       std::make_pair("return 'a' || 0;\n",
    2762          10 :                      factory->NewStringFromStaticChars("a")),
    2763             :       std::make_pair("var a = '0', b = 10; return (a == 0) || b;\n",
    2764           5 :                      factory->true_value())};
    2765             : 
    2766          65 :   for (size_t i = 0; i < arraysize(literals); i++) {
    2767          30 :     std::string source(InterpreterTester::SourceForBody(literals[i].first));
    2768          60 :     InterpreterTester tester(isolate, source.c_str());
    2769             :     auto callable = tester.GetCallable<>();
    2770             : 
    2771             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2772          60 :     CHECK(return_value->SameValue(*literals[i].second));
    2773             :   }
    2774           5 : }
    2775             : 
    2776       26661 : TEST(InterpreterLogicalAnd) {
    2777          10 :   HandleAndZoneScope handles;
    2778             :   Isolate* isolate = handles.main_isolate();
    2779             :   Factory* factory = isolate->factory();
    2780             : 
    2781             :   std::pair<const char*, Handle<Object>> literals[] = {
    2782             :       std::make_pair("var a, b = 10; return a && b;\n",
    2783             :                      factory->undefined_value()),
    2784             :       std::make_pair("var a = 0, b = 10; return a && b / a;\n",
    2785             :                      handle(Smi::kZero, isolate)),
    2786             :       std::make_pair("var a = '0', b = 10; return a && b;\n",
    2787             :                      handle(Smi::FromInt(10), isolate)),
    2788             :       std::make_pair("return 0.0 && 3.2;\n", handle(Smi::kZero, isolate)),
    2789             :       std::make_pair("return 'a' && 'b';\n",
    2790          10 :                      factory->NewStringFromStaticChars("b")),
    2791             :       std::make_pair("return 'a' && 0 || 'b', 'c';\n",
    2792          10 :                      factory->NewStringFromStaticChars("c")),
    2793             :       std::make_pair("var x = 1, y = 3; return x && 0 + 1 || y;\n",
    2794             :                      handle(Smi::FromInt(1), isolate)),
    2795             :       std::make_pair("var x = 1, y = 3; return (x == 1) && (3 == 3) || y;\n",
    2796          10 :                      factory->true_value())};
    2797             : 
    2798          85 :   for (size_t i = 0; i < arraysize(literals); i++) {
    2799          40 :     std::string source(InterpreterTester::SourceForBody(literals[i].first));
    2800          80 :     InterpreterTester tester(isolate, source.c_str());
    2801             :     auto callable = tester.GetCallable<>();
    2802             : 
    2803             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2804          80 :     CHECK(return_value->SameValue(*literals[i].second));
    2805             :   }
    2806           5 : }
    2807             : 
    2808       26661 : TEST(InterpreterTryCatch) {
    2809          10 :   HandleAndZoneScope handles;
    2810             :   Isolate* isolate = handles.main_isolate();
    2811             : 
    2812             :   std::pair<const char*, Handle<Object>> catches[] = {
    2813             :       std::make_pair("var a = 1; try { a = 2 } catch(e) { a = 3 }; return a;",
    2814             :                      handle(Smi::FromInt(2), isolate)),
    2815             :       std::make_pair("var a; try { undef.x } catch(e) { a = 2 }; return a;",
    2816             :                      handle(Smi::FromInt(2), isolate)),
    2817             :       std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 }; return a;",
    2818             :                      handle(Smi::FromInt(3), isolate)),
    2819             :       std::make_pair("var a; try { throw 1 } catch(e) { a = e + 2 };"
    2820             :                      "       try { throw a } catch(e) { a = e + 3 }; return a;",
    2821             :                      handle(Smi::FromInt(6), isolate)),
    2822             :   };
    2823             : 
    2824          45 :   for (size_t i = 0; i < arraysize(catches); i++) {
    2825          20 :     std::string source(InterpreterTester::SourceForBody(catches[i].first));
    2826          40 :     InterpreterTester tester(isolate, source.c_str());
    2827             :     auto callable = tester.GetCallable<>();
    2828             : 
    2829             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2830          40 :     CHECK(return_value->SameValue(*catches[i].second));
    2831             :   }
    2832           5 : }
    2833             : 
    2834       26661 : TEST(InterpreterTryFinally) {
    2835          10 :   HandleAndZoneScope handles;
    2836             :   Isolate* isolate = handles.main_isolate();
    2837             :   Factory* factory = isolate->factory();
    2838             : 
    2839             :   std::pair<const char*, Handle<Object>> finallies[] = {
    2840             :       std::make_pair(
    2841             :           "var a = 1; try { a = a + 1; } finally { a = a + 2; }; return a;",
    2842          10 :           factory->NewStringFromStaticChars("R4")),
    2843             :       std::make_pair(
    2844             :           "var a = 1; try { a = 2; return 23; } finally { a = 3 }; return a;",
    2845          10 :           factory->NewStringFromStaticChars("R23")),
    2846             :       std::make_pair(
    2847             :           "var a = 1; try { a = 2; throw 23; } finally { a = 3 }; return a;",
    2848          10 :           factory->NewStringFromStaticChars("E23")),
    2849             :       std::make_pair(
    2850             :           "var a = 1; try { a = 2; throw 23; } finally { return a; };",
    2851          10 :           factory->NewStringFromStaticChars("R2")),
    2852             :       std::make_pair(
    2853             :           "var a = 1; try { a = 2; throw 23; } finally { throw 42; };",
    2854          10 :           factory->NewStringFromStaticChars("E42")),
    2855             :       std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
    2856             :                      "  try { a = 2; break; } finally { a = 3; }"
    2857             :                      "} return a + i;",
    2858          10 :                      factory->NewStringFromStaticChars("R13")),
    2859             :       std::make_pair("var a = 1; for (var i = 10; i < 20; i += 5) {"
    2860             :                      "  try { a = 2; continue; } finally { a = 3; }"
    2861             :                      "} return a + i;",
    2862          10 :                      factory->NewStringFromStaticChars("R23")),
    2863             :       std::make_pair("var a = 1; try { a = 2;"
    2864             :                      "  try { a = 3; throw 23; } finally { a = 4; }"
    2865             :                      "} catch(e) { a = a + e; } return a;",
    2866          10 :                      factory->NewStringFromStaticChars("R27")),
    2867             :       std::make_pair("var func_name;"
    2868             :                      "function tcf2(a) {"
    2869             :                      "  try { throw new Error('boom');} "
    2870             :                      "  catch(e) {return 153; } "
    2871             :                      "  finally {func_name = tcf2.name;}"
    2872             :                      "}"
    2873             :                      "tcf2();"
    2874             :                      "return func_name;",
    2875          10 :                      factory->NewStringFromStaticChars("Rtcf2")),
    2876             :   };
    2877             : 
    2878             :   const char* try_wrapper =
    2879             :       "(function() { try { return 'R' + f() } catch(e) { return 'E' + e }})()";
    2880             : 
    2881          95 :   for (size_t i = 0; i < arraysize(finallies); i++) {
    2882          45 :     std::string source(InterpreterTester::SourceForBody(finallies[i].first));
    2883          90 :     InterpreterTester tester(isolate, source.c_str());
    2884             :     tester.GetCallable<>();
    2885             :     Handle<Object> wrapped = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
    2886          90 :     CHECK(wrapped->SameValue(*finallies[i].second));
    2887             :   }
    2888           5 : }
    2889             : 
    2890       26661 : TEST(InterpreterThrow) {
    2891          10 :   HandleAndZoneScope handles;
    2892             :   Isolate* isolate = handles.main_isolate();
    2893             :   Factory* factory = isolate->factory();
    2894             : 
    2895             :   std::pair<const char*, Handle<Object>> throws[] = {
    2896             :       std::make_pair("throw undefined;\n",
    2897             :                      factory->undefined_value()),
    2898             :       std::make_pair("throw 1;\n",
    2899             :                      handle(Smi::FromInt(1), isolate)),
    2900             :       std::make_pair("throw 'Error';\n",
    2901          10 :                      factory->NewStringFromStaticChars("Error")),
    2902             :       std::make_pair("var a = true; if (a) { throw 'Error'; }\n",
    2903          10 :                      factory->NewStringFromStaticChars("Error")),
    2904             :       std::make_pair("var a = false; if (a) { throw 'Error'; }\n",
    2905             :                      factory->undefined_value()),
    2906             :       std::make_pair("throw 'Error1'; throw 'Error2'\n",
    2907          10 :                      factory->NewStringFromStaticChars("Error1")),
    2908             :   };
    2909             : 
    2910             :   const char* try_wrapper =
    2911             :       "(function() { try { f(); } catch(e) { return e; }})()";
    2912             : 
    2913          65 :   for (size_t i = 0; i < arraysize(throws); i++) {
    2914          30 :     std::string source(InterpreterTester::SourceForBody(throws[i].first));
    2915          60 :     InterpreterTester tester(isolate, source.c_str());
    2916             :     tester.GetCallable<>();
    2917             :     Handle<Object> thrown_obj = v8::Utils::OpenHandle(*CompileRun(try_wrapper));
    2918          60 :     CHECK(thrown_obj->SameValue(*throws[i].second));
    2919             :   }
    2920           5 : }
    2921             : 
    2922       26661 : TEST(InterpreterCountOperators) {
    2923          10 :   HandleAndZoneScope handles;
    2924             :   Isolate* isolate = handles.main_isolate();
    2925             :   Factory* factory = isolate->factory();
    2926             : 
    2927             :   std::pair<const char*, Handle<Object>> count_ops[] = {
    2928             :       std::make_pair("var a = 1; return ++a;",
    2929             :                      handle(Smi::FromInt(2), isolate)),
    2930             :       std::make_pair("var a = 1; return a++;",
    2931             :                      handle(Smi::FromInt(1), isolate)),
    2932             :       std::make_pair("var a = 5; return --a;",
    2933             :                      handle(Smi::FromInt(4), isolate)),
    2934             :       std::make_pair("var a = 5; return a--;",
    2935             :                      handle(Smi::FromInt(5), isolate)),
    2936          10 :       std::make_pair("var a = 5.2; return --a;", factory->NewHeapNumber(4.2)),
    2937             :       std::make_pair("var a = 'string'; return ++a;", factory->nan_value()),
    2938             :       std::make_pair("var a = 'string'; return a--;", factory->nan_value()),
    2939             :       std::make_pair("var a = true; return ++a;",
    2940             :                      handle(Smi::FromInt(2), isolate)),
    2941             :       std::make_pair("var a = false; return a--;", handle(Smi::kZero, isolate)),
    2942             :       std::make_pair("var a = { val: 11 }; return ++a.val;",
    2943             :                      handle(Smi::FromInt(12), isolate)),
    2944             :       std::make_pair("var a = { val: 11 }; return a.val--;",
    2945             :                      handle(Smi::FromInt(11), isolate)),
    2946             :       std::make_pair("var a = { val: 11 }; return ++a.val;",
    2947             :                      handle(Smi::FromInt(12), isolate)),
    2948             :       std::make_pair("var name = 'val'; var a = { val: 22 }; return --a[name];",
    2949             :                      handle(Smi::FromInt(21), isolate)),
    2950             :       std::make_pair("var name = 'val'; var a = { val: 22 }; return a[name]++;",
    2951             :                      handle(Smi::FromInt(22), isolate)),
    2952             :       std::make_pair("var a = 1; (function() { a = 2 })(); return ++a;",
    2953             :                      handle(Smi::FromInt(3), isolate)),
    2954             :       std::make_pair("var a = 1; (function() { a = 2 })(); return a--;",
    2955             :                      handle(Smi::FromInt(2), isolate)),
    2956             :       std::make_pair("var i = 5; while(i--) {}; return i;",
    2957             :                      handle(Smi::FromInt(-1), isolate)),
    2958             :       std::make_pair("var i = 1; if(i--) { return 1; } else { return 2; };",
    2959             :                      handle(Smi::FromInt(1), isolate)),
    2960             :       std::make_pair("var i = -2; do {} while(i++) {}; return i;",
    2961             :                      handle(Smi::FromInt(1), isolate)),
    2962             :       std::make_pair("var i = -1; for(; i++; ) {}; return i",
    2963             :                      handle(Smi::FromInt(1), isolate)),
    2964             :       std::make_pair("var i = 20; switch(i++) {\n"
    2965             :                      "  case 20: return 1;\n"
    2966             :                      "  default: return 2;\n"
    2967             :                      "}",
    2968             :                      handle(Smi::FromInt(1), isolate)),
    2969           5 :   };
    2970             : 
    2971         215 :   for (size_t i = 0; i < arraysize(count_ops); i++) {
    2972         105 :     std::string source(InterpreterTester::SourceForBody(count_ops[i].first));
    2973         210 :     InterpreterTester tester(isolate, source.c_str());
    2974             :     auto callable = tester.GetCallable<>();
    2975             : 
    2976             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    2977         210 :     CHECK(return_value->SameValue(*count_ops[i].second));
    2978             :   }
    2979           5 : }
    2980             : 
    2981       26661 : TEST(InterpreterGlobalCountOperators) {
    2982          10 :   HandleAndZoneScope handles;
    2983             :   Isolate* isolate = handles.main_isolate();
    2984             : 
    2985             :   std::pair<const char*, Handle<Object>> count_ops[] = {
    2986             :       std::make_pair("var global = 100;function f(){ return ++global; }",
    2987             :                      handle(Smi::FromInt(101), isolate)),
    2988             :       std::make_pair("var global = 100; function f(){ return --global; }",
    2989             :                      handle(Smi::FromInt(99), isolate)),
    2990             :       std::make_pair("var global = 100; function f(){ return global++; }",
    2991             :                      handle(Smi::FromInt(100), isolate)),
    2992             :       std::make_pair("unallocated = 200; function f(){ return ++unallocated; }",
    2993             :                      handle(Smi::FromInt(201), isolate)),
    2994             :       std::make_pair("unallocated = 200; function f(){ return --unallocated; }",
    2995             :                      handle(Smi::FromInt(199), isolate)),
    2996             :       std::make_pair("unallocated = 200; function f(){ return unallocated++; }",
    2997             :                      handle(Smi::FromInt(200), isolate)),
    2998             :   };
    2999             : 
    3000          65 :   for (size_t i = 0; i < arraysize(count_ops); i++) {
    3001          60 :     InterpreterTester tester(isolate, count_ops[i].first);
    3002             :     auto callable = tester.GetCallable<>();
    3003             : 
    3004             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3005          60 :     CHECK(return_value->SameValue(*count_ops[i].second));
    3006             :   }
    3007           5 : }
    3008             : 
    3009       26661 : TEST(InterpreterCompoundExpressions) {
    3010          10 :   HandleAndZoneScope handles;
    3011             :   Isolate* isolate = handles.main_isolate();
    3012             :   Factory* factory = isolate->factory();
    3013             : 
    3014             :   std::pair<const char*, Handle<Object>> compound_expr[] = {
    3015             :       std::make_pair("var a = 1; a += 2; return a;",
    3016             :                      Handle<Object>(Smi::FromInt(3), isolate)),
    3017             :       std::make_pair("var a = 10; a /= 2; return a;",
    3018             :                      Handle<Object>(Smi::FromInt(5), isolate)),
    3019             :       std::make_pair("var a = 'test'; a += 'ing'; return a;",
    3020          10 :                      factory->NewStringFromStaticChars("testing")),
    3021             :       std::make_pair("var a = { val: 2 }; a.val *= 2; return a.val;",
    3022             :                      Handle<Object>(Smi::FromInt(4), isolate)),
    3023             :       std::make_pair("var a = 1; (function f() { a = 2; })(); a += 24;"
    3024             :                      "return a;",
    3025             :                      Handle<Object>(Smi::FromInt(26), isolate)),
    3026          20 :   };
    3027             : 
    3028          55 :   for (size_t i = 0; i < arraysize(compound_expr); i++) {
    3029             :     std::string source(
    3030          25 :         InterpreterTester::SourceForBody(compound_expr[i].first));
    3031          50 :     InterpreterTester tester(isolate, source.c_str());
    3032             :     auto callable = tester.GetCallable<>();
    3033             : 
    3034             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3035          50 :     CHECK(return_value->SameValue(*compound_expr[i].second));
    3036             :   }
    3037           5 : }
    3038             : 
    3039       26661 : TEST(InterpreterGlobalCompoundExpressions) {
    3040          10 :   HandleAndZoneScope handles;
    3041             :   Isolate* isolate = handles.main_isolate();
    3042             : 
    3043             :   std::pair<const char*, Handle<Object>> compound_expr[2] = {
    3044             :       std::make_pair("var global = 100;"
    3045             :                      "function f() { global += 20; return global; }",
    3046             :                      Handle<Object>(Smi::FromInt(120), isolate)),
    3047             :       std::make_pair("unallocated = 100;"
    3048             :                      "function f() { unallocated -= 20; return unallocated; }",
    3049             :                      Handle<Object>(Smi::FromInt(80), isolate)),
    3050          10 :   };
    3051             : 
    3052          25 :   for (size_t i = 0; i < arraysize(compound_expr); i++) {
    3053          20 :     InterpreterTester tester(isolate, compound_expr[i].first);
    3054             :     auto callable = tester.GetCallable<>();
    3055             : 
    3056             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3057          20 :     CHECK(return_value->SameValue(*compound_expr[i].second));
    3058             :   }
    3059           5 : }
    3060             : 
    3061       26661 : TEST(InterpreterCreateArguments) {
    3062          10 :   HandleAndZoneScope handles;
    3063             :   Isolate* isolate = handles.main_isolate();
    3064             :   Factory* factory = isolate->factory();
    3065             : 
    3066             :   std::pair<const char*, int> create_args[] = {
    3067             :       std::make_pair("function f() { return arguments[0]; }", 0),
    3068             :       std::make_pair("function f(a) { return arguments[0]; }", 0),
    3069             :       std::make_pair("function f() { return arguments[2]; }", 2),
    3070             :       std::make_pair("function f(a) { return arguments[2]; }", 2),
    3071             :       std::make_pair("function f(a, b, c, d) { return arguments[2]; }", 2),
    3072             :       std::make_pair("function f(a) {"
    3073             :                      "'use strict'; return arguments[0]; }",
    3074             :                      0),
    3075             :       std::make_pair("function f(a, b, c, d) {"
    3076             :                      "'use strict'; return arguments[2]; }",
    3077             :                      2),
    3078             :       // Check arguments are mapped in sloppy mode and unmapped in strict.
    3079             :       std::make_pair("function f(a, b, c, d) {"
    3080             :                      "  c = b; return arguments[2]; }",
    3081             :                      1),
    3082             :       std::make_pair("function f(a, b, c, d) {"
    3083             :                      "  'use strict'; c = b; return arguments[2]; }",
    3084             :                      2),
    3085             :       // Check arguments for duplicate parameters in sloppy mode.
    3086             :       std::make_pair("function f(a, a, b) { return arguments[1]; }", 1),
    3087             :       // check rest parameters
    3088             :       std::make_pair("function f(...restArray) { return restArray[0]; }", 0),
    3089             :       std::make_pair("function f(a, ...restArray) { return restArray[0]; }", 1),
    3090             :       std::make_pair("function f(a, ...restArray) { return arguments[0]; }", 0),
    3091             :       std::make_pair("function f(a, ...restArray) { return arguments[1]; }", 1),
    3092             :       std::make_pair("function f(a, ...restArray) { return restArray[1]; }", 2),
    3093             :       std::make_pair("function f(a, ...arguments) { return arguments[0]; }", 1),
    3094             :       std::make_pair("function f(a, b, ...restArray) { return restArray[0]; }",
    3095             :                      2),
    3096           5 :   };
    3097             : 
    3098             :   // Test passing no arguments.
    3099         175 :   for (size_t i = 0; i < arraysize(create_args); i++) {
    3100         170 :     InterpreterTester tester(isolate, create_args[i].first);
    3101             :     auto callable = tester.GetCallable<>();
    3102             :     Handle<Object> return_val = callable().ToHandleChecked();
    3103          85 :     CHECK(return_val.is_identical_to(factory->undefined_value()));
    3104             :   }
    3105             : 
    3106             :   // Test passing one argument.
    3107         175 :   for (size_t i = 0; i < arraysize(create_args); i++) {
    3108         170 :     InterpreterTester tester(isolate, create_args[i].first);
    3109             :     auto callable = tester.GetCallable<Handle<Object>>();
    3110             :     Handle<Object> return_val =
    3111         170 :         callable(handle(Smi::FromInt(40), isolate)).ToHandleChecked();
    3112          85 :     if (create_args[i].second == 0) {
    3113          25 :       CHECK_EQ(Smi::cast(*return_val), Smi::FromInt(40));
    3114             :     } else {
    3115          60 :       CHECK(return_val.is_identical_to(factory->undefined_value()));
    3116             :     }
    3117             :   }
    3118             : 
    3119             :   // Test passing three argument.
    3120         175 :   for (size_t i = 0; i < arraysize(create_args); i++) {
    3121             :     Handle<Object> args[3] = {
    3122             :         handle(Smi::FromInt(40), isolate),
    3123             :         handle(Smi::FromInt(60), isolate),
    3124             :         handle(Smi::FromInt(80), isolate),
    3125             :     };
    3126             : 
    3127         170 :     InterpreterTester tester(isolate, create_args[i].first);
    3128             :     auto callable =
    3129             :         tester.GetCallable<Handle<Object>, Handle<Object>, Handle<Object>>();
    3130             :     Handle<Object> return_val =
    3131             :         callable(args[0], args[1], args[2]).ToHandleChecked();
    3132         170 :     CHECK(return_val->SameValue(*args[create_args[i].second]));
    3133             :   }
    3134           5 : }
    3135             : 
    3136       26661 : TEST(InterpreterConditional) {
    3137          10 :   HandleAndZoneScope handles;
    3138             :   Isolate* isolate = handles.main_isolate();
    3139             : 
    3140             :   std::pair<const char*, Handle<Object>> conditional[] = {
    3141             :       std::make_pair("return true ? 2 : 3;",
    3142             :                      handle(Smi::FromInt(2), isolate)),
    3143             :       std::make_pair("return false ? 2 : 3;",
    3144             :                      handle(Smi::FromInt(3), isolate)),
    3145             :       std::make_pair("var a = 1; return a ? 20 : 30;",
    3146             :                      handle(Smi::FromInt(20), isolate)),
    3147             :       std::make_pair("var a = 1; return a ? 20 : 30;",
    3148             :                      handle(Smi::FromInt(20), isolate)),
    3149             :       std::make_pair("var a = 'string'; return a ? 20 : 30;",
    3150             :                      handle(Smi::FromInt(20), isolate)),
    3151             :       std::make_pair("var a = undefined; return a ? 20 : 30;",
    3152             :                      handle(Smi::FromInt(30), isolate)),
    3153             :       std::make_pair("return 1 ? 2 ? 3 : 4 : 5;",
    3154             :                      handle(Smi::FromInt(3), isolate)),
    3155             :       std::make_pair("return 0 ? 2 ? 3 : 4 : 5;",
    3156             :                      handle(Smi::FromInt(5), isolate)),
    3157             :   };
    3158             : 
    3159          85 :   for (size_t i = 0; i < arraysize(conditional); i++) {
    3160          40 :     std::string source(InterpreterTester::SourceForBody(conditional[i].first));
    3161          80 :     InterpreterTester tester(isolate, source.c_str());
    3162             :     auto callable = tester.GetCallable<>();
    3163             : 
    3164             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3165          80 :     CHECK(return_value->SameValue(*conditional[i].second));
    3166             :   }
    3167           5 : }
    3168             : 
    3169       26661 : TEST(InterpreterDelete) {
    3170          10 :   HandleAndZoneScope handles;
    3171             :   Isolate* isolate = handles.main_isolate();
    3172             :   Factory* factory = isolate->factory();
    3173             : 
    3174             :   // Tests for delete for local variables that work both in strict
    3175             :   // and sloppy modes
    3176             :   std::pair<const char*, Handle<Object>> test_delete[] = {
    3177             :       std::make_pair(
    3178             :           "var a = { x:10, y:'abc', z:30.2}; delete a.x; return a.x;\n",
    3179             :           factory->undefined_value()),
    3180             :       std::make_pair(
    3181             :           "var b = { x:10, y:'abc', z:30.2}; delete b.x; return b.y;\n",
    3182          10 :           factory->NewStringFromStaticChars("abc")),
    3183             :       std::make_pair("var c = { x:10, y:'abc', z:30.2}; var d = c; delete d.x; "
    3184             :                      "return c.x;\n",
    3185             :                      factory->undefined_value()),
    3186             :       std::make_pair("var e = { x:10, y:'abc', z:30.2}; var g = e; delete g.x; "
    3187             :                      "return e.y;\n",
    3188          10 :                      factory->NewStringFromStaticChars("abc")),
    3189             :       std::make_pair("var a = { x:10, y:'abc', z:30.2};\n"
    3190             :                      "var b = a;"
    3191             :                      "delete b.x;"
    3192             :                      "return b.x;\n",
    3193             :                      factory->undefined_value()),
    3194             :       std::make_pair("var a = {1:10};\n"
    3195             :                      "(function f1() {return a;});"
    3196             :                      "return delete a[1];",
    3197          10 :                      factory->ToBoolean(true)),
    3198          10 :       std::make_pair("return delete this;", factory->ToBoolean(true)),
    3199          20 :       std::make_pair("return delete 'test';", factory->ToBoolean(true))};
    3200             : 
    3201             :   // Test delete in sloppy mode
    3202          85 :   for (size_t i = 0; i < arraysize(test_delete); i++) {
    3203          40 :     std::string source(InterpreterTester::SourceForBody(test_delete[i].first));
    3204          80 :     InterpreterTester tester(isolate, source.c_str());
    3205             :     auto callable = tester.GetCallable<>();
    3206             : 
    3207             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3208          80 :     CHECK(return_value->SameValue(*test_delete[i].second));
    3209             :   }
    3210             : 
    3211             :   // Test delete in strict mode
    3212          85 :   for (size_t i = 0; i < arraysize(test_delete); i++) {
    3213             :     std::string strict_test =
    3214          80 :         "'use strict'; " + std::string(test_delete[i].first);
    3215          40 :     std::string source(InterpreterTester::SourceForBody(strict_test.c_str()));
    3216          80 :     InterpreterTester tester(isolate, source.c_str());
    3217             :     auto callable = tester.GetCallable<>();
    3218             : 
    3219             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3220          80 :     CHECK(return_value->SameValue(*test_delete[i].second));
    3221             :   }
    3222           5 : }
    3223             : 
    3224       26661 : TEST(InterpreterDeleteSloppyUnqualifiedIdentifier) {
    3225          10 :   HandleAndZoneScope handles;
    3226             :   Isolate* isolate = handles.main_isolate();
    3227             :   Factory* factory = isolate->factory();
    3228             : 
    3229             :   // These tests generate a syntax error for strict mode. We don't
    3230             :   // test for it here.
    3231             :   std::pair<const char*, Handle<Object>> test_delete[] = {
    3232             :       std::make_pair("var sloppy_a = { x:10, y:'abc'};\n"
    3233             :                      "var sloppy_b = delete sloppy_a;\n"
    3234             :                      "if (delete sloppy_a) {\n"
    3235             :                      "  return undefined;\n"
    3236             :                      "} else {\n"
    3237             :                      "  return sloppy_a.x;\n"
    3238             :                      "}\n",
    3239             :                      Handle<Object>(Smi::FromInt(10), isolate)),
    3240             :       // TODO(mythria) When try-catch is implemented change the tests to check
    3241             :       // if delete actually deletes
    3242             :       std::make_pair("sloppy_a = { x:10, y:'abc'};\n"
    3243             :                      "var sloppy_b = delete sloppy_a;\n"
    3244             :                      // "try{return a.x;} catch(e) {return b;}\n"
    3245             :                      "return sloppy_b;",
    3246          10 :                      factory->ToBoolean(true)),
    3247             :       std::make_pair("sloppy_a = { x:10, y:'abc'};\n"
    3248             :                      "var sloppy_b = delete sloppy_c;\n"
    3249             :                      "return sloppy_b;",
    3250          20 :                      factory->ToBoolean(true))};
    3251             : 
    3252          35 :   for (size_t i = 0; i < arraysize(test_delete); i++) {
    3253          15 :     std::string source(InterpreterTester::SourceForBody(test_delete[i].first));
    3254          30 :     InterpreterTester tester(isolate, source.c_str());
    3255             :     auto callable = tester.GetCallable<>();
    3256             : 
    3257             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3258          30 :     CHECK(return_value->SameValue(*test_delete[i].second));
    3259             :   }
    3260           5 : }
    3261             : 
    3262       26661 : TEST(InterpreterGlobalDelete) {
    3263          10 :   HandleAndZoneScope handles;
    3264             :   Isolate* isolate = handles.main_isolate();
    3265             :   Factory* factory = isolate->factory();
    3266             : 
    3267             :   std::pair<const char*, Handle<Object>> test_global_delete[] = {
    3268             :       std::make_pair("var a = { x:10, y:'abc', z:30.2 };\n"
    3269             :                      "function f() {\n"
    3270             :                      "  delete a.x;\n"
    3271             :                      "  return a.x;\n"
    3272             :                      "}\n"
    3273             :                      "f();\n",
    3274             :                      factory->undefined_value()),
    3275             :       std::make_pair("var b = {1:10, 2:'abc', 3:30.2 };\n"
    3276             :                      "function f() {\n"
    3277             :                      "  delete b[2];\n"
    3278             :                      "  return b[1];\n"
    3279             :                      " }\n"
    3280             :                      "f();\n",
    3281             :                      Handle<Object>(Smi::FromInt(10), isolate)),
    3282             :       std::make_pair("var c = { x:10, y:'abc', z:30.2 };\n"
    3283             :                      "function f() {\n"
    3284             :                      "   var d = c;\n"
    3285             :                      "   delete d.y;\n"
    3286             :                      "   return d.x;\n"
    3287             :                      "}\n"
    3288             :                      "f();\n",
    3289             :                      Handle<Object>(Smi::FromInt(10), isolate)),
    3290             :       std::make_pair("e = { x:10, y:'abc' };\n"
    3291             :                      "function f() {\n"
    3292             :                      "  return delete e;\n"
    3293             :                      "}\n"
    3294             :                      "f();\n",
    3295          10 :                      factory->ToBoolean(true)),
    3296             :       std::make_pair("var g = { x:10, y:'abc' };\n"
    3297             :                      "function f() {\n"
    3298             :                      "  return delete g;\n"
    3299             :                      "}\n"
    3300             :                      "f();\n",
    3301          10 :                      factory->ToBoolean(false)),
    3302             :       std::make_pair("function f() {\n"
    3303             :                      "  var obj = {h:10, f1() {return delete this;}};\n"
    3304             :                      "  return obj.f1();\n"
    3305             :                      "}\n"
    3306             :                      "f();",
    3307          10 :                      factory->ToBoolean(true)),
    3308             :       std::make_pair("function f() {\n"
    3309             :                      "  var obj = {h:10,\n"
    3310             :                      "             f1() {\n"
    3311             :                      "              'use strict';\n"
    3312             :                      "              return delete this.h;}};\n"
    3313             :                      "  return obj.f1();\n"
    3314             :                      "}\n"
    3315             :                      "f();",
    3316          35 :                      factory->ToBoolean(true))};
    3317             : 
    3318          75 :   for (size_t i = 0; i < arraysize(test_global_delete); i++) {
    3319          70 :     InterpreterTester tester(isolate, test_global_delete[i].first);
    3320             :     auto callable = tester.GetCallable<>();
    3321             : 
    3322             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3323          70 :     CHECK(return_value->SameValue(*test_global_delete[i].second));
    3324             :   }
    3325           5 : }
    3326             : 
    3327       26661 : TEST(InterpreterBasicLoops) {
    3328          10 :   HandleAndZoneScope handles;
    3329             :   Isolate* isolate = handles.main_isolate();
    3330             :   Factory* factory = isolate->factory();
    3331             : 
    3332             :   std::pair<const char*, Handle<Object>> loops[] = {
    3333             :       std::make_pair("var a = 10; var b = 1;\n"
    3334             :                      "while (a) {\n"
    3335             :                      "  b = b * 2;\n"
    3336             :                      "  a = a - 1;\n"
    3337             :                      "};\n"
    3338             :                      "return b;\n",
    3339          10 :                      factory->NewHeapNumber(1024)),
    3340             :       std::make_pair("var a = 1; var b = 1;\n"
    3341             :                      "do {\n"
    3342             :                      "  b = b * 2;\n"
    3343             :                      "  --a;\n"
    3344             :                      "} while(a);\n"
    3345             :                      "return b;\n",
    3346             :                      handle(Smi::FromInt(2), isolate)),
    3347             :       std::make_pair("var b = 1;\n"
    3348             :                      "for ( var a = 10; a; a--) {\n"
    3349             :                      "  b *= 2;\n"
    3350             :                      "}\n"
    3351             :                      "return b;",
    3352          10 :                      factory->NewHeapNumber(1024)),
    3353             :       std::make_pair("var a = 10; var b = 1;\n"
    3354             :                      "while (a > 0) {\n"
    3355             :                      "  b = b * 2;\n"
    3356             :                      "  a = a - 1;\n"
    3357             :                      "};\n"
    3358             :                      "return b;\n",
    3359          10 :                      factory->NewHeapNumber(1024)),
    3360             :       std::make_pair("var a = 1; var b = 1;\n"
    3361             :                      "do {\n"
    3362             :                      "  b = b * 2;\n"
    3363             :                      "  --a;\n"
    3364             :                      "} while(a);\n"
    3365             :                      "return b;\n",
    3366             :                      handle(Smi::FromInt(2), isolate)),
    3367             :       std::make_pair("var b = 1;\n"
    3368             :                      "for ( var a = 10; a > 0; a--) {\n"
    3369             :                      "  b *= 2;\n"
    3370             :                      "}\n"
    3371             :                      "return b;",
    3372          10 :                      factory->NewHeapNumber(1024)),
    3373             :       std::make_pair("var a = 10; var b = 1;\n"
    3374             :                      "while (false) {\n"
    3375             :                      "  b = b * 2;\n"
    3376             :                      "  a = a - 1;\n"
    3377             :                      "}\n"
    3378             :                      "return b;\n",
    3379             :                      Handle<Object>(Smi::FromInt(1), isolate)),
    3380             :       std::make_pair("var a = 10; var b = 1;\n"
    3381             :                      "while (true) {\n"
    3382             :                      "  b = b * 2;\n"
    3383             :                      "  a = a - 1;\n"
    3384             :                      "  if (a == 0) break;"
    3385             :                      "  continue;"
    3386             :                      "}\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(true);\n"
    3395             :                      "return b;\n",
    3396          10 :                      factory->NewHeapNumber(1024)),
    3397             :       std::make_pair("var a = 10; var b = 1;\n"
    3398             :                      "do {\n"
    3399             :                      "  b = b * 2;\n"
    3400             :                      "  a = a - 1;\n"
    3401             :                      "  if (a == 0) break;"
    3402             :                      "} while(false);\n"
    3403             :                      "return b;\n",
    3404             :                      Handle<Object>(Smi::FromInt(2), isolate)),
    3405             :       std::make_pair("var a = 10; var b = 1;\n"
    3406             :                      "for ( a = 1, b = 30; false; ) {\n"
    3407             :                      "  b = b * 2;\n"
    3408             :                      "}\n"
    3409             :                      "return b;\n",
    3410          15 :                      Handle<Object>(Smi::FromInt(30), isolate))};
    3411             : 
    3412         115 :   for (size_t i = 0; i < arraysize(loops); i++) {
    3413          55 :     std::string source(InterpreterTester::SourceForBody(loops[i].first));
    3414         110 :     InterpreterTester tester(isolate, source.c_str());
    3415             :     auto callable = tester.GetCallable<>();
    3416             : 
    3417             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3418         110 :     CHECK(return_value->SameValue(*loops[i].second));
    3419             :   }
    3420           5 : }
    3421             : 
    3422       26661 : TEST(InterpreterForIn) {
    3423             :   std::pair<const char*, int> for_in_samples[] = {
    3424             :       {"var r = -1;\n"
    3425             :        "for (var a in null) { r = a; }\n"
    3426             :        "return r;\n",
    3427             :        -1},
    3428             :       {"var r = -1;\n"
    3429             :        "for (var a in undefined) { r = a; }\n"
    3430             :        "return r;\n",
    3431             :        -1},
    3432             :       {"var r = 0;\n"
    3433             :        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
    3434             :        "return r;\n",
    3435             :        0xF},
    3436             :       {"var r = 0;\n"
    3437             :        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
    3438             :        "var r = 0;\n"
    3439             :        "for (var a in [0,6,7,9]) { r = r + (1 << a); }\n"
    3440             :        "return r;\n",
    3441             :        0xF},
    3442             :       {"var r = 0;\n"
    3443             :        "for (var a in 'foobar') { r = r + (1 << a); }\n"
    3444             :        "return r;\n",
    3445             :        0x3F},
    3446             :       {"var r = 0;\n"
    3447             :        "for (var a in {1:0, 10:1, 100:2, 1000:3}) {\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 == 1) delete data[1];\n"
    3456             :        "  r = r + Number(a);\n"
    3457             :        " }\n"
    3458             :        " return r;\n",
    3459             :        1111},
    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) delete data[100];\n"
    3464             :        "  r = r + Number(a);\n"
    3465             :        " }\n"
    3466             :        " return r;\n",
    3467             :        1011},
    3468             :       {"var r = 0;\n"
    3469             :        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
    3470             :        "for (var a in data) {\n"
    3471             :        "  if (a == 10) data[10000] = 4;\n"
    3472             :        "  r = r + Number(a);\n"
    3473             :        " }\n"
    3474             :        " return r;\n",
    3475             :        1111},
    3476             :       {"var r = 0;\n"
    3477             :        "var input = 'foobar';\n"
    3478             :        "for (var a in input) {\n"
    3479             :        "  if (input[a] == 'b') break;\n"
    3480             :        "  r = r + (1 << a);\n"
    3481             :        "}\n"
    3482             :        "return r;\n",
    3483             :        0x7},
    3484             :       {"var r = 0;\n"
    3485             :        "var input = 'foobar';\n"
    3486             :        "for (var a in input) {\n"
    3487             :        " if (input[a] == 'b') continue;\n"
    3488             :        " r = r + (1 << a);\n"
    3489             :        "}\n"
    3490             :        "return r;\n",
    3491             :        0x37},
    3492             :       {"var r = 0;\n"
    3493             :        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
    3494             :        "for (var a in data) {\n"
    3495             :        "  if (a == 10) {\n"
    3496             :        "     data[10000] = 4;\n"
    3497             :        "  }\n"
    3498             :        "  r = r + Number(a);\n"
    3499             :        "}\n"
    3500             :        "return r;\n",
    3501             :        1111},
    3502             :       {"var r = [ 3 ];\n"
    3503             :        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
    3504             :        "for (r[10] in data) {\n"
    3505             :        "}\n"
    3506             :        "return Number(r[10]);\n",
    3507             :        1000},
    3508             :       {"var r = [ 3 ];\n"
    3509             :        "var data = {1:0, 10:1, 100:2, 1000:3};\n"
    3510             :        "for (r['100'] in data) {\n"
    3511             :        "}\n"
    3512             :        "return Number(r['100']);\n",
    3513             :        1000},
    3514             :       {"var obj = {}\n"
    3515             :        "var descObj = new Boolean(false);\n"
    3516             :        "var accessed = 0;\n"
    3517             :        "descObj.enumerable = true;\n"
    3518             :        "Object.defineProperties(obj, { prop:descObj });\n"
    3519             :        "for (var p in obj) {\n"
    3520             :        "  if (p === 'prop') { accessed = 1; }\n"
    3521             :        "}\n"
    3522             :        "return accessed;",
    3523             :        1},
    3524             :       {"var appointment = {};\n"
    3525             :        "Object.defineProperty(appointment, 'startTime', {\n"
    3526             :        "    value: 1001,\n"
    3527             :        "    writable: false,\n"
    3528             :        "    enumerable: false,\n"
    3529             :        "    configurable: true\n"
    3530             :        "});\n"
    3531             :        "Object.defineProperty(appointment, 'name', {\n"
    3532             :        "    value: 'NAME',\n"
    3533             :        "    writable: false,\n"
    3534             :        "    enumerable: false,\n"
    3535             :        "    configurable: true\n"
    3536             :        "});\n"
    3537             :        "var meeting = Object.create(appointment);\n"
    3538             :        "Object.defineProperty(meeting, 'conferenceCall', {\n"
    3539             :        "    value: 'In-person meeting',\n"
    3540             :        "    writable: false,\n"
    3541             :        "    enumerable: false,\n"
    3542             :        "    configurable: true\n"
    3543             :        "});\n"
    3544             :        "\n"
    3545             :        "var teamMeeting = Object.create(meeting);\n"
    3546             :        "\n"
    3547             :        "var flags = 0;\n"
    3548             :        "for (var p in teamMeeting) {\n"
    3549             :        "    if (p === 'startTime') {\n"
    3550             :        "        flags |= 1;\n"
    3551             :        "    }\n"
    3552             :        "    if (p === 'name') {\n"
    3553             :        "        flags |= 2;\n"
    3554             :        "    }\n"
    3555             :        "    if (p === 'conferenceCall') {\n"
    3556             :        "        flags |= 4;\n"
    3557             :        "    }\n"
    3558             :        "}\n"
    3559             :        "\n"
    3560             :        "var hasOwnProperty = !teamMeeting.hasOwnProperty('name') &&\n"
    3561             :        "    !teamMeeting.hasOwnProperty('startTime') &&\n"
    3562             :        "    !teamMeeting.hasOwnProperty('conferenceCall');\n"
    3563             :        "if (!hasOwnProperty) {\n"
    3564             :        "    flags |= 8;\n"
    3565             :        "}\n"
    3566             :        "return flags;\n",
    3567             :        0},
    3568             :       {"var data = {x:23, y:34};\n"
    3569             :        " var result = 0;\n"
    3570             :        "var o = {};\n"
    3571             :        "var arr = [o];\n"
    3572             :        "for (arr[0].p in data)\n"       // This is to test if value is loaded
    3573             :        "  result += data[arr[0].p];\n"  // back from accumulator before storing
    3574             :        "return result;\n",              // named properties.
    3575             :        57},
    3576             :       {"var data = {x:23, y:34};\n"
    3577             :        "var result = 0;\n"
    3578             :        "var o = {};\n"
    3579             :        "var i = 0;\n"
    3580             :        "for (o[i++] in data)\n"       // This is to test if value is loaded
    3581             :        "  result += data[o[i-1]];\n"  // back from accumulator before
    3582             :        "return result;\n",            // storing keyed properties.
    3583           5 :        57}};
    3584             : 
    3585             :   // Two passes are made for this test. On the first, 8-bit register
    3586             :   // operands are employed, and on the 16-bit register operands are
    3587             :   // used.
    3588          25 :   for (int pass = 0; pass < 2; pass++) {
    3589          20 :     HandleAndZoneScope handles;
    3590             :     Isolate* isolate = handles.main_isolate();
    3591          20 :     std::ostringstream wide_os;
    3592          10 :     if (pass == 1) {
    3593        2005 :       for (int i = 0; i < 200; i++) {
    3594        1000 :         wide_os << "var local" << i << " = 0;\n";
    3595             :       }
    3596             :     }
    3597             : 
    3598         370 :     for (size_t i = 0; i < arraysize(for_in_samples); i++) {
    3599         360 :       std::ostringstream body_os;
    3600         540 :       body_os << wide_os.str() << for_in_samples[i].first;
    3601             :       std::string body(body_os.str());
    3602         180 :       std::string function = InterpreterTester::SourceForBody(body.c_str());
    3603         360 :       InterpreterTester tester(isolate, function.c_str());
    3604             :       auto callable = tester.GetCallable<>();
    3605             :       Handle<Object> return_val = callable().ToHandleChecked();
    3606         360 :       CHECK_EQ(Handle<Smi>::cast(return_val)->value(),
    3607             :                for_in_samples[i].second);
    3608             :     }
    3609             :   }
    3610           5 : }
    3611             : 
    3612       26661 : TEST(InterpreterForOf) {
    3613          10 :   HandleAndZoneScope handles;
    3614             :   Isolate* isolate = handles.main_isolate();
    3615             :   Factory* factory = isolate->factory();
    3616             : 
    3617             :   std::pair<const char*, Handle<Object>> for_of[] = {
    3618             :       {"function f() {\n"
    3619             :        "  var r = 0;\n"
    3620             :        "  for (var a of [0,6,7,9]) { r += a; }\n"
    3621             :        "  return r;\n"
    3622             :        "}",
    3623             :        handle(Smi::FromInt(22), isolate)},
    3624             :       {"function f() {\n"
    3625             :        "  var r = '';\n"
    3626             :        "  for (var a of 'foobar') { r = a + r; }\n"
    3627             :        "  return r;\n"
    3628             :        "}",
    3629          10 :        factory->NewStringFromStaticChars("raboof")},
    3630             :       {"function f() {\n"
    3631             :        "  var a = [1, 2, 3];\n"
    3632             :        "  a.name = 4;\n"
    3633             :        "  var r = 0;\n"
    3634             :        "  for (var x of a) { r += x; }\n"
    3635             :        "  return r;\n"
    3636             :        "}",
    3637             :        handle(Smi::FromInt(6), isolate)},
    3638             :       {"function f() {\n"
    3639             :        "  var r = '';\n"
    3640             :        "  var data = [1, 2, 3]; \n"
    3641             :        "  for (a of data) { delete data[0]; r += a; } return r; }",
    3642          10 :        factory->NewStringFromStaticChars("123")},
    3643             :       {"function f() {\n"
    3644             :        "  var r = '';\n"
    3645             :        "  var data = [1, 2, 3]; \n"
    3646             :        "  for (a of data) { delete data[2]; r += a; } return r; }",
    3647          10 :        factory->NewStringFromStaticChars("12undefined")},
    3648             :       {"function f() {\n"
    3649             :        "  var r = '';\n"
    3650             :        "  var data = [1, 2, 3]; \n"
    3651             :        "  for (a of data) { delete data; r += a; } return r; }",
    3652          10 :        factory->NewStringFromStaticChars("123")},
    3653             :       {"function f() {\n"
    3654             :        "  var r = '';\n"
    3655             :        "  var input = 'foobar';\n"
    3656             :        "  for (var a of input) {\n"
    3657             :        "    if (a == 'b') break;\n"
    3658             :        "    r += a;\n"
    3659             :        "  }\n"
    3660             :        "  return r;\n"
    3661             :        "}",
    3662          10 :        factory->NewStringFromStaticChars("foo")},
    3663             :       {"function f() {\n"
    3664             :        "  var r = '';\n"
    3665             :        "  var input = 'foobar';\n"
    3666             :        "  for (var a of input) {\n"
    3667             :        "    if (a == 'b') continue;\n"
    3668             :        "    r += a;\n"
    3669             :        "  }\n"
    3670             :        "  return r;\n"
    3671             :        "}",
    3672          10 :        factory->NewStringFromStaticChars("fooar")},
    3673             :       {"function f() {\n"
    3674             :        "  var r = '';\n"
    3675             :        "  var data = [1, 2, 3, 4]; \n"
    3676             :        "  for (a of data) { data[2] = 567; r += a; }\n"
    3677             :        "  return r;\n"
    3678             :        "}",
    3679          10 :        factory->NewStringFromStaticChars("125674")},
    3680             :       {"function f() {\n"
    3681             :        "  var r = '';\n"
    3682             :        "  var data = [1, 2, 3, 4]; \n"
    3683             :        "  for (a of data) { data[4] = 567; r += a; }\n"
    3684             :        "  return r;\n"
    3685             :        "}",
    3686          10 :        factory->NewStringFromStaticChars("1234567")},
    3687             :       {"function f() {\n"
    3688             :        "  var r = '';\n"
    3689             :        "  var data = [1, 2, 3, 4]; \n"
    3690             :        "  for (a of data) { data[5] = 567; r += a; }\n"
    3691             :        "  return r;\n"
    3692             :        "}",
    3693          10 :        factory->NewStringFromStaticChars("1234undefined567")},
    3694             :       {"function f() {\n"
    3695             :        "  var r = '';\n"
    3696             :        "  var obj = new Object();\n"
    3697             :        "  obj[Symbol.iterator] = function() { return {\n"
    3698             :        "    index: 3,\n"
    3699             :        "    data: ['a', 'b', 'c', 'd'],"
    3700             :        "    next: function() {"
    3701             :        "      return {"
    3702             :        "        done: this.index == -1,\n"
    3703             :        "        value: this.index < 0 ? undefined : this.data[this.index--]\n"
    3704             :        "      }\n"
    3705             :        "    }\n"
    3706             :        "    }}\n"
    3707             :        "  for (a of obj) { r += a }\n"
    3708             :        "  return r;\n"
    3709             :        "}",
    3710          10 :        factory->NewStringFromStaticChars("dcba")},
    3711             :   };
    3712             : 
    3713         125 :   for (size_t i = 0; i < arraysize(for_of); i++) {
    3714         120 :     InterpreterTester tester(isolate, for_of[i].first);
    3715             :     auto callable = tester.GetCallable<>();
    3716             :     Handle<Object> return_val = callable().ToHandleChecked();
    3717         120 :     CHECK(return_val->SameValue(*for_of[i].second));
    3718             :   }
    3719           5 : }
    3720             : 
    3721       26661 : TEST(InterpreterSwitch) {
    3722          10 :   HandleAndZoneScope handles;
    3723             :   Isolate* isolate = handles.main_isolate();
    3724             :   Factory* factory = isolate->factory();
    3725             : 
    3726             :   std::pair<const char*, Handle<Object>> switch_ops[] = {
    3727             :       std::make_pair("var a = 1;\n"
    3728             :                      "switch(a) {\n"
    3729             :                      " case 1: return 2;\n"
    3730             :                      " case 2: return 3;\n"
    3731             :                      "}\n",
    3732             :                      handle(Smi::FromInt(2), isolate)),
    3733             :       std::make_pair("var a = 1;\n"
    3734             :                      "switch(a) {\n"
    3735             :                      " case 2: a = 2; break;\n"
    3736             :                      " case 1: a = 3; break;\n"
    3737             :                      "}\n"
    3738             :                      "return a;",
    3739             :                      handle(Smi::FromInt(3), isolate)),
    3740             :       std::make_pair("var a = 1;\n"
    3741             :                      "switch(a) {\n"
    3742             :                      " case 1: a = 2; // fall-through\n"
    3743             :                      " case 2: a = 3; break;\n"
    3744             :                      "}\n"
    3745             :                      "return a;",
    3746             :                      handle(Smi::FromInt(3), isolate)),
    3747             :       std::make_pair("var a = 100;\n"
    3748             :                      "switch(a) {\n"
    3749             :                      " case 1: return 100;\n"
    3750             :                      " case 2: return 200;\n"
    3751             :                      "}\n"
    3752             :                      "return undefined;",
    3753             :                      factory->undefined_value()),
    3754             :       std::make_pair("var a = 100;\n"
    3755             :                      "switch(a) {\n"
    3756             :                      " case 1: return 100;\n"
    3757             :                      " case 2: return 200;\n"
    3758             :                      " default: return 300;\n"
    3759             :                      "}\n"
    3760             :                      "return undefined;",
    3761             :                      handle(Smi::FromInt(300), isolate)),
    3762             :       std::make_pair("var a = 100;\n"
    3763             :                      "switch(typeof(a)) {\n"
    3764             :                      " case 'string': return 1;\n"
    3765             :                      " case 'number': return 2;\n"
    3766             :                      " default: return 3;\n"
    3767             :                      "}\n",
    3768             :                      handle(Smi::FromInt(2), isolate)),
    3769             :       std::make_pair("var a = 100;\n"
    3770             :                      "switch(a) {\n"
    3771             :                      " case a += 20: return 1;\n"
    3772             :                      " case a -= 10: return 2;\n"
    3773             :                      " case a -= 10: return 3;\n"
    3774             :                      " default: return 3;\n"
    3775             :                      "}\n",
    3776             :                      handle(Smi::FromInt(3), isolate)),
    3777             :       std::make_pair("var a = 1;\n"
    3778             :                      "switch(a) {\n"
    3779             :                      " case 1: \n"
    3780             :                      "   switch(a + 1) {\n"
    3781             :                      "      case 2 : a += 1; break;\n"
    3782             :                      "      default : a += 2; break;\n"
    3783             :                      "   }  // fall-through\n"
    3784             :                      " case 2: a += 3;\n"
    3785             :                      "}\n"
    3786             :                      "return a;",
    3787             :                      handle(Smi::FromInt(5), isolate)),
    3788             :   };
    3789             : 
    3790          85 :   for (size_t i = 0; i < arraysize(switch_ops); i++) {
    3791          40 :     std::string source(InterpreterTester::SourceForBody(switch_ops[i].first));
    3792          80 :     InterpreterTester tester(isolate, source.c_str());
    3793             :     auto callable = tester.GetCallable<>();
    3794             : 
    3795             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3796          80 :     CHECK(return_value->SameValue(*switch_ops[i].second));
    3797             :   }
    3798           5 : }
    3799             : 
    3800       26661 : TEST(InterpreterSloppyThis) {
    3801          10 :   HandleAndZoneScope handles;
    3802             :   Isolate* isolate = handles.main_isolate();
    3803             :   Factory* factory = isolate->factory();
    3804             : 
    3805             :   std::pair<const char*, Handle<Object>> sloppy_this[] = {
    3806             :       std::make_pair("var global_val = 100;\n"
    3807             :                      "function f() { return this.global_val; }\n",
    3808             :                      handle(Smi::FromInt(100), isolate)),
    3809             :       std::make_pair("var global_val = 110;\n"
    3810             :                      "function g() { return this.global_val; };"
    3811             :                      "function f() { return g(); }\n",
    3812             :                      handle(Smi::FromInt(110), isolate)),
    3813             :       std::make_pair("var global_val = 110;\n"
    3814             :                      "function g() { return this.global_val };"
    3815             :                      "function f() { 'use strict'; return g(); }\n",
    3816             :                      handle(Smi::FromInt(110), isolate)),
    3817             :       std::make_pair("function f() { 'use strict'; return this; }\n",
    3818             :                      factory->undefined_value()),
    3819             :       std::make_pair("function g() { 'use strict'; return this; };"
    3820             :                      "function f() { return g(); }\n",
    3821             :                      factory->undefined_value()),
    3822             :   };
    3823             : 
    3824          55 :   for (size_t i = 0; i < arraysize(sloppy_this); i++) {
    3825          50 :     InterpreterTester tester(isolate, sloppy_this[i].first);
    3826             :     auto callable = tester.GetCallable<>();
    3827             : 
    3828             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    3829          50 :     CHECK(return_value->SameValue(*sloppy_this[i].second));
    3830             :   }
    3831           5 : }
    3832             : 
    3833       26661 : TEST(InterpreterThisFunction) {
    3834          10 :   HandleAndZoneScope handles;
    3835             :   Isolate* isolate = handles.main_isolate();
    3836             :   Factory* factory = isolate->factory();
    3837             : 
    3838             :   InterpreterTester tester(isolate,
    3839          10 :                            "var f;\n f = function f() { return f.name; }");
    3840             :   auto callable = tester.GetCallable<>();
    3841             : 
    3842             :   Handle<i::Object> return_value = callable().ToHandleChecked();
    3843          15 :   CHECK(return_value->SameValue(*factory->NewStringFromStaticChars("f")));
    3844           5 : }
    3845             : 
    3846       26661 : TEST(InterpreterNewTarget) {
    3847          10 :   HandleAndZoneScope handles;
    3848             :   Isolate* isolate = handles.main_isolate();
    3849             :   Factory* factory = isolate->factory();
    3850             : 
    3851             :   // TODO(rmcilroy): Add tests that we get the original constructor for
    3852             :   // superclass constructors once we have class support.
    3853          10 :   InterpreterTester tester(isolate, "function f() { this.a = new.target; }");
    3854             :   auto callable = tester.GetCallable<>();
    3855             :   callable().ToHandleChecked();
    3856             : 
    3857             :   Handle<Object> new_target_name = v8::Utils::OpenHandle(
    3858             :       *CompileRun("(function() { return (new f()).a.name; })();"));
    3859          15 :   CHECK(new_target_name->SameValue(*factory->NewStringFromStaticChars("f")));
    3860           5 : }
    3861             : 
    3862       26661 : TEST(InterpreterAssignmentInExpressions) {
    3863          10 :   HandleAndZoneScope handles;
    3864             :   Isolate* isolate = handles.main_isolate();
    3865             : 
    3866             :   std::pair<const char*, int> samples[] = {
    3867             :       {"function f() {\n"
    3868             :        "  var x = 7;\n"
    3869             :        "  var y = x + (x = 1) + (x = 2);\n"
    3870             :        "  return y;\n"
    3871             :        "}",
    3872             :        10},
    3873             :       {"function f() {\n"
    3874             :        "  var x = 7;\n"
    3875             :        "  var y = x + (x = 1) + (x = 2);\n"
    3876             :        "  return x;\n"
    3877             :        "}",
    3878             :        2},
    3879             :       {"function f() {\n"
    3880             :        "  var x = 55;\n"
    3881             :        "  x = x + (x = 100) + (x = 101);\n"
    3882             :        "  return x;\n"
    3883             :        "}",
    3884             :        256},
    3885             :       {"function f() {\n"
    3886             :        "  var x = 7;\n"
    3887             :        "  return ++x + x + x++;\n"
    3888             :        "}",
    3889             :        24},
    3890             :       {"function f() {\n"
    3891             :        "  var x = 7;\n"
    3892             :        "  var y = 1 + ++x + x + x++;\n"
    3893             :        "  return x;\n"
    3894             :        "}",
    3895             :        9},
    3896             :       {"function f() {\n"
    3897             :        "  var x = 7;\n"
    3898             :        "  var y = ++x + x + x++;\n"
    3899             :        "  return x;\n"
    3900             :        "}",
    3901             :        9},
    3902             :       {"function f() {\n"
    3903             :        "  var x = 7, y = 100, z = 1000;\n"
    3904             :        "  return x + (x += 3) + y + (y *= 10) + (z *= 7) + z;\n"
    3905             :        "}",
    3906             :        15117},
    3907             :       {"function f() {\n"
    3908             :        "  var inner = function (x) { return x + (x = 2) + (x = 4) + x; };\n"
    3909             :        "  return inner(1);\n"
    3910             :        "}",
    3911             :        11},
    3912             :       {"function f() {\n"
    3913             :        "  var x = 1, y = 2;\n"
    3914             :        "  x = x + (x = 3) + y + (y = 4), y = y + (y = 5) + y + x;\n"
    3915             :        "  return x + y;\n"
    3916             :        "}",
    3917             :        10 + 24},
    3918             :       {"function f() {\n"
    3919             :        "  var x = 0;\n"
    3920             :        "  var y = x | (x = 1) | (x = 2);\n"
    3921             :        "  return x;\n"
    3922             :        "}",
    3923             :        2},
    3924             :       {"function f() {\n"
    3925             :        "  var x = 0;\n"
    3926             :        "  var y = x || (x = 1);\n"
    3927             :        "  return x;\n"
    3928             :        "}",
    3929             :        1},
    3930             :       {"function f() {\n"
    3931             :        "  var x = 1;\n"
    3932             :        "  var y = x && (x = 2) && (x = 3);\n"
    3933             :        "  return x;\n"
    3934             :        "}",
    3935             :        3},
    3936             :       {"function f() {\n"
    3937             :        "  var x = 1;\n"
    3938             :        "  var y = x || (x = 2);\n"
    3939             :        "  return x;\n"
    3940             :        "}",
    3941             :        1},
    3942             :       {"function f() {\n"
    3943             :        "  var x = 1;\n"
    3944             :        "  x = (x << (x = 3)) | (x = 16);\n"
    3945             :        "  return x;\n"
    3946             :        "}",
    3947             :        24},
    3948             :       {"function f() {\n"
    3949             :        "  var r = 7;\n"
    3950             :        "  var s = 11;\n"
    3951             :        "  var t = 13;\n"
    3952             :        "  var u = r + s + t + (r = 10) + (s = 20) +"
    3953             :        "          (t = (r + s)) + r + s + t;\n"
    3954             :        "  return r + s + t + u;\n"
    3955             :        "}",
    3956             :        211},
    3957             :       {"function f() {\n"
    3958             :        "  var r = 7;\n"
    3959             :        "  var s = 11;\n"
    3960             :        "  var t = 13;\n"
    3961             :        "  return r > (3 * s * (s = 1)) ? (t + (t += 1)) : (r + (r = 4));\n"
    3962             :        "}",
    3963             :        11},
    3964             :       {"function f() {\n"
    3965             :        "  var r = 7;\n"
    3966             :        "  var s = 11;\n"
    3967             :        "  var t = 13;\n"
    3968             :        "  return r > (3 * s * (s = 0)) ? (t + (t += 1)) : (r + (r = 4));\n"
    3969             :        "}",
    3970             :        27},
    3971             :       {"function f() {\n"
    3972             :        "  var r = 7;\n"
    3973             :        "  var s = 11;\n"
    3974             :        "  var t = 13;\n"
    3975             :        "  return (r + (r = 5)) > s ? r : t;\n"
    3976             :        "}",
    3977             :        5},
    3978             :       {"function f(a) {\n"
    3979             :        "  return a + (arguments[0] = 10);\n"
    3980             :        "}",
    3981             :        50},
    3982             :       {"function f(a) {\n"
    3983             :        "  return a + (arguments[0] = 10) + a;\n"
    3984             :        "}",
    3985             :        60},
    3986             :       {"function f(a) {\n"
    3987             :        "  return a + (arguments[0] = 10) + arguments[0];\n"
    3988             :        "}",
    3989             :        60},
    3990           5 :   };
    3991             : 
    3992             :   const int arg_value = 40;
    3993         215 :   for (size_t i = 0; i < arraysize(samples); i++) {
    3994         210 :     InterpreterTester tester(isolate, samples[i].first);
    3995             :     auto callable = tester.GetCallable<Handle<Object>>();
    3996             :     Handle<Object> return_val =
    3997         210 :         callable(handle(Smi::FromInt(arg_value), handles.main_isolate()))
    3998             :             .ToHandleChecked();
    3999         210 :     CHECK_EQ(Handle<Smi>::cast(return_val)->value(), samples[i].second);
    4000             :   }
    4001           5 : }
    4002             : 
    4003       26661 : TEST(InterpreterToName) {
    4004          10 :   HandleAndZoneScope handles;
    4005             :   Isolate* isolate = handles.main_isolate();
    4006             :   Factory* factory = isolate->factory();
    4007             : 
    4008             :   std::pair<const char*, Handle<Object>> to_name_tests[] = {
    4009             :       {"var a = 'val'; var obj = {[a] : 10}; return obj.val;",
    4010          10 :        factory->NewNumberFromInt(10)},
    4011             :       {"var a = 20; var obj = {[a] : 10}; return obj['20'];",
    4012          10 :        factory->NewNumberFromInt(10)},
    4013             :       {"var a = 20; var obj = {[a] : 10}; return obj[20];",
    4014          10 :        factory->NewNumberFromInt(10)},
    4015             :       {"var a = {val:23}; var obj = {[a] : 10}; return obj[a];",
    4016          10 :        factory->NewNumberFromInt(10)},
    4017             :       {"var a = {val:23}; var obj = {[a] : 10};\n"
    4018             :        "return obj['[object Object]'];",
    4019          10 :        factory->NewNumberFromInt(10)},
    4020             :       {"var a = {toString : function() { return 'x'}};\n"
    4021             :        "var obj = {[a] : 10};\n"
    4022             :        "return obj.x;",
    4023          10 :        factory->NewNumberFromInt(10)},
    4024             :       {"var a = {valueOf : function() { return 'x'}};\n"
    4025             :        "var obj = {[a] : 10};\n"
    4026             :        "return obj.x;",
    4027             :        factory->undefined_value()},
    4028             :       {"var a = {[Symbol.toPrimitive] : function() { return 'x'}};\n"
    4029             :        "var obj = {[a] : 10};\n"
    4030             :        "return obj.x;",
    4031          10 :        factory->NewNumberFromInt(10)},
    4032             :   };
    4033             : 
    4034          85 :   for (size_t i = 0; i < arraysize(to_name_tests); i++) {
    4035             :     std::string source(
    4036          40 :         InterpreterTester::SourceForBody(to_name_tests[i].first));
    4037          80 :     InterpreterTester tester(isolate, source.c_str());
    4038             :     auto callable = tester.GetCallable<>();
    4039             : 
    4040             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4041          80 :     CHECK(return_value->SameValue(*to_name_tests[i].second));
    4042             :   }
    4043           5 : }
    4044             : 
    4045       26661 : TEST(TemporaryRegisterAllocation) {
    4046          10 :   HandleAndZoneScope handles;
    4047             :   Isolate* isolate = handles.main_isolate();
    4048             :   Factory* factory = isolate->factory();
    4049             : 
    4050             :   std::pair<const char*, Handle<Object>> reg_tests[] = {
    4051             :       {"function add(a, b, c) {"
    4052             :        "   return a + b + c;"
    4053             :        "}"
    4054             :        "function f() {"
    4055             :        "  var a = 10, b = 10;"
    4056             :        "   return add(a, b++, b);"
    4057             :        "}",
    4058          10 :        factory->NewNumberFromInt(31)},
    4059             :       {"function add(a, b, c, d) {"
    4060             :        "  return a + b + c + d;"
    4061             :        "}"
    4062             :        "function f() {"
    4063             :        "  var x = 10, y = 20, z = 30;"
    4064             :        "  return x + add(x, (y= x++), x, z);"
    4065             :        "}",
    4066          10 :        factory->NewNumberFromInt(71)},
    4067             :   };
    4068             : 
    4069          25 :   for (size_t i = 0; i < arraysize(reg_tests); i++) {
    4070          20 :     InterpreterTester tester(isolate, reg_tests[i].first);
    4071             :     auto callable = tester.GetCallable<>();
    4072             : 
    4073             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4074          20 :     CHECK(return_value->SameValue(*reg_tests[i].second));
    4075             :   }
    4076           5 : }
    4077             : 
    4078       26661 : TEST(InterpreterLookupSlot) {
    4079          10 :   HandleAndZoneScope handles;
    4080             :   Isolate* isolate = handles.main_isolate();
    4081             :   Factory* factory = isolate->factory();
    4082             : 
    4083             :   // TODO(mythria): Add more tests when we have support for eval/with.
    4084             :   const char* function_prologue = "var f;"
    4085             :                                   "var x = 1;"
    4086             :                                   "function f1() {"
    4087             :                                   "  eval(\"function t() {";
    4088             :   const char* function_epilogue = "        }; f = t;\");"
    4089             :                                   "}"
    4090             :                                   "f1();";
    4091             : 
    4092             : 
    4093             :   std::pair<const char*, Handle<Object>> lookup_slot[] = {
    4094             :       {"return x;", handle(Smi::FromInt(1), isolate)},
    4095          10 :       {"return typeof x;", factory->NewStringFromStaticChars("number")},
    4096          10 :       {"return typeof dummy;", factory->NewStringFromStaticChars("undefined")},
    4097             :       {"x = 10; return x;", handle(Smi::FromInt(10), isolate)},
    4098             :       {"'use strict'; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
    4099             :   };
    4100             : 
    4101          55 :   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
    4102         100 :     std::string script = std::string(function_prologue) +
    4103             :                          std::string(lookup_slot[i].first) +
    4104          75 :                          std::string(function_epilogue);
    4105             : 
    4106          50 :     InterpreterTester tester(isolate, script.c_str(), "t");
    4107             :     auto callable = tester.GetCallable<>();
    4108             : 
    4109             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4110          50 :     CHECK(return_value->SameValue(*lookup_slot[i].second));
    4111             :   }
    4112           5 : }
    4113             : 
    4114       26661 : TEST(InterpreterLookupContextSlot) {
    4115          10 :   HandleAndZoneScope handles;
    4116             :   Isolate* isolate = handles.main_isolate();
    4117             : 
    4118             :   const char* inner_function_prologue = "function inner() {";
    4119             :   const char* inner_function_epilogue = "};";
    4120             :   const char* outer_function_epilogue = "return inner();";
    4121             : 
    4122             :   std::tuple<const char*, const char*, Handle<Object>> lookup_slot[] = {
    4123             :       // Eval in inner 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("var x = 0;",
    4129             :                       "'use strict'; eval('var x = 1'); return x;",
    4130             :                       handle(Smi::kZero, isolate)),
    4131             :       // Eval in outer context.
    4132             :       std::make_tuple("var x = 0; eval('');", "return x;",
    4133             :                       handle(Smi::kZero, isolate)),
    4134             :       std::make_tuple("var x = 0; eval('var x = 1');", "return x;",
    4135             :                       handle(Smi::FromInt(1), isolate)),
    4136             :       std::make_tuple("'use strict'; var x = 0; eval('var x = 1');",
    4137             :                       "return x;", handle(Smi::kZero, isolate)),
    4138             :   };
    4139             : 
    4140          65 :   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
    4141         120 :     std::string body = std::string(std::get<0>(lookup_slot[i])) +
    4142         120 :                        std::string(inner_function_prologue) +
    4143         120 :                        std::string(std::get<1>(lookup_slot[i])) +
    4144             :                        std::string(inner_function_epilogue) +
    4145          90 :                        std::string(outer_function_epilogue);
    4146          30 :     std::string script = InterpreterTester::SourceForBody(body.c_str());
    4147             : 
    4148          60 :     InterpreterTester tester(isolate, script.c_str());
    4149             :     auto callable = tester.GetCallable<>();
    4150             : 
    4151             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4152          30 :     CHECK(return_value->SameValue(*std::get<2>(lookup_slot[i])));
    4153             :   }
    4154           5 : }
    4155             : 
    4156       26661 : TEST(InterpreterLookupGlobalSlot) {
    4157          10 :   HandleAndZoneScope handles;
    4158             :   Isolate* isolate = handles.main_isolate();
    4159             : 
    4160             :   const char* inner_function_prologue = "function inner() {";
    4161             :   const char* inner_function_epilogue = "};";
    4162             :   const char* outer_function_epilogue = "return inner();";
    4163             : 
    4164             :   std::tuple<const char*, const char*, Handle<Object>> lookup_slot[] = {
    4165             :       // Eval in inner context.
    4166             :       std::make_tuple("x = 0;", "eval(''); return x;",
    4167             :                       handle(Smi::kZero, isolate)),
    4168             :       std::make_tuple("x = 0;", "eval('var x = 1'); return x;",
    4169             :                       handle(Smi::FromInt(1), isolate)),
    4170             :       std::make_tuple("x = 0;", "'use strict'; eval('var x = 1'); return x;",
    4171             :                       handle(Smi::kZero, isolate)),
    4172             :       // Eval in outer context.
    4173             :       std::make_tuple("x = 0; eval('');", "return x;",
    4174             :                       handle(Smi::kZero, isolate)),
    4175             :       std::make_tuple("x = 0; eval('var x = 1');", "return x;",
    4176             :                       handle(Smi::FromInt(1), isolate)),
    4177             :       std::make_tuple("'use strict'; x = 0; eval('var x = 1');", "return x;",
    4178             :                       handle(Smi::kZero, isolate)),
    4179             :   };
    4180             : 
    4181          65 :   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
    4182         120 :     std::string body = std::string(std::get<0>(lookup_slot[i])) +
    4183         120 :                        std::string(inner_function_prologue) +
    4184         120 :                        std::string(std::get<1>(lookup_slot[i])) +
    4185             :                        std::string(inner_function_epilogue) +
    4186          90 :                        std::string(outer_function_epilogue);
    4187          30 :     std::string script = InterpreterTester::SourceForBody(body.c_str());
    4188             : 
    4189          60 :     InterpreterTester tester(isolate, script.c_str());
    4190             :     auto callable = tester.GetCallable<>();
    4191             : 
    4192             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4193          30 :     CHECK(return_value->SameValue(*std::get<2>(lookup_slot[i])));
    4194             :   }
    4195           5 : }
    4196             : 
    4197       26661 : TEST(InterpreterCallLookupSlot) {
    4198          10 :   HandleAndZoneScope handles;
    4199             :   Isolate* isolate = handles.main_isolate();
    4200             : 
    4201             :   std::pair<const char*, Handle<Object>> call_lookup[] = {
    4202             :       {"g = function(){ return 2 }; eval(''); return g();",
    4203             :        handle(Smi::FromInt(2), isolate)},
    4204             :       {"g = function(){ return 2 }; eval('g = function() {return 3}');\n"
    4205             :        "return g();",
    4206             :        handle(Smi::FromInt(3), isolate)},
    4207             :       {"g = { x: function(){ return this.y }, y: 20 };\n"
    4208             :        "eval('g = { x: g.x, y: 30 }');\n"
    4209             :        "return g.x();",
    4210             :        handle(Smi::FromInt(30), isolate)},
    4211             :   };
    4212             : 
    4213          35 :   for (size_t i = 0; i < arraysize(call_lookup); i++) {
    4214          15 :     std::string source(InterpreterTester::SourceForBody(call_lookup[i].first));
    4215          30 :     InterpreterTester tester(isolate, source.c_str());
    4216             :     auto callable = tester.GetCallable<>();
    4217             : 
    4218             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4219          30 :     CHECK(return_value->SameValue(*call_lookup[i].second));
    4220             :   }
    4221           5 : }
    4222             : 
    4223       26661 : TEST(InterpreterLookupSlotWide) {
    4224          10 :   HandleAndZoneScope handles;
    4225             :   Isolate* isolate = handles.main_isolate();
    4226             :   Factory* factory = isolate->factory();
    4227             : 
    4228             :   const char* function_prologue =
    4229             :       "var f;"
    4230             :       "var x = 1;"
    4231             :       "function f1() {"
    4232             :       "  eval(\"function t() {";
    4233             :   const char* function_epilogue =
    4234             :       "        }; f = t;\");"
    4235             :       "}"
    4236             :       "f1();";
    4237          10 :   std::ostringstream str;
    4238           5 :   str << "var y = 2.3;";
    4239        2555 :   for (int i = 1; i < 256; i++) {
    4240        2550 :     str << "y = " << 2.3 + i << ";";
    4241             :   }
    4242             :   std::string init_function_body = str.str();
    4243             : 
    4244             :   std::pair<std::string, Handle<Object>> lookup_slot[] = {
    4245           5 :       {init_function_body + "return x;", handle(Smi::FromInt(1), isolate)},
    4246           5 :       {init_function_body + "return typeof x;",
    4247          10 :        factory->NewStringFromStaticChars("number")},
    4248           5 :       {init_function_body + "return x = 10;",
    4249             :        handle(Smi::FromInt(10), isolate)},
    4250          15 :       {"'use strict';" + init_function_body + "x = 20; return x;",
    4251             :        handle(Smi::FromInt(20), isolate)},
    4252          25 :   };
    4253             : 
    4254          45 :   for (size_t i = 0; i < arraysize(lookup_slot); i++) {
    4255          60 :     std::string script = std::string(function_prologue) + lookup_slot[i].first +
    4256          60 :                          std::string(function_epilogue);
    4257             : 
    4258          40 :     InterpreterTester tester(isolate, script.c_str(), "t");
    4259             :     auto callable = tester.GetCallable<>();
    4260             : 
    4261             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4262          40 :     CHECK(return_value->SameValue(*lookup_slot[i].second));
    4263             :   }
    4264           5 : }
    4265             : 
    4266       26661 : TEST(InterpreterDeleteLookupSlot) {
    4267          10 :   HandleAndZoneScope handles;
    4268             :   Isolate* isolate = handles.main_isolate();
    4269             :   Factory* factory = isolate->factory();
    4270             : 
    4271             :   // TODO(mythria): Add more tests when we have support for eval/with.
    4272             :   const char* function_prologue = "var f;"
    4273             :                                   "var x = 1;"
    4274             :                                   "y = 10;"
    4275             :                                   "var obj = {val:10};"
    4276             :                                   "var z = 30;"
    4277             :                                   "function f1() {"
    4278             :                                   "  var z = 20;"
    4279             :                                   "  eval(\"function t() {";
    4280             :   const char* function_epilogue = "        }; f = t;\");"
    4281             :                                   "}"
    4282             :                                   "f1();";
    4283             : 
    4284             : 
    4285             :   std::pair<const char*, Handle<Object>> delete_lookup_slot[] = {
    4286             :       {"return delete x;", factory->false_value()},
    4287             :       {"return delete y;", factory->true_value()},
    4288             :       {"return delete z;", factory->false_value()},
    4289             :       {"return delete obj.val;", factory->true_value()},
    4290             :       {"'use strict'; return delete obj.val;", factory->true_value()},
    4291             :   };
    4292             : 
    4293          55 :   for (size_t i = 0; i < arraysize(delete_lookup_slot); i++) {
    4294         100 :     std::string script = std::string(function_prologue) +
    4295             :                          std::string(delete_lookup_slot[i].first) +
    4296          75 :                          std::string(function_epilogue);
    4297             : 
    4298          50 :     InterpreterTester tester(isolate, script.c_str(), "t");
    4299             :     auto callable = tester.GetCallable<>();
    4300             : 
    4301             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4302          50 :     CHECK(return_value->SameValue(*delete_lookup_slot[i].second));
    4303             :   }
    4304           5 : }
    4305             : 
    4306       26661 : TEST(JumpWithConstantsAndWideConstants) {
    4307          10 :   HandleAndZoneScope handles;
    4308             :   Isolate* isolate = handles.main_isolate();
    4309             :   Factory* factory = isolate->factory();
    4310             :   const int kStep = 13;
    4311         225 :   for (int constants = 11; constants < 256 + 3 * kStep; constants += kStep) {
    4312         220 :     std::ostringstream filler_os;
    4313             :     // Generate a string that consumes constant pool entries and
    4314             :     // spread out branch distances in script below.
    4315       32560 :     for (int i = 0; i < constants; i++) {
    4316       16225 :       filler_os << "var x_ = 'x_" << i << "';\n";
    4317             :     }
    4318             :     std::string filler(filler_os.str());
    4319         220 :     std::ostringstream script_os;
    4320         330 :     script_os << "function " << InterpreterTester::function_name() << "(a) {\n";
    4321             :     script_os << "  " << filler;
    4322         110 :     script_os << "  for (var i = a; i < 2; i++) {\n";
    4323             :     script_os << "  " << filler;
    4324         110 :     script_os << "    if (i == 0) { " << filler << "i = 10; continue; }\n";
    4325         110 :     script_os << "    else if (i == a) { " << filler << "i = 12; break; }\n";
    4326         110 :     script_os << "    else { " << filler << " }\n";
    4327         110 :     script_os << "  }\n";
    4328         110 :     script_os << "  return i;\n";
    4329         110 :     script_os << "}\n";
    4330             :     std::string script(script_os.str());
    4331         770 :     for (int a = 0; a < 3; a++) {
    4332         660 :       InterpreterTester tester(isolate, script.c_str());
    4333             :       auto callable = tester.GetCallable<Handle<Object>>();
    4334         330 :       Handle<Object> argument = factory->NewNumberFromInt(a);
    4335         660 :       Handle<Object> return_val = callable(argument).ToHandleChecked();
    4336             :       static const int results[] = {11, 12, 2};
    4337         660 :       CHECK_EQ(Handle<Smi>::cast(return_val)->value(), results[a]);
    4338             :     }
    4339             :   }
    4340           5 : }
    4341             : 
    4342       26661 : TEST(InterpreterEval) {
    4343          10 :   HandleAndZoneScope handles;
    4344             :   Isolate* isolate = handles.main_isolate();
    4345             :   Factory* factory = isolate->factory();
    4346             : 
    4347             :   std::pair<const char*, Handle<Object>> eval[] = {
    4348             :       {"return eval('1;');", handle(Smi::FromInt(1), isolate)},
    4349             :       {"return eval('100 * 20;');", handle(Smi::FromInt(2000), isolate)},
    4350             :       {"var x = 10; return eval('x + 20;');",
    4351             :        handle(Smi::FromInt(30), isolate)},
    4352             :       {"var x = 10; eval('x = 33;'); return x;",
    4353             :        handle(Smi::FromInt(33), isolate)},
    4354             :       {"'use strict'; var x = 20; var z = 0;\n"
    4355             :        "eval('var x = 33; z = x;'); return x + z;",
    4356             :        handle(Smi::FromInt(53), isolate)},
    4357             :       {"eval('var x = 33;'); eval('var y = x + 20'); return x + y;",
    4358             :        handle(Smi::FromInt(86), isolate)},
    4359             :       {"var x = 1; eval('for(i = 0; i < 10; i++) x = x + 1;'); return x",
    4360             :        handle(Smi::FromInt(11), isolate)},
    4361             :       {"var x = 10; eval('var x = 20;'); return x;",
    4362             :        handle(Smi::FromInt(20), isolate)},
    4363             :       {"var x = 1; eval('\"use strict\"; var x = 2;'); return x;",
    4364             :        handle(Smi::FromInt(1), isolate)},
    4365             :       {"'use strict'; var x = 1; eval('var x = 2;'); return x;",
    4366             :        handle(Smi::FromInt(1), isolate)},
    4367             :       {"var x = 10; eval('x + 20;'); return typeof x;",
    4368          10 :        factory->NewStringFromStaticChars("number")},
    4369             :       {"eval('var y = 10;'); return typeof unallocated;",
    4370          10 :        factory->NewStringFromStaticChars("undefined")},
    4371             :       {"'use strict'; eval('var y = 10;'); return typeof unallocated;",
    4372          10 :        factory->NewStringFromStaticChars("undefined")},
    4373             :       {"eval('var x = 10;'); return typeof x;",
    4374          10 :        factory->NewStringFromStaticChars("number")},
    4375             :       {"var x = {}; eval('var x = 10;'); return typeof x;",
    4376          10 :        factory->NewStringFromStaticChars("number")},
    4377             :       {"'use strict'; var x = {}; eval('var x = 10;'); return typeof x;",
    4378          10 :        factory->NewStringFromStaticChars("object")},
    4379             :   };
    4380             : 
    4381         165 :   for (size_t i = 0; i < arraysize(eval); i++) {
    4382          80 :     std::string source(InterpreterTester::SourceForBody(eval[i].first));
    4383         160 :     InterpreterTester tester(isolate, source.c_str());
    4384             :     auto callable = tester.GetCallable<>();
    4385             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4386         160 :     CHECK(return_value->SameValue(*eval[i].second));
    4387             :   }
    4388           5 : }
    4389             : 
    4390       26661 : TEST(InterpreterEvalParams) {
    4391          10 :   HandleAndZoneScope handles;
    4392             :   Isolate* isolate = handles.main_isolate();
    4393             : 
    4394             :   std::pair<const char*, Handle<Object>> eval_params[] = {
    4395             :       {"var x = 10; return eval('x + p1;');",
    4396             :        handle(Smi::FromInt(30), isolate)},
    4397             :       {"var x = 10; eval('p1 = x;'); return p1;",
    4398             :        handle(Smi::FromInt(10), isolate)},
    4399             :       {"var a = 10;"
    4400             :        "function inner() { return eval('a + p1;');}"
    4401             :        "return inner();",
    4402             :        handle(Smi::FromInt(30), isolate)},
    4403             :   };
    4404             : 
    4405          35 :   for (size_t i = 0; i < arraysize(eval_params); i++) {
    4406          60 :     std::string source = "function " + InterpreterTester::function_name() +
    4407          45 :                          "(p1) {" + eval_params[i].first + "}";
    4408          30 :     InterpreterTester tester(isolate, source.c_str());
    4409             :     auto callable = tester.GetCallable<Handle<Object>>();
    4410             : 
    4411             :     Handle<i::Object> return_value =
    4412          30 :         callable(handle(Smi::FromInt(20), isolate)).ToHandleChecked();
    4413          30 :     CHECK(return_value->SameValue(*eval_params[i].second));
    4414             :   }
    4415           5 : }
    4416             : 
    4417       26661 : TEST(InterpreterEvalGlobal) {
    4418          10 :   HandleAndZoneScope handles;
    4419             :   Isolate* isolate = handles.main_isolate();
    4420             :   Factory* factory = isolate->factory();
    4421             : 
    4422             :   std::pair<const char*, Handle<Object>> eval_global[] = {
    4423             :       {"function add_global() { eval('function test() { z = 33; }; test()'); };"
    4424             :        "function f() { add_global(); return z; }; f();",
    4425             :        handle(Smi::FromInt(33), isolate)},
    4426             :       {"function add_global() {\n"
    4427             :        " eval('\"use strict\"; function test() { y = 33; };"
    4428             :        "      try { test() } catch(e) {}');\n"
    4429             :        "}\n"
    4430             :        "function f() { add_global(); return typeof y; } f();",
    4431          10 :        factory->NewStringFromStaticChars("undefined")},
    4432             :   };
    4433             : 
    4434          25 :   for (size_t i = 0; i < arraysize(eval_global); i++) {
    4435          20 :     InterpreterTester tester(isolate, eval_global[i].first, "test");
    4436             :     auto callable = tester.GetCallable<>();
    4437             : 
    4438             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4439          20 :     CHECK(return_value->SameValue(*eval_global[i].second));
    4440             :   }
    4441           5 : }
    4442             : 
    4443       26661 : TEST(InterpreterEvalVariableDecl) {
    4444          10 :   HandleAndZoneScope handles;
    4445             :   Isolate* isolate = handles.main_isolate();
    4446             :   Factory* factory = isolate->factory();
    4447             : 
    4448             :   std::pair<const char*, Handle<Object>> eval_global[] = {
    4449             :       {"function f() { eval('var x = 10; x++;'); return x; }",
    4450             :        handle(Smi::FromInt(11), isolate)},
    4451             :       {"function f() { var x = 20; eval('var x = 10; x++;'); return x; }",
    4452             :        handle(Smi::FromInt(11), isolate)},
    4453             :       {"function f() {"
    4454             :        " var x = 20;"
    4455             :        " eval('\"use strict\"; var x = 10; x++;');"
    4456             :        " return x; }",
    4457             :        handle(Smi::FromInt(20), isolate)},
    4458             :       {"function f() {"
    4459             :        " var y = 30;"
    4460             :        " eval('var x = {1:20}; x[2]=y;');"
    4461             :        " return x[2]; }",
    4462             :        handle(Smi::FromInt(30), isolate)},
    4463             :       {"function f() {"
    4464             :        " eval('var x = {name:\"test\"};');"
    4465             :        " return x.name; }",
    4466          10 :        factory->NewStringFromStaticChars("test")},
    4467             :       {"function f() {"
    4468             :        "  eval('var x = [{name:\"test\"}, {type:\"cc\"}];');"
    4469             :        "  return x[1].type+x[0].name; }",
    4470          10 :        factory->NewStringFromStaticChars("cctest")},
    4471             :       {"function f() {\n"
    4472             :        " var x = 3;\n"
    4473             :        " var get_eval_x;\n"
    4474             :        " eval('\"use strict\"; "
    4475             :        "      var x = 20; "
    4476             :        "      get_eval_x = function func() {return x;};');\n"
    4477             :        " return get_eval_x() + x;\n"
    4478             :        "}",
    4479             :        handle(Smi::FromInt(23), isolate)},
    4480             :       // TODO(mythria): Add tests with const declarations.
    4481             :   };
    4482             : 
    4483          75 :   for (size_t i = 0; i < arraysize(eval_global); i++) {
    4484          70 :     InterpreterTester tester(isolate, eval_global[i].first, "*");
    4485             :     auto callable = tester.GetCallable<>();
    4486             : 
    4487             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4488          70 :     CHECK(return_value->SameValue(*eval_global[i].second));
    4489             :   }
    4490           5 : }
    4491             : 
    4492       26661 : TEST(InterpreterEvalFunctionDecl) {
    4493          10 :   HandleAndZoneScope handles;
    4494             :   Isolate* isolate = handles.main_isolate();
    4495             : 
    4496             :   std::pair<const char*, Handle<Object>> eval_func_decl[] = {
    4497             :       {"function f() {\n"
    4498             :        " var x = 3;\n"
    4499             :        " eval('var x = 20;"
    4500             :        "       function get_x() {return x;};');\n"
    4501             :        " return get_x() + x;\n"
    4502             :        "}",
    4503             :        handle(Smi::FromInt(40), isolate)},
    4504             :   };
    4505             : 
    4506          15 :   for (size_t i = 0; i < arraysize(eval_func_decl); i++) {
    4507          10 :     InterpreterTester tester(isolate, eval_func_decl[i].first, "*");
    4508             :     auto callable = tester.GetCallable<>();
    4509             : 
    4510             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4511          10 :     CHECK(return_value->SameValue(*eval_func_decl[i].second));
    4512             :   }
    4513           5 : }
    4514             : 
    4515       26661 : TEST(InterpreterWideRegisterArithmetic) {
    4516          10 :   HandleAndZoneScope handles;
    4517             :   Isolate* isolate = handles.main_isolate();
    4518             : 
    4519             :   static const size_t kMaxRegisterForTest = 150;
    4520          10 :   std::ostringstream os;
    4521          15 :   os << "function " << InterpreterTester::function_name() << "(arg) {\n";
    4522           5 :   os << "  var retval = -77;\n";
    4523        1505 :   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
    4524         750 :     os << "  var x" << i << " = " << i << ";\n";
    4525             :   }
    4526         755 :   for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
    4527         375 :     size_t j = kMaxRegisterForTest - i - 1;
    4528         375 :     os << "  var tmp = x" << j << ";\n";
    4529         375 :     os << "  var x" << j << " = x" << i << ";\n";
    4530         375 :     os << "  var x" << i << " = tmp;\n";
    4531             :   }
    4532         755 :   for (size_t i = 0; i < kMaxRegisterForTest / 2; i++) {
    4533         375 :     size_t j = kMaxRegisterForTest - i - 1;
    4534         375 :     os << "  var tmp = x" << j << ";\n";
    4535         375 :     os << "  var x" << j << " = x" << i << ";\n";
    4536         375 :     os << "  var x" << i << " = tmp;\n";
    4537             :   }
    4538        1505 :   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
    4539             :     os << "  if (arg == " << i << ") {\n"  //
    4540             :        << "    retval = x" << i << ";\n"   //
    4541         750 :        << "  }\n";                         //
    4542             :   }
    4543           5 :   os << "  return retval;\n";
    4544           5 :   os << "}\n";
    4545             : 
    4546             :   std::string source = os.str();
    4547          10 :   InterpreterTester tester(isolate, source.c_str());
    4548             :   auto callable = tester.GetCallable<Handle<Object>>();
    4549        1505 :   for (size_t i = 0; i < kMaxRegisterForTest; i++) {
    4550         750 :     Handle<Object> arg = handle(Smi::FromInt(static_cast<int>(i)), isolate);
    4551        1500 :     Handle<Object> return_value = callable(arg).ToHandleChecked();
    4552         750 :     CHECK(return_value->SameValue(*arg));
    4553             :   }
    4554           5 : }
    4555             : 
    4556       26661 : TEST(InterpreterCallWideRegisters) {
    4557             :   static const int kPeriod = 25;
    4558             :   static const int kLength = 512;
    4559             :   static const int kStartChar = 65;
    4560             : 
    4561          10 :   HandleAndZoneScope handles;
    4562             :   Isolate* isolate = handles.main_isolate();
    4563             : 
    4564          35 :   for (int pass = 0; pass < 3; pass += 1) {
    4565          30 :     std::ostringstream os;
    4566        2925 :     for (int i = 0; i < pass * 97; i += 1) {
    4567        2910 :       os << "var x" << i << " = " << i << "\n";
    4568             :     }
    4569          15 :     os << "return String.fromCharCode(";
    4570          15 :     os << kStartChar;
    4571       15345 :     for (int i = 1; i < kLength; i += 1) {
    4572       15330 :       os << "," << kStartChar + (i % kPeriod);
    4573             :     }
    4574          15 :     os << ");";
    4575          30 :     std::string source = InterpreterTester::SourceForBody(os.str().c_str());
    4576          30 :     InterpreterTester tester(isolate, source.c_str());
    4577             :     auto callable = tester.GetCallable();
    4578             :     Handle<Object> return_val = callable().ToHandleChecked();
    4579             :     Handle<String> return_string = Handle<String>::cast(return_val);
    4580          15 :     CHECK_EQ(return_string->length(), kLength);
    4581       15375 :     for (int i = 0; i < kLength; i += 1) {
    4582       15360 :       CHECK_EQ(return_string->Get(i), 65 + (i % kPeriod));
    4583             :     }
    4584             :   }
    4585           5 : }
    4586             : 
    4587       26661 : TEST(InterpreterWideParametersPickOne) {
    4588          10 :   HandleAndZoneScope handles;
    4589             :   Isolate* isolate = handles.main_isolate();
    4590             :   static const int kParameterCount = 130;
    4591         105 :   for (int parameter = 0; parameter < 10; parameter++) {
    4592         100 :     std::ostringstream os;
    4593         150 :     os << "function " << InterpreterTester::function_name() << "(arg) {\n";
    4594          50 :     os << "  function selector(i";
    4595       13050 :     for (int i = 0; i < kParameterCount; i++) {
    4596             :       os << ","
    4597        6500 :          << "a" << i;
    4598             :     }
    4599          50 :     os << ") {\n";
    4600          50 :     os << "  return a" << parameter << ";\n";
    4601          50 :     os << "  };\n";
    4602          50 :     os << "  return selector(arg";
    4603       13050 :     for (int i = 0; i < kParameterCount; i++) {
    4604        6500 :       os << "," << i;
    4605             :     }
    4606          50 :     os << ");";
    4607          50 :     os << "}\n";
    4608             : 
    4609             :     std::string source = os.str();
    4610         100 :     InterpreterTester tester(isolate, source.c_str(), "*");
    4611             :     auto callable = tester.GetCallable<Handle<Object>>();
    4612             :     Handle<Object> arg = handle(Smi::FromInt(0xAA55), isolate);
    4613         100 :     Handle<Object> return_value = callable(arg).ToHandleChecked();
    4614             :     Handle<Smi> actual = Handle<Smi>::cast(return_value);
    4615          50 :     CHECK_EQ(actual->value(), parameter);
    4616             :   }
    4617           5 : }
    4618             : 
    4619       26661 : TEST(InterpreterWideParametersSummation) {
    4620             :   static int kParameterCount = 200;
    4621             :   static int kBaseValue = 17000;
    4622          10 :   HandleAndZoneScope handles;
    4623             :   Isolate* isolate = handles.main_isolate();
    4624          10 :   std::ostringstream os;
    4625          15 :   os << "function " << InterpreterTester::function_name() << "(arg) {\n";
    4626           5 :   os << "  function summation(i";
    4627        2005 :   for (int i = 0; i < kParameterCount; i++) {
    4628             :     os << ","
    4629        1000 :        << "a" << i;
    4630             :   }
    4631           5 :   os << ") {\n";
    4632          10 :   os << "    var sum = " << kBaseValue << ";\n";
    4633           5 :   os << "    switch(i) {\n";
    4634        2005 :   for (int i = 0; i < kParameterCount; i++) {
    4635        1000 :     int j = kParameterCount - i - 1;
    4636        2000 :     os << "      case " << j << ": sum += a" << j << ";\n";
    4637             :   }
    4638           5 :   os << "  }\n";
    4639           5 :   os << "    return sum;\n";
    4640           5 :   os << "  };\n";
    4641           5 :   os << "  return summation(arg";
    4642        2005 :   for (int i = 0; i < kParameterCount; i++) {
    4643        1000 :     os << "," << i;
    4644             :   }
    4645           5 :   os << ");";
    4646           5 :   os << "}\n";
    4647             : 
    4648             :   std::string source = os.str();
    4649          10 :   InterpreterTester tester(isolate, source.c_str(), "*");
    4650             :   auto callable = tester.GetCallable<Handle<Object>>();
    4651        2005 :   for (int i = 0; i < kParameterCount; i++) {
    4652             :     Handle<Object> arg = handle(Smi::FromInt(i), isolate);
    4653        2000 :     Handle<Object> return_value = callable(arg).ToHandleChecked();
    4654        1000 :     int expected = kBaseValue + i * (i + 1) / 2;
    4655             :     Handle<Smi> actual = Handle<Smi>::cast(return_value);
    4656        1000 :     CHECK_EQ(actual->value(), expected);
    4657             :   }
    4658           5 : }
    4659             : 
    4660       26661 : TEST(InterpreterWithStatement) {
    4661          10 :   HandleAndZoneScope handles;
    4662             :   Isolate* isolate = handles.main_isolate();
    4663             : 
    4664             :   std::pair<const char*, Handle<Object>> with_stmt[] = {
    4665             :       {"with({x:42}) return x;", handle(Smi::FromInt(42), isolate)},
    4666             :       {"with({}) { var y = 10; return y;}", handle(Smi::FromInt(10), isolate)},
    4667             :       {"var y = {x:42};"
    4668             :        " function inner() {"
    4669             :        "   var x = 20;"
    4670             :        "   with(y) return x;"
    4671             :        "}"
    4672             :        "return inner();",
    4673             :        handle(Smi::FromInt(42), isolate)},
    4674             :       {"var y = {x:42};"
    4675             :        " function inner(o) {"
    4676             :        "   var x = 20;"
    4677             :        "   with(o) return x;"
    4678             :        "}"
    4679             :        "return inner(y);",
    4680             :        handle(Smi::FromInt(42), isolate)},
    4681             :   };
    4682             : 
    4683          45 :   for (size_t i = 0; i < arraysize(with_stmt); i++) {
    4684          20 :     std::string source(InterpreterTester::SourceForBody(with_stmt[i].first));
    4685          40 :     InterpreterTester tester(isolate, source.c_str());
    4686             :     auto callable = tester.GetCallable<>();
    4687             : 
    4688             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4689          40 :     CHECK(return_value->SameValue(*with_stmt[i].second));
    4690             :   }
    4691           5 : }
    4692             : 
    4693       26661 : TEST(InterpreterClassLiterals) {
    4694          10 :   HandleAndZoneScope handles;
    4695             :   Isolate* isolate = handles.main_isolate();
    4696             :   std::pair<const char*, Handle<Object>> examples[] = {
    4697             :       {"class C {\n"
    4698             :        "  constructor(x) { this.x_ = x; }\n"
    4699             :        "  method() { return this.x_; }\n"
    4700             :        "}\n"
    4701             :        "return new C(99).method();",
    4702             :        handle(Smi::FromInt(99), isolate)},
    4703             :       {"class C {\n"
    4704             :        "  constructor(x) { this.x_ = x; }\n"
    4705             :        "  static static_method(x) { return x; }\n"
    4706             :        "}\n"
    4707             :        "return C.static_method(101);",
    4708             :        handle(Smi::FromInt(101), isolate)},
    4709             :       {"class C {\n"
    4710             :        "  get x() { return 102; }\n"
    4711             :        "}\n"
    4712             :        "return new C().x",
    4713             :        handle(Smi::FromInt(102), isolate)},
    4714             :       {"class C {\n"
    4715             :        "  static get x() { return 103; }\n"
    4716             :        "}\n"
    4717             :        "return C.x",
    4718             :        handle(Smi::FromInt(103), isolate)},
    4719             :       {"class C {\n"
    4720             :        "  constructor() { this.x_ = 0; }"
    4721             :        "  set x(value) { this.x_ = value; }\n"
    4722             :        "  get x() { return this.x_; }\n"
    4723             :        "}\n"
    4724             :        "var c = new C();"
    4725             :        "c.x = 104;"
    4726             :        "return c.x;",
    4727             :        handle(Smi::FromInt(104), isolate)},
    4728             :       {"var x = 0;"
    4729             :        "class C {\n"
    4730             :        "  static set x(value) { x = value; }\n"
    4731             :        "  static get x() { return x; }\n"
    4732             :        "}\n"
    4733             :        "C.x = 105;"
    4734             :        "return C.x;",
    4735             :        handle(Smi::FromInt(105), isolate)},
    4736             :       {"var method = 'f';"
    4737             :        "class C {\n"
    4738             :        "  [method]() { return 106; }\n"
    4739             :        "}\n"
    4740             :        "return new C().f();",
    4741             :        handle(Smi::FromInt(106), isolate)},
    4742             :   };
    4743             : 
    4744          75 :   for (size_t i = 0; i < arraysize(examples); ++i) {
    4745          35 :     std::string source(InterpreterTester::SourceForBody(examples[i].first));
    4746          70 :     InterpreterTester tester(isolate, source.c_str(), "*");
    4747             :     auto callable = tester.GetCallable<>();
    4748             : 
    4749             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4750          70 :     CHECK(return_value->SameValue(*examples[i].second));
    4751             :   }
    4752           5 : }
    4753             : 
    4754       26661 : TEST(InterpreterClassAndSuperClass) {
    4755          10 :   HandleAndZoneScope handles;
    4756             :   Isolate* isolate = handles.main_isolate();
    4757             :   std::pair<const char*, Handle<Object>> examples[] = {
    4758             :       {"class A {\n"
    4759             :        "  constructor(x) { this.x_ = x; }\n"
    4760             :        "  method() { return this.x_; }\n"
    4761             :        "}\n"
    4762             :        "class B extends A {\n"
    4763             :        "   constructor(x, y) { super(x); this.y_ = y; }\n"
    4764             :        "   method() { return super.method() + 1; }\n"
    4765             :        "}\n"
    4766             :        "return new B(998, 0).method();\n",
    4767             :        handle(Smi::FromInt(999), isolate)},
    4768             :       {"class A {\n"
    4769             :        "  constructor() { this.x_ = 2; this.y_ = 3; }\n"
    4770             :        "}\n"
    4771             :        "class B extends A {\n"
    4772             :        "  constructor() { super(); }"
    4773             :        "  method() { this.x_++; this.y_++; return this.x_ + this.y_; }\n"
    4774             :        "}\n"
    4775             :        "return new B().method();\n",
    4776             :        handle(Smi::FromInt(7), isolate)},
    4777             :       {"var calls = 0;\n"
    4778             :        "class B {}\n"
    4779             :        "B.prototype.x = 42;\n"
    4780             :        "class C extends B {\n"
    4781             :        "  constructor() {\n"
    4782             :        "    super();\n"
    4783             :        "    calls++;\n"
    4784             :        "  }\n"
    4785             :        "}\n"
    4786             :        "new C;\n"
    4787             :        "return calls;\n",
    4788             :        handle(Smi::FromInt(1), isolate)},
    4789             :       {"class A {\n"
    4790             :        "  method() { return 1; }\n"
    4791             :        "  get x() { return 2; }\n"
    4792             :        "}\n"
    4793             :        "class B extends A {\n"
    4794             :        "  method() { return super.x === 2 ? super.method() : -1; }\n"
    4795             :        "}\n"
    4796             :        "return new B().method();\n",
    4797             :        handle(Smi::FromInt(1), isolate)},
    4798             :       {"var object = { setY(v) { super.y = v; }};\n"
    4799             :        "object.setY(10);\n"
    4800             :        "return object.y;\n",
    4801             :        handle(Smi::FromInt(10), isolate)},
    4802             :   };
    4803             : 
    4804          55 :   for (size_t i = 0; i < arraysize(examples); ++i) {
    4805          25 :     std::string source(InterpreterTester::SourceForBody(examples[i].first));
    4806          50 :     InterpreterTester tester(isolate, source.c_str(), "*");
    4807             :     auto callable = tester.GetCallable<>();
    4808             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4809          50 :     CHECK(return_value->SameValue(*examples[i].second));
    4810             :   }
    4811           5 : }
    4812             : 
    4813       26661 : TEST(InterpreterConstDeclaration) {
    4814          10 :   HandleAndZoneScope handles;
    4815             :   Isolate* isolate = handles.main_isolate();
    4816             :   Factory* factory = isolate->factory();
    4817             : 
    4818             :   std::pair<const char*, Handle<Object>> const_decl[] = {
    4819             :       {"const x = 3; return x;", handle(Smi::FromInt(3), isolate)},
    4820             :       {"let x = 10; x = x + 20; return x;", handle(Smi::FromInt(30), isolate)},
    4821             :       {"let x = 10; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
    4822             :       {"let x; x = 20; return x;", handle(Smi::FromInt(20), isolate)},
    4823             :       {"let x; return x;", factory->undefined_value()},
    4824             :       {"var x = 10; { let x = 30; } return x;",
    4825             :        handle(Smi::FromInt(10), isolate)},
    4826             :       {"let x = 10; { let x = 20; } return x;",
    4827             :        handle(Smi::FromInt(10), isolate)},
    4828             :       {"var x = 10; eval('let x = 20;'); return x;",
    4829             :        handle(Smi::FromInt(10), isolate)},
    4830             :       {"var x = 10; eval('const x = 20;'); return x;",
    4831             :        handle(Smi::FromInt(10), isolate)},
    4832             :       {"var x = 10; { const x = 20; } return x;",
    4833             :        handle(Smi::FromInt(10), isolate)},
    4834             :       {"var x = 10; { const x = 20; return x;} return -1;",
    4835             :        handle(Smi::FromInt(20), isolate)},
    4836             :       {"var a = 10;\n"
    4837             :        "for (var i = 0; i < 10; ++i) {\n"
    4838             :        " const x = i;\n"  // const declarations are block scoped.
    4839             :        " a = a + x;\n"
    4840             :        "}\n"
    4841             :        "return a;\n",
    4842             :        handle(Smi::FromInt(55), isolate)},
    4843             :   };
    4844             : 
    4845             :   // Tests for sloppy mode.
    4846         125 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4847          60 :     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
    4848         120 :     InterpreterTester tester(isolate, source.c_str());
    4849             :     auto callable = tester.GetCallable<>();
    4850             : 
    4851             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4852         120 :     CHECK(return_value->SameValue(*const_decl[i].second));
    4853             :   }
    4854             : 
    4855             :   // Tests for strict mode.
    4856         125 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4857             :     std::string strict_body =
    4858         120 :         "'use strict'; " + std::string(const_decl[i].first);
    4859          60 :     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
    4860         120 :     InterpreterTester tester(isolate, source.c_str());
    4861             :     auto callable = tester.GetCallable<>();
    4862             : 
    4863             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4864         120 :     CHECK(return_value->SameValue(*const_decl[i].second));
    4865             :   }
    4866           5 : }
    4867             : 
    4868       26661 : TEST(InterpreterConstDeclarationLookupSlots) {
    4869          10 :   HandleAndZoneScope handles;
    4870             :   Isolate* isolate = handles.main_isolate();
    4871             :   Factory* factory = isolate->factory();
    4872             : 
    4873             :   std::pair<const char*, Handle<Object>> const_decl[] = {
    4874             :       {"const x = 3; function f1() {return x;}; return x;",
    4875             :        handle(Smi::FromInt(3), isolate)},
    4876             :       {"let x = 10; x = x + 20; function f1() {return x;}; return x;",
    4877             :        handle(Smi::FromInt(30), isolate)},
    4878             :       {"let x; x = 20; function f1() {return x;}; return x;",
    4879             :        handle(Smi::FromInt(20), isolate)},
    4880             :       {"let x; function f1() {return x;}; return x;",
    4881             :        factory->undefined_value()},
    4882             :   };
    4883             : 
    4884             :   // Tests for sloppy mode.
    4885          45 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4886          20 :     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
    4887          40 :     InterpreterTester tester(isolate, source.c_str());
    4888             :     auto callable = tester.GetCallable<>();
    4889             : 
    4890             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4891          40 :     CHECK(return_value->SameValue(*const_decl[i].second));
    4892             :   }
    4893             : 
    4894             :   // Tests for strict mode.
    4895          45 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4896             :     std::string strict_body =
    4897          40 :         "'use strict'; " + std::string(const_decl[i].first);
    4898          20 :     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
    4899          40 :     InterpreterTester tester(isolate, source.c_str());
    4900             :     auto callable = tester.GetCallable<>();
    4901             : 
    4902             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4903          40 :     CHECK(return_value->SameValue(*const_decl[i].second));
    4904             :   }
    4905           5 : }
    4906             : 
    4907       26661 : TEST(InterpreterConstInLookupContextChain) {
    4908          10 :   HandleAndZoneScope handles;
    4909             :   Isolate* isolate = handles.main_isolate();
    4910             : 
    4911             :   const char* prologue =
    4912             :       "function OuterMost() {\n"
    4913             :       "  const outerConst = 10;\n"
    4914             :       "  let outerLet = 20;\n"
    4915             :       "  function Outer() {\n"
    4916             :       "    function Inner() {\n"
    4917             :       "      this.innerFunc = function() { ";
    4918             :   const char* epilogue =
    4919             :       "      }\n"
    4920             :       "    }\n"
    4921             :       "    this.getInnerFunc ="
    4922             :       "         function() {return new Inner().innerFunc;}\n"
    4923             :       "  }\n"
    4924             :       "  this.getOuterFunc ="
    4925             :       "     function() {return new Outer().getInnerFunc();}"
    4926             :       "}\n"
    4927             :       "var f = new OuterMost().getOuterFunc();\n"
    4928             :       "f();\n";
    4929             :   std::pair<const char*, Handle<Object>> const_decl[] = {
    4930             :       {"return outerConst;", handle(Smi::FromInt(10), isolate)},
    4931             :       {"return outerLet;", handle(Smi::FromInt(20), isolate)},
    4932             :       {"outerLet = 30; return outerLet;", handle(Smi::FromInt(30), isolate)},
    4933             :       {"var outerLet = 40; return outerLet;",
    4934             :        handle(Smi::FromInt(40), isolate)},
    4935             :       {"var outerConst = 50; return outerConst;",
    4936             :        handle(Smi::FromInt(50), isolate)},
    4937             :       {"try { outerConst = 30 } catch(e) { return -1; }",
    4938             :        handle(Smi::FromInt(-1), isolate)}};
    4939             : 
    4940          65 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4941         120 :     std::string script = std::string(prologue) +
    4942             :                          std::string(const_decl[i].first) +
    4943          90 :                          std::string(epilogue);
    4944          60 :     InterpreterTester tester(isolate, script.c_str(), "*");
    4945             :     auto callable = tester.GetCallable<>();
    4946             : 
    4947             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    4948          60 :     CHECK(return_value->SameValue(*const_decl[i].second));
    4949             :   }
    4950           5 : }
    4951             : 
    4952       26661 : TEST(InterpreterIllegalConstDeclaration) {
    4953          10 :   HandleAndZoneScope handles;
    4954             :   Isolate* isolate = handles.main_isolate();
    4955             : 
    4956             :   std::pair<const char*, const char*> const_decl[] = {
    4957             :       {"const x = x = 10 + 3; return x;",
    4958             :        "Uncaught ReferenceError: Cannot access 'x' before initialization"},
    4959             :       {"const x = 10; x = 20; return x;",
    4960             :        "Uncaught TypeError: Assignment to constant variable."},
    4961             :       {"const x = 10; { x = 20; } return x;",
    4962             :        "Uncaught TypeError: Assignment to constant variable."},
    4963             :       {"const x = 10; eval('x = 20;'); return x;",
    4964             :        "Uncaught TypeError: Assignment to constant variable."},
    4965             :       {"let x = x + 10; return x;",
    4966             :        "Uncaught ReferenceError: Cannot access 'x' before initialization"},
    4967             :       {"'use strict'; (function f1() { f1 = 123; })() ",
    4968             :        "Uncaught TypeError: Assignment to constant variable."},
    4969           5 :   };
    4970             : 
    4971             :   // Tests for sloppy mode.
    4972          65 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4973          30 :     std::string source(InterpreterTester::SourceForBody(const_decl[i].first));
    4974          60 :     InterpreterTester tester(isolate, source.c_str());
    4975          60 :     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
    4976          30 :     v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
    4977          90 :     CHECK(
    4978             :         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
    4979             :             .FromJust());
    4980             :   }
    4981             : 
    4982             :   // Tests for strict mode.
    4983          65 :   for (size_t i = 0; i < arraysize(const_decl); i++) {
    4984             :     std::string strict_body =
    4985          60 :         "'use strict'; " + std::string(const_decl[i].first);
    4986          30 :     std::string source(InterpreterTester::SourceForBody(strict_body.c_str()));
    4987          60 :     InterpreterTester tester(isolate, source.c_str());
    4988          60 :     v8::Local<v8::String> message = tester.CheckThrowsReturnMessage()->Get();
    4989          30 :     v8::Local<v8::String> expected_string = v8_str(const_decl[i].second);
    4990          90 :     CHECK(
    4991             :         message->Equals(CcTest::isolate()->GetCurrentContext(), expected_string)
    4992             :             .FromJust());
    4993             :   }
    4994           5 : }
    4995             : 
    4996       26661 : TEST(InterpreterGenerators) {
    4997          10 :   HandleAndZoneScope handles;
    4998             :   Isolate* isolate = handles.main_isolate();
    4999             :   Factory* factory = isolate->factory();
    5000             : 
    5001             :   std::pair<const char*, Handle<Object>> tests[] = {
    5002             :       {"function* f() { }; return f().next().value",
    5003             :        factory->undefined_value()},
    5004             :       {"function* f() { yield 42 }; return f().next().value",
    5005          10 :        factory->NewNumberFromInt(42)},
    5006             :       {"function* f() { for (let x of [42]) yield x}; return f().next().value",
    5007          10 :        factory->NewNumberFromInt(42)},
    5008             :   };
    5009             : 
    5010          35 :   for (size_t i = 0; i < arraysize(tests); i++) {
    5011          15 :     std::string source(InterpreterTester::SourceForBody(tests[i].first));
    5012          30 :     InterpreterTester tester(isolate, source.c_str());
    5013             :     auto callable = tester.GetCallable<>();
    5014             : 
    5015             :     Handle<i::Object> return_value = callable().ToHandleChecked();
    5016          30 :     CHECK(return_value->SameValue(*tests[i].second));
    5017             :   }
    5018           5 : }
    5019             : 
    5020             : #ifndef V8_TARGET_ARCH_ARM
    5021       26661 : TEST(InterpreterWithNativeStack) {
    5022           5 :   i::FLAG_interpreted_frames_native_stack = true;
    5023             : 
    5024          10 :   HandleAndZoneScope handles;
    5025             :   i::Isolate* isolate = handles.main_isolate();
    5026             : 
    5027             :   const char* source_text =
    5028             :       "function testInterpreterWithNativeStack(a,b) { return a + b };";
    5029             : 
    5030             :   i::Handle<i::Object> o = v8::Utils::OpenHandle(*v8_compile(source_text));
    5031             :   i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o);
    5032             : 
    5033           5 :   CHECK(f->shared()->HasBytecodeArray());
    5034           5 :   i::Code code = f->shared()->GetCode();
    5035             :   i::Handle<i::Code> interpreter_entry_trampoline =
    5036           5 :       BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
    5037             : 
    5038           5 :   CHECK(code->IsCode());
    5039           5 :   CHECK(code->is_interpreter_trampoline_builtin());
    5040           5 :   CHECK_NE(code->address(), interpreter_entry_trampoline->address());
    5041           5 : }
    5042             : #endif  // V8_TARGET_ARCH_ARM
    5043             : 
    5044       26661 : TEST(InterpreterGetBytecodeHandler) {
    5045          10 :   HandleAndZoneScope handles;
    5046             :   Isolate* isolate = handles.main_isolate();
    5047             :   Interpreter* interpreter = isolate->interpreter();
    5048             : 
    5049             :   // Test that single-width bytecode handlers deserializer correctly.
    5050             :   Code wide_handler =
    5051           5 :       interpreter->GetBytecodeHandler(Bytecode::kWide, OperandScale::kSingle);
    5052             : 
    5053           5 :   CHECK_EQ(wide_handler->builtin_index(), Builtins::kWideHandler);
    5054             : 
    5055             :   Code add_handler =
    5056           5 :       interpreter->GetBytecodeHandler(Bytecode::kAdd, OperandScale::kSingle);
    5057             : 
    5058           5 :   CHECK_EQ(add_handler->builtin_index(), Builtins::kAddHandler);
    5059             : 
    5060             :   // Test that double-width bytecode handlers deserializer correctly, including
    5061             :   // an illegal bytecode handler since there is no Wide.Wide handler.
    5062             :   Code wide_wide_handler =
    5063           5 :       interpreter->GetBytecodeHandler(Bytecode::kWide, OperandScale::kDouble);
    5064             : 
    5065           5 :   CHECK_EQ(wide_wide_handler->builtin_index(), Builtins::kIllegalHandler);
    5066             : 
    5067             :   Code add_wide_handler =
    5068           5 :       interpreter->GetBytecodeHandler(Bytecode::kAdd, OperandScale::kDouble);
    5069             : 
    5070           5 :   CHECK_EQ(add_wide_handler->builtin_index(), Builtins::kAddWideHandler);
    5071           5 : }
    5072             : 
    5073       26661 : TEST(InterpreterCollectSourcePositions) {
    5074           5 :   FLAG_enable_lazy_source_positions = true;
    5075          10 :   HandleAndZoneScope handles;
    5076             :   Isolate* isolate = handles.main_isolate();
    5077             : 
    5078             :   const char* source =
    5079             :       "(function () {\n"
    5080             :       "  return 1;\n"
    5081             :       "})";
    5082             : 
    5083             :   Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
    5084             :       *v8::Local<v8::Function>::Cast(CompileRun(source))));
    5085             : 
    5086             :   Handle<SharedFunctionInfo> sfi = handle(function->shared(), isolate);
    5087             :   Handle<BytecodeArray> bytecode_array =
    5088          10 :       handle(sfi->GetBytecodeArray(), isolate);
    5089           5 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5090             : 
    5091           5 :   Compiler::CollectSourcePositions(isolate, sfi);
    5092             : 
    5093           5 :   ByteArray source_position_table = bytecode_array->SourcePositionTable();
    5094           5 :   CHECK(bytecode_array->HasSourcePositionTable());
    5095           5 :   CHECK_GT(source_position_table->length(), 0);
    5096           5 : }
    5097             : 
    5098       26661 : TEST(InterpreterCollectSourcePositions_StackOverflow) {
    5099           5 :   FLAG_enable_lazy_source_positions = true;
    5100          10 :   HandleAndZoneScope handles;
    5101             :   Isolate* isolate = handles.main_isolate();
    5102             : 
    5103             :   const char* source =
    5104             :       "(function () {\n"
    5105             :       "  return 1;\n"
    5106             :       "})";
    5107             : 
    5108             :   Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
    5109             :       *v8::Local<v8::Function>::Cast(CompileRun(source))));
    5110             : 
    5111             :   Handle<SharedFunctionInfo> sfi = handle(function->shared(), isolate);
    5112             :   Handle<BytecodeArray> bytecode_array =
    5113          10 :       handle(sfi->GetBytecodeArray(), isolate);
    5114           5 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5115             : 
    5116             :   // Make the stack limit the same as the current position so recompilation
    5117             :   // overflows.
    5118             :   uint64_t previous_limit = isolate->stack_guard()->real_climit();
    5119          10 :   isolate->stack_guard()->SetStackLimit(GetCurrentStackPosition());
    5120           5 :   Compiler::CollectSourcePositions(isolate, sfi);
    5121             :   // Stack overflowed so source position table can be returned but is empty.
    5122           5 :   ByteArray source_position_table = bytecode_array->SourcePositionTable();
    5123           5 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5124           5 :   CHECK_EQ(source_position_table->length(), 0);
    5125             : 
    5126             :   // Reset the stack limit and try again.
    5127           5 :   isolate->stack_guard()->SetStackLimit(previous_limit);
    5128           5 :   Compiler::CollectSourcePositions(isolate, sfi);
    5129           5 :   source_position_table = bytecode_array->SourcePositionTable();
    5130           5 :   CHECK(bytecode_array->HasSourcePositionTable());
    5131           5 :   CHECK_GT(source_position_table->length(), 0);
    5132           5 : }
    5133             : 
    5134             : // TODO(v8:8510): When an exception is thrown, the top frame still has its
    5135             : // source positions collected. Re-enable this test when that is fixed.
    5136       26656 : DISABLED_TEST(InterpreterCollectSourcePositions_ThrowFrom1stFrame) {
    5137           0 :   FLAG_enable_lazy_source_positions = true;
    5138           0 :   HandleAndZoneScope handles;
    5139             :   Isolate* isolate = handles.main_isolate();
    5140             : 
    5141             :   const char* source =
    5142             :       R"javascript(
    5143             :       (function () {
    5144             :         throw new Error();
    5145             :       });
    5146             :       )javascript";
    5147             : 
    5148             :   Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
    5149             :       *v8::Local<v8::Function>::Cast(CompileRun(source))));
    5150             : 
    5151             :   Handle<SharedFunctionInfo> sfi = handle(function->shared(), isolate);
    5152             :   // This is the bytecode for the top-level iife.
    5153             :   Handle<BytecodeArray> bytecode_array =
    5154           0 :       handle(sfi->GetBytecodeArray(), isolate);
    5155           0 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5156             : 
    5157             :   {
    5158           0 :     v8::TryCatch try_catch(CcTest::isolate());
    5159             :     MaybeHandle<Object> result = Execution::Call(
    5160             :         isolate, function, ReadOnlyRoots(isolate).undefined_value_handle(), 0,
    5161           0 :         nullptr);
    5162           0 :     CHECK(result.is_null());
    5163           0 :     CHECK(try_catch.HasCaught());
    5164             :   }
    5165             : 
    5166             :   // The exception was caught but source positions were not retrieved from it so
    5167             :   // there should be no source position table.
    5168           0 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5169           0 : }
    5170             : 
    5171       26661 : TEST(InterpreterCollectSourcePositions_ThrowFrom2ndFrame) {
    5172           5 :   FLAG_enable_lazy_source_positions = true;
    5173          10 :   HandleAndZoneScope handles;
    5174             :   Isolate* isolate = handles.main_isolate();
    5175             : 
    5176             :   const char* source =
    5177             :       R"javascript(
    5178             :       (function () {
    5179             :         (function () {
    5180             :           throw new Error();
    5181             :         })();
    5182             :       });
    5183             :       )javascript";
    5184             : 
    5185             :   Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
    5186             :       *v8::Local<v8::Function>::Cast(CompileRun(source))));
    5187             : 
    5188             :   Handle<SharedFunctionInfo> sfi = handle(function->shared(), isolate);
    5189             :   // This is the bytecode for the top-level iife.
    5190             :   Handle<BytecodeArray> bytecode_array =
    5191          10 :       handle(sfi->GetBytecodeArray(), isolate);
    5192           5 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5193             : 
    5194             :   {
    5195          10 :     v8::TryCatch try_catch(CcTest::isolate());
    5196             :     MaybeHandle<Object> result = Execution::Call(
    5197             :         isolate, function, ReadOnlyRoots(isolate).undefined_value_handle(), 0,
    5198           5 :         nullptr);
    5199           5 :     CHECK(result.is_null());
    5200           5 :     CHECK(try_catch.HasCaught());
    5201             :   }
    5202             : 
    5203             :   // The exception was caught but source positions were not retrieved from it so
    5204             :   // there should be no source position table.
    5205           5 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5206           5 : }
    5207             : 
    5208             : namespace {
    5209             : 
    5210           5 : void CheckStringEqual(const char* expected_ptr, Handle<Object> actual_handle) {
    5211             :   v8::String::Utf8Value utf8(
    5212             :       v8::Isolate::GetCurrent(),
    5213          10 :       v8::Utils::ToLocal(Handle<String>::cast(actual_handle)));
    5214           5 :   std::string expected(expected_ptr);
    5215           5 :   std::string actual(*utf8);
    5216           5 :   CHECK_EQ(expected, actual);
    5217           5 : }
    5218             : 
    5219             : }  // namespace
    5220             : 
    5221       26661 : TEST(InterpreterCollectSourcePositions_GenerateStackTrace) {
    5222           5 :   FLAG_enable_lazy_source_positions = true;
    5223          10 :   HandleAndZoneScope handles;
    5224             :   Isolate* isolate = handles.main_isolate();
    5225             : 
    5226             :   const char* source =
    5227             :       R"javascript(
    5228             :       (function () {
    5229             :         try {
    5230             :           throw new Error();
    5231             :         } catch (e) {
    5232             :           return e.stack;
    5233             :         }
    5234             :       });
    5235             :       )javascript";
    5236             : 
    5237             :   Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle(
    5238             :       *v8::Local<v8::Function>::Cast(CompileRun(source))));
    5239             : 
    5240             :   Handle<SharedFunctionInfo> sfi = handle(function->shared(), isolate);
    5241             :   Handle<BytecodeArray> bytecode_array =
    5242          10 :       handle(sfi->GetBytecodeArray(), isolate);
    5243           5 :   CHECK(!bytecode_array->HasSourcePositionTable());
    5244             : 
    5245             :   {
    5246             :     Handle<Object> result =
    5247          10 :         Execution::Call(isolate, function,
    5248             :                         ReadOnlyRoots(isolate).undefined_value_handle(), 0,
    5249           5 :                         nullptr)
    5250           5 :             .ToHandleChecked();
    5251           5 :     CheckStringEqual("Error\n    at <anonymous>:4:17", result);
    5252             :   }
    5253             : 
    5254           5 :   CHECK(bytecode_array->HasSourcePositionTable());
    5255           5 :   ByteArray source_position_table = bytecode_array->SourcePositionTable();
    5256           5 :   CHECK_GT(source_position_table->length(), 0);
    5257           5 : }
    5258             : 
    5259             : }  // namespace interpreter
    5260             : }  // namespace internal
    5261       79968 : }  // namespace v8

Generated by: LCOV version 1.10