LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1880 1894 99.3 %
Date: 2017-04-26 Functions: 302 306 98.7 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/interpreter/interpreter-generator.h"
       6             : 
       7             : #include <array>
       8             : #include <tuple>
       9             : 
      10             : #include "src/builtins/builtins-arguments-gen.h"
      11             : #include "src/builtins/builtins-constructor-gen.h"
      12             : #include "src/builtins/builtins-forin-gen.h"
      13             : #include "src/code-events.h"
      14             : #include "src/code-factory.h"
      15             : #include "src/factory.h"
      16             : #include "src/ic/accessor-assembler.h"
      17             : #include "src/ic/binary-op-assembler.h"
      18             : #include "src/interpreter/bytecode-flags.h"
      19             : #include "src/interpreter/bytecodes.h"
      20             : #include "src/interpreter/interpreter-assembler.h"
      21             : #include "src/interpreter/interpreter-intrinsics-generator.h"
      22             : #include "src/objects-inl.h"
      23             : 
      24             : namespace v8 {
      25             : namespace internal {
      26             : namespace interpreter {
      27             : 
      28             : namespace {
      29             : 
      30             : using compiler::Node;
      31             : typedef CodeStubAssembler::Label Label;
      32             : typedef CodeStubAssembler::Variable Variable;
      33             : 
      34             : #define IGNITION_HANDLER(Name, BaseAssembler)                         \
      35             :   class Name##Assembler : public BaseAssembler {                      \
      36             :    public:                                                            \
      37             :     explicit Name##Assembler(compiler::CodeAssemblerState* state,     \
      38             :                              Bytecode bytecode, OperandScale scale)   \
      39             :         : BaseAssembler(state, bytecode, scale) {}                    \
      40             :     static void Generate(compiler::CodeAssemblerState* state,         \
      41             :                          OperandScale scale);                         \
      42             :                                                                       \
      43             :    private:                                                           \
      44             :     void GenerateImpl();                                              \
      45             :     DISALLOW_COPY_AND_ASSIGN(Name##Assembler);                        \
      46             :   };                                                                  \
      47             :   void Name##Assembler::Generate(compiler::CodeAssemblerState* state, \
      48             :                                  OperandScale scale) {                \
      49             :     Name##Assembler assembler(state, Bytecode::k##Name, scale);       \
      50             :     state->SetInitialDebugInformation(#Name, __FILE__, __LINE__);     \
      51             :     assembler.GenerateImpl();                                         \
      52             :   }                                                                   \
      53             :   void Name##Assembler::GenerateImpl()
      54             : 
      55             : // LdaZero
      56             : //
      57             : // Load literal '0' into the accumulator.
      58          86 : IGNITION_HANDLER(LdaZero, InterpreterAssembler) {
      59          43 :   Node* zero_value = NumberConstant(0.0);
      60          43 :   SetAccumulator(zero_value);
      61          43 :   Dispatch();
      62          43 : }
      63             : 
      64             : // LdaSmi <imm>
      65             : //
      66             : // Load an integer literal into the accumulator as a Smi.
      67         258 : IGNITION_HANDLER(LdaSmi, InterpreterAssembler) {
      68         129 :   Node* smi_int = BytecodeOperandImmSmi(0);
      69         129 :   SetAccumulator(smi_int);
      70         129 :   Dispatch();
      71         129 : }
      72             : 
      73             : // LdaConstant <idx>
      74             : //
      75             : // Load constant literal at |idx| in the constant pool into the accumulator.
      76         258 : IGNITION_HANDLER(LdaConstant, InterpreterAssembler) {
      77         129 :   Node* index = BytecodeOperandIdx(0);
      78         129 :   Node* constant = LoadConstantPoolEntry(index);
      79         129 :   SetAccumulator(constant);
      80         129 :   Dispatch();
      81         129 : }
      82             : 
      83             : // LdaUndefined
      84             : //
      85             : // Load Undefined into the accumulator.
      86          86 : IGNITION_HANDLER(LdaUndefined, InterpreterAssembler) {
      87          43 :   SetAccumulator(UndefinedConstant());
      88          43 :   Dispatch();
      89          43 : }
      90             : 
      91             : // LdaNull
      92             : //
      93             : // Load Null into the accumulator.
      94          86 : IGNITION_HANDLER(LdaNull, InterpreterAssembler) {
      95          43 :   SetAccumulator(NullConstant());
      96          43 :   Dispatch();
      97          43 : }
      98             : 
      99             : // LdaTheHole
     100             : //
     101             : // Load TheHole into the accumulator.
     102          86 : IGNITION_HANDLER(LdaTheHole, InterpreterAssembler) {
     103          43 :   SetAccumulator(TheHoleConstant());
     104          43 :   Dispatch();
     105          43 : }
     106             : 
     107             : // LdaTrue
     108             : //
     109             : // Load True into the accumulator.
     110          86 : IGNITION_HANDLER(LdaTrue, InterpreterAssembler) {
     111          43 :   SetAccumulator(TrueConstant());
     112          43 :   Dispatch();
     113          43 : }
     114             : 
     115             : // LdaFalse
     116             : //
     117             : // Load False into the accumulator.
     118          86 : IGNITION_HANDLER(LdaFalse, InterpreterAssembler) {
     119          43 :   SetAccumulator(FalseConstant());
     120          43 :   Dispatch();
     121          43 : }
     122             : 
     123             : // Ldar <src>
     124             : //
     125             : // Load accumulator with value from register <src>.
     126         258 : IGNITION_HANDLER(Ldar, InterpreterAssembler) {
     127         129 :   Node* reg_index = BytecodeOperandReg(0);
     128         129 :   Node* value = LoadRegister(reg_index);
     129         129 :   SetAccumulator(value);
     130         129 :   Dispatch();
     131         129 : }
     132             : 
     133             : // Star <dst>
     134             : //
     135             : // Store accumulator to register <dst>.
     136         258 : IGNITION_HANDLER(Star, InterpreterAssembler) {
     137         129 :   Node* reg_index = BytecodeOperandReg(0);
     138         129 :   Node* accumulator = GetAccumulator();
     139         129 :   StoreRegister(accumulator, reg_index);
     140         129 :   Dispatch();
     141         129 : }
     142             : 
     143             : // Mov <src> <dst>
     144             : //
     145             : // Stores the value of register <src> to register <dst>.
     146         258 : IGNITION_HANDLER(Mov, InterpreterAssembler) {
     147         129 :   Node* src_index = BytecodeOperandReg(0);
     148         129 :   Node* src_value = LoadRegister(src_index);
     149         129 :   Node* dst_index = BytecodeOperandReg(1);
     150         129 :   StoreRegister(src_value, dst_index);
     151         129 :   Dispatch();
     152         129 : }
     153             : 
     154         516 : class InterpreterLoadGlobalAssembler : public InterpreterAssembler {
     155             :  public:
     156             :   InterpreterLoadGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
     157             :                                  OperandScale operand_scale)
     158         516 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     159             : 
     160         516 :   void LdaGlobal(int slot_operand_index, int name_operand_index,
     161             :                  TypeofMode typeof_mode) {
     162             :     // Must be kept in sync with AccessorAssembler::LoadGlobalIC.
     163             : 
     164             :     // Load the global via the LoadGlobalIC.
     165         516 :     Node* feedback_vector = LoadFeedbackVector();
     166         516 :     Node* feedback_slot = BytecodeOperandIdx(slot_operand_index);
     167             : 
     168             :     AccessorAssembler accessor_asm(state());
     169             : 
     170        1032 :     Label try_handler(this, Label::kDeferred), miss(this, Label::kDeferred);
     171             : 
     172             :     // Fast path without frame construction for the data case.
     173             :     {
     174             :       Label done(this);
     175        1032 :       Variable var_result(this, MachineRepresentation::kTagged);
     176         516 :       ExitPoint exit_point(this, &done, &var_result);
     177             : 
     178             :       accessor_asm.LoadGlobalIC_TryPropertyCellCase(
     179             :           feedback_vector, feedback_slot, &exit_point, &try_handler, &miss,
     180         516 :           CodeStubAssembler::INTPTR_PARAMETERS);
     181             : 
     182         516 :       Bind(&done);
     183         516 :       SetAccumulator(var_result.value());
     184        1032 :       Dispatch();
     185             :     }
     186             : 
     187             :     // Slow path with frame construction.
     188             :     {
     189             :       Label done(this);
     190        1032 :       Variable var_result(this, MachineRepresentation::kTagged);
     191             :       ExitPoint exit_point(this, &done, &var_result);
     192             : 
     193         516 :       Bind(&try_handler);
     194             :       {
     195         516 :         Node* context = GetContext();
     196         516 :         Node* smi_slot = SmiTag(feedback_slot);
     197         516 :         Node* name_index = BytecodeOperandIdx(name_operand_index);
     198         516 :         Node* name = LoadConstantPoolEntry(name_index);
     199             : 
     200             :         AccessorAssembler::LoadICParameters params(context, nullptr, name,
     201             :                                                    smi_slot, feedback_vector);
     202             :         accessor_asm.LoadGlobalIC_TryHandlerCase(&params, typeof_mode,
     203         516 :                                                  &exit_point, &miss);
     204             :       }
     205             : 
     206         516 :       Bind(&miss);
     207             :       {
     208         516 :         Node* context = GetContext();
     209         516 :         Node* smi_slot = SmiTag(feedback_slot);
     210         516 :         Node* name_index = BytecodeOperandIdx(name_operand_index);
     211         516 :         Node* name = LoadConstantPoolEntry(name_index);
     212             : 
     213             :         AccessorAssembler::LoadICParameters params(context, nullptr, name,
     214             :                                                    smi_slot, feedback_vector);
     215         516 :         accessor_asm.LoadGlobalIC_MissCase(&params, &exit_point);
     216             :       }
     217             : 
     218         516 :       Bind(&done);
     219             :       {
     220         516 :         SetAccumulator(var_result.value());
     221         516 :         Dispatch();
     222         516 :       }
     223             :     }
     224         516 :   }
     225             : };
     226             : 
     227             : // LdaGlobal <name_index> <slot>
     228             : //
     229             : // Load the global with name in constant pool entry <name_index> into the
     230             : // accumulator using FeedBackVector slot <slot> outside of a typeof.
     231         387 : IGNITION_HANDLER(LdaGlobal, InterpreterLoadGlobalAssembler) {
     232             :   static const int kNameOperandIndex = 0;
     233             :   static const int kSlotOperandIndex = 1;
     234             : 
     235         129 :   LdaGlobal(kSlotOperandIndex, kNameOperandIndex, NOT_INSIDE_TYPEOF);
     236             : }
     237             : 
     238             : // LdaGlobalInsideTypeof <name_index> <slot>
     239             : //
     240             : // Load the global with name in constant pool entry <name_index> into the
     241             : // accumulator using FeedBackVector slot <slot> inside of a typeof.
     242         387 : IGNITION_HANDLER(LdaGlobalInsideTypeof, InterpreterLoadGlobalAssembler) {
     243             :   static const int kNameOperandIndex = 0;
     244             :   static const int kSlotOperandIndex = 1;
     245             : 
     246         129 :   LdaGlobal(kSlotOperandIndex, kNameOperandIndex, INSIDE_TYPEOF);
     247             : }
     248             : 
     249         258 : class InterpreterStoreGlobalAssembler : public InterpreterAssembler {
     250             :  public:
     251             :   InterpreterStoreGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
     252             :                                   OperandScale operand_scale)
     253         258 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     254             : 
     255         258 :   void StaGlobal(Callable ic) {
     256             :     // Get the global object.
     257         258 :     Node* context = GetContext();
     258         258 :     Node* native_context = LoadNativeContext(context);
     259         258 :     Node* global = LoadContextElement(native_context, Context::EXTENSION_INDEX);
     260             : 
     261             :     // Store the global via the StoreIC.
     262         258 :     Node* code_target = HeapConstant(ic.code());
     263         258 :     Node* constant_index = BytecodeOperandIdx(0);
     264         258 :     Node* name = LoadConstantPoolEntry(constant_index);
     265         258 :     Node* value = GetAccumulator();
     266         258 :     Node* raw_slot = BytecodeOperandIdx(1);
     267         258 :     Node* smi_slot = SmiTag(raw_slot);
     268         258 :     Node* feedback_vector = LoadFeedbackVector();
     269             :     CallStub(ic.descriptor(), code_target, context, global, name, value,
     270         258 :              smi_slot, feedback_vector);
     271         258 :     Dispatch();
     272         258 :   }
     273             : };
     274             : 
     275             : // StaGlobalSloppy <name_index> <slot>
     276             : //
     277             : // Store the value in the accumulator into the global with name in constant pool
     278             : // entry <name_index> using FeedBackVector slot <slot> in sloppy mode.
     279         516 : IGNITION_HANDLER(StaGlobalSloppy, InterpreterStoreGlobalAssembler) {
     280         129 :   Callable ic = CodeFactory::StoreGlobalICInOptimizedCode(isolate(), SLOPPY);
     281         129 :   StaGlobal(ic);
     282         129 : }
     283             : 
     284             : // StaGlobalStrict <name_index> <slot>
     285             : //
     286             : // Store the value in the accumulator into the global with name in constant pool
     287             : // entry <name_index> using FeedBackVector slot <slot> in strict mode.
     288         516 : IGNITION_HANDLER(StaGlobalStrict, InterpreterStoreGlobalAssembler) {
     289         129 :   Callable ic = CodeFactory::StoreGlobalICInOptimizedCode(isolate(), STRICT);
     290         129 :   StaGlobal(ic);
     291         129 : }
     292             : 
     293             : // LdaContextSlot <context> <slot_index> <depth>
     294             : //
     295             : // Load the object in |slot_index| of the context at |depth| in the context
     296             : // chain starting at |context| into the accumulator.
     297         258 : IGNITION_HANDLER(LdaContextSlot, InterpreterAssembler) {
     298         129 :   Node* reg_index = BytecodeOperandReg(0);
     299         129 :   Node* context = LoadRegister(reg_index);
     300         129 :   Node* slot_index = BytecodeOperandIdx(1);
     301         129 :   Node* depth = BytecodeOperandUImm(2);
     302         129 :   Node* slot_context = GetContextAtDepth(context, depth);
     303         129 :   Node* result = LoadContextElement(slot_context, slot_index);
     304         129 :   SetAccumulator(result);
     305         129 :   Dispatch();
     306         129 : }
     307             : 
     308             : // LdaImmutableContextSlot <context> <slot_index> <depth>
     309             : //
     310             : // Load the object in |slot_index| of the context at |depth| in the context
     311             : // chain starting at |context| into the accumulator.
     312           0 : IGNITION_HANDLER(LdaImmutableContextSlot, InterpreterAssembler) {
     313             :   // Same as LdaContextSlot, should never be called.
     314           0 :   UNREACHABLE();
     315             : }
     316             : 
     317             : // LdaCurrentContextSlot <slot_index>
     318             : //
     319             : // Load the object in |slot_index| of the current context into the accumulator.
     320         258 : IGNITION_HANDLER(LdaCurrentContextSlot, InterpreterAssembler) {
     321         129 :   Node* slot_index = BytecodeOperandIdx(0);
     322         129 :   Node* slot_context = GetContext();
     323         129 :   Node* result = LoadContextElement(slot_context, slot_index);
     324         129 :   SetAccumulator(result);
     325         129 :   Dispatch();
     326         129 : }
     327             : 
     328             : // LdaImmutableCurrentContextSlot <slot_index>
     329             : //
     330             : // Load the object in |slot_index| of the current context into the accumulator.
     331           0 : IGNITION_HANDLER(LdaImmutableCurrentContextSlot, InterpreterAssembler) {
     332             :   // Same as LdaCurrentContextSlot, should never be called.
     333           0 :   UNREACHABLE();
     334             : }
     335             : 
     336             : // StaContextSlot <context> <slot_index> <depth>
     337             : //
     338             : // Stores the object in the accumulator into |slot_index| of the context at
     339             : // |depth| in the context chain starting at |context|.
     340         258 : IGNITION_HANDLER(StaContextSlot, InterpreterAssembler) {
     341         129 :   Node* value = GetAccumulator();
     342         129 :   Node* reg_index = BytecodeOperandReg(0);
     343         129 :   Node* context = LoadRegister(reg_index);
     344         129 :   Node* slot_index = BytecodeOperandIdx(1);
     345         129 :   Node* depth = BytecodeOperandUImm(2);
     346         129 :   Node* slot_context = GetContextAtDepth(context, depth);
     347         129 :   StoreContextElement(slot_context, slot_index, value);
     348         129 :   Dispatch();
     349         129 : }
     350             : 
     351             : // StaCurrentContextSlot <slot_index>
     352             : //
     353             : // Stores the object in the accumulator into |slot_index| of the current
     354             : // context.
     355         258 : IGNITION_HANDLER(StaCurrentContextSlot, InterpreterAssembler) {
     356         129 :   Node* value = GetAccumulator();
     357         129 :   Node* slot_index = BytecodeOperandIdx(0);
     358         129 :   Node* slot_context = GetContext();
     359         129 :   StoreContextElement(slot_context, slot_index, value);
     360         129 :   Dispatch();
     361         129 : }
     362             : 
     363             : // LdaLookupSlot <name_index>
     364             : //
     365             : // Lookup the object with the name in constant pool entry |name_index|
     366             : // dynamically.
     367         258 : IGNITION_HANDLER(LdaLookupSlot, InterpreterAssembler) {
     368         129 :   Node* name_index = BytecodeOperandIdx(0);
     369         129 :   Node* name = LoadConstantPoolEntry(name_index);
     370         129 :   Node* context = GetContext();
     371         129 :   Node* result = CallRuntime(Runtime::kLoadLookupSlot, context, name);
     372         129 :   SetAccumulator(result);
     373         129 :   Dispatch();
     374         129 : }
     375             : 
     376             : // LdaLookupSlotInsideTypeof <name_index>
     377             : //
     378             : // Lookup the object with the name in constant pool entry |name_index|
     379             : // dynamically without causing a NoReferenceError.
     380         258 : IGNITION_HANDLER(LdaLookupSlotInsideTypeof, InterpreterAssembler) {
     381         129 :   Node* name_index = BytecodeOperandIdx(0);
     382         129 :   Node* name = LoadConstantPoolEntry(name_index);
     383         129 :   Node* context = GetContext();
     384             :   Node* result =
     385         129 :       CallRuntime(Runtime::kLoadLookupSlotInsideTypeof, context, name);
     386         129 :   SetAccumulator(result);
     387         129 :   Dispatch();
     388         129 : }
     389             : 
     390         258 : class InterpreterLookupContextSlotAssembler : public InterpreterAssembler {
     391             :  public:
     392             :   InterpreterLookupContextSlotAssembler(CodeAssemblerState* state,
     393             :                                         Bytecode bytecode,
     394             :                                         OperandScale operand_scale)
     395         258 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     396             : 
     397         258 :   void LookupContextSlot(Runtime::FunctionId function_id) {
     398         258 :     Node* context = GetContext();
     399         258 :     Node* name_index = BytecodeOperandIdx(0);
     400         258 :     Node* slot_index = BytecodeOperandIdx(1);
     401         258 :     Node* depth = BytecodeOperandUImm(2);
     402             : 
     403         258 :     Label slowpath(this, Label::kDeferred);
     404             : 
     405             :     // Check for context extensions to allow the fast path.
     406         258 :     GotoIfHasContextExtensionUpToDepth(context, depth, &slowpath);
     407             : 
     408             :     // Fast path does a normal load context.
     409             :     {
     410         258 :       Node* slot_context = GetContextAtDepth(context, depth);
     411         258 :       Node* result = LoadContextElement(slot_context, slot_index);
     412         258 :       SetAccumulator(result);
     413         258 :       Dispatch();
     414             :     }
     415             : 
     416             :     // Slow path when we have to call out to the runtime.
     417         258 :     Bind(&slowpath);
     418             :     {
     419         258 :       Node* name = LoadConstantPoolEntry(name_index);
     420         258 :       Node* result = CallRuntime(function_id, context, name);
     421         258 :       SetAccumulator(result);
     422         258 :       Dispatch();
     423         258 :     }
     424         258 :   }
     425             : };
     426             : 
     427             : // LdaLookupSlot <name_index>
     428             : //
     429             : // Lookup the object with the name in constant pool entry |name_index|
     430             : // dynamically.
     431         387 : IGNITION_HANDLER(LdaLookupContextSlot, InterpreterLookupContextSlotAssembler) {
     432         129 :   LookupContextSlot(Runtime::kLoadLookupSlot);
     433             : }
     434             : 
     435             : // LdaLookupSlotInsideTypeof <name_index>
     436             : //
     437             : // Lookup the object with the name in constant pool entry |name_index|
     438             : // dynamically without causing a NoReferenceError.
     439         387 : IGNITION_HANDLER(LdaLookupContextSlotInsideTypeof,
     440             :                  InterpreterLookupContextSlotAssembler) {
     441         129 :   LookupContextSlot(Runtime::kLoadLookupSlotInsideTypeof);
     442             : }
     443             : 
     444             : class InterpreterLookupGlobalAssembler : public InterpreterLoadGlobalAssembler {
     445             :  public:
     446             :   InterpreterLookupGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
     447             :                                    OperandScale operand_scale)
     448             :       : InterpreterLoadGlobalAssembler(state, bytecode, operand_scale) {}
     449             : 
     450         258 :   void LookupGlobalSlot(Runtime::FunctionId function_id) {
     451         258 :     Node* context = GetContext();
     452         258 :     Node* depth = BytecodeOperandUImm(2);
     453             : 
     454         258 :     Label slowpath(this, Label::kDeferred);
     455             : 
     456             :     // Check for context extensions to allow the fast path
     457         258 :     GotoIfHasContextExtensionUpToDepth(context, depth, &slowpath);
     458             : 
     459             :     // Fast path does a normal load global
     460             :     {
     461             :       static const int kNameOperandIndex = 0;
     462             :       static const int kSlotOperandIndex = 1;
     463             : 
     464             :       TypeofMode typeof_mode =
     465             :           function_id == Runtime::kLoadLookupSlotInsideTypeof
     466             :               ? INSIDE_TYPEOF
     467         258 :               : NOT_INSIDE_TYPEOF;
     468             : 
     469         258 :       LdaGlobal(kSlotOperandIndex, kNameOperandIndex, typeof_mode);
     470             :     }
     471             : 
     472             :     // Slow path when we have to call out to the runtime
     473         258 :     Bind(&slowpath);
     474             :     {
     475         258 :       Node* name_index = BytecodeOperandIdx(0);
     476         258 :       Node* name = LoadConstantPoolEntry(name_index);
     477         258 :       Node* result = CallRuntime(function_id, context, name);
     478         258 :       SetAccumulator(result);
     479         258 :       Dispatch();
     480         258 :     }
     481         258 :   }
     482             : };
     483             : 
     484             : // LdaLookupGlobalSlot <name_index> <feedback_slot> <depth>
     485             : //
     486             : // Lookup the object with the name in constant pool entry |name_index|
     487             : // dynamically.
     488         387 : IGNITION_HANDLER(LdaLookupGlobalSlot, InterpreterLookupGlobalAssembler) {
     489         129 :   LookupGlobalSlot(Runtime::kLoadLookupSlot);
     490             : }
     491             : 
     492             : // LdaLookupGlobalSlotInsideTypeof <name_index> <feedback_slot> <depth>
     493             : //
     494             : // Lookup the object with the name in constant pool entry |name_index|
     495             : // dynamically without causing a NoReferenceError.
     496         387 : IGNITION_HANDLER(LdaLookupGlobalSlotInsideTypeof,
     497             :                  InterpreterLookupGlobalAssembler) {
     498         129 :   LookupGlobalSlot(Runtime::kLoadLookupSlotInsideTypeof);
     499             : }
     500             : 
     501             : // StaLookupSlotSloppy <name_index>
     502             : //
     503             : // Store the object in accumulator to the object with the name in constant
     504             : // pool entry |name_index| in sloppy mode.
     505         258 : IGNITION_HANDLER(StaLookupSlotSloppy, InterpreterAssembler) {
     506         129 :   Node* value = GetAccumulator();
     507         129 :   Node* index = BytecodeOperandIdx(0);
     508         129 :   Node* name = LoadConstantPoolEntry(index);
     509         129 :   Node* context = GetContext();
     510             :   Node* result =
     511         129 :       CallRuntime(Runtime::kStoreLookupSlot_Sloppy, context, name, value);
     512         129 :   SetAccumulator(result);
     513         129 :   Dispatch();
     514         129 : }
     515             : 
     516             : // StaLookupSlotStrict <name_index>
     517             : //
     518             : // Store the object in accumulator to the object with the name in constant
     519             : // pool entry |name_index| in strict mode.
     520         258 : IGNITION_HANDLER(StaLookupSlotStrict, InterpreterAssembler) {
     521         129 :   Node* value = GetAccumulator();
     522         129 :   Node* index = BytecodeOperandIdx(0);
     523         129 :   Node* name = LoadConstantPoolEntry(index);
     524         129 :   Node* context = GetContext();
     525             :   Node* result =
     526         129 :       CallRuntime(Runtime::kStoreLookupSlot_Strict, context, name, value);
     527         129 :   SetAccumulator(result);
     528         129 :   Dispatch();
     529         129 : }
     530             : 
     531             : // LdaNamedProperty <object> <name_index> <slot>
     532             : //
     533             : // Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
     534             : // constant pool entry <name_index>.
     535         258 : IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
     536         129 :   Node* feedback_vector = LoadFeedbackVector();
     537         129 :   Node* feedback_slot = BytecodeOperandIdx(2);
     538         129 :   Node* smi_slot = SmiTag(feedback_slot);
     539             : 
     540             :   // Load receiver.
     541         129 :   Node* register_index = BytecodeOperandReg(0);
     542         129 :   Node* recv = LoadRegister(register_index);
     543             : 
     544             :   // Load the name.
     545             :   // TODO(jgruber): Not needed for monomorphic smi handler constant/field case.
     546         129 :   Node* constant_index = BytecodeOperandIdx(1);
     547         129 :   Node* name = LoadConstantPoolEntry(constant_index);
     548             : 
     549         129 :   Node* context = GetContext();
     550             : 
     551         129 :   Label done(this);
     552         258 :   Variable var_result(this, MachineRepresentation::kTagged);
     553             :   ExitPoint exit_point(this, &done, &var_result);
     554             : 
     555             :   AccessorAssembler::LoadICParameters params(context, recv, name, smi_slot,
     556             :                                              feedback_vector);
     557             :   AccessorAssembler accessor_asm(state());
     558         129 :   accessor_asm.LoadIC_BytecodeHandler(&params, &exit_point);
     559             : 
     560         129 :   Bind(&done);
     561             :   {
     562         129 :     SetAccumulator(var_result.value());
     563         129 :     Dispatch();
     564         129 :   }
     565         129 : }
     566             : 
     567             : // KeyedLoadIC <object> <slot>
     568             : //
     569             : // Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
     570             : // in the accumulator.
     571         258 : IGNITION_HANDLER(LdaKeyedProperty, InterpreterAssembler) {
     572         129 :   Callable ic = CodeFactory::KeyedLoadICInOptimizedCode(isolate());
     573         129 :   Node* code_target = HeapConstant(ic.code());
     574         129 :   Node* reg_index = BytecodeOperandReg(0);
     575         129 :   Node* object = LoadRegister(reg_index);
     576         129 :   Node* name = GetAccumulator();
     577         129 :   Node* raw_slot = BytecodeOperandIdx(1);
     578         129 :   Node* smi_slot = SmiTag(raw_slot);
     579         129 :   Node* feedback_vector = LoadFeedbackVector();
     580         129 :   Node* context = GetContext();
     581             :   Node* result = CallStub(ic.descriptor(), code_target, context, object, name,
     582         129 :                           smi_slot, feedback_vector);
     583         129 :   SetAccumulator(result);
     584         129 :   Dispatch();
     585         129 : }
     586             : 
     587         387 : class InterpreterStoreNamedPropertyAssembler : public InterpreterAssembler {
     588             :  public:
     589             :   InterpreterStoreNamedPropertyAssembler(CodeAssemblerState* state,
     590             :                                          Bytecode bytecode,
     591             :                                          OperandScale operand_scale)
     592         387 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     593             : 
     594         387 :   void StaNamedProperty(Callable ic) {
     595         387 :     Node* code_target = HeapConstant(ic.code());
     596         387 :     Node* object_reg_index = BytecodeOperandReg(0);
     597         387 :     Node* object = LoadRegister(object_reg_index);
     598         387 :     Node* constant_index = BytecodeOperandIdx(1);
     599         387 :     Node* name = LoadConstantPoolEntry(constant_index);
     600         387 :     Node* value = GetAccumulator();
     601         387 :     Node* raw_slot = BytecodeOperandIdx(2);
     602         387 :     Node* smi_slot = SmiTag(raw_slot);
     603         387 :     Node* feedback_vector = LoadFeedbackVector();
     604         387 :     Node* context = GetContext();
     605             :     CallStub(ic.descriptor(), code_target, context, object, name, value,
     606         387 :              smi_slot, feedback_vector);
     607         387 :     Dispatch();
     608         387 :   }
     609             : };
     610             : 
     611             : // StaNamedPropertySloppy <object> <name_index> <slot>
     612             : //
     613             : // Calls the sloppy mode StoreIC at FeedBackVector slot <slot> for <object> and
     614             : // the name in constant pool entry <name_index> with the value in the
     615             : // accumulator.
     616         516 : IGNITION_HANDLER(StaNamedPropertySloppy,
     617             :                  InterpreterStoreNamedPropertyAssembler) {
     618         129 :   Callable ic = CodeFactory::StoreICInOptimizedCode(isolate(), SLOPPY);
     619         129 :   StaNamedProperty(ic);
     620         129 : }
     621             : 
     622             : // StaNamedPropertyStrict <object> <name_index> <slot>
     623             : //
     624             : // Calls the strict mode StoreIC at FeedBackVector slot <slot> for <object> and
     625             : // the name in constant pool entry <name_index> with the value in the
     626             : // accumulator.
     627         516 : IGNITION_HANDLER(StaNamedPropertyStrict,
     628             :                  InterpreterStoreNamedPropertyAssembler) {
     629         129 :   Callable ic = CodeFactory::StoreICInOptimizedCode(isolate(), STRICT);
     630         129 :   StaNamedProperty(ic);
     631         129 : }
     632             : 
     633             : // StaNamedOwnProperty <object> <name_index> <slot>
     634             : //
     635             : // Calls the StoreOwnIC at FeedBackVector slot <slot> for <object> and
     636             : // the name in constant pool entry <name_index> with the value in the
     637             : // accumulator.
     638         516 : IGNITION_HANDLER(StaNamedOwnProperty, InterpreterStoreNamedPropertyAssembler) {
     639         129 :   Callable ic = CodeFactory::StoreOwnICInOptimizedCode(isolate());
     640         129 :   StaNamedProperty(ic);
     641         129 : }
     642             : 
     643         258 : class InterpreterStoreKeyedPropertyAssembler : public InterpreterAssembler {
     644             :  public:
     645             :   InterpreterStoreKeyedPropertyAssembler(CodeAssemblerState* state,
     646             :                                          Bytecode bytecode,
     647             :                                          OperandScale operand_scale)
     648         258 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     649             : 
     650         258 :   void StaKeyedProperty(Callable ic) {
     651         258 :     Node* code_target = HeapConstant(ic.code());
     652         258 :     Node* object_reg_index = BytecodeOperandReg(0);
     653         258 :     Node* object = LoadRegister(object_reg_index);
     654         258 :     Node* name_reg_index = BytecodeOperandReg(1);
     655         258 :     Node* name = LoadRegister(name_reg_index);
     656         258 :     Node* value = GetAccumulator();
     657         258 :     Node* raw_slot = BytecodeOperandIdx(2);
     658         258 :     Node* smi_slot = SmiTag(raw_slot);
     659         258 :     Node* feedback_vector = LoadFeedbackVector();
     660         258 :     Node* context = GetContext();
     661             :     CallStub(ic.descriptor(), code_target, context, object, name, value,
     662         258 :              smi_slot, feedback_vector);
     663         258 :     Dispatch();
     664         258 :   }
     665             : };
     666             : 
     667             : // StaKeyedPropertySloppy <object> <key> <slot>
     668             : //
     669             : // Calls the sloppy mode KeyStoreIC at FeedBackVector slot <slot> for <object>
     670             : // and the key <key> with the value in the accumulator.
     671         516 : IGNITION_HANDLER(StaKeyedPropertySloppy,
     672             :                  InterpreterStoreKeyedPropertyAssembler) {
     673         129 :   Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate(), SLOPPY);
     674         129 :   StaKeyedProperty(ic);
     675         129 : }
     676             : 
     677             : // StaKeyedPropertyStrict <object> <key> <slot>
     678             : //
     679             : // Calls the strict mode KeyStoreIC at FeedBackVector slot <slot> for <object>
     680             : // and the key <key> with the value in the accumulator.
     681         516 : IGNITION_HANDLER(StaKeyedPropertyStrict,
     682             :                  InterpreterStoreKeyedPropertyAssembler) {
     683         129 :   Callable ic = CodeFactory::KeyedStoreICInOptimizedCode(isolate(), STRICT);
     684         129 :   StaKeyedProperty(ic);
     685         129 : }
     686             : 
     687             : // StaDataPropertyInLiteral <object> <name> <flags>
     688             : //
     689             : // Define a property <name> with value from the accumulator in <object>.
     690             : // Property attributes and whether set_function_name are stored in
     691             : // DataPropertyInLiteralFlags <flags>.
     692             : //
     693             : // This definition is not observable and is used only for definitions
     694             : // in object or class literals.
     695         258 : IGNITION_HANDLER(StaDataPropertyInLiteral, InterpreterAssembler) {
     696         129 :   Node* object = LoadRegister(BytecodeOperandReg(0));
     697         129 :   Node* name = LoadRegister(BytecodeOperandReg(1));
     698         129 :   Node* value = GetAccumulator();
     699         129 :   Node* flags = SmiFromWord32(BytecodeOperandFlag(2));
     700         129 :   Node* vector_index = SmiTag(BytecodeOperandIdx(3));
     701             : 
     702         129 :   Node* feedback_vector = LoadFeedbackVector();
     703         129 :   Node* context = GetContext();
     704             : 
     705             :   CallRuntime(Runtime::kDefineDataPropertyInLiteral, context, object, name,
     706         129 :               value, flags, feedback_vector, vector_index);
     707         129 :   Dispatch();
     708         129 : }
     709             : 
     710         258 : IGNITION_HANDLER(CollectTypeProfile, InterpreterAssembler) {
     711         129 :   Node* position = BytecodeOperandImmSmi(0);
     712         129 :   Node* value = GetAccumulator();
     713             : 
     714         129 :   Node* feedback_vector = LoadFeedbackVector();
     715         129 :   Node* context = GetContext();
     716             : 
     717             :   CallRuntime(Runtime::kCollectTypeProfile, context, position, value,
     718         129 :               feedback_vector);
     719         129 :   Dispatch();
     720         129 : }
     721             : 
     722             : // LdaModuleVariable <cell_index> <depth>
     723             : //
     724             : // Load the contents of a module variable into the accumulator.  The variable is
     725             : // identified by <cell_index>.  <depth> is the depth of the current context
     726             : // relative to the module context.
     727         258 : IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) {
     728         129 :   Node* cell_index = BytecodeOperandImmIntPtr(0);
     729         129 :   Node* depth = BytecodeOperandUImm(1);
     730             : 
     731         129 :   Node* module_context = GetContextAtDepth(GetContext(), depth);
     732         129 :   Node* module = LoadContextElement(module_context, Context::EXTENSION_INDEX);
     733             : 
     734         258 :   Label if_export(this), if_import(this), end(this);
     735             :   Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export,
     736         129 :          &if_import);
     737             : 
     738         129 :   Bind(&if_export);
     739             :   {
     740             :     Node* regular_exports =
     741         129 :         LoadObjectField(module, Module::kRegularExportsOffset);
     742             :     // The actual array index is (cell_index - 1).
     743         129 :     Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1));
     744         129 :     Node* cell = LoadFixedArrayElement(regular_exports, export_index);
     745         129 :     SetAccumulator(LoadObjectField(cell, Cell::kValueOffset));
     746         129 :     Goto(&end);
     747             :   }
     748             : 
     749         129 :   Bind(&if_import);
     750             :   {
     751             :     Node* regular_imports =
     752         129 :         LoadObjectField(module, Module::kRegularImportsOffset);
     753             :     // The actual array index is (-cell_index - 1).
     754         129 :     Node* import_index = IntPtrSub(IntPtrConstant(-1), cell_index);
     755         129 :     Node* cell = LoadFixedArrayElement(regular_imports, import_index);
     756         129 :     SetAccumulator(LoadObjectField(cell, Cell::kValueOffset));
     757         129 :     Goto(&end);
     758             :   }
     759             : 
     760         129 :   Bind(&end);
     761         258 :   Dispatch();
     762         129 : }
     763             : 
     764             : // StaModuleVariable <cell_index> <depth>
     765             : //
     766             : // Store accumulator to the module variable identified by <cell_index>.
     767             : // <depth> is the depth of the current context relative to the module context.
     768         258 : IGNITION_HANDLER(StaModuleVariable, InterpreterAssembler) {
     769         129 :   Node* value = GetAccumulator();
     770         129 :   Node* cell_index = BytecodeOperandImmIntPtr(0);
     771         129 :   Node* depth = BytecodeOperandUImm(1);
     772             : 
     773         129 :   Node* module_context = GetContextAtDepth(GetContext(), depth);
     774         129 :   Node* module = LoadContextElement(module_context, Context::EXTENSION_INDEX);
     775             : 
     776         258 :   Label if_export(this), if_import(this), end(this);
     777             :   Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export,
     778         129 :          &if_import);
     779             : 
     780         129 :   Bind(&if_export);
     781             :   {
     782             :     Node* regular_exports =
     783         129 :         LoadObjectField(module, Module::kRegularExportsOffset);
     784             :     // The actual array index is (cell_index - 1).
     785         129 :     Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1));
     786         129 :     Node* cell = LoadFixedArrayElement(regular_exports, export_index);
     787         129 :     StoreObjectField(cell, Cell::kValueOffset, value);
     788         129 :     Goto(&end);
     789             :   }
     790             : 
     791         129 :   Bind(&if_import);
     792             :   {
     793             :     // Not supported (probably never).
     794         129 :     Abort(kUnsupportedModuleOperation);
     795         129 :     Goto(&end);
     796             :   }
     797             : 
     798         129 :   Bind(&end);
     799         258 :   Dispatch();
     800         129 : }
     801             : 
     802             : // PushContext <context>
     803             : //
     804             : // Saves the current context in <context>, and pushes the accumulator as the
     805             : // new current context.
     806         258 : IGNITION_HANDLER(PushContext, InterpreterAssembler) {
     807         129 :   Node* reg_index = BytecodeOperandReg(0);
     808         129 :   Node* new_context = GetAccumulator();
     809         129 :   Node* old_context = GetContext();
     810         129 :   StoreRegister(old_context, reg_index);
     811         129 :   SetContext(new_context);
     812         129 :   Dispatch();
     813         129 : }
     814             : 
     815             : // PopContext <context>
     816             : //
     817             : // Pops the current context and sets <context> as the new context.
     818         258 : IGNITION_HANDLER(PopContext, InterpreterAssembler) {
     819         129 :   Node* reg_index = BytecodeOperandReg(0);
     820         129 :   Node* context = LoadRegister(reg_index);
     821         129 :   SetContext(context);
     822         129 :   Dispatch();
     823         129 : }
     824             : 
     825         645 : class InterpreterBinaryOpAssembler : public InterpreterAssembler {
     826             :  public:
     827             :   InterpreterBinaryOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
     828             :                                OperandScale operand_scale)
     829         645 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     830             : 
     831             :   typedef Node* (BinaryOpAssembler::*BinaryOpGenerator)(Node* context,
     832             :                                                         Node* left, Node* right,
     833             :                                                         Node* slot,
     834             :                                                         Node* vector);
     835             : 
     836         645 :   void BinaryOpWithFeedback(BinaryOpGenerator generator) {
     837         645 :     Node* reg_index = BytecodeOperandReg(0);
     838         645 :     Node* lhs = LoadRegister(reg_index);
     839         645 :     Node* rhs = GetAccumulator();
     840         645 :     Node* context = GetContext();
     841         645 :     Node* slot_index = BytecodeOperandIdx(1);
     842         645 :     Node* feedback_vector = LoadFeedbackVector();
     843             : 
     844             :     BinaryOpAssembler binop_asm(state());
     845             :     Node* result =
     846         645 :         (binop_asm.*generator)(context, lhs, rhs, slot_index, feedback_vector);
     847         645 :     SetAccumulator(result);
     848         645 :     Dispatch();
     849         645 :   }
     850             : };
     851             : 
     852             : // Add <src>
     853             : //
     854             : // Add register <src> to accumulator.
     855         387 : IGNITION_HANDLER(Add, InterpreterBinaryOpAssembler) {
     856         129 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
     857             : }
     858             : 
     859             : // Sub <src>
     860             : //
     861             : // Subtract register <src> from accumulator.
     862         387 : IGNITION_HANDLER(Sub, InterpreterBinaryOpAssembler) {
     863         129 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_SubtractWithFeedback);
     864             : }
     865             : 
     866             : // Mul <src>
     867             : //
     868             : // Multiply accumulator by register <src>.
     869         387 : IGNITION_HANDLER(Mul, InterpreterBinaryOpAssembler) {
     870         129 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_MultiplyWithFeedback);
     871             : }
     872             : 
     873             : // Div <src>
     874             : //
     875             : // Divide register <src> by accumulator.
     876         387 : IGNITION_HANDLER(Div, InterpreterBinaryOpAssembler) {
     877         129 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_DivideWithFeedback);
     878             : }
     879             : 
     880             : // Mod <src>
     881             : //
     882             : // Modulo register <src> by accumulator.
     883         387 : IGNITION_HANDLER(Mod, InterpreterBinaryOpAssembler) {
     884         129 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
     885             : }
     886             : 
     887             : // AddSmi <imm>
     888             : //
     889             : // Adds an immediate value <imm> to the value in the accumulator.
     890         258 : IGNITION_HANDLER(AddSmi, InterpreterAssembler) {
     891         129 :   Variable var_result(this, MachineRepresentation::kTagged);
     892         129 :   Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
     893             : 
     894         129 :   Node* left = GetAccumulator();
     895         129 :   Node* right = BytecodeOperandImmSmi(0);
     896         129 :   Node* slot_index = BytecodeOperandIdx(1);
     897         129 :   Node* feedback_vector = LoadFeedbackVector();
     898             : 
     899             :   // {right} is known to be a Smi.
     900             :   // Check if the {left} is a Smi take the fast path.
     901         129 :   Branch(TaggedIsSmi(left), &fastpath, &slowpath);
     902         129 :   Bind(&fastpath);
     903             :   {
     904             :     // Try fast Smi addition first.
     905             :     Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(left),
     906         129 :                                        BitcastTaggedToWord(right));
     907         129 :     Node* overflow = Projection(1, pair);
     908             : 
     909             :     // Check if the Smi additon overflowed.
     910             :     Label if_notoverflow(this);
     911         129 :     Branch(overflow, &slowpath, &if_notoverflow);
     912         129 :     Bind(&if_notoverflow);
     913             :     {
     914             :       UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall),
     915         129 :                      feedback_vector, slot_index);
     916         129 :       var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
     917         129 :       Goto(&end);
     918         129 :     }
     919             :   }
     920         129 :   Bind(&slowpath);
     921             :   {
     922         129 :     Node* context = GetContext();
     923             :     // TODO(ishell): pass slot as word-size value.
     924             :     var_result.Bind(CallBuiltin(Builtins::kAddWithFeedback, context, left,
     925             :                                 right, TruncateWordToWord32(slot_index),
     926         129 :                                 feedback_vector));
     927         129 :     Goto(&end);
     928             :   }
     929         129 :   Bind(&end);
     930             :   {
     931         129 :     SetAccumulator(var_result.value());
     932         129 :     Dispatch();
     933         129 :   }
     934         129 : }
     935             : 
     936             : // SubSmi <imm>
     937             : //
     938             : // Subtracts an immediate value <imm> from the value in the accumulator.
     939         258 : IGNITION_HANDLER(SubSmi, InterpreterAssembler) {
     940         129 :   Variable var_result(this, MachineRepresentation::kTagged);
     941         129 :   Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
     942             : 
     943         129 :   Node* left = GetAccumulator();
     944         129 :   Node* right = BytecodeOperandImmSmi(0);
     945         129 :   Node* slot_index = BytecodeOperandIdx(1);
     946         129 :   Node* feedback_vector = LoadFeedbackVector();
     947             : 
     948             :   // {right} is known to be a Smi.
     949             :   // Check if the {left} is a Smi take the fast path.
     950         129 :   Branch(TaggedIsSmi(left), &fastpath, &slowpath);
     951         129 :   Bind(&fastpath);
     952             :   {
     953             :     // Try fast Smi subtraction first.
     954             :     Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(left),
     955         129 :                                        BitcastTaggedToWord(right));
     956         129 :     Node* overflow = Projection(1, pair);
     957             : 
     958             :     // Check if the Smi subtraction overflowed.
     959             :     Label if_notoverflow(this);
     960         129 :     Branch(overflow, &slowpath, &if_notoverflow);
     961         129 :     Bind(&if_notoverflow);
     962             :     {
     963             :       UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall),
     964         129 :                      feedback_vector, slot_index);
     965         129 :       var_result.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
     966         129 :       Goto(&end);
     967         129 :     }
     968             :   }
     969         129 :   Bind(&slowpath);
     970             :   {
     971         129 :     Node* context = GetContext();
     972             :     // TODO(ishell): pass slot as word-size value.
     973             :     var_result.Bind(CallBuiltin(Builtins::kSubtractWithFeedback, context, left,
     974             :                                 right, TruncateWordToWord32(slot_index),
     975         129 :                                 feedback_vector));
     976         129 :     Goto(&end);
     977             :   }
     978         129 :   Bind(&end);
     979             :   {
     980         129 :     SetAccumulator(var_result.value());
     981         129 :     Dispatch();
     982         129 :   }
     983         129 : }
     984             : 
     985             : // MulSmi <imm>
     986             : //
     987             : // Multiplies an immediate value <imm> to the value in the accumulator.
     988         258 : IGNITION_HANDLER(MulSmi, InterpreterAssembler) {
     989         129 :   Variable var_result(this, MachineRepresentation::kTagged);
     990         129 :   Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
     991             : 
     992         129 :   Node* left = GetAccumulator();
     993         129 :   Node* right = BytecodeOperandImmSmi(0);
     994         129 :   Node* slot_index = BytecodeOperandIdx(1);
     995         129 :   Node* feedback_vector = LoadFeedbackVector();
     996             : 
     997             :   // {right} is known to be a Smi.
     998             :   // Check if the {left} is a Smi take the fast path.
     999         129 :   Branch(TaggedIsSmi(left), &fastpath, &slowpath);
    1000         129 :   Bind(&fastpath);
    1001             :   {
    1002             :     // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi,
    1003             :     // in case of overflow.
    1004         129 :     var_result.Bind(SmiMul(left, right));
    1005             :     Node* feedback = SelectSmiConstant(TaggedIsSmi(var_result.value()),
    1006             :                                        BinaryOperationFeedback::kSignedSmall,
    1007         129 :                                        BinaryOperationFeedback::kNumber);
    1008         129 :     UpdateFeedback(feedback, feedback_vector, slot_index);
    1009         129 :     Goto(&end);
    1010             :   }
    1011         129 :   Bind(&slowpath);
    1012             :   {
    1013         129 :     Node* context = GetContext();
    1014             :     // TODO(ishell): pass slot as word-size value.
    1015             :     var_result.Bind(CallBuiltin(Builtins::kMultiplyWithFeedback, context, left,
    1016             :                                 right, TruncateWordToWord32(slot_index),
    1017         129 :                                 feedback_vector));
    1018         129 :     Goto(&end);
    1019             :   }
    1020             : 
    1021         129 :   Bind(&end);
    1022             :   {
    1023         129 :     SetAccumulator(var_result.value());
    1024         129 :     Dispatch();
    1025         129 :   }
    1026         129 : }
    1027             : 
    1028             : // DivSmi <imm>
    1029             : //
    1030             : // Divides the value in the accumulator by immediate value <imm>.
    1031         258 : IGNITION_HANDLER(DivSmi, InterpreterAssembler) {
    1032         129 :   Variable var_result(this, MachineRepresentation::kTagged);
    1033         129 :   Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
    1034             : 
    1035         129 :   Node* left = GetAccumulator();
    1036         129 :   Node* right = BytecodeOperandImmSmi(0);
    1037         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1038         129 :   Node* feedback_vector = LoadFeedbackVector();
    1039             : 
    1040             :   // {right} is known to be a Smi.
    1041             :   // Check if the {left} is a Smi take the fast path.
    1042         129 :   Branch(TaggedIsSmi(left), &fastpath, &slowpath);
    1043         129 :   Bind(&fastpath);
    1044             :   {
    1045         129 :     var_result.Bind(TrySmiDiv(left, right, &slowpath));
    1046             :     UpdateFeedback(SmiConstant(BinaryOperationFeedback::kSignedSmall),
    1047         129 :                    feedback_vector, slot_index);
    1048         129 :     Goto(&end);
    1049             :   }
    1050         129 :   Bind(&slowpath);
    1051             :   {
    1052         129 :     Node* context = GetContext();
    1053             :     // TODO(ishell): pass slot as word-size value.
    1054             :     var_result.Bind(CallBuiltin(Builtins::kDivideWithFeedback, context, left,
    1055             :                                 right, TruncateWordToWord32(slot_index),
    1056         129 :                                 feedback_vector));
    1057         129 :     Goto(&end);
    1058             :   }
    1059             : 
    1060         129 :   Bind(&end);
    1061             :   {
    1062         129 :     SetAccumulator(var_result.value());
    1063         129 :     Dispatch();
    1064         129 :   }
    1065         129 : }
    1066             : 
    1067             : // ModSmi <imm>
    1068             : //
    1069             : // Modulo accumulator by immediate value <imm>.
    1070         258 : IGNITION_HANDLER(ModSmi, InterpreterAssembler) {
    1071         129 :   Variable var_result(this, MachineRepresentation::kTagged);
    1072         129 :   Label fastpath(this), slowpath(this, Label::kDeferred), end(this);
    1073             : 
    1074         129 :   Node* left = GetAccumulator();
    1075         129 :   Node* right = BytecodeOperandImmSmi(0);
    1076         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1077         129 :   Node* feedback_vector = LoadFeedbackVector();
    1078             : 
    1079             :   // {right} is known to be a Smi.
    1080             :   // Check if the {left} is a Smi take the fast path.
    1081         129 :   Branch(TaggedIsSmi(left), &fastpath, &slowpath);
    1082         129 :   Bind(&fastpath);
    1083             :   {
    1084             :     // Both {lhs} and {rhs} are Smis. The result is not necessarily a smi.
    1085         129 :     var_result.Bind(SmiMod(left, right));
    1086             :     Node* feedback = SelectSmiConstant(TaggedIsSmi(var_result.value()),
    1087             :                                        BinaryOperationFeedback::kSignedSmall,
    1088         129 :                                        BinaryOperationFeedback::kNumber);
    1089         129 :     UpdateFeedback(feedback, feedback_vector, slot_index);
    1090         129 :     Goto(&end);
    1091             :   }
    1092         129 :   Bind(&slowpath);
    1093             :   {
    1094         129 :     Node* context = GetContext();
    1095             :     // TODO(ishell): pass slot as word-size value.
    1096             :     var_result.Bind(CallBuiltin(Builtins::kModulusWithFeedback, context, left,
    1097             :                                 right, TruncateWordToWord32(slot_index),
    1098         129 :                                 feedback_vector));
    1099         129 :     Goto(&end);
    1100             :   }
    1101             : 
    1102         129 :   Bind(&end);
    1103             :   {
    1104         129 :     SetAccumulator(var_result.value());
    1105         129 :     Dispatch();
    1106         129 :   }
    1107         129 : }
    1108             : 
    1109         774 : class InterpreterBitwiseBinaryOpAssembler : public InterpreterAssembler {
    1110             :  public:
    1111             :   InterpreterBitwiseBinaryOpAssembler(CodeAssemblerState* state,
    1112             :                                       Bytecode bytecode,
    1113             :                                       OperandScale operand_scale)
    1114         774 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    1115             : 
    1116         774 :   void BitwiseBinaryOpWithFeedback(Token::Value bitwise_op) {
    1117         774 :     Node* reg_index = BytecodeOperandReg(0);
    1118         774 :     Node* lhs = LoadRegister(reg_index);
    1119         774 :     Node* rhs = GetAccumulator();
    1120         774 :     Node* context = GetContext();
    1121         774 :     Node* slot_index = BytecodeOperandIdx(1);
    1122         774 :     Node* feedback_vector = LoadFeedbackVector();
    1123             : 
    1124         774 :     Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned),
    1125        1548 :         var_rhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1126             :     Node* lhs_value = TruncateTaggedToWord32WithFeedback(
    1127         774 :         context, lhs, &var_lhs_type_feedback);
    1128             :     Node* rhs_value = TruncateTaggedToWord32WithFeedback(
    1129         774 :         context, rhs, &var_rhs_type_feedback);
    1130             :     Node* result = nullptr;
    1131             : 
    1132         774 :     switch (bitwise_op) {
    1133             :       case Token::BIT_OR: {
    1134         129 :         Node* value = Word32Or(lhs_value, rhs_value);
    1135         129 :         result = ChangeInt32ToTagged(value);
    1136         129 :       } break;
    1137             :       case Token::BIT_AND: {
    1138         129 :         Node* value = Word32And(lhs_value, rhs_value);
    1139         129 :         result = ChangeInt32ToTagged(value);
    1140         129 :       } break;
    1141             :       case Token::BIT_XOR: {
    1142         129 :         Node* value = Word32Xor(lhs_value, rhs_value);
    1143         129 :         result = ChangeInt32ToTagged(value);
    1144         129 :       } break;
    1145             :       case Token::SHL: {
    1146             :         Node* value =
    1147         129 :             Word32Shl(lhs_value, Word32And(rhs_value, Int32Constant(0x1f)));
    1148         129 :         result = ChangeInt32ToTagged(value);
    1149         129 :       } break;
    1150             :       case Token::SHR: {
    1151             :         Node* value =
    1152         129 :             Word32Shr(lhs_value, Word32And(rhs_value, Int32Constant(0x1f)));
    1153         129 :         result = ChangeUint32ToTagged(value);
    1154         129 :       } break;
    1155             :       case Token::SAR: {
    1156             :         Node* value =
    1157         129 :             Word32Sar(lhs_value, Word32And(rhs_value, Int32Constant(0x1f)));
    1158         129 :         result = ChangeInt32ToTagged(value);
    1159         129 :       } break;
    1160             :       default:
    1161           0 :         UNREACHABLE();
    1162             :     }
    1163             : 
    1164             :     Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1165             :                                           BinaryOperationFeedback::kSignedSmall,
    1166         774 :                                           BinaryOperationFeedback::kNumber);
    1167             : 
    1168         774 :     if (FLAG_debug_code) {
    1169             :       Label ok(this);
    1170           0 :       GotoIf(TaggedIsSmi(result), &ok);
    1171           0 :       Node* result_map = LoadMap(result);
    1172             :       AbortIfWordNotEqual(result_map, HeapNumberMapConstant(),
    1173           0 :                           kExpectedHeapNumber);
    1174           0 :       Goto(&ok);
    1175           0 :       Bind(&ok);
    1176             :     }
    1177             : 
    1178             :     Node* input_feedback =
    1179         774 :         SmiOr(var_lhs_type_feedback.value(), var_rhs_type_feedback.value());
    1180             :     UpdateFeedback(SmiOr(result_type, input_feedback), feedback_vector,
    1181         774 :                    slot_index);
    1182         774 :     SetAccumulator(result);
    1183        1548 :     Dispatch();
    1184         774 :   }
    1185             : };
    1186             : 
    1187             : // BitwiseOr <src>
    1188             : //
    1189             : // BitwiseOr register <src> to accumulator.
    1190         387 : IGNITION_HANDLER(BitwiseOr, InterpreterBitwiseBinaryOpAssembler) {
    1191         129 :   BitwiseBinaryOpWithFeedback(Token::BIT_OR);
    1192             : }
    1193             : 
    1194             : // BitwiseXor <src>
    1195             : //
    1196             : // BitwiseXor register <src> to accumulator.
    1197         387 : IGNITION_HANDLER(BitwiseXor, InterpreterBitwiseBinaryOpAssembler) {
    1198         129 :   BitwiseBinaryOpWithFeedback(Token::BIT_XOR);
    1199             : }
    1200             : 
    1201             : // BitwiseAnd <src>
    1202             : //
    1203             : // BitwiseAnd register <src> to accumulator.
    1204         387 : IGNITION_HANDLER(BitwiseAnd, InterpreterBitwiseBinaryOpAssembler) {
    1205         129 :   BitwiseBinaryOpWithFeedback(Token::BIT_AND);
    1206             : }
    1207             : 
    1208             : // ShiftLeft <src>
    1209             : //
    1210             : // Left shifts register <src> by the count specified in the accumulator.
    1211             : // Register <src> is converted to an int32 and the accumulator to uint32
    1212             : // before the operation. 5 lsb bits from the accumulator are used as count
    1213             : // i.e. <src> << (accumulator & 0x1F).
    1214         387 : IGNITION_HANDLER(ShiftLeft, InterpreterBitwiseBinaryOpAssembler) {
    1215         129 :   BitwiseBinaryOpWithFeedback(Token::SHL);
    1216             : }
    1217             : 
    1218             : // ShiftRight <src>
    1219             : //
    1220             : // Right shifts register <src> by the count specified in the accumulator.
    1221             : // Result is sign extended. Register <src> is converted to an int32 and the
    1222             : // accumulator to uint32 before the operation. 5 lsb bits from the accumulator
    1223             : // are used as count i.e. <src> >> (accumulator & 0x1F).
    1224         387 : IGNITION_HANDLER(ShiftRight, InterpreterBitwiseBinaryOpAssembler) {
    1225         129 :   BitwiseBinaryOpWithFeedback(Token::SAR);
    1226             : }
    1227             : 
    1228             : // ShiftRightLogical <src>
    1229             : //
    1230             : // Right Shifts register <src> by the count specified in the accumulator.
    1231             : // Result is zero-filled. The accumulator and register <src> are converted to
    1232             : // uint32 before the operation 5 lsb bits from the accumulator are used as
    1233             : // count i.e. <src> << (accumulator & 0x1F).
    1234         387 : IGNITION_HANDLER(ShiftRightLogical, InterpreterBitwiseBinaryOpAssembler) {
    1235         129 :   BitwiseBinaryOpWithFeedback(Token::SHR);
    1236             : }
    1237             : 
    1238             : // BitwiseOr <imm>
    1239             : //
    1240             : // BitwiseOr accumulator with <imm>.
    1241         258 : IGNITION_HANDLER(BitwiseOrSmi, InterpreterAssembler) {
    1242         129 :   Node* left = GetAccumulator();
    1243         129 :   Node* right = BytecodeOperandImmSmi(0);
    1244         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1245         129 :   Node* feedback_vector = LoadFeedbackVector();
    1246         129 :   Node* context = GetContext();
    1247             : 
    1248         129 :   Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1249             :   Node* lhs_value =
    1250         129 :       TruncateTaggedToWord32WithFeedback(context, left, &var_lhs_type_feedback);
    1251         129 :   Node* rhs_value = SmiToWord32(right);
    1252         129 :   Node* value = Word32Or(lhs_value, rhs_value);
    1253         129 :   Node* result = ChangeInt32ToTagged(value);
    1254             :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1255             :                                         BinaryOperationFeedback::kSignedSmall,
    1256         129 :                                         BinaryOperationFeedback::kNumber);
    1257             :   UpdateFeedback(SmiOr(result_type, var_lhs_type_feedback.value()),
    1258         129 :                  feedback_vector, slot_index);
    1259         129 :   SetAccumulator(result);
    1260         129 :   Dispatch();
    1261         129 : }
    1262             : 
    1263             : // BitwiseXor <imm>
    1264             : //
    1265             : // BitwiseXor accumulator with <imm>.
    1266         258 : IGNITION_HANDLER(BitwiseXorSmi, InterpreterAssembler) {
    1267         129 :   Node* left = GetAccumulator();
    1268         129 :   Node* right = BytecodeOperandImmSmi(0);
    1269         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1270         129 :   Node* feedback_vector = LoadFeedbackVector();
    1271         129 :   Node* context = GetContext();
    1272             : 
    1273         129 :   Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1274             :   Node* lhs_value =
    1275         129 :       TruncateTaggedToWord32WithFeedback(context, left, &var_lhs_type_feedback);
    1276         129 :   Node* rhs_value = SmiToWord32(right);
    1277         129 :   Node* value = Word32Xor(lhs_value, rhs_value);
    1278         129 :   Node* result = ChangeInt32ToTagged(value);
    1279             :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1280             :                                         BinaryOperationFeedback::kSignedSmall,
    1281         129 :                                         BinaryOperationFeedback::kNumber);
    1282             :   UpdateFeedback(SmiOr(result_type, var_lhs_type_feedback.value()),
    1283         129 :                  feedback_vector, slot_index);
    1284         129 :   SetAccumulator(result);
    1285         129 :   Dispatch();
    1286         129 : }
    1287             : 
    1288             : // BitwiseAnd <imm>
    1289             : //
    1290             : // BitwiseAnd accumulator with <imm>.
    1291         258 : IGNITION_HANDLER(BitwiseAndSmi, InterpreterAssembler) {
    1292         129 :   Node* left = GetAccumulator();
    1293         129 :   Node* right = BytecodeOperandImmSmi(0);
    1294         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1295         129 :   Node* feedback_vector = LoadFeedbackVector();
    1296         129 :   Node* context = GetContext();
    1297             : 
    1298         129 :   Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1299             :   Node* lhs_value =
    1300         129 :       TruncateTaggedToWord32WithFeedback(context, left, &var_lhs_type_feedback);
    1301         129 :   Node* rhs_value = SmiToWord32(right);
    1302         129 :   Node* value = Word32And(lhs_value, rhs_value);
    1303         129 :   Node* result = ChangeInt32ToTagged(value);
    1304             :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1305             :                                         BinaryOperationFeedback::kSignedSmall,
    1306         129 :                                         BinaryOperationFeedback::kNumber);
    1307             :   UpdateFeedback(SmiOr(result_type, var_lhs_type_feedback.value()),
    1308         129 :                  feedback_vector, slot_index);
    1309         129 :   SetAccumulator(result);
    1310         129 :   Dispatch();
    1311         129 : }
    1312             : 
    1313             : // ShiftLeftSmi <imm>
    1314             : //
    1315             : // Left shifts accumulator by the count specified in <imm>.
    1316             : // The accumulator is converted to an int32 before the operation. The 5
    1317             : // lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F).
    1318         258 : IGNITION_HANDLER(ShiftLeftSmi, InterpreterAssembler) {
    1319         129 :   Node* left = GetAccumulator();
    1320         129 :   Node* right = BytecodeOperandImmSmi(0);
    1321         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1322         129 :   Node* feedback_vector = LoadFeedbackVector();
    1323         129 :   Node* context = GetContext();
    1324             : 
    1325         129 :   Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1326             :   Node* lhs_value =
    1327         129 :       TruncateTaggedToWord32WithFeedback(context, left, &var_lhs_type_feedback);
    1328         129 :   Node* rhs_value = SmiToWord32(right);
    1329         129 :   Node* shift_count = Word32And(rhs_value, Int32Constant(0x1f));
    1330         129 :   Node* value = Word32Shl(lhs_value, shift_count);
    1331         129 :   Node* result = ChangeInt32ToTagged(value);
    1332             :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1333             :                                         BinaryOperationFeedback::kSignedSmall,
    1334         129 :                                         BinaryOperationFeedback::kNumber);
    1335             :   UpdateFeedback(SmiOr(result_type, var_lhs_type_feedback.value()),
    1336         129 :                  feedback_vector, slot_index);
    1337         129 :   SetAccumulator(result);
    1338         129 :   Dispatch();
    1339         129 : }
    1340             : 
    1341             : // ShiftRightSmi <imm>
    1342             : //
    1343             : // Right shifts accumulator by the count specified in <imm>. Result is sign
    1344             : // extended. The accumulator is converted to an int32 before the operation. The
    1345             : // 5 lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F).
    1346         258 : IGNITION_HANDLER(ShiftRightSmi, InterpreterAssembler) {
    1347         129 :   Node* left = GetAccumulator();
    1348         129 :   Node* right = BytecodeOperandImmSmi(0);
    1349         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1350         129 :   Node* feedback_vector = LoadFeedbackVector();
    1351         129 :   Node* context = GetContext();
    1352             : 
    1353         129 :   Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1354             :   Node* lhs_value =
    1355         129 :       TruncateTaggedToWord32WithFeedback(context, left, &var_lhs_type_feedback);
    1356         129 :   Node* rhs_value = SmiToWord32(right);
    1357         129 :   Node* shift_count = Word32And(rhs_value, Int32Constant(0x1f));
    1358         129 :   Node* value = Word32Sar(lhs_value, shift_count);
    1359         129 :   Node* result = ChangeInt32ToTagged(value);
    1360             :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1361             :                                         BinaryOperationFeedback::kSignedSmall,
    1362         129 :                                         BinaryOperationFeedback::kNumber);
    1363             :   UpdateFeedback(SmiOr(result_type, var_lhs_type_feedback.value()),
    1364         129 :                  feedback_vector, slot_index);
    1365         129 :   SetAccumulator(result);
    1366         129 :   Dispatch();
    1367         129 : }
    1368             : 
    1369             : // ShiftRightLogicalSmi <imm>
    1370             : //
    1371             : // Right shifts accumulator by the count specified in <imm>. Result is zero
    1372             : // extended. The accumulator is converted to an int32 before the operation. The
    1373             : // 5 lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F).
    1374         258 : IGNITION_HANDLER(ShiftRightLogicalSmi, InterpreterAssembler) {
    1375         129 :   Node* left = GetAccumulator();
    1376         129 :   Node* right = BytecodeOperandImmSmi(0);
    1377         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1378         129 :   Node* feedback_vector = LoadFeedbackVector();
    1379         129 :   Node* context = GetContext();
    1380             : 
    1381         129 :   Variable var_lhs_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1382             :   Node* lhs_value =
    1383         129 :       TruncateTaggedToWord32WithFeedback(context, left, &var_lhs_type_feedback);
    1384         129 :   Node* rhs_value = SmiToWord32(right);
    1385         129 :   Node* shift_count = Word32And(rhs_value, Int32Constant(0x1f));
    1386         129 :   Node* value = Word32Shr(lhs_value, shift_count);
    1387         129 :   Node* result = ChangeUint32ToTagged(value);
    1388             :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1389             :                                         BinaryOperationFeedback::kSignedSmall,
    1390         129 :                                         BinaryOperationFeedback::kNumber);
    1391             :   UpdateFeedback(SmiOr(result_type, var_lhs_type_feedback.value()),
    1392         129 :                  feedback_vector, slot_index);
    1393         129 :   SetAccumulator(result);
    1394         129 :   Dispatch();
    1395         129 : }
    1396             : 
    1397             : // ToName
    1398             : //
    1399             : // Convert the object referenced by the accumulator to a name.
    1400         258 : IGNITION_HANDLER(ToName, InterpreterAssembler) {
    1401         129 :   Node* object = GetAccumulator();
    1402         129 :   Node* context = GetContext();
    1403         129 :   Node* result = ToName(context, object);
    1404         129 :   StoreRegister(result, BytecodeOperandReg(0));
    1405         129 :   Dispatch();
    1406         129 : }
    1407             : 
    1408             : // ToNumber <dst> <slot>
    1409             : //
    1410             : // Convert the object referenced by the accumulator to a number.
    1411         258 : IGNITION_HANDLER(ToNumber, InterpreterAssembler) {
    1412         129 :   Node* object = GetAccumulator();
    1413         129 :   Node* context = GetContext();
    1414             : 
    1415             :   // Convert the {object} to a Number and collect feedback for the {object}.
    1416         129 :   Variable var_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1417         258 :   Variable var_result(this, MachineRepresentation::kTagged);
    1418         129 :   Label if_done(this), if_objectissmi(this), if_objectisnumber(this),
    1419         129 :       if_objectisother(this, Label::kDeferred);
    1420             : 
    1421         129 :   GotoIf(TaggedIsSmi(object), &if_objectissmi);
    1422         129 :   Node* object_map = LoadMap(object);
    1423         129 :   Branch(IsHeapNumberMap(object_map), &if_objectisnumber, &if_objectisother);
    1424             : 
    1425         129 :   Bind(&if_objectissmi);
    1426             :   {
    1427         129 :     var_result.Bind(object);
    1428         129 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
    1429         129 :     Goto(&if_done);
    1430             :   }
    1431             : 
    1432         129 :   Bind(&if_objectisnumber);
    1433             :   {
    1434         129 :     var_result.Bind(object);
    1435         129 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNumber));
    1436         129 :     Goto(&if_done);
    1437             :   }
    1438             : 
    1439         129 :   Bind(&if_objectisother);
    1440             :   {
    1441             :     // Convert the {object} to a Number.
    1442         129 :     Callable callable = CodeFactory::NonNumberToNumber(isolate());
    1443         129 :     var_result.Bind(CallStub(callable, context, object));
    1444         129 :     var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
    1445         129 :     Goto(&if_done);
    1446             :   }
    1447             : 
    1448         129 :   Bind(&if_done);
    1449         129 :   StoreRegister(var_result.value(), BytecodeOperandReg(0));
    1450             : 
    1451             :   // Record the type feedback collected for {object}.
    1452         129 :   Node* slot_index = BytecodeOperandIdx(1);
    1453         129 :   Node* feedback_vector = LoadFeedbackVector();
    1454         129 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index);
    1455             : 
    1456         258 :   Dispatch();
    1457         129 : }
    1458             : 
    1459             : // ToObject
    1460             : //
    1461             : // Convert the object referenced by the accumulator to a JSReceiver.
    1462         258 : IGNITION_HANDLER(ToObject, InterpreterAssembler) {
    1463         129 :   Callable callable(CodeFactory::ToObject(isolate()));
    1464         129 :   Node* target = HeapConstant(callable.code());
    1465         129 :   Node* accumulator = GetAccumulator();
    1466         129 :   Node* context = GetContext();
    1467         129 :   Node* result = CallStub(callable.descriptor(), target, context, accumulator);
    1468         129 :   StoreRegister(result, BytecodeOperandReg(0));
    1469         129 :   Dispatch();
    1470         129 : }
    1471             : 
    1472             : // Inc
    1473             : //
    1474             : // Increments value in the accumulator by one.
    1475         258 : IGNITION_HANDLER(Inc, InterpreterAssembler) {
    1476             :   typedef CodeStubAssembler::Label Label;
    1477             :   typedef compiler::Node Node;
    1478             :   typedef CodeStubAssembler::Variable Variable;
    1479             : 
    1480         129 :   Node* value = GetAccumulator();
    1481         129 :   Node* context = GetContext();
    1482         129 :   Node* slot_index = BytecodeOperandIdx(0);
    1483         129 :   Node* feedback_vector = LoadFeedbackVector();
    1484             : 
    1485             :   // Shared entry for floating point increment.
    1486         258 :   Label do_finc(this), end(this);
    1487         258 :   Variable var_finc_value(this, MachineRepresentation::kFloat64);
    1488             : 
    1489             :   // We might need to try again due to ToNumber conversion.
    1490         258 :   Variable value_var(this, MachineRepresentation::kTagged);
    1491         258 :   Variable result_var(this, MachineRepresentation::kTagged);
    1492         258 :   Variable var_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1493         129 :   Variable* loop_vars[] = {&value_var, &var_type_feedback};
    1494         258 :   Label start(this, 2, loop_vars);
    1495         129 :   value_var.Bind(value);
    1496         129 :   var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNone));
    1497         129 :   Goto(&start);
    1498         129 :   Bind(&start);
    1499             :   {
    1500         129 :     value = value_var.value();
    1501             : 
    1502         129 :     Label if_issmi(this), if_isnotsmi(this);
    1503         129 :     Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
    1504             : 
    1505         129 :     Bind(&if_issmi);
    1506             :     {
    1507             :       // Try fast Smi addition first.
    1508         129 :       Node* one = SmiConstant(Smi::FromInt(1));
    1509             :       Node* pair = IntPtrAddWithOverflow(BitcastTaggedToWord(value),
    1510         129 :                                          BitcastTaggedToWord(one));
    1511         129 :       Node* overflow = Projection(1, pair);
    1512             : 
    1513             :       // Check if the Smi addition overflowed.
    1514         129 :       Label if_overflow(this), if_notoverflow(this);
    1515         129 :       Branch(overflow, &if_overflow, &if_notoverflow);
    1516             : 
    1517         129 :       Bind(&if_notoverflow);
    1518             :       var_type_feedback.Bind(
    1519             :           SmiOr(var_type_feedback.value(),
    1520         129 :                 SmiConstant(BinaryOperationFeedback::kSignedSmall)));
    1521         129 :       result_var.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
    1522         129 :       Goto(&end);
    1523             : 
    1524         129 :       Bind(&if_overflow);
    1525             :       {
    1526         129 :         var_finc_value.Bind(SmiToFloat64(value));
    1527         129 :         Goto(&do_finc);
    1528         129 :       }
    1529             :     }
    1530             : 
    1531         129 :     Bind(&if_isnotsmi);
    1532             :     {
    1533             :       // Check if the value is a HeapNumber.
    1534         129 :       Label if_valueisnumber(this), if_valuenotnumber(this, Label::kDeferred);
    1535         129 :       Node* value_map = LoadMap(value);
    1536         129 :       Branch(IsHeapNumberMap(value_map), &if_valueisnumber, &if_valuenotnumber);
    1537             : 
    1538         129 :       Bind(&if_valueisnumber);
    1539             :       {
    1540             :         // Load the HeapNumber value.
    1541         129 :         var_finc_value.Bind(LoadHeapNumberValue(value));
    1542         129 :         Goto(&do_finc);
    1543             :       }
    1544             : 
    1545         129 :       Bind(&if_valuenotnumber);
    1546             :       {
    1547             :         // We do not require an Or with earlier feedback here because once we
    1548             :         // convert the value to a number, we cannot reach this path. We can
    1549             :         // only reach this path on the first pass when the feedback is kNone.
    1550             :         CSA_ASSERT(this, SmiEqual(var_type_feedback.value(),
    1551             :                                   SmiConstant(BinaryOperationFeedback::kNone)));
    1552             : 
    1553         129 :         Label if_valueisoddball(this), if_valuenotoddball(this);
    1554         129 :         Node* instance_type = LoadMapInstanceType(value_map);
    1555             :         Node* is_oddball =
    1556         129 :             Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE));
    1557         129 :         Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball);
    1558             : 
    1559         129 :         Bind(&if_valueisoddball);
    1560             :         {
    1561             :           // Convert Oddball to Number and check again.
    1562         129 :           value_var.Bind(LoadObjectField(value, Oddball::kToNumberOffset));
    1563             :           var_type_feedback.Bind(
    1564         129 :               SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
    1565         129 :           Goto(&start);
    1566             :         }
    1567             : 
    1568         129 :         Bind(&if_valuenotoddball);
    1569             :         {
    1570             :           // Convert to a Number first and try again.
    1571         129 :           Callable callable = CodeFactory::NonNumberToNumber(isolate());
    1572         129 :           var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
    1573         129 :           value_var.Bind(CallStub(callable, context, value));
    1574         129 :           Goto(&start);
    1575         129 :         }
    1576         129 :       }
    1577         129 :     }
    1578             :   }
    1579             : 
    1580         129 :   Bind(&do_finc);
    1581             :   {
    1582         129 :     Node* finc_value = var_finc_value.value();
    1583         129 :     Node* one = Float64Constant(1.0);
    1584         129 :     Node* finc_result = Float64Add(finc_value, one);
    1585             :     var_type_feedback.Bind(
    1586             :         SmiOr(var_type_feedback.value(),
    1587         129 :               SmiConstant(BinaryOperationFeedback::kNumber)));
    1588         129 :     result_var.Bind(AllocateHeapNumberWithValue(finc_result));
    1589         129 :     Goto(&end);
    1590             :   }
    1591             : 
    1592         129 :   Bind(&end);
    1593         129 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index);
    1594             : 
    1595         129 :   SetAccumulator(result_var.value());
    1596         258 :   Dispatch();
    1597         129 : }
    1598             : 
    1599             : // Dec
    1600             : //
    1601             : // Decrements value in the accumulator by one.
    1602         258 : IGNITION_HANDLER(Dec, InterpreterAssembler) {
    1603             :   typedef CodeStubAssembler::Label Label;
    1604             :   typedef compiler::Node Node;
    1605             :   typedef CodeStubAssembler::Variable Variable;
    1606             : 
    1607         129 :   Node* value = GetAccumulator();
    1608         129 :   Node* context = GetContext();
    1609         129 :   Node* slot_index = BytecodeOperandIdx(0);
    1610         129 :   Node* feedback_vector = LoadFeedbackVector();
    1611             : 
    1612             :   // Shared entry for floating point decrement.
    1613         258 :   Label do_fdec(this), end(this);
    1614         258 :   Variable var_fdec_value(this, MachineRepresentation::kFloat64);
    1615             : 
    1616             :   // We might need to try again due to ToNumber conversion.
    1617         258 :   Variable value_var(this, MachineRepresentation::kTagged);
    1618         258 :   Variable result_var(this, MachineRepresentation::kTagged);
    1619         258 :   Variable var_type_feedback(this, MachineRepresentation::kTaggedSigned);
    1620         129 :   Variable* loop_vars[] = {&value_var, &var_type_feedback};
    1621         258 :   Label start(this, 2, loop_vars);
    1622         129 :   var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kNone));
    1623         129 :   value_var.Bind(value);
    1624         129 :   Goto(&start);
    1625         129 :   Bind(&start);
    1626             :   {
    1627         129 :     value = value_var.value();
    1628             : 
    1629         129 :     Label if_issmi(this), if_isnotsmi(this);
    1630         129 :     Branch(TaggedIsSmi(value), &if_issmi, &if_isnotsmi);
    1631             : 
    1632         129 :     Bind(&if_issmi);
    1633             :     {
    1634             :       // Try fast Smi subtraction first.
    1635         129 :       Node* one = SmiConstant(Smi::FromInt(1));
    1636             :       Node* pair = IntPtrSubWithOverflow(BitcastTaggedToWord(value),
    1637         129 :                                          BitcastTaggedToWord(one));
    1638         129 :       Node* overflow = Projection(1, pair);
    1639             : 
    1640             :       // Check if the Smi subtraction overflowed.
    1641         129 :       Label if_overflow(this), if_notoverflow(this);
    1642         129 :       Branch(overflow, &if_overflow, &if_notoverflow);
    1643             : 
    1644         129 :       Bind(&if_notoverflow);
    1645             :       var_type_feedback.Bind(
    1646             :           SmiOr(var_type_feedback.value(),
    1647         129 :                 SmiConstant(BinaryOperationFeedback::kSignedSmall)));
    1648         129 :       result_var.Bind(BitcastWordToTaggedSigned(Projection(0, pair)));
    1649         129 :       Goto(&end);
    1650             : 
    1651         129 :       Bind(&if_overflow);
    1652             :       {
    1653         129 :         var_fdec_value.Bind(SmiToFloat64(value));
    1654         129 :         Goto(&do_fdec);
    1655         129 :       }
    1656             :     }
    1657             : 
    1658         129 :     Bind(&if_isnotsmi);
    1659             :     {
    1660             :       // Check if the value is a HeapNumber.
    1661         129 :       Label if_valueisnumber(this), if_valuenotnumber(this, Label::kDeferred);
    1662         129 :       Node* value_map = LoadMap(value);
    1663         129 :       Branch(IsHeapNumberMap(value_map), &if_valueisnumber, &if_valuenotnumber);
    1664             : 
    1665         129 :       Bind(&if_valueisnumber);
    1666             :       {
    1667             :         // Load the HeapNumber value.
    1668         129 :         var_fdec_value.Bind(LoadHeapNumberValue(value));
    1669         129 :         Goto(&do_fdec);
    1670             :       }
    1671             : 
    1672         129 :       Bind(&if_valuenotnumber);
    1673             :       {
    1674             :         // We do not require an Or with earlier feedback here because once we
    1675             :         // convert the value to a number, we cannot reach this path. We can
    1676             :         // only reach this path on the first pass when the feedback is kNone.
    1677             :         CSA_ASSERT(this, SmiEqual(var_type_feedback.value(),
    1678             :                                   SmiConstant(BinaryOperationFeedback::kNone)));
    1679             : 
    1680         129 :         Label if_valueisoddball(this), if_valuenotoddball(this);
    1681         129 :         Node* instance_type = LoadMapInstanceType(value_map);
    1682             :         Node* is_oddball =
    1683         129 :             Word32Equal(instance_type, Int32Constant(ODDBALL_TYPE));
    1684         129 :         Branch(is_oddball, &if_valueisoddball, &if_valuenotoddball);
    1685             : 
    1686         129 :         Bind(&if_valueisoddball);
    1687             :         {
    1688             :           // Convert Oddball to Number and check again.
    1689         129 :           value_var.Bind(LoadObjectField(value, Oddball::kToNumberOffset));
    1690             :           var_type_feedback.Bind(
    1691         129 :               SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
    1692         129 :           Goto(&start);
    1693             :         }
    1694             : 
    1695         129 :         Bind(&if_valuenotoddball);
    1696             :         {
    1697             :           // Convert to a Number first and try again.
    1698         129 :           Callable callable = CodeFactory::NonNumberToNumber(isolate());
    1699         129 :           var_type_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
    1700         129 :           value_var.Bind(CallStub(callable, context, value));
    1701         129 :           Goto(&start);
    1702         129 :         }
    1703         129 :       }
    1704         129 :     }
    1705             :   }
    1706             : 
    1707         129 :   Bind(&do_fdec);
    1708             :   {
    1709         129 :     Node* fdec_value = var_fdec_value.value();
    1710         129 :     Node* one = Float64Constant(1.0);
    1711         129 :     Node* fdec_result = Float64Sub(fdec_value, one);
    1712             :     var_type_feedback.Bind(
    1713             :         SmiOr(var_type_feedback.value(),
    1714         129 :               SmiConstant(BinaryOperationFeedback::kNumber)));
    1715         129 :     result_var.Bind(AllocateHeapNumberWithValue(fdec_result));
    1716         129 :     Goto(&end);
    1717             :   }
    1718             : 
    1719         129 :   Bind(&end);
    1720         129 :   UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index);
    1721             : 
    1722         129 :   SetAccumulator(result_var.value());
    1723         258 :   Dispatch();
    1724         129 : }
    1725             : 
    1726             : // LogicalNot
    1727             : //
    1728             : // Perform logical-not on the accumulator, first casting the
    1729             : // accumulator to a boolean value if required.
    1730             : // ToBooleanLogicalNot
    1731          86 : IGNITION_HANDLER(ToBooleanLogicalNot, InterpreterAssembler) {
    1732          43 :   Node* value = GetAccumulator();
    1733          43 :   Variable result(this, MachineRepresentation::kTagged);
    1734          43 :   Label if_true(this), if_false(this), end(this);
    1735          43 :   Node* true_value = BooleanConstant(true);
    1736          43 :   Node* false_value = BooleanConstant(false);
    1737          43 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    1738          43 :   Bind(&if_true);
    1739             :   {
    1740          43 :     result.Bind(false_value);
    1741          43 :     Goto(&end);
    1742             :   }
    1743          43 :   Bind(&if_false);
    1744             :   {
    1745          43 :     result.Bind(true_value);
    1746          43 :     Goto(&end);
    1747             :   }
    1748          43 :   Bind(&end);
    1749          43 :   SetAccumulator(result.value());
    1750          86 :   Dispatch();
    1751          43 : }
    1752             : 
    1753             : // LogicalNot
    1754             : //
    1755             : // Perform logical-not on the accumulator, which must already be a boolean
    1756             : // value.
    1757          86 : IGNITION_HANDLER(LogicalNot, InterpreterAssembler) {
    1758          43 :   Node* value = GetAccumulator();
    1759          43 :   Variable result(this, MachineRepresentation::kTagged);
    1760          43 :   Label if_true(this), if_false(this), end(this);
    1761          43 :   Node* true_value = BooleanConstant(true);
    1762          43 :   Node* false_value = BooleanConstant(false);
    1763          43 :   Branch(WordEqual(value, true_value), &if_true, &if_false);
    1764          43 :   Bind(&if_true);
    1765             :   {
    1766          43 :     result.Bind(false_value);
    1767          43 :     Goto(&end);
    1768             :   }
    1769          43 :   Bind(&if_false);
    1770             :   {
    1771          43 :     if (FLAG_debug_code) {
    1772             :       AbortIfWordNotEqual(value, false_value,
    1773           0 :                           BailoutReason::kExpectedBooleanValue);
    1774             :     }
    1775          43 :     result.Bind(true_value);
    1776          43 :     Goto(&end);
    1777             :   }
    1778          43 :   Bind(&end);
    1779          43 :   SetAccumulator(result.value());
    1780          86 :   Dispatch();
    1781          43 : }
    1782             : 
    1783             : // TypeOf
    1784             : //
    1785             : // Load the accumulator with the string representating type of the
    1786             : // object in the accumulator.
    1787          86 : IGNITION_HANDLER(TypeOf, InterpreterAssembler) {
    1788          43 :   Node* value = GetAccumulator();
    1789          43 :   Node* result = Typeof(value);
    1790          43 :   SetAccumulator(result);
    1791          43 :   Dispatch();
    1792          43 : }
    1793             : 
    1794             : // DeletePropertyStrict
    1795             : //
    1796             : // Delete the property specified in the accumulator from the object
    1797             : // referenced by the register operand following strict mode semantics.
    1798         258 : IGNITION_HANDLER(DeletePropertyStrict, InterpreterAssembler) {
    1799         129 :   Node* reg_index = BytecodeOperandReg(0);
    1800         129 :   Node* object = LoadRegister(reg_index);
    1801         129 :   Node* key = GetAccumulator();
    1802         129 :   Node* context = GetContext();
    1803             :   Node* result = CallBuiltin(Builtins::kDeleteProperty, context, object, key,
    1804         129 :                              SmiConstant(STRICT));
    1805         129 :   SetAccumulator(result);
    1806         129 :   Dispatch();
    1807         129 : }
    1808             : 
    1809             : // DeletePropertySloppy
    1810             : //
    1811             : // Delete the property specified in the accumulator from the object
    1812             : // referenced by the register operand following sloppy mode semantics.
    1813         258 : IGNITION_HANDLER(DeletePropertySloppy, InterpreterAssembler) {
    1814         129 :   Node* reg_index = BytecodeOperandReg(0);
    1815         129 :   Node* object = LoadRegister(reg_index);
    1816         129 :   Node* key = GetAccumulator();
    1817         129 :   Node* context = GetContext();
    1818             :   Node* result = CallBuiltin(Builtins::kDeleteProperty, context, object, key,
    1819         129 :                              SmiConstant(SLOPPY));
    1820         129 :   SetAccumulator(result);
    1821         129 :   Dispatch();
    1822         129 : }
    1823             : 
    1824             : // GetSuperConstructor
    1825             : //
    1826             : // Get the super constructor from the object referenced by the accumulator.
    1827             : // The result is stored in register |reg|.
    1828         258 : IGNITION_HANDLER(GetSuperConstructor, InterpreterAssembler) {
    1829         129 :   Node* active_function = GetAccumulator();
    1830         129 :   Node* context = GetContext();
    1831         129 :   Node* result = GetSuperConstructor(active_function, context);
    1832         129 :   Node* reg = BytecodeOperandReg(0);
    1833         129 :   StoreRegister(result, reg);
    1834         129 :   Dispatch();
    1835         129 : }
    1836             : 
    1837        1290 : class InterpreterJSCallAssembler : public InterpreterAssembler {
    1838             :  public:
    1839             :   InterpreterJSCallAssembler(CodeAssemblerState* state, Bytecode bytecode,
    1840             :                              OperandScale operand_scale)
    1841        1290 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    1842             : 
    1843             :   // Generates code to perform a JS call that collects type feedback.
    1844         516 :   void JSCall(ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode) {
    1845         516 :     Node* function_reg = BytecodeOperandReg(0);
    1846         516 :     Node* function = LoadRegister(function_reg);
    1847         516 :     Node* first_arg_reg = BytecodeOperandReg(1);
    1848         516 :     Node* first_arg = RegisterLocation(first_arg_reg);
    1849         516 :     Node* arg_list_count = BytecodeOperandCount(2);
    1850             :     Node* args_count;
    1851         516 :     if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
    1852             :       // The receiver is implied, so it is not in the argument list.
    1853             :       args_count = arg_list_count;
    1854             :     } else {
    1855             :       // Subtract the receiver from the argument count.
    1856         387 :       Node* receiver_count = Int32Constant(1);
    1857         387 :       args_count = Int32Sub(arg_list_count, receiver_count);
    1858             :     }
    1859         516 :     Node* slot_id = BytecodeOperandIdx(3);
    1860         516 :     Node* feedback_vector = LoadFeedbackVector();
    1861         516 :     Node* context = GetContext();
    1862             :     Node* result =
    1863             :         CallJSWithFeedback(function, context, first_arg, args_count, slot_id,
    1864         516 :                            feedback_vector, receiver_mode, tail_call_mode);
    1865         516 :     SetAccumulator(result);
    1866         516 :     Dispatch();
    1867         516 :   }
    1868             : 
    1869             :   // Generates code to perform a JS call with a known number of arguments that
    1870             :   // collects type feedback.
    1871         774 :   void JSCallN(int arg_count, ConvertReceiverMode receiver_mode) {
    1872             :     // Indices and counts of operands on the bytecode.
    1873             :     const int kFirstArgumentOperandIndex = 1;
    1874             :     const int kReceiverOperandCount =
    1875         774 :         (receiver_mode == ConvertReceiverMode::kNullOrUndefined) ? 0 : 1;
    1876             :     const int kSlotOperandIndex =
    1877         774 :         kFirstArgumentOperandIndex + kReceiverOperandCount + arg_count;
    1878             :     // Indices and counts of parameters to the call stub.
    1879             :     const int kBoilerplateParameterCount = 7;
    1880             :     const int kReceiverParameterIndex = 5;
    1881             :     const int kReceiverParameterCount = 1;
    1882             :     // Only used in a DCHECK.
    1883             :     USE(kReceiverParameterCount);
    1884             : 
    1885         774 :     Node* function_reg = BytecodeOperandReg(0);
    1886         774 :     Node* function = LoadRegister(function_reg);
    1887             :     std::array<Node*, Bytecodes::kMaxOperands + kBoilerplateParameterCount>
    1888             :         temp;
    1889         774 :     Callable call_ic = CodeFactory::CallIC(isolate());
    1890         774 :     temp[0] = HeapConstant(call_ic.code());
    1891         774 :     temp[1] = function;
    1892         774 :     temp[2] = Int32Constant(arg_count);
    1893         774 :     temp[3] = BytecodeOperandIdxInt32(kSlotOperandIndex);
    1894         774 :     temp[4] = LoadFeedbackVector();
    1895             : 
    1896             :     int parameter_index = kReceiverParameterIndex;
    1897         774 :     if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
    1898             :       // The first argument parameter (the receiver) is implied to be undefined.
    1899             :       Node* undefined_value =
    1900         774 :           HeapConstant(isolate()->factory()->undefined_value());
    1901         387 :       temp[parameter_index++] = undefined_value;
    1902             :     }
    1903             :     // The bytecode argument operands are copied into the remaining argument
    1904             :     // parameters.
    1905        1935 :     for (int i = 0; i < (kReceiverOperandCount + arg_count); ++i) {
    1906        1161 :       Node* reg = BytecodeOperandReg(kFirstArgumentOperandIndex + i);
    1907        1161 :       temp[parameter_index++] = LoadRegister(reg);
    1908             :     }
    1909             : 
    1910             :     DCHECK_EQ(parameter_index,
    1911             :               kReceiverParameterIndex + kReceiverParameterCount + arg_count);
    1912         774 :     temp[parameter_index] = GetContext();
    1913             : 
    1914             :     Node* result = CallStubN(call_ic.descriptor(), 1,
    1915        2322 :                              arg_count + kBoilerplateParameterCount, &temp[0]);
    1916         774 :     SetAccumulator(result);
    1917         774 :     Dispatch();
    1918         774 :   }
    1919             : };
    1920             : 
    1921             : // Call <callable> <receiver> <arg_count> <feedback_slot_id>
    1922             : //
    1923             : // Call a JSfunction or Callable in |callable| with the |receiver| and
    1924             : // |arg_count| arguments in subsequent registers. Collect type feedback
    1925             : // into |feedback_slot_id|
    1926         387 : IGNITION_HANDLER(CallAnyReceiver, InterpreterJSCallAssembler) {
    1927         129 :   JSCall(ConvertReceiverMode::kAny, TailCallMode::kDisallow);
    1928             : }
    1929             : 
    1930         387 : IGNITION_HANDLER(CallProperty, InterpreterJSCallAssembler) {
    1931         129 :   JSCall(ConvertReceiverMode::kNotNullOrUndefined, TailCallMode::kDisallow);
    1932             : }
    1933             : 
    1934         387 : IGNITION_HANDLER(CallProperty0, InterpreterJSCallAssembler) {
    1935         129 :   JSCallN(0, ConvertReceiverMode::kNotNullOrUndefined);
    1936             : }
    1937             : 
    1938         387 : IGNITION_HANDLER(CallProperty1, InterpreterJSCallAssembler) {
    1939         129 :   JSCallN(1, ConvertReceiverMode::kNotNullOrUndefined);
    1940             : }
    1941             : 
    1942         387 : IGNITION_HANDLER(CallProperty2, InterpreterJSCallAssembler) {
    1943         129 :   JSCallN(2, ConvertReceiverMode::kNotNullOrUndefined);
    1944             : }
    1945             : 
    1946         387 : IGNITION_HANDLER(CallUndefinedReceiver, InterpreterJSCallAssembler) {
    1947         129 :   JSCall(ConvertReceiverMode::kNullOrUndefined, TailCallMode::kDisallow);
    1948             : }
    1949             : 
    1950         387 : IGNITION_HANDLER(CallUndefinedReceiver0, InterpreterJSCallAssembler) {
    1951         129 :   JSCallN(0, ConvertReceiverMode::kNullOrUndefined);
    1952             : }
    1953             : 
    1954         387 : IGNITION_HANDLER(CallUndefinedReceiver1, InterpreterJSCallAssembler) {
    1955         129 :   JSCallN(1, ConvertReceiverMode::kNullOrUndefined);
    1956             : }
    1957             : 
    1958         387 : IGNITION_HANDLER(CallUndefinedReceiver2, InterpreterJSCallAssembler) {
    1959         129 :   JSCallN(2, ConvertReceiverMode::kNullOrUndefined);
    1960             : }
    1961             : 
    1962             : // TailCall <callable> <receiver> <arg_count> <feedback_slot_id>
    1963             : //
    1964             : // Tail call a JSfunction or Callable in |callable| with the |receiver| and
    1965             : // |arg_count| arguments in subsequent registers. Collect type feedback
    1966             : // into |feedback_slot_id|
    1967         387 : IGNITION_HANDLER(TailCall, InterpreterJSCallAssembler) {
    1968         129 :   JSCall(ConvertReceiverMode::kAny, TailCallMode::kAllow);
    1969             : }
    1970             : 
    1971             : // CallRuntime <function_id> <first_arg> <arg_count>
    1972             : //
    1973             : // Call the runtime function |function_id| with the first argument in
    1974             : // register |first_arg| and |arg_count| arguments in subsequent
    1975             : // registers.
    1976         258 : IGNITION_HANDLER(CallRuntime, InterpreterAssembler) {
    1977         129 :   Node* function_id = BytecodeOperandRuntimeId(0);
    1978         129 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1979         129 :   Node* first_arg = RegisterLocation(first_arg_reg);
    1980         129 :   Node* args_count = BytecodeOperandCount(2);
    1981         129 :   Node* context = GetContext();
    1982         129 :   Node* result = CallRuntimeN(function_id, context, first_arg, args_count);
    1983         129 :   SetAccumulator(result);
    1984         129 :   Dispatch();
    1985         129 : }
    1986             : 
    1987             : // InvokeIntrinsic <function_id> <first_arg> <arg_count>
    1988             : //
    1989             : // Implements the semantic equivalent of calling the runtime function
    1990             : // |function_id| with the first argument in |first_arg| and |arg_count|
    1991             : // arguments in subsequent registers.
    1992         258 : IGNITION_HANDLER(InvokeIntrinsic, InterpreterAssembler) {
    1993         129 :   Node* function_id = BytecodeOperandIntrinsicId(0);
    1994         129 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1995         129 :   Node* arg_count = BytecodeOperandCount(2);
    1996         129 :   Node* context = GetContext();
    1997             :   Node* result = GenerateInvokeIntrinsic(this, function_id, context,
    1998         129 :                                          first_arg_reg, arg_count);
    1999         129 :   SetAccumulator(result);
    2000         129 :   Dispatch();
    2001         129 : }
    2002             : 
    2003             : // CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
    2004             : //
    2005             : // Call the runtime function |function_id| which returns a pair, with the
    2006             : // first argument in register |first_arg| and |arg_count| arguments in
    2007             : // subsequent registers. Returns the result in <first_return> and
    2008             : // <first_return + 1>
    2009         258 : IGNITION_HANDLER(CallRuntimeForPair, InterpreterAssembler) {
    2010             :   // Call the runtime function.
    2011         129 :   Node* function_id = BytecodeOperandRuntimeId(0);
    2012         129 :   Node* first_arg_reg = BytecodeOperandReg(1);
    2013         129 :   Node* first_arg = RegisterLocation(first_arg_reg);
    2014         129 :   Node* args_count = BytecodeOperandCount(2);
    2015         129 :   Node* context = GetContext();
    2016             :   Node* result_pair =
    2017         129 :       CallRuntimeN(function_id, context, first_arg, args_count, 2);
    2018             :   // Store the results in <first_return> and <first_return + 1>
    2019         129 :   Node* first_return_reg = BytecodeOperandReg(3);
    2020         129 :   Node* second_return_reg = NextRegister(first_return_reg);
    2021         129 :   Node* result0 = Projection(0, result_pair);
    2022         129 :   Node* result1 = Projection(1, result_pair);
    2023         129 :   StoreRegister(result0, first_return_reg);
    2024         129 :   StoreRegister(result1, second_return_reg);
    2025         129 :   Dispatch();
    2026         129 : }
    2027             : 
    2028             : // CallJSRuntime <context_index> <receiver> <arg_count>
    2029             : //
    2030             : // Call the JS runtime function that has the |context_index| with the receiver
    2031             : // in register |receiver| and |arg_count| arguments in subsequent registers.
    2032         258 : IGNITION_HANDLER(CallJSRuntime, InterpreterAssembler) {
    2033         129 :   Node* context_index = BytecodeOperandIdx(0);
    2034         129 :   Node* receiver_reg = BytecodeOperandReg(1);
    2035         129 :   Node* first_arg = RegisterLocation(receiver_reg);
    2036         129 :   Node* receiver_args_count = BytecodeOperandCount(2);
    2037         129 :   Node* receiver_count = Int32Constant(1);
    2038         129 :   Node* args_count = Int32Sub(receiver_args_count, receiver_count);
    2039             : 
    2040             :   // Get the function to call from the native context.
    2041         129 :   Node* context = GetContext();
    2042         129 :   Node* native_context = LoadNativeContext(context);
    2043         129 :   Node* function = LoadContextElement(native_context, context_index);
    2044             : 
    2045             :   // Call the function.
    2046             :   Node* result = CallJS(function, context, first_arg, args_count,
    2047         129 :                         ConvertReceiverMode::kAny, TailCallMode::kDisallow);
    2048         129 :   SetAccumulator(result);
    2049         129 :   Dispatch();
    2050         129 : }
    2051             : 
    2052             : // CallWithSpread <callable> <first_arg> <arg_count>
    2053             : //
    2054             : // Call a JSfunction or Callable in |callable| with the receiver in
    2055             : // |first_arg| and |arg_count - 1| arguments in subsequent registers. The
    2056             : // final argument is always a spread.
    2057             : //
    2058         258 : IGNITION_HANDLER(CallWithSpread, InterpreterAssembler) {
    2059         129 :   Node* callable_reg = BytecodeOperandReg(0);
    2060         129 :   Node* callable = LoadRegister(callable_reg);
    2061         129 :   Node* receiver_reg = BytecodeOperandReg(1);
    2062         129 :   Node* receiver_arg = RegisterLocation(receiver_reg);
    2063         129 :   Node* receiver_args_count = BytecodeOperandCount(2);
    2064         129 :   Node* receiver_count = Int32Constant(1);
    2065         129 :   Node* args_count = Int32Sub(receiver_args_count, receiver_count);
    2066         129 :   Node* context = GetContext();
    2067             : 
    2068             :   // Call into Runtime function CallWithSpread which does everything.
    2069         129 :   Node* result = CallJSWithSpread(callable, context, receiver_arg, args_count);
    2070         129 :   SetAccumulator(result);
    2071         129 :   Dispatch();
    2072         129 : }
    2073             : 
    2074             : // ConstructWithSpread <first_arg> <arg_count>
    2075             : //
    2076             : // Call the constructor in |constructor| with the first argument in register
    2077             : // |first_arg| and |arg_count| arguments in subsequent registers. The final
    2078             : // argument is always a spread. The new.target is in the accumulator.
    2079             : //
    2080         258 : IGNITION_HANDLER(ConstructWithSpread, InterpreterAssembler) {
    2081         129 :   Node* new_target = GetAccumulator();
    2082         129 :   Node* constructor_reg = BytecodeOperandReg(0);
    2083         129 :   Node* constructor = LoadRegister(constructor_reg);
    2084         129 :   Node* first_arg_reg = BytecodeOperandReg(1);
    2085         129 :   Node* first_arg = RegisterLocation(first_arg_reg);
    2086         129 :   Node* args_count = BytecodeOperandCount(2);
    2087         129 :   Node* context = GetContext();
    2088             :   Node* result = ConstructWithSpread(constructor, context, new_target,
    2089         129 :                                      first_arg, args_count);
    2090         129 :   SetAccumulator(result);
    2091         129 :   Dispatch();
    2092         129 : }
    2093             : 
    2094             : // Construct <constructor> <first_arg> <arg_count>
    2095             : //
    2096             : // Call operator construct with |constructor| and the first argument in
    2097             : // register |first_arg| and |arg_count| arguments in subsequent
    2098             : // registers. The new.target is in the accumulator.
    2099             : //
    2100         258 : IGNITION_HANDLER(Construct, InterpreterAssembler) {
    2101         129 :   Node* new_target = GetAccumulator();
    2102         129 :   Node* constructor_reg = BytecodeOperandReg(0);
    2103         129 :   Node* constructor = LoadRegister(constructor_reg);
    2104         129 :   Node* first_arg_reg = BytecodeOperandReg(1);
    2105         129 :   Node* first_arg = RegisterLocation(first_arg_reg);
    2106         129 :   Node* args_count = BytecodeOperandCount(2);
    2107         129 :   Node* slot_id = BytecodeOperandIdx(3);
    2108         129 :   Node* feedback_vector = LoadFeedbackVector();
    2109         129 :   Node* context = GetContext();
    2110             :   Node* result = Construct(constructor, context, new_target, first_arg,
    2111         129 :                            args_count, slot_id, feedback_vector);
    2112         129 :   SetAccumulator(result);
    2113         129 :   Dispatch();
    2114         129 : }
    2115             : 
    2116         774 : class InterpreterCompareOpAssembler : public InterpreterAssembler {
    2117             :  public:
    2118             :   InterpreterCompareOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
    2119             :                                 OperandScale operand_scale)
    2120         774 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    2121             : 
    2122         774 :   void CompareOpWithFeedback(Token::Value compare_op) {
    2123         774 :     Node* reg_index = BytecodeOperandReg(0);
    2124         774 :     Node* lhs = LoadRegister(reg_index);
    2125         774 :     Node* rhs = GetAccumulator();
    2126         774 :     Node* context = GetContext();
    2127         774 :     Node* slot_index = BytecodeOperandIdx(1);
    2128         774 :     Node* feedback_vector = LoadFeedbackVector();
    2129             : 
    2130         774 :     Variable var_result(this, MachineRepresentation::kTagged),
    2131        1548 :         var_fcmp_lhs(this, MachineRepresentation::kFloat64),
    2132        1548 :         var_fcmp_rhs(this, MachineRepresentation::kFloat64),
    2133        1548 :         non_number_value(this, MachineRepresentation::kTagged),
    2134        1548 :         maybe_smi_value(this, MachineRepresentation::kTagged);
    2135         774 :     Label lhs_is_not_smi(this), do_fcmp(this), slow_path(this),
    2136         774 :         fast_path_dispatch(this);
    2137             : 
    2138         774 :     GotoIf(TaggedIsNotSmi(lhs), &lhs_is_not_smi);
    2139             :     {
    2140             :       Label rhs_is_not_smi(this);
    2141         774 :       GotoIf(TaggedIsNotSmi(rhs), &rhs_is_not_smi);
    2142             :       {
    2143         774 :         Comment("Do integer comparison");
    2144             :         UpdateFeedback(SmiConstant(CompareOperationFeedback::kSignedSmall),
    2145         774 :                        feedback_vector, slot_index);
    2146             :         Node* result;
    2147         774 :         switch (compare_op) {
    2148             :           case Token::LT:
    2149         129 :             result = SelectBooleanConstant(SmiLessThan(lhs, rhs));
    2150         129 :             break;
    2151             :           case Token::LTE:
    2152         129 :             result = SelectBooleanConstant(SmiLessThanOrEqual(lhs, rhs));
    2153         129 :             break;
    2154             :           case Token::GT:
    2155         129 :             result = SelectBooleanConstant(SmiLessThan(rhs, lhs));
    2156         129 :             break;
    2157             :           case Token::GTE:
    2158         129 :             result = SelectBooleanConstant(SmiLessThanOrEqual(rhs, lhs));
    2159         129 :             break;
    2160             :           case Token::EQ:
    2161             :           case Token::EQ_STRICT:
    2162         258 :             result = SelectBooleanConstant(WordEqual(lhs, rhs));
    2163         258 :             break;
    2164             :           default:
    2165           0 :             UNREACHABLE();
    2166             :         }
    2167         774 :         var_result.Bind(result);
    2168         774 :         Goto(&fast_path_dispatch);
    2169             :       }
    2170             : 
    2171         774 :       Bind(&rhs_is_not_smi);
    2172             :       {
    2173         774 :         Node* rhs_map = LoadMap(rhs);
    2174             :         Label rhs_is_not_number(this);
    2175         774 :         GotoIfNot(IsHeapNumberMap(rhs_map), &rhs_is_not_number);
    2176             : 
    2177         774 :         Comment("Convert lhs to float and load HeapNumber value from rhs");
    2178         774 :         var_fcmp_lhs.Bind(SmiToFloat64(lhs));
    2179         774 :         var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
    2180         774 :         Goto(&do_fcmp);
    2181             : 
    2182         774 :         Bind(&rhs_is_not_number);
    2183             :         {
    2184         774 :           non_number_value.Bind(rhs);
    2185         774 :           maybe_smi_value.Bind(lhs);
    2186         774 :           Goto(&slow_path);
    2187         774 :         }
    2188         774 :       }
    2189             :     }
    2190             : 
    2191         774 :     Bind(&lhs_is_not_smi);
    2192             :     {
    2193         774 :       Label rhs_is_not_smi(this), lhs_is_not_number(this),
    2194         774 :           rhs_is_not_number(this);
    2195             : 
    2196         774 :       Node* lhs_map = LoadMap(lhs);
    2197         774 :       GotoIfNot(IsHeapNumberMap(lhs_map), &lhs_is_not_number);
    2198             : 
    2199         774 :       GotoIfNot(TaggedIsSmi(rhs), &rhs_is_not_smi);
    2200             : 
    2201         774 :       Comment("Convert rhs to double and load HeapNumber value from lhs");
    2202         774 :       var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
    2203         774 :       var_fcmp_rhs.Bind(SmiToFloat64(rhs));
    2204         774 :       Goto(&do_fcmp);
    2205             : 
    2206         774 :       Bind(&rhs_is_not_smi);
    2207             :       {
    2208         774 :         Node* rhs_map = LoadMap(rhs);
    2209         774 :         GotoIfNot(IsHeapNumberMap(rhs_map), &rhs_is_not_number);
    2210             : 
    2211         774 :         Comment("Load HeapNumber values from lhs and rhs");
    2212         774 :         var_fcmp_lhs.Bind(LoadHeapNumberValue(lhs));
    2213         774 :         var_fcmp_rhs.Bind(LoadHeapNumberValue(rhs));
    2214         774 :         Goto(&do_fcmp);
    2215             :       }
    2216             : 
    2217         774 :       Bind(&lhs_is_not_number);
    2218             :       {
    2219         774 :         non_number_value.Bind(lhs);
    2220         774 :         maybe_smi_value.Bind(rhs);
    2221         774 :         Goto(&slow_path);
    2222             :       }
    2223             : 
    2224         774 :       Bind(&rhs_is_not_number);
    2225             :       {
    2226         774 :         non_number_value.Bind(rhs);
    2227         774 :         maybe_smi_value.Bind(lhs);
    2228         774 :         Goto(&slow_path);
    2229         774 :       }
    2230             :     }
    2231             : 
    2232         774 :     Bind(&do_fcmp);
    2233             :     {
    2234         774 :       Comment("Do floating point comparison");
    2235         774 :       Node* lhs_float = var_fcmp_lhs.value();
    2236         774 :       Node* rhs_float = var_fcmp_rhs.value();
    2237             :       UpdateFeedback(SmiConstant(CompareOperationFeedback::kNumber),
    2238         774 :                      feedback_vector, slot_index);
    2239             : 
    2240             :       // Perform a fast floating point comparison.
    2241             :       Node* result;
    2242         774 :       switch (compare_op) {
    2243             :         case Token::LT:
    2244         129 :           result = SelectBooleanConstant(Float64LessThan(lhs_float, rhs_float));
    2245         129 :           break;
    2246             :         case Token::LTE:
    2247             :           result = SelectBooleanConstant(
    2248         129 :               Float64LessThanOrEqual(lhs_float, rhs_float));
    2249         129 :           break;
    2250             :         case Token::GT:
    2251             :           result =
    2252         129 :               SelectBooleanConstant(Float64GreaterThan(lhs_float, rhs_float));
    2253         129 :           break;
    2254             :         case Token::GTE:
    2255             :           result = SelectBooleanConstant(
    2256         129 :               Float64GreaterThanOrEqual(lhs_float, rhs_float));
    2257         129 :           break;
    2258             :         case Token::EQ:
    2259             :         case Token::EQ_STRICT: {
    2260             :           Label check_nan(this);
    2261         258 :           var_result.Bind(BooleanConstant(false));
    2262             :           Branch(Float64Equal(lhs_float, rhs_float), &check_nan,
    2263         258 :                  &fast_path_dispatch);
    2264         258 :           Bind(&check_nan);
    2265         258 :           result = SelectBooleanConstant(Float64Equal(lhs_float, lhs_float));
    2266         258 :         } break;
    2267             :         default:
    2268           0 :           UNREACHABLE();
    2269             :       }
    2270         774 :       var_result.Bind(result);
    2271         774 :       Goto(&fast_path_dispatch);
    2272             :     }
    2273             : 
    2274         774 :     Bind(&fast_path_dispatch);
    2275             :     {
    2276         774 :       SetAccumulator(var_result.value());
    2277         774 :       Dispatch();
    2278             :     }
    2279             : 
    2280             :     // Marking a block with more than one predecessor causes register allocator
    2281             :     // to fail (v8:5998). Add a dummy block as a workaround.
    2282             :     Label slow_path_deferred(this, Label::kDeferred);
    2283         774 :     Bind(&slow_path);
    2284         774 :     Goto(&slow_path_deferred);
    2285             : 
    2286         774 :     Bind(&slow_path_deferred);
    2287             :     {
    2288             :       // When we reach here, one of the operands is not a Smi / HeapNumber and
    2289             :       // the other operand could be of any type. The cases where both of them
    2290             :       // are HeapNumbers / Smis are handled earlier.
    2291         774 :       Comment("Collect feedback for non HeapNumber cases.");
    2292             :       Label update_feedback_and_do_compare(this);
    2293        1548 :       Variable var_type_feedback(this, MachineRepresentation::kTaggedSigned);
    2294         774 :       var_type_feedback.Bind(SmiConstant(CompareOperationFeedback::kAny));
    2295             : 
    2296         774 :       if (Token::IsOrderedRelationalCompareOp(compare_op)) {
    2297             :         Label check_for_oddball(this);
    2298             :         // Check for NumberOrOddball feedback.
    2299             :         Node* non_number_instance_type =
    2300         516 :             LoadInstanceType(non_number_value.value());
    2301             :         GotoIf(
    2302             :             Word32Equal(non_number_instance_type, Int32Constant(ODDBALL_TYPE)),
    2303         516 :             &check_for_oddball);
    2304             : 
    2305             :         // Check for string feedback.
    2306             :         GotoIfNot(IsStringInstanceType(non_number_instance_type),
    2307         516 :                   &update_feedback_and_do_compare);
    2308             : 
    2309             :         GotoIf(TaggedIsSmi(maybe_smi_value.value()),
    2310         516 :                &update_feedback_and_do_compare);
    2311             : 
    2312             :         Node* maybe_smi_instance_type =
    2313         516 :             LoadInstanceType(maybe_smi_value.value());
    2314             :         GotoIfNot(IsStringInstanceType(maybe_smi_instance_type),
    2315         516 :                   &update_feedback_and_do_compare);
    2316             : 
    2317         516 :         var_type_feedback.Bind(SmiConstant(CompareOperationFeedback::kString));
    2318         516 :         Goto(&update_feedback_and_do_compare);
    2319             : 
    2320         516 :         Bind(&check_for_oddball);
    2321             :         {
    2322             :           Label compare_with_oddball_feedback(this);
    2323             :           GotoIf(TaggedIsSmi(maybe_smi_value.value()),
    2324         516 :                  &compare_with_oddball_feedback);
    2325             : 
    2326             :           Node* maybe_smi_instance_type =
    2327         516 :               LoadInstanceType(maybe_smi_value.value());
    2328             :           GotoIf(Word32Equal(maybe_smi_instance_type,
    2329             :                              Int32Constant(HEAP_NUMBER_TYPE)),
    2330         516 :                  &compare_with_oddball_feedback);
    2331             : 
    2332             :           Branch(
    2333             :               Word32Equal(maybe_smi_instance_type, Int32Constant(ODDBALL_TYPE)),
    2334         516 :               &compare_with_oddball_feedback, &update_feedback_and_do_compare);
    2335             : 
    2336         516 :           Bind(&compare_with_oddball_feedback);
    2337             :           {
    2338             :             var_type_feedback.Bind(
    2339         516 :                 SmiConstant(CompareOperationFeedback::kNumberOrOddball));
    2340         516 :             Goto(&update_feedback_and_do_compare);
    2341         516 :           }
    2342         516 :         }
    2343             :       } else {
    2344         258 :         Label not_string(this), both_are_strings(this);
    2345             : 
    2346             :         DCHECK(Token::IsEqualityOp(compare_op));
    2347             : 
    2348             :         // If one of them is a Smi and the other is not a number, record "Any"
    2349             :         // feedback. Equality comparisons do not need feedback about oddballs.
    2350             :         GotoIf(TaggedIsSmi(maybe_smi_value.value()),
    2351         258 :                &update_feedback_and_do_compare);
    2352             : 
    2353             :         Node* maybe_smi_instance_type =
    2354         258 :             LoadInstanceType(maybe_smi_value.value());
    2355             :         Node* non_number_instance_type =
    2356         258 :             LoadInstanceType(non_number_value.value());
    2357         258 :         GotoIfNot(IsStringInstanceType(maybe_smi_instance_type), &not_string);
    2358             : 
    2359             :         // If one value is string and other isn't record "Any" feedback.
    2360             :         Branch(IsStringInstanceType(non_number_instance_type),
    2361         258 :                &both_are_strings, &update_feedback_and_do_compare);
    2362             : 
    2363         258 :         Bind(&both_are_strings);
    2364             :         {
    2365             :           Node* operand1_feedback = SelectSmiConstant(
    2366             :               Word32Equal(Word32And(maybe_smi_instance_type,
    2367             :                                     Int32Constant(kIsNotInternalizedMask)),
    2368             :                           Int32Constant(kInternalizedTag)),
    2369             :               CompareOperationFeedback::kInternalizedString,
    2370         258 :               CompareOperationFeedback::kString);
    2371             : 
    2372             :           Node* operand2_feedback = SelectSmiConstant(
    2373             :               Word32Equal(Word32And(non_number_instance_type,
    2374             :                                     Int32Constant(kIsNotInternalizedMask)),
    2375             :                           Int32Constant(kInternalizedTag)),
    2376             :               CompareOperationFeedback::kInternalizedString,
    2377         258 :               CompareOperationFeedback::kString);
    2378             : 
    2379         258 :           var_type_feedback.Bind(SmiOr(operand1_feedback, operand2_feedback));
    2380         258 :           Goto(&update_feedback_and_do_compare);
    2381             :         }
    2382             : 
    2383         258 :         Bind(&not_string);
    2384             :         {
    2385             :           // Check if both operands are of type JSReceiver.
    2386             :           GotoIfNot(IsJSReceiverInstanceType(maybe_smi_instance_type),
    2387         258 :                     &update_feedback_and_do_compare);
    2388             : 
    2389             :           GotoIfNot(IsJSReceiverInstanceType(non_number_instance_type),
    2390         258 :                     &update_feedback_and_do_compare);
    2391             : 
    2392             :           var_type_feedback.Bind(
    2393         258 :               SmiConstant(CompareOperationFeedback::kReceiver));
    2394         258 :           Goto(&update_feedback_and_do_compare);
    2395         258 :         }
    2396             :       }
    2397             : 
    2398         774 :       Bind(&update_feedback_and_do_compare);
    2399             :       {
    2400         774 :         Comment("Do the full compare operation");
    2401         774 :         UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index);
    2402             :         Node* result;
    2403         774 :         switch (compare_op) {
    2404             :           case Token::EQ:
    2405         129 :             result = Equal(lhs, rhs, context);
    2406         129 :             break;
    2407             :           case Token::EQ_STRICT:
    2408         129 :             result = StrictEqual(lhs, rhs);
    2409         129 :             break;
    2410             :           case Token::LT:
    2411             :             result = RelationalComparison(CodeStubAssembler::kLessThan, lhs,
    2412         129 :                                           rhs, context);
    2413         129 :             break;
    2414             :           case Token::GT:
    2415             :             result = RelationalComparison(CodeStubAssembler::kGreaterThan, lhs,
    2416         129 :                                           rhs, context);
    2417         129 :             break;
    2418             :           case Token::LTE:
    2419             :             result = RelationalComparison(CodeStubAssembler::kLessThanOrEqual,
    2420         129 :                                           lhs, rhs, context);
    2421         129 :             break;
    2422             :           case Token::GTE:
    2423             :             result = RelationalComparison(
    2424         129 :                 CodeStubAssembler::kGreaterThanOrEqual, lhs, rhs, context);
    2425         129 :             break;
    2426             :           default:
    2427           0 :             UNREACHABLE();
    2428             :         }
    2429         774 :         var_result.Bind(result);
    2430         774 :         SetAccumulator(var_result.value());
    2431         774 :         Dispatch();
    2432         774 :       }
    2433        1548 :     }
    2434         774 :   }
    2435             : };
    2436             : 
    2437             : // TestEqual <src>
    2438             : //
    2439             : // Test if the value in the <src> register equals the accumulator.
    2440         387 : IGNITION_HANDLER(TestEqual, InterpreterCompareOpAssembler) {
    2441         129 :   CompareOpWithFeedback(Token::Value::EQ);
    2442             : }
    2443             : 
    2444             : // TestEqualStrict <src>
    2445             : //
    2446             : // Test if the value in the <src> register is strictly equal to the accumulator.
    2447         387 : IGNITION_HANDLER(TestEqualStrict, InterpreterCompareOpAssembler) {
    2448         129 :   CompareOpWithFeedback(Token::Value::EQ_STRICT);
    2449             : }
    2450             : 
    2451             : // TestLessThan <src>
    2452             : //
    2453             : // Test if the value in the <src> register is less than the accumulator.
    2454         387 : IGNITION_HANDLER(TestLessThan, InterpreterCompareOpAssembler) {
    2455         129 :   CompareOpWithFeedback(Token::Value::LT);
    2456             : }
    2457             : 
    2458             : // TestGreaterThan <src>
    2459             : //
    2460             : // Test if the value in the <src> register is greater than the accumulator.
    2461         387 : IGNITION_HANDLER(TestGreaterThan, InterpreterCompareOpAssembler) {
    2462         129 :   CompareOpWithFeedback(Token::Value::GT);
    2463             : }
    2464             : 
    2465             : // TestLessThanOrEqual <src>
    2466             : //
    2467             : // Test if the value in the <src> register is less than or equal to the
    2468             : // accumulator.
    2469         387 : IGNITION_HANDLER(TestLessThanOrEqual, InterpreterCompareOpAssembler) {
    2470         129 :   CompareOpWithFeedback(Token::Value::LTE);
    2471             : }
    2472             : 
    2473             : // TestGreaterThanOrEqual <src>
    2474             : //
    2475             : // Test if the value in the <src> register is greater than or equal to the
    2476             : // accumulator.
    2477         387 : IGNITION_HANDLER(TestGreaterThanOrEqual, InterpreterCompareOpAssembler) {
    2478         129 :   CompareOpWithFeedback(Token::Value::GTE);
    2479             : }
    2480             : 
    2481             : // TestEqualStrictNoFeedback <src>
    2482             : //
    2483             : // Test if the value in the <src> register is strictly equal to the accumulator.
    2484             : // Type feedback is not collected.
    2485         258 : IGNITION_HANDLER(TestEqualStrictNoFeedback, InterpreterAssembler) {
    2486         129 :   Node* reg_index = BytecodeOperandReg(0);
    2487         129 :   Node* lhs = LoadRegister(reg_index);
    2488         129 :   Node* rhs = GetAccumulator();
    2489             :   // TODO(5310): This is called only when lhs and rhs are Smis (for ex:
    2490             :   // try-finally or generators) or strings (only when visiting
    2491             :   // ClassLiteralProperties). We should be able to optimize this and not perform
    2492             :   // the full strict equality.
    2493         129 :   Node* result = StrictEqual(lhs, rhs);
    2494         129 :   SetAccumulator(result);
    2495         129 :   Dispatch();
    2496         129 : }
    2497             : 
    2498             : // TestIn <src>
    2499             : //
    2500             : // Test if the object referenced by the register operand is a property of the
    2501             : // object referenced by the accumulator.
    2502         258 : IGNITION_HANDLER(TestIn, InterpreterAssembler) {
    2503         129 :   Node* reg_index = BytecodeOperandReg(0);
    2504         129 :   Node* property = LoadRegister(reg_index);
    2505         129 :   Node* object = GetAccumulator();
    2506         129 :   Node* context = GetContext();
    2507         129 :   SetAccumulator(HasProperty(object, property, context));
    2508         129 :   Dispatch();
    2509         129 : }
    2510             : 
    2511             : // TestInstanceOf <src>
    2512             : //
    2513             : // Test if the object referenced by the <src> register is an an instance of type
    2514             : // referenced by the accumulator.
    2515         258 : IGNITION_HANDLER(TestInstanceOf, InterpreterAssembler) {
    2516         129 :   Node* reg_index = BytecodeOperandReg(0);
    2517         129 :   Node* name = LoadRegister(reg_index);
    2518         129 :   Node* object = GetAccumulator();
    2519         129 :   Node* context = GetContext();
    2520         129 :   SetAccumulator(InstanceOf(name, object, context));
    2521         129 :   Dispatch();
    2522         129 : }
    2523             : 
    2524             : // TestUndetectable
    2525             : //
    2526             : // Test if the value in the accumulator is undetectable (null, undefined or
    2527             : // document.all).
    2528          86 : IGNITION_HANDLER(TestUndetectable, InterpreterAssembler) {
    2529          86 :   Label return_false(this), end(this);
    2530          43 :   Node* object = GetAccumulator();
    2531             : 
    2532             :   // If the object is an Smi then return false.
    2533          43 :   SetAccumulator(BooleanConstant(false));
    2534          43 :   GotoIf(TaggedIsSmi(object), &end);
    2535             : 
    2536             :   // If it is a HeapObject, load the map and check for undetectable bit.
    2537          43 :   Node* map = LoadMap(object);
    2538          43 :   Node* map_bitfield = LoadMapBitField(map);
    2539             :   Node* map_undetectable =
    2540          43 :       Word32And(map_bitfield, Int32Constant(1 << Map::kIsUndetectable));
    2541             :   Node* result =
    2542          43 :       SelectBooleanConstant(Word32NotEqual(map_undetectable, Int32Constant(0)));
    2543          43 :   SetAccumulator(result);
    2544          43 :   Goto(&end);
    2545             : 
    2546          43 :   Bind(&end);
    2547          86 :   Dispatch();
    2548          43 : }
    2549             : 
    2550             : // TestNull
    2551             : //
    2552             : // Test if the value in accumulator is strictly equal to null.
    2553          86 : IGNITION_HANDLER(TestNull, InterpreterAssembler) {
    2554          43 :   Node* object = GetAccumulator();
    2555          86 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2556          43 :   Node* result = SelectBooleanConstant(WordEqual(object, null_value));
    2557          43 :   SetAccumulator(result);
    2558          43 :   Dispatch();
    2559          43 : }
    2560             : 
    2561             : // TestUndefined
    2562             : //
    2563             : // Test if the value in the accumulator is strictly equal to undefined.
    2564          86 : IGNITION_HANDLER(TestUndefined, InterpreterAssembler) {
    2565          43 :   Node* object = GetAccumulator();
    2566          86 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2567          43 :   Node* result = SelectBooleanConstant(WordEqual(object, undefined_value));
    2568          43 :   SetAccumulator(result);
    2569          43 :   Dispatch();
    2570          43 : }
    2571             : 
    2572             : // TestTypeOf <literal_flag>
    2573             : //
    2574             : // Tests if the object in the <accumulator> is typeof the literal represented
    2575             : // by |literal_flag|.
    2576          86 : IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) {
    2577          43 :   Node* object = GetAccumulator();
    2578          43 :   Node* literal_flag = BytecodeOperandFlag(0);
    2579             : 
    2580             : #define MAKE_LABEL(name, lower_case) Label if_##lower_case(this);
    2581          86 :   TYPEOF_LITERAL_LIST(MAKE_LABEL)
    2582             : #undef MAKE_LABEL
    2583             : 
    2584             : #define LABEL_POINTER(name, lower_case) &if_##lower_case,
    2585          43 :   Label* labels[] = {TYPEOF_LITERAL_LIST(LABEL_POINTER)};
    2586             : #undef LABEL_POINTER
    2587             : 
    2588             : #define CASE(name, lower_case) \
    2589             :   static_cast<int32_t>(TestTypeOfFlags::LiteralFlag::k##name),
    2590          43 :   int32_t cases[] = {TYPEOF_LITERAL_LIST(CASE)};
    2591             : #undef CASE
    2592             : 
    2593          43 :   Label if_true(this), if_false(this), end(this), abort(this, Label::kDeferred);
    2594             : 
    2595          43 :   Switch(literal_flag, &abort, cases, labels, arraysize(cases));
    2596             : 
    2597          43 :   Bind(&abort);
    2598             :   {
    2599          43 :     Comment("Abort");
    2600          43 :     Abort(BailoutReason::kUnexpectedTestTypeofLiteralFlag);
    2601          43 :     Goto(&if_false);
    2602             :   }
    2603          43 :   Bind(&if_number);
    2604             :   {
    2605          43 :     Comment("IfNumber");
    2606          43 :     GotoIfNumber(object, &if_true);
    2607          43 :     Goto(&if_false);
    2608             :   }
    2609          43 :   Bind(&if_string);
    2610             :   {
    2611          43 :     Comment("IfString");
    2612          43 :     GotoIf(TaggedIsSmi(object), &if_false);
    2613          43 :     Branch(IsString(object), &if_true, &if_false);
    2614             :   }
    2615          43 :   Bind(&if_symbol);
    2616             :   {
    2617          43 :     Comment("IfSymbol");
    2618          43 :     GotoIf(TaggedIsSmi(object), &if_false);
    2619          43 :     Branch(IsSymbol(object), &if_true, &if_false);
    2620             :   }
    2621          43 :   Bind(&if_boolean);
    2622             :   {
    2623          43 :     Comment("IfBoolean");
    2624          43 :     GotoIf(WordEqual(object, BooleanConstant(true)), &if_true);
    2625          43 :     Branch(WordEqual(object, BooleanConstant(false)), &if_true, &if_false);
    2626             :   }
    2627          43 :   Bind(&if_undefined);
    2628             :   {
    2629          43 :     Comment("IfUndefined");
    2630          43 :     GotoIf(TaggedIsSmi(object), &if_false);
    2631             :     // Check it is not null and the map has the undetectable bit set.
    2632          43 :     GotoIf(WordEqual(object, NullConstant()), &if_false);
    2633          43 :     Node* map_bitfield = LoadMapBitField(LoadMap(object));
    2634             :     Node* undetectable_bit =
    2635          43 :         Word32And(map_bitfield, Int32Constant(1 << Map::kIsUndetectable));
    2636             :     Branch(Word32Equal(undetectable_bit, Int32Constant(0)), &if_false,
    2637          43 :            &if_true);
    2638             :   }
    2639          43 :   Bind(&if_function);
    2640             :   {
    2641          43 :     Comment("IfFunction");
    2642          43 :     GotoIf(TaggedIsSmi(object), &if_false);
    2643             :     // Check if callable bit is set and not undetectable.
    2644          43 :     Node* map_bitfield = LoadMapBitField(LoadMap(object));
    2645             :     Node* callable_undetectable = Word32And(
    2646             :         map_bitfield,
    2647          43 :         Int32Constant(1 << Map::kIsUndetectable | 1 << Map::kIsCallable));
    2648             :     Branch(Word32Equal(callable_undetectable,
    2649             :                        Int32Constant(1 << Map::kIsCallable)),
    2650          43 :            &if_true, &if_false);
    2651             :   }
    2652          43 :   Bind(&if_object);
    2653             :   {
    2654          43 :     Comment("IfObject");
    2655          43 :     GotoIf(TaggedIsSmi(object), &if_false);
    2656             : 
    2657             :     // If the object is null then return true.
    2658          43 :     GotoIf(WordEqual(object, NullConstant()), &if_true);
    2659             : 
    2660             :     // Check if the object is a receiver type and is not undefined or callable.
    2661          43 :     Node* map = LoadMap(object);
    2662          43 :     GotoIfNot(IsJSReceiverMap(map), &if_false);
    2663          43 :     Node* map_bitfield = LoadMapBitField(map);
    2664             :     Node* callable_undetectable = Word32And(
    2665             :         map_bitfield,
    2666          43 :         Int32Constant(1 << Map::kIsUndetectable | 1 << Map::kIsCallable));
    2667             :     Branch(Word32Equal(callable_undetectable, Int32Constant(0)), &if_true,
    2668          43 :            &if_false);
    2669             :   }
    2670          43 :   Bind(&if_other);
    2671             :   {
    2672             :     // Typeof doesn't return any other string value.
    2673          43 :     Goto(&if_false);
    2674             :   }
    2675             : 
    2676          43 :   Bind(&if_false);
    2677             :   {
    2678          43 :     SetAccumulator(BooleanConstant(false));
    2679          43 :     Goto(&end);
    2680             :   }
    2681          43 :   Bind(&if_true);
    2682             :   {
    2683          43 :     SetAccumulator(BooleanConstant(true));
    2684          43 :     Goto(&end);
    2685             :   }
    2686          43 :   Bind(&end);
    2687          86 :   Dispatch();
    2688          43 : }
    2689             : 
    2690             : // Jump <imm>
    2691             : //
    2692             : // Jump by number of bytes represented by the immediate operand |imm|.
    2693         258 : IGNITION_HANDLER(Jump, InterpreterAssembler) {
    2694         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2695         129 :   Jump(relative_jump);
    2696         129 : }
    2697             : 
    2698             : // JumpConstant <idx>
    2699             : //
    2700             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool.
    2701         258 : IGNITION_HANDLER(JumpConstant, InterpreterAssembler) {
    2702         129 :   Node* index = BytecodeOperandIdx(0);
    2703         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2704         129 :   Jump(relative_jump);
    2705         129 : }
    2706             : 
    2707             : // JumpIfTrue <imm>
    2708             : //
    2709             : // Jump by number of bytes represented by an immediate operand if the
    2710             : // accumulator contains true. This only works for boolean inputs, and
    2711             : // will misbehave if passed arbitrary input values.
    2712         258 : IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) {
    2713         129 :   Node* accumulator = GetAccumulator();
    2714         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2715         129 :   Node* true_value = BooleanConstant(true);
    2716             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2717             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2718         129 :   JumpIfWordEqual(accumulator, true_value, relative_jump);
    2719         129 : }
    2720             : 
    2721             : // JumpIfTrueConstant <idx>
    2722             : //
    2723             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2724             : // if the accumulator contains true. This only works for boolean inputs, and
    2725             : // will misbehave if passed arbitrary input values.
    2726         258 : IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) {
    2727         129 :   Node* accumulator = GetAccumulator();
    2728         129 :   Node* index = BytecodeOperandIdx(0);
    2729         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2730         129 :   Node* true_value = BooleanConstant(true);
    2731             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2732             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2733         129 :   JumpIfWordEqual(accumulator, true_value, relative_jump);
    2734         129 : }
    2735             : 
    2736             : // JumpIfFalse <imm>
    2737             : //
    2738             : // Jump by number of bytes represented by an immediate operand if the
    2739             : // accumulator contains false. This only works for boolean inputs, and
    2740             : // will misbehave if passed arbitrary input values.
    2741         258 : IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) {
    2742         129 :   Node* accumulator = GetAccumulator();
    2743         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2744         129 :   Node* false_value = BooleanConstant(false);
    2745             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2746             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2747         129 :   JumpIfWordEqual(accumulator, false_value, relative_jump);
    2748         129 : }
    2749             : 
    2750             : // JumpIfFalseConstant <idx>
    2751             : //
    2752             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2753             : // if the accumulator contains false. This only works for boolean inputs, and
    2754             : // will misbehave if passed arbitrary input values.
    2755         258 : IGNITION_HANDLER(JumpIfFalseConstant, InterpreterAssembler) {
    2756         129 :   Node* accumulator = GetAccumulator();
    2757         129 :   Node* index = BytecodeOperandIdx(0);
    2758         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2759         129 :   Node* false_value = BooleanConstant(false);
    2760             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2761             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2762         129 :   JumpIfWordEqual(accumulator, false_value, relative_jump);
    2763         129 : }
    2764             : 
    2765             : // JumpIfToBooleanTrue <imm>
    2766             : //
    2767             : // Jump by number of bytes represented by an immediate operand if the object
    2768             : // referenced by the accumulator is true when the object is cast to boolean.
    2769         258 : IGNITION_HANDLER(JumpIfToBooleanTrue, InterpreterAssembler) {
    2770         129 :   Node* value = GetAccumulator();
    2771         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2772         258 :   Label if_true(this), if_false(this);
    2773         129 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2774         129 :   Bind(&if_true);
    2775         129 :   Jump(relative_jump);
    2776         129 :   Bind(&if_false);
    2777         258 :   Dispatch();
    2778         129 : }
    2779             : 
    2780             : // JumpIfToBooleanTrueConstant <idx>
    2781             : //
    2782             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2783             : // if the object referenced by the accumulator is true when the object is cast
    2784             : // to boolean.
    2785         258 : IGNITION_HANDLER(JumpIfToBooleanTrueConstant, InterpreterAssembler) {
    2786         129 :   Node* value = GetAccumulator();
    2787         129 :   Node* index = BytecodeOperandIdx(0);
    2788         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2789         258 :   Label if_true(this), if_false(this);
    2790         129 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2791         129 :   Bind(&if_true);
    2792         129 :   Jump(relative_jump);
    2793         129 :   Bind(&if_false);
    2794         258 :   Dispatch();
    2795         129 : }
    2796             : 
    2797             : // JumpIfToBooleanFalse <imm>
    2798             : //
    2799             : // Jump by number of bytes represented by an immediate operand if the object
    2800             : // referenced by the accumulator is false when the object is cast to boolean.
    2801         258 : IGNITION_HANDLER(JumpIfToBooleanFalse, InterpreterAssembler) {
    2802         129 :   Node* value = GetAccumulator();
    2803         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2804         258 :   Label if_true(this), if_false(this);
    2805         129 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2806         129 :   Bind(&if_true);
    2807         129 :   Dispatch();
    2808         129 :   Bind(&if_false);
    2809         258 :   Jump(relative_jump);
    2810         129 : }
    2811             : 
    2812             : // JumpIfToBooleanFalseConstant <idx>
    2813             : //
    2814             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2815             : // if the object referenced by the accumulator is false when the object is cast
    2816             : // to boolean.
    2817         258 : IGNITION_HANDLER(JumpIfToBooleanFalseConstant, InterpreterAssembler) {
    2818         129 :   Node* value = GetAccumulator();
    2819         129 :   Node* index = BytecodeOperandIdx(0);
    2820         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2821         258 :   Label if_true(this), if_false(this);
    2822         129 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2823         129 :   Bind(&if_true);
    2824         129 :   Dispatch();
    2825         129 :   Bind(&if_false);
    2826         258 :   Jump(relative_jump);
    2827         129 : }
    2828             : 
    2829             : // JumpIfNull <imm>
    2830             : //
    2831             : // Jump by number of bytes represented by an immediate operand if the object
    2832             : // referenced by the accumulator is the null constant.
    2833         258 : IGNITION_HANDLER(JumpIfNull, InterpreterAssembler) {
    2834         129 :   Node* accumulator = GetAccumulator();
    2835         258 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2836         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2837         129 :   JumpIfWordEqual(accumulator, null_value, relative_jump);
    2838         129 : }
    2839             : 
    2840             : // JumpIfNullConstant <idx>
    2841             : //
    2842             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2843             : // if the object referenced by the accumulator is the null constant.
    2844         258 : IGNITION_HANDLER(JumpIfNullConstant, InterpreterAssembler) {
    2845         129 :   Node* accumulator = GetAccumulator();
    2846         258 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2847         129 :   Node* index = BytecodeOperandIdx(0);
    2848         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2849         129 :   JumpIfWordEqual(accumulator, null_value, relative_jump);
    2850         129 : }
    2851             : 
    2852             : // JumpIfNotNull <imm>
    2853             : //
    2854             : // Jump by number of bytes represented by an immediate operand if the object
    2855             : // referenced by the accumulator is not the null constant.
    2856         258 : IGNITION_HANDLER(JumpIfNotNull, InterpreterAssembler) {
    2857         129 :   Node* accumulator = GetAccumulator();
    2858         258 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2859         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2860         129 :   JumpIfWordNotEqual(accumulator, null_value, relative_jump);
    2861         129 : }
    2862             : 
    2863             : // JumpIfNotNullConstant <idx>
    2864             : //
    2865             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2866             : // if the object referenced by the accumulator is not the null constant.
    2867         258 : IGNITION_HANDLER(JumpIfNotNullConstant, InterpreterAssembler) {
    2868         129 :   Node* accumulator = GetAccumulator();
    2869         258 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2870         129 :   Node* index = BytecodeOperandIdx(0);
    2871         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2872         129 :   JumpIfWordNotEqual(accumulator, null_value, relative_jump);
    2873         129 : }
    2874             : 
    2875             : // JumpIfUndefined <imm>
    2876             : //
    2877             : // Jump by number of bytes represented by an immediate operand if the object
    2878             : // referenced by the accumulator is the undefined constant.
    2879         258 : IGNITION_HANDLER(JumpIfUndefined, InterpreterAssembler) {
    2880         129 :   Node* accumulator = GetAccumulator();
    2881         258 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2882         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2883         129 :   JumpIfWordEqual(accumulator, undefined_value, relative_jump);
    2884         129 : }
    2885             : 
    2886             : // JumpIfUndefinedConstant <idx>
    2887             : //
    2888             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2889             : // if the object referenced by the accumulator is the undefined constant.
    2890         258 : IGNITION_HANDLER(JumpIfUndefinedConstant, InterpreterAssembler) {
    2891         129 :   Node* accumulator = GetAccumulator();
    2892         258 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2893         129 :   Node* index = BytecodeOperandIdx(0);
    2894         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2895         129 :   JumpIfWordEqual(accumulator, undefined_value, relative_jump);
    2896         129 : }
    2897             : 
    2898             : // JumpIfNotUndefined <imm>
    2899             : //
    2900             : // Jump by number of bytes represented by an immediate operand if the object
    2901             : // referenced by the accumulator is not the undefined constant.
    2902         258 : IGNITION_HANDLER(JumpIfNotUndefined, InterpreterAssembler) {
    2903         129 :   Node* accumulator = GetAccumulator();
    2904         258 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2905         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2906         129 :   JumpIfWordNotEqual(accumulator, undefined_value, relative_jump);
    2907         129 : }
    2908             : 
    2909             : // JumpIfNotUndefinedConstant <idx>
    2910             : //
    2911             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2912             : // if the object referenced by the accumulator is not the undefined constant.
    2913         258 : IGNITION_HANDLER(JumpIfNotUndefinedConstant, InterpreterAssembler) {
    2914         129 :   Node* accumulator = GetAccumulator();
    2915         258 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2916         129 :   Node* index = BytecodeOperandIdx(0);
    2917         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2918         129 :   JumpIfWordNotEqual(accumulator, undefined_value, relative_jump);
    2919         129 : }
    2920             : 
    2921             : // JumpIfJSReceiver <imm>
    2922             : //
    2923             : // Jump by number of bytes represented by an immediate operand if the object
    2924             : // referenced by the accumulator is a JSReceiver.
    2925         258 : IGNITION_HANDLER(JumpIfJSReceiver, InterpreterAssembler) {
    2926         129 :   Node* accumulator = GetAccumulator();
    2927         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2928             : 
    2929         258 :   Label if_object(this), if_notobject(this, Label::kDeferred), if_notsmi(this);
    2930         129 :   Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi);
    2931             : 
    2932         129 :   Bind(&if_notsmi);
    2933         129 :   Branch(IsJSReceiver(accumulator), &if_object, &if_notobject);
    2934         129 :   Bind(&if_object);
    2935         129 :   Jump(relative_jump);
    2936             : 
    2937         129 :   Bind(&if_notobject);
    2938         258 :   Dispatch();
    2939         129 : }
    2940             : 
    2941             : // JumpIfJSReceiverConstant <idx>
    2942             : //
    2943             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool if
    2944             : // the object referenced by the accumulator is a JSReceiver.
    2945         258 : IGNITION_HANDLER(JumpIfJSReceiverConstant, InterpreterAssembler) {
    2946         129 :   Node* accumulator = GetAccumulator();
    2947         129 :   Node* index = BytecodeOperandIdx(0);
    2948         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2949             : 
    2950         258 :   Label if_object(this), if_notobject(this), if_notsmi(this);
    2951         129 :   Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi);
    2952             : 
    2953         129 :   Bind(&if_notsmi);
    2954         129 :   Branch(IsJSReceiver(accumulator), &if_object, &if_notobject);
    2955             : 
    2956         129 :   Bind(&if_object);
    2957         129 :   Jump(relative_jump);
    2958             : 
    2959         129 :   Bind(&if_notobject);
    2960         258 :   Dispatch();
    2961         129 : }
    2962             : 
    2963             : // JumpIfNotHole <imm>
    2964             : //
    2965             : // Jump by number of bytes represented by an immediate operand if the object
    2966             : // referenced by the accumulator is the hole.
    2967         258 : IGNITION_HANDLER(JumpIfNotHole, InterpreterAssembler) {
    2968         129 :   Node* accumulator = GetAccumulator();
    2969         258 :   Node* the_hole_value = HeapConstant(isolate()->factory()->the_hole_value());
    2970         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2971         129 :   JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
    2972         129 : }
    2973             : 
    2974             : // JumpIfNotHoleConstant <idx>
    2975             : //
    2976             : // Jump by number of bytes in the Smi in the |idx| entry in the constant pool
    2977             : // if the object referenced by the accumulator is the hole constant.
    2978         258 : IGNITION_HANDLER(JumpIfNotHoleConstant, InterpreterAssembler) {
    2979         129 :   Node* accumulator = GetAccumulator();
    2980         258 :   Node* the_hole_value = HeapConstant(isolate()->factory()->the_hole_value());
    2981         129 :   Node* index = BytecodeOperandIdx(0);
    2982         129 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2983         129 :   JumpIfWordNotEqual(accumulator, the_hole_value, relative_jump);
    2984         129 : }
    2985             : 
    2986             : // JumpLoop <imm> <loop_depth>
    2987             : //
    2988             : // Jump by number of bytes represented by the immediate operand |imm|. Also
    2989             : // performs a loop nesting check and potentially triggers OSR in case the
    2990             : // current OSR level matches (or exceeds) the specified |loop_depth|.
    2991         258 : IGNITION_HANDLER(JumpLoop, InterpreterAssembler) {
    2992         129 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2993         129 :   Node* loop_depth = BytecodeOperandImm(1);
    2994         129 :   Node* osr_level = LoadOSRNestingLevel();
    2995             : 
    2996             :   // Check if OSR points at the given {loop_depth} are armed by comparing it to
    2997             :   // the current {osr_level} loaded from the header of the BytecodeArray.
    2998         258 :   Label ok(this), osr_armed(this, Label::kDeferred);
    2999         129 :   Node* condition = Int32GreaterThanOrEqual(loop_depth, osr_level);
    3000         129 :   Branch(condition, &ok, &osr_armed);
    3001             : 
    3002         129 :   Bind(&ok);
    3003         129 :   JumpBackward(relative_jump);
    3004             : 
    3005         129 :   Bind(&osr_armed);
    3006             :   {
    3007         129 :     Callable callable = CodeFactory::InterpreterOnStackReplacement(isolate());
    3008         129 :     Node* target = HeapConstant(callable.code());
    3009         129 :     Node* context = GetContext();
    3010         129 :     CallStub(callable.descriptor(), target, context);
    3011         129 :     JumpBackward(relative_jump);
    3012         129 :   }
    3013         129 : }
    3014             : 
    3015             : // CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
    3016             : //
    3017             : // Creates a regular expression literal for literal index <literal_idx> with
    3018             : // <flags> and the pattern in <pattern_idx>.
    3019         258 : IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
    3020         129 :   Node* index = BytecodeOperandIdx(0);
    3021         129 :   Node* pattern = LoadConstantPoolEntry(index);
    3022         129 :   Node* literal_index = BytecodeOperandIdxSmi(1);
    3023         129 :   Node* flags = SmiFromWord32(BytecodeOperandFlag(2));
    3024         129 :   Node* closure = LoadRegister(Register::function_closure());
    3025         129 :   Node* context = GetContext();
    3026             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    3027             :   Node* result = constructor_assembler.EmitFastCloneRegExp(
    3028         129 :       closure, literal_index, pattern, flags, context);
    3029         129 :   SetAccumulator(result);
    3030         129 :   Dispatch();
    3031         129 : }
    3032             : 
    3033             : // CreateArrayLiteral <element_idx> <literal_idx> <flags>
    3034             : //
    3035             : // Creates an array literal for literal index <literal_idx> with
    3036             : // CreateArrayLiteral flags <flags> and constant elements in <element_idx>.
    3037         258 : IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
    3038         129 :   Node* literal_index = BytecodeOperandIdxSmi(1);
    3039         129 :   Node* closure = LoadRegister(Register::function_closure());
    3040         129 :   Node* context = GetContext();
    3041         129 :   Node* bytecode_flags = BytecodeOperandFlag(2);
    3042             : 
    3043         258 :   Label fast_shallow_clone(this), call_runtime(this, Label::kDeferred);
    3044             :   Branch(
    3045             :       IsSetWord32<CreateArrayLiteralFlags::FastShallowCloneBit>(bytecode_flags),
    3046         258 :       &fast_shallow_clone, &call_runtime);
    3047             : 
    3048         129 :   Bind(&fast_shallow_clone);
    3049             :   {
    3050             :     ConstructorBuiltinsAssembler constructor_assembler(state());
    3051             :     Node* result = constructor_assembler.EmitFastCloneShallowArray(
    3052         129 :         closure, literal_index, context, &call_runtime, TRACK_ALLOCATION_SITE);
    3053         129 :     SetAccumulator(result);
    3054         129 :     Dispatch();
    3055             :   }
    3056             : 
    3057         129 :   Bind(&call_runtime);
    3058             :   {
    3059             :     Node* flags_raw = DecodeWordFromWord32<CreateArrayLiteralFlags::FlagsBits>(
    3060         129 :         bytecode_flags);
    3061         129 :     Node* flags = SmiTag(flags_raw);
    3062         129 :     Node* index = BytecodeOperandIdx(0);
    3063         129 :     Node* constant_elements = LoadConstantPoolEntry(index);
    3064             :     Node* result = CallRuntime(Runtime::kCreateArrayLiteral, context, closure,
    3065         129 :                                literal_index, constant_elements, flags);
    3066         129 :     SetAccumulator(result);
    3067         129 :     Dispatch();
    3068         129 :   }
    3069         129 : }
    3070             : 
    3071             : // CreateObjectLiteral <element_idx> <literal_idx> <flags>
    3072             : //
    3073             : // Creates an object literal for literal index <literal_idx> with
    3074             : // CreateObjectLiteralFlags <flags> and constant elements in <element_idx>.
    3075         258 : IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
    3076         129 :   Node* literal_index = BytecodeOperandIdxSmi(1);
    3077         129 :   Node* bytecode_flags = BytecodeOperandFlag(2);
    3078         129 :   Node* closure = LoadRegister(Register::function_closure());
    3079             : 
    3080             :   // Check if we can do a fast clone or have to call the runtime.
    3081         258 :   Label if_fast_clone(this), if_not_fast_clone(this, Label::kDeferred);
    3082             :   Node* fast_clone_properties_count = DecodeWordFromWord32<
    3083         129 :       CreateObjectLiteralFlags::FastClonePropertiesCountBits>(bytecode_flags);
    3084             :   Branch(WordNotEqual(fast_clone_properties_count, IntPtrConstant(0)),
    3085         129 :          &if_fast_clone, &if_not_fast_clone);
    3086             : 
    3087         129 :   Bind(&if_fast_clone);
    3088             :   {
    3089             :     // If we can do a fast clone do the fast-path in FastCloneShallowObjectStub.
    3090             :     ConstructorBuiltinsAssembler constructor_assembler(state());
    3091             :     Node* result = constructor_assembler.EmitFastCloneShallowObject(
    3092             :         &if_not_fast_clone, closure, literal_index,
    3093         129 :         fast_clone_properties_count);
    3094         129 :     StoreRegister(result, BytecodeOperandReg(3));
    3095         129 :     Dispatch();
    3096             :   }
    3097             : 
    3098         129 :   Bind(&if_not_fast_clone);
    3099             :   {
    3100             :     // If we can't do a fast clone, call into the runtime.
    3101         129 :     Node* index = BytecodeOperandIdx(0);
    3102         129 :     Node* constant_elements = LoadConstantPoolEntry(index);
    3103         129 :     Node* context = GetContext();
    3104             : 
    3105             :     Node* flags_raw = DecodeWordFromWord32<CreateObjectLiteralFlags::FlagsBits>(
    3106         129 :         bytecode_flags);
    3107         129 :     Node* flags = SmiTag(flags_raw);
    3108             : 
    3109             :     Node* result = CallRuntime(Runtime::kCreateObjectLiteral, context, closure,
    3110         129 :                                literal_index, constant_elements, flags);
    3111         129 :     StoreRegister(result, BytecodeOperandReg(3));
    3112             :     // TODO(klaasb) build a single dispatch once the call is inlined
    3113         129 :     Dispatch();
    3114         129 :   }
    3115         129 : }
    3116             : 
    3117             : // CreateClosure <index> <slot> <tenured>
    3118             : //
    3119             : // Creates a new closure for SharedFunctionInfo at position |index| in the
    3120             : // constant pool and with the PretenureFlag <tenured>.
    3121         258 : IGNITION_HANDLER(CreateClosure, InterpreterAssembler) {
    3122         129 :   Node* index = BytecodeOperandIdx(0);
    3123         129 :   Node* shared = LoadConstantPoolEntry(index);
    3124         129 :   Node* flags = BytecodeOperandFlag(2);
    3125         129 :   Node* context = GetContext();
    3126             : 
    3127         129 :   Label call_runtime(this, Label::kDeferred);
    3128             :   GotoIfNot(IsSetWord32<CreateClosureFlags::FastNewClosureBit>(flags),
    3129         258 :             &call_runtime);
    3130             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    3131         129 :   Node* vector_index = BytecodeOperandIdx(1);
    3132         129 :   vector_index = SmiTag(vector_index);
    3133         129 :   Node* feedback_vector = LoadFeedbackVector();
    3134             :   SetAccumulator(constructor_assembler.EmitFastNewClosure(
    3135         129 :       shared, feedback_vector, vector_index, context));
    3136         129 :   Dispatch();
    3137             : 
    3138         129 :   Bind(&call_runtime);
    3139             :   {
    3140             :     Node* tenured_raw =
    3141         129 :         DecodeWordFromWord32<CreateClosureFlags::PretenuredBit>(flags);
    3142         129 :     Node* tenured = SmiTag(tenured_raw);
    3143         129 :     feedback_vector = LoadFeedbackVector();
    3144         129 :     vector_index = BytecodeOperandIdx(1);
    3145         129 :     vector_index = SmiTag(vector_index);
    3146             :     Node* result = CallRuntime(Runtime::kInterpreterNewClosure, context, shared,
    3147         129 :                                feedback_vector, vector_index, tenured);
    3148         129 :     SetAccumulator(result);
    3149         129 :     Dispatch();
    3150         129 :   }
    3151         129 : }
    3152             : 
    3153             : // CreateBlockContext <index>
    3154             : //
    3155             : // Creates a new block context with the scope info constant at |index| and the
    3156             : // closure in the accumulator.
    3157         258 : IGNITION_HANDLER(CreateBlockContext, InterpreterAssembler) {
    3158         129 :   Node* index = BytecodeOperandIdx(0);
    3159         129 :   Node* scope_info = LoadConstantPoolEntry(index);
    3160         129 :   Node* closure = GetAccumulator();
    3161         129 :   Node* context = GetContext();
    3162             :   SetAccumulator(
    3163         129 :       CallRuntime(Runtime::kPushBlockContext, context, scope_info, closure));
    3164         129 :   Dispatch();
    3165         129 : }
    3166             : 
    3167             : // CreateCatchContext <exception> <name_idx> <scope_info_idx>
    3168             : //
    3169             : // Creates a new context for a catch block with the |exception| in a register,
    3170             : // the variable name at |name_idx|, the ScopeInfo at |scope_info_idx|, and the
    3171             : // closure in the accumulator.
    3172         258 : IGNITION_HANDLER(CreateCatchContext, InterpreterAssembler) {
    3173         129 :   Node* exception_reg = BytecodeOperandReg(0);
    3174         129 :   Node* exception = LoadRegister(exception_reg);
    3175         129 :   Node* name_idx = BytecodeOperandIdx(1);
    3176         129 :   Node* name = LoadConstantPoolEntry(name_idx);
    3177         129 :   Node* scope_info_idx = BytecodeOperandIdx(2);
    3178         129 :   Node* scope_info = LoadConstantPoolEntry(scope_info_idx);
    3179         129 :   Node* closure = GetAccumulator();
    3180         129 :   Node* context = GetContext();
    3181             :   SetAccumulator(CallRuntime(Runtime::kPushCatchContext, context, name,
    3182         129 :                              exception, scope_info, closure));
    3183         129 :   Dispatch();
    3184         129 : }
    3185             : 
    3186             : // CreateFunctionContext <slots>
    3187             : //
    3188             : // Creates a new context with number of |slots| for the function closure.
    3189         258 : IGNITION_HANDLER(CreateFunctionContext, InterpreterAssembler) {
    3190         129 :   Node* closure = LoadRegister(Register::function_closure());
    3191         129 :   Node* slots = BytecodeOperandUImm(0);
    3192         129 :   Node* context = GetContext();
    3193             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    3194             :   SetAccumulator(constructor_assembler.EmitFastNewFunctionContext(
    3195         129 :       closure, slots, context, FUNCTION_SCOPE));
    3196         129 :   Dispatch();
    3197         129 : }
    3198             : 
    3199             : // CreateEvalContext <slots>
    3200             : //
    3201             : // Creates a new context with number of |slots| for an eval closure.
    3202         258 : IGNITION_HANDLER(CreateEvalContext, InterpreterAssembler) {
    3203         129 :   Node* closure = LoadRegister(Register::function_closure());
    3204         129 :   Node* slots = BytecodeOperandUImm(0);
    3205         129 :   Node* context = GetContext();
    3206             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    3207             :   SetAccumulator(constructor_assembler.EmitFastNewFunctionContext(
    3208         129 :       closure, slots, context, EVAL_SCOPE));
    3209         129 :   Dispatch();
    3210         129 : }
    3211             : 
    3212             : // CreateWithContext <register> <scope_info_idx>
    3213             : //
    3214             : // Creates a new context with the ScopeInfo at |scope_info_idx| for a
    3215             : // with-statement with the object in |register| and the closure in the
    3216             : // accumulator.
    3217         258 : IGNITION_HANDLER(CreateWithContext, InterpreterAssembler) {
    3218         129 :   Node* reg_index = BytecodeOperandReg(0);
    3219         129 :   Node* object = LoadRegister(reg_index);
    3220         129 :   Node* scope_info_idx = BytecodeOperandIdx(1);
    3221         129 :   Node* scope_info = LoadConstantPoolEntry(scope_info_idx);
    3222         129 :   Node* closure = GetAccumulator();
    3223         129 :   Node* context = GetContext();
    3224             :   SetAccumulator(CallRuntime(Runtime::kPushWithContext, context, object,
    3225         129 :                              scope_info, closure));
    3226         129 :   Dispatch();
    3227         129 : }
    3228             : 
    3229             : // CreateMappedArguments
    3230             : //
    3231             : // Creates a new mapped arguments object.
    3232          86 : IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) {
    3233          43 :   Node* closure = LoadRegister(Register::function_closure());
    3234          43 :   Node* context = GetContext();
    3235             : 
    3236          43 :   Label if_duplicate_parameters(this, Label::kDeferred);
    3237          43 :   Label if_not_duplicate_parameters(this);
    3238             : 
    3239             :   // Check if function has duplicate parameters.
    3240             :   // TODO(rmcilroy): Remove this check when FastNewSloppyArgumentsStub supports
    3241             :   // duplicate parameters.
    3242             :   Node* shared_info =
    3243          43 :       LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
    3244             :   Node* compiler_hints = LoadObjectField(
    3245             :       shared_info, SharedFunctionInfo::kHasDuplicateParametersByteOffset,
    3246          43 :       MachineType::Uint8());
    3247             :   Node* duplicate_parameters_bit = Int32Constant(
    3248          43 :       1 << SharedFunctionInfo::kHasDuplicateParametersBitWithinByte);
    3249          43 :   Node* compare = Word32And(compiler_hints, duplicate_parameters_bit);
    3250          43 :   Branch(compare, &if_duplicate_parameters, &if_not_duplicate_parameters);
    3251             : 
    3252          43 :   Bind(&if_not_duplicate_parameters);
    3253             :   {
    3254             :     ArgumentsBuiltinsAssembler constructor_assembler(state());
    3255             :     Node* result =
    3256          43 :         constructor_assembler.EmitFastNewSloppyArguments(context, closure);
    3257          43 :     SetAccumulator(result);
    3258          43 :     Dispatch();
    3259             :   }
    3260             : 
    3261          43 :   Bind(&if_duplicate_parameters);
    3262             :   {
    3263             :     Node* result =
    3264          43 :         CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
    3265          43 :     SetAccumulator(result);
    3266          43 :     Dispatch();
    3267          43 :   }
    3268          43 : }
    3269             : 
    3270             : // CreateUnmappedArguments
    3271             : //
    3272             : // Creates a new unmapped arguments object.
    3273          86 : IGNITION_HANDLER(CreateUnmappedArguments, InterpreterAssembler) {
    3274          43 :   Node* context = GetContext();
    3275          43 :   Node* closure = LoadRegister(Register::function_closure());
    3276             :   ArgumentsBuiltinsAssembler builtins_assembler(state());
    3277             :   Node* result =
    3278          43 :       builtins_assembler.EmitFastNewStrictArguments(context, closure);
    3279          43 :   SetAccumulator(result);
    3280          43 :   Dispatch();
    3281          43 : }
    3282             : 
    3283             : // CreateRestParameter
    3284             : //
    3285             : // Creates a new rest parameter array.
    3286          86 : IGNITION_HANDLER(CreateRestParameter, InterpreterAssembler) {
    3287          43 :   Node* closure = LoadRegister(Register::function_closure());
    3288          43 :   Node* context = GetContext();
    3289             :   ArgumentsBuiltinsAssembler builtins_assembler(state());
    3290          43 :   Node* result = builtins_assembler.EmitFastNewRestParameter(context, closure);
    3291          43 :   SetAccumulator(result);
    3292          43 :   Dispatch();
    3293          43 : }
    3294             : 
    3295             : // StackCheck
    3296             : //
    3297             : // Performs a stack guard check.
    3298          86 : IGNITION_HANDLER(StackCheck, InterpreterAssembler) {
    3299          86 :   Label ok(this), stack_check_interrupt(this, Label::kDeferred);
    3300             : 
    3301          43 :   Node* interrupt = StackCheckTriggeredInterrupt();
    3302          43 :   Branch(interrupt, &stack_check_interrupt, &ok);
    3303             : 
    3304          43 :   Bind(&ok);
    3305          43 :   Dispatch();
    3306             : 
    3307          43 :   Bind(&stack_check_interrupt);
    3308             :   {
    3309          43 :     Node* context = GetContext();
    3310          43 :     CallRuntime(Runtime::kStackGuard, context);
    3311          43 :     Dispatch();
    3312          43 :   }
    3313          43 : }
    3314             : 
    3315             : // SetPendingMessage
    3316             : //
    3317             : // Sets the pending message to the value in the accumulator, and returns the
    3318             : // previous pending message in the accumulator.
    3319          86 : IGNITION_HANDLER(SetPendingMessage, InterpreterAssembler) {
    3320             :   Node* pending_message = ExternalConstant(
    3321          43 :       ExternalReference::address_of_pending_message_obj(isolate()));
    3322          43 :   Node* previous_message = Load(MachineType::TaggedPointer(), pending_message);
    3323          43 :   Node* new_message = GetAccumulator();
    3324             :   StoreNoWriteBarrier(MachineRepresentation::kTaggedPointer, pending_message,
    3325          43 :                       new_message);
    3326          43 :   SetAccumulator(previous_message);
    3327          43 :   Dispatch();
    3328          43 : }
    3329             : 
    3330             : // Throw
    3331             : //
    3332             : // Throws the exception in the accumulator.
    3333          86 : IGNITION_HANDLER(Throw, InterpreterAssembler) {
    3334          43 :   Node* exception = GetAccumulator();
    3335          43 :   Node* context = GetContext();
    3336          43 :   CallRuntime(Runtime::kThrow, context, exception);
    3337             :   // We shouldn't ever return from a throw.
    3338          43 :   Abort(kUnexpectedReturnFromThrow);
    3339          43 : }
    3340             : 
    3341             : // ReThrow
    3342             : //
    3343             : // Re-throws the exception in the accumulator.
    3344          86 : IGNITION_HANDLER(ReThrow, InterpreterAssembler) {
    3345          43 :   Node* exception = GetAccumulator();
    3346          43 :   Node* context = GetContext();
    3347          43 :   CallRuntime(Runtime::kReThrow, context, exception);
    3348             :   // We shouldn't ever return from a throw.
    3349          43 :   Abort(kUnexpectedReturnFromThrow);
    3350          43 : }
    3351             : 
    3352             : // Return
    3353             : //
    3354             : // Return the value in the accumulator.
    3355          86 : IGNITION_HANDLER(Return, InterpreterAssembler) {
    3356          43 :   UpdateInterruptBudgetOnReturn();
    3357          43 :   Node* accumulator = GetAccumulator();
    3358          43 :   Return(accumulator);
    3359          43 : }
    3360             : 
    3361             : // Debugger
    3362             : //
    3363             : // Call runtime to handle debugger statement.
    3364          86 : IGNITION_HANDLER(Debugger, InterpreterAssembler) {
    3365          43 :   Node* context = GetContext();
    3366          86 :   CallStub(CodeFactory::HandleDebuggerStatement(isolate()), context);
    3367          43 :   Dispatch();
    3368          43 : }
    3369             : 
    3370             : // DebugBreak
    3371             : //
    3372             : // Call runtime to handle a debug break.
    3373             : #define DEBUG_BREAK(Name, ...)                                             \
    3374             :   IGNITION_HANDLER(Name, InterpreterAssembler) {                           \
    3375             :     Node* context = GetContext();                                          \
    3376             :     Node* accumulator = GetAccumulator();                                  \
    3377             :     Node* original_handler =                                               \
    3378             :         CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \
    3379             :     MaybeDropFrames(context);                                              \
    3380             :     DispatchToBytecodeHandler(original_handler);                           \
    3381             :   }
    3382        1806 : DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
    3383             : #undef DEBUG_BREAK
    3384             : 
    3385         129 : class InterpreterForInPrepareAssembler : public InterpreterAssembler {
    3386             :  public:
    3387             :   InterpreterForInPrepareAssembler(CodeAssemblerState* state, Bytecode bytecode,
    3388             :                                    OperandScale operand_scale)
    3389         129 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    3390             : 
    3391         387 :   void BuildForInPrepareResult(Node* output_register, Node* cache_type,
    3392             :                                Node* cache_array, Node* cache_length) {
    3393         387 :     StoreRegister(cache_type, output_register);
    3394         387 :     output_register = NextRegister(output_register);
    3395         387 :     StoreRegister(cache_array, output_register);
    3396         387 :     output_register = NextRegister(output_register);
    3397         387 :     StoreRegister(cache_length, output_register);
    3398         387 :   }
    3399             : };
    3400             : 
    3401             : // ForInPrepare <receiver> <cache_info_triple>
    3402             : //
    3403             : // Returns state for for..in loop execution based on the object in the register
    3404             : // |receiver|. The object must not be null or undefined and must have been
    3405             : // converted to a receiver already.
    3406             : // The result is output in registers |cache_info_triple| to
    3407             : // |cache_info_triple + 2|, with the registers holding cache_type, cache_array,
    3408             : // and cache_length respectively.
    3409         516 : IGNITION_HANDLER(ForInPrepare, InterpreterForInPrepareAssembler) {
    3410         129 :   Node* object_register = BytecodeOperandReg(0);
    3411         129 :   Node* output_register = BytecodeOperandReg(1);
    3412         129 :   Node* receiver = LoadRegister(object_register);
    3413         129 :   Node* context = GetContext();
    3414             : 
    3415             :   Node* cache_type;
    3416             :   Node* cache_array;
    3417             :   Node* cache_length;
    3418         129 :   Label call_runtime(this, Label::kDeferred),
    3419         129 :       nothing_to_iterate(this, Label::kDeferred);
    3420             : 
    3421             :   ForInBuiltinsAssembler forin_assembler(state());
    3422         258 :   std::tie(cache_type, cache_array, cache_length) =
    3423             :       forin_assembler.EmitForInPrepare(receiver, context, &call_runtime,
    3424             :                                        &nothing_to_iterate);
    3425             : 
    3426             :   BuildForInPrepareResult(output_register, cache_type, cache_array,
    3427         129 :                           cache_length);
    3428         129 :   Dispatch();
    3429             : 
    3430         129 :   Bind(&call_runtime);
    3431             :   {
    3432             :     Node* result_triple =
    3433         129 :         CallRuntime(Runtime::kForInPrepare, context, receiver);
    3434         129 :     Node* cache_type = Projection(0, result_triple);
    3435         129 :     Node* cache_array = Projection(1, result_triple);
    3436         129 :     Node* cache_length = Projection(2, result_triple);
    3437             :     BuildForInPrepareResult(output_register, cache_type, cache_array,
    3438         129 :                             cache_length);
    3439         129 :     Dispatch();
    3440             :   }
    3441         129 :   Bind(&nothing_to_iterate);
    3442             :   {
    3443             :     // Receiver is null or undefined or descriptors are zero length.
    3444         129 :     Node* zero = SmiConstant(0);
    3445         129 :     BuildForInPrepareResult(output_register, zero, zero, zero);
    3446         129 :     Dispatch();
    3447         129 :   }
    3448         129 : }
    3449             : 
    3450             : // ForInNext <receiver> <index> <cache_info_pair>
    3451             : //
    3452             : // Returns the next enumerable property in the the accumulator.
    3453         258 : IGNITION_HANDLER(ForInNext, InterpreterAssembler) {
    3454         129 :   Node* receiver_reg = BytecodeOperandReg(0);
    3455         129 :   Node* receiver = LoadRegister(receiver_reg);
    3456         129 :   Node* index_reg = BytecodeOperandReg(1);
    3457         129 :   Node* index = LoadRegister(index_reg);
    3458         129 :   Node* cache_type_reg = BytecodeOperandReg(2);
    3459         129 :   Node* cache_type = LoadRegister(cache_type_reg);
    3460         129 :   Node* cache_array_reg = NextRegister(cache_type_reg);
    3461         129 :   Node* cache_array = LoadRegister(cache_array_reg);
    3462             : 
    3463             :   // Load the next key from the enumeration array.
    3464             :   Node* key = LoadFixedArrayElement(cache_array, index, 0,
    3465         129 :                                     CodeStubAssembler::SMI_PARAMETERS);
    3466             : 
    3467             :   // Check if we can use the for-in fast path potentially using the enum cache.
    3468         258 :   Label if_fast(this), if_slow(this, Label::kDeferred);
    3469         129 :   Node* receiver_map = LoadMap(receiver);
    3470         129 :   Branch(WordEqual(receiver_map, cache_type), &if_fast, &if_slow);
    3471         129 :   Bind(&if_fast);
    3472             :   {
    3473             :     // Enum cache in use for {receiver}, the {key} is definitely valid.
    3474         129 :     SetAccumulator(key);
    3475         129 :     Dispatch();
    3476             :   }
    3477         129 :   Bind(&if_slow);
    3478             :   {
    3479             :     // Record the fact that we hit the for-in slow path.
    3480         129 :     Node* vector_index = BytecodeOperandIdx(3);
    3481         129 :     Node* feedback_vector = LoadFeedbackVector();
    3482             :     Node* megamorphic_sentinel =
    3483         258 :         HeapConstant(FeedbackVector::MegamorphicSentinel(isolate()));
    3484             :     StoreFixedArrayElement(feedback_vector, vector_index, megamorphic_sentinel,
    3485         129 :                            SKIP_WRITE_BARRIER);
    3486             : 
    3487             :     // Need to filter the {key} for the {receiver}.
    3488         129 :     Node* context = GetContext();
    3489         129 :     Callable callable = CodeFactory::ForInFilter(isolate());
    3490         129 :     Node* result = CallStub(callable, context, key, receiver);
    3491         129 :     SetAccumulator(result);
    3492         129 :     Dispatch();
    3493         129 :   }
    3494         129 : }
    3495             : 
    3496             : // ForInContinue <index> <cache_length>
    3497             : //
    3498             : // Returns false if the end of the enumerable properties has been reached.
    3499         258 : IGNITION_HANDLER(ForInContinue, InterpreterAssembler) {
    3500         129 :   Node* index_reg = BytecodeOperandReg(0);
    3501         129 :   Node* index = LoadRegister(index_reg);
    3502         129 :   Node* cache_length_reg = BytecodeOperandReg(1);
    3503         129 :   Node* cache_length = LoadRegister(cache_length_reg);
    3504             : 
    3505             :   // Check if {index} is at {cache_length} already.
    3506         258 :   Label if_true(this), if_false(this), end(this);
    3507         129 :   Branch(WordEqual(index, cache_length), &if_true, &if_false);
    3508         129 :   Bind(&if_true);
    3509             :   {
    3510         129 :     SetAccumulator(BooleanConstant(false));
    3511         129 :     Goto(&end);
    3512             :   }
    3513         129 :   Bind(&if_false);
    3514             :   {
    3515         129 :     SetAccumulator(BooleanConstant(true));
    3516         129 :     Goto(&end);
    3517             :   }
    3518         129 :   Bind(&end);
    3519         258 :   Dispatch();
    3520         129 : }
    3521             : 
    3522             : // ForInStep <index>
    3523             : //
    3524             : // Increments the loop counter in register |index| and stores the result
    3525             : // in the accumulator.
    3526         258 : IGNITION_HANDLER(ForInStep, InterpreterAssembler) {
    3527         129 :   Node* index_reg = BytecodeOperandReg(0);
    3528         129 :   Node* index = LoadRegister(index_reg);
    3529         129 :   Node* one = SmiConstant(Smi::FromInt(1));
    3530         129 :   Node* result = SmiAdd(index, one);
    3531         129 :   SetAccumulator(result);
    3532         129 :   Dispatch();
    3533         129 : }
    3534             : 
    3535             : // Wide
    3536             : //
    3537             : // Prefix bytecode indicating next bytecode has wide (16-bit) operands.
    3538          86 : IGNITION_HANDLER(Wide, InterpreterAssembler) {
    3539          43 :   DispatchWide(OperandScale::kDouble);
    3540             : }
    3541             : 
    3542             : // ExtraWide
    3543             : //
    3544             : // Prefix bytecode indicating next bytecode has extra-wide (32-bit) operands.
    3545          86 : IGNITION_HANDLER(ExtraWide, InterpreterAssembler) {
    3546          43 :   DispatchWide(OperandScale::kQuadruple);
    3547             : }
    3548             : 
    3549             : // Illegal
    3550             : //
    3551             : // An invalid bytecode aborting execution if dispatched.
    3552          43 : IGNITION_HANDLER(Illegal, InterpreterAssembler) { Abort(kInvalidBytecode); }
    3553             : 
    3554             : // Nop
    3555             : //
    3556             : // No operation.
    3557          43 : IGNITION_HANDLER(Nop, InterpreterAssembler) { Dispatch(); }
    3558             : 
    3559             : // SuspendGenerator <generator>
    3560             : //
    3561             : // Exports the register file and stores it into the generator.  Also stores the
    3562             : // current context, the state given in the accumulator, and the current bytecode
    3563             : // offset (for debugging purposes) into the generator.
    3564         258 : IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) {
    3565         129 :   Node* generator_reg = BytecodeOperandReg(0);
    3566         129 :   Node* flags = BytecodeOperandFlag(1);
    3567         129 :   Node* generator = LoadRegister(generator_reg);
    3568             : 
    3569         258 :   Label if_stepping(this, Label::kDeferred), ok(this);
    3570             :   Node* step_action_address = ExternalConstant(
    3571         129 :       ExternalReference::debug_last_step_action_address(isolate()));
    3572         129 :   Node* step_action = Load(MachineType::Int8(), step_action_address);
    3573             :   STATIC_ASSERT(StepIn > StepNext);
    3574             :   STATIC_ASSERT(LastStepAction == StepIn);
    3575         129 :   Node* step_next = Int32Constant(StepNext);
    3576         129 :   Branch(Int32LessThanOrEqual(step_next, step_action), &if_stepping, &ok);
    3577         129 :   Bind(&ok);
    3578             : 
    3579             :   Node* array =
    3580         129 :       LoadObjectField(generator, JSGeneratorObject::kRegisterFileOffset);
    3581         129 :   Node* context = GetContext();
    3582         129 :   Node* state = GetAccumulator();
    3583             : 
    3584         129 :   ExportRegisterFile(array);
    3585         129 :   StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
    3586         129 :   StoreObjectField(generator, JSGeneratorObject::kContinuationOffset, state);
    3587             : 
    3588         129 :   Label if_asyncgeneratorawait(this), if_notasyncgeneratorawait(this),
    3589         129 :       merge(this);
    3590             : 
    3591             :   // Calculate bytecode offset to store in the [input_or_debug_pos] or
    3592             :   // [await_input_or_debug_pos] fields, to be used by the inspector.
    3593         129 :   Node* offset = SmiTag(BytecodeOffset());
    3594             : 
    3595             :   using AsyncGeneratorAwaitBits = SuspendGeneratorBytecodeFlags::FlagsBits;
    3596             :   Branch(Word32Equal(DecodeWord32<AsyncGeneratorAwaitBits>(flags),
    3597             :                      Int32Constant(
    3598             :                          static_cast<int>(SuspendFlags::kAsyncGeneratorAwait))),
    3599         258 :          &if_asyncgeneratorawait, &if_notasyncgeneratorawait);
    3600             : 
    3601         129 :   Bind(&if_notasyncgeneratorawait);
    3602             :   {
    3603             :     // For ordinary yields (and for AwaitExpressions in Async Functions, which
    3604             :     // are implemented as ordinary yields), it is safe to write over the
    3605             :     // [input_or_debug_pos] field.
    3606             :     StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
    3607         129 :                      offset);
    3608         129 :     Goto(&merge);
    3609             :   }
    3610             : 
    3611         129 :   Bind(&if_asyncgeneratorawait);
    3612             :   {
    3613             :     // An AwaitExpression in an Async Generator requires writing to the
    3614             :     // [await_input_or_debug_pos] field.
    3615             :     CSA_ASSERT(this,
    3616             :                HasInstanceType(generator, JS_ASYNC_GENERATOR_OBJECT_TYPE));
    3617             :     StoreObjectField(
    3618         129 :         generator, JSAsyncGeneratorObject::kAwaitInputOrDebugPosOffset, offset);
    3619         129 :     Goto(&merge);
    3620             :   }
    3621             : 
    3622         129 :   Bind(&merge);
    3623         129 :   Dispatch();
    3624             : 
    3625         129 :   Bind(&if_stepping);
    3626             :   {
    3627         129 :     Node* context = GetContext();
    3628         129 :     CallRuntime(Runtime::kDebugRecordGenerator, context, generator);
    3629         129 :     Goto(&ok);
    3630         129 :   }
    3631         129 : }
    3632             : 
    3633             : // ResumeGenerator <generator>
    3634             : //
    3635             : // Imports the register file stored in the generator. Also loads the
    3636             : // generator's state and stores it in the accumulator, before overwriting it
    3637             : // with kGeneratorExecuting.
    3638         258 : IGNITION_HANDLER(ResumeGenerator, InterpreterAssembler) {
    3639         129 :   Node* generator_reg = BytecodeOperandReg(0);
    3640         129 :   Node* generator = LoadRegister(generator_reg);
    3641             : 
    3642             :   ImportRegisterFile(
    3643         129 :       LoadObjectField(generator, JSGeneratorObject::kRegisterFileOffset));
    3644             : 
    3645             :   Node* old_state =
    3646         129 :       LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
    3647         129 :   Node* new_state = Int32Constant(JSGeneratorObject::kGeneratorExecuting);
    3648             :   StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
    3649         129 :                    SmiTag(new_state));
    3650         129 :   SetAccumulator(old_state);
    3651             : 
    3652         129 :   Dispatch();
    3653         129 : }
    3654             : 
    3655             : }  // namespace
    3656             : 
    3657       18533 : Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode,
    3658             :                                      OperandScale operand_scale) {
    3659       18533 :   Zone zone(isolate->allocator(), ZONE_NAME);
    3660       18533 :   InterpreterDispatchDescriptor descriptor(isolate);
    3661             :   compiler::CodeAssemblerState state(
    3662             :       isolate, &zone, descriptor, Code::ComputeFlags(Code::BYTECODE_HANDLER),
    3663       37066 :       Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode));
    3664             : 
    3665       18533 :   switch (bytecode) {
    3666             : #define CALL_GENERATOR(Name, ...)                     \
    3667             :   case Bytecode::k##Name:                             \
    3668             :     Name##Assembler::Generate(&state, operand_scale); \
    3669             :     break;
    3670          43 :     BYTECODE_LIST(CALL_GENERATOR);
    3671             : #undef CALL_GENERATOR
    3672             :   }
    3673             : 
    3674       18533 :   Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
    3675       55599 :   PROFILE(isolate, CodeCreateEvent(
    3676             :                        CodeEventListener::BYTECODE_HANDLER_TAG,
    3677             :                        AbstractCode::cast(*code),
    3678             :                        Bytecodes::ToString(bytecode, operand_scale).c_str()));
    3679             : #ifdef ENABLE_DISASSEMBLER
    3680             :   if (FLAG_trace_ignition_codegen) {
    3681             :     OFStream os(stdout);
    3682             :     code->Disassemble(Bytecodes::ToString(bytecode), os);
    3683             :     os << std::flush;
    3684             :   }
    3685             : #endif  // ENABLE_DISASSEMBLER
    3686       37066 :   return code;
    3687             : }
    3688             : 
    3689             : }  // namespace interpreter
    3690             : }  // namespace internal
    3691             : }  // namespace v8

Generated by: LCOV version 1.10