LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1602 1609 99.6 %
Date: 2017-10-20 Functions: 311 315 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/code-events.h"
      13             : #include "src/code-factory.h"
      14             : #include "src/debug/debug.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          62 : IGNITION_HANDLER(LdaZero, InterpreterAssembler) {
      59          62 :   Node* zero_value = NumberConstant(0.0);
      60          31 :   SetAccumulator(zero_value);
      61          31 :   Dispatch();
      62          31 : }
      63             : 
      64             : // LdaSmi <imm>
      65             : //
      66             : // Load an integer literal into the accumulator as a Smi.
      67         186 : IGNITION_HANDLER(LdaSmi, InterpreterAssembler) {
      68          93 :   Node* smi_int = BytecodeOperandImmSmi(0);
      69          93 :   SetAccumulator(smi_int);
      70          93 :   Dispatch();
      71          93 : }
      72             : 
      73             : // LdaConstant <idx>
      74             : //
      75             : // Load constant literal at |idx| in the constant pool into the accumulator.
      76         186 : IGNITION_HANDLER(LdaConstant, InterpreterAssembler) {
      77          93 :   Node* index = BytecodeOperandIdx(0);
      78          93 :   Node* constant = LoadConstantPoolEntry(index);
      79          93 :   SetAccumulator(constant);
      80          93 :   Dispatch();
      81          93 : }
      82             : 
      83             : // LdaUndefined
      84             : //
      85             : // Load Undefined into the accumulator.
      86          62 : IGNITION_HANDLER(LdaUndefined, InterpreterAssembler) {
      87          62 :   SetAccumulator(UndefinedConstant());
      88          31 :   Dispatch();
      89          31 : }
      90             : 
      91             : // LdaNull
      92             : //
      93             : // Load Null into the accumulator.
      94          62 : IGNITION_HANDLER(LdaNull, InterpreterAssembler) {
      95          62 :   SetAccumulator(NullConstant());
      96          31 :   Dispatch();
      97          31 : }
      98             : 
      99             : // LdaTheHole
     100             : //
     101             : // Load TheHole into the accumulator.
     102          62 : IGNITION_HANDLER(LdaTheHole, InterpreterAssembler) {
     103          62 :   SetAccumulator(TheHoleConstant());
     104          31 :   Dispatch();
     105          31 : }
     106             : 
     107             : // LdaTrue
     108             : //
     109             : // Load True into the accumulator.
     110          62 : IGNITION_HANDLER(LdaTrue, InterpreterAssembler) {
     111          62 :   SetAccumulator(TrueConstant());
     112          31 :   Dispatch();
     113          31 : }
     114             : 
     115             : // LdaFalse
     116             : //
     117             : // Load False into the accumulator.
     118          62 : IGNITION_HANDLER(LdaFalse, InterpreterAssembler) {
     119          62 :   SetAccumulator(FalseConstant());
     120          31 :   Dispatch();
     121          31 : }
     122             : 
     123             : // Ldar <src>
     124             : //
     125             : // Load accumulator with value from register <src>.
     126         186 : IGNITION_HANDLER(Ldar, InterpreterAssembler) {
     127          93 :   Node* reg_index = BytecodeOperandReg(0);
     128          93 :   Node* value = LoadRegister(reg_index);
     129          93 :   SetAccumulator(value);
     130          93 :   Dispatch();
     131          93 : }
     132             : 
     133             : // Star <dst>
     134             : //
     135             : // Store accumulator to register <dst>.
     136         186 : IGNITION_HANDLER(Star, InterpreterAssembler) {
     137          93 :   Node* reg_index = BytecodeOperandReg(0);
     138          93 :   Node* accumulator = GetAccumulator();
     139          93 :   StoreRegister(accumulator, reg_index);
     140          93 :   Dispatch();
     141          93 : }
     142             : 
     143             : // Mov <src> <dst>
     144             : //
     145             : // Stores the value of register <src> to register <dst>.
     146         186 : IGNITION_HANDLER(Mov, InterpreterAssembler) {
     147          93 :   Node* src_index = BytecodeOperandReg(0);
     148          93 :   Node* src_value = LoadRegister(src_index);
     149          93 :   Node* dst_index = BytecodeOperandReg(1);
     150          93 :   StoreRegister(src_value, dst_index);
     151          93 :   Dispatch();
     152          93 : }
     153             : 
     154         372 : class InterpreterLoadGlobalAssembler : public InterpreterAssembler {
     155             :  public:
     156             :   InterpreterLoadGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
     157             :                                  OperandScale operand_scale)
     158         372 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     159             : 
     160         372 :   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         372 :     Node* feedback_vector = LoadFeedbackVector();
     166         372 :     Node* feedback_slot = BytecodeOperandIdx(slot_operand_index);
     167             : 
     168             :     AccessorAssembler accessor_asm(state());
     169             : 
     170         744 :     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         744 :       Variable var_result(this, MachineRepresentation::kTagged);
     176         372 :       ExitPoint exit_point(this, &done, &var_result);
     177             : 
     178             :       accessor_asm.LoadGlobalIC_TryPropertyCellCase(
     179             :           feedback_vector, feedback_slot, &exit_point, &try_handler, &miss,
     180         372 :           CodeStubAssembler::INTPTR_PARAMETERS);
     181             : 
     182         372 :       BIND(&done);
     183         372 :       SetAccumulator(var_result.value());
     184         744 :       Dispatch();
     185             :     }
     186             : 
     187             :     // Slow path with frame construction.
     188             :     {
     189             :       Label done(this);
     190         744 :       Variable var_result(this, MachineRepresentation::kTagged);
     191             :       ExitPoint exit_point(this, &done, &var_result);
     192             : 
     193         372 :       BIND(&try_handler);
     194             :       {
     195         372 :         Node* context = GetContext();
     196         744 :         Node* smi_slot = SmiTag(feedback_slot);
     197         372 :         Node* name_index = BytecodeOperandIdx(name_operand_index);
     198         372 :         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         372 :                                                  &exit_point, &miss);
     204             :       }
     205             : 
     206         372 :       BIND(&miss);
     207             :       {
     208         372 :         Node* context = GetContext();
     209         744 :         Node* smi_slot = SmiTag(feedback_slot);
     210         372 :         Node* name_index = BytecodeOperandIdx(name_operand_index);
     211         372 :         Node* name = LoadConstantPoolEntry(name_index);
     212             : 
     213             :         AccessorAssembler::LoadICParameters params(context, nullptr, name,
     214             :                                                    smi_slot, feedback_vector);
     215         372 :         accessor_asm.LoadGlobalIC_MissCase(&params, &exit_point);
     216             :       }
     217             : 
     218         372 :       BIND(&done);
     219             :       {
     220         372 :         SetAccumulator(var_result.value());
     221         372 :         Dispatch();
     222         372 :       }
     223             :     }
     224         372 :   }
     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         279 : IGNITION_HANDLER(LdaGlobal, InterpreterLoadGlobalAssembler) {
     232             :   static const int kNameOperandIndex = 0;
     233             :   static const int kSlotOperandIndex = 1;
     234             : 
     235          93 :   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         279 : IGNITION_HANDLER(LdaGlobalInsideTypeof, InterpreterLoadGlobalAssembler) {
     243             :   static const int kNameOperandIndex = 0;
     244             :   static const int kSlotOperandIndex = 1;
     245             : 
     246          93 :   LdaGlobal(kSlotOperandIndex, kNameOperandIndex, INSIDE_TYPEOF);
     247             : }
     248             : 
     249         186 : class InterpreterStoreGlobalAssembler : public InterpreterAssembler {
     250             :  public:
     251             :   InterpreterStoreGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
     252             :                                   OperandScale operand_scale)
     253         186 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     254             : 
     255         186 :   void StaGlobal(Callable ic) {
     256             :     // Get the global object.
     257         186 :     Node* context = GetContext();
     258         372 :     Node* native_context = LoadNativeContext(context);
     259         372 :     Node* global = LoadContextElement(native_context, Context::EXTENSION_INDEX);
     260             : 
     261             :     // Store the global via the StoreIC.
     262         186 :     Node* code_target = HeapConstant(ic.code());
     263         186 :     Node* constant_index = BytecodeOperandIdx(0);
     264         186 :     Node* name = LoadConstantPoolEntry(constant_index);
     265         186 :     Node* value = GetAccumulator();
     266         186 :     Node* raw_slot = BytecodeOperandIdx(1);
     267         372 :     Node* smi_slot = SmiTag(raw_slot);
     268         186 :     Node* feedback_vector = LoadFeedbackVector();
     269             :     CallStub(ic.descriptor(), code_target, context, global, name, value,
     270         186 :              smi_slot, feedback_vector);
     271         186 :     Dispatch();
     272         186 :   }
     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         372 : IGNITION_HANDLER(StaGlobalSloppy, InterpreterStoreGlobalAssembler) {
     280             :   Callable ic = CodeFactory::StoreGlobalICInOptimizedCode(
     281          93 :       isolate(), LanguageMode::kSloppy);
     282          93 :   StaGlobal(ic);
     283          93 : }
     284             : 
     285             : // StaGlobalStrict <name_index> <slot>
     286             : //
     287             : // Store the value in the accumulator into the global with name in constant pool
     288             : // entry <name_index> using FeedBackVector slot <slot> in strict mode.
     289         372 : IGNITION_HANDLER(StaGlobalStrict, InterpreterStoreGlobalAssembler) {
     290             :   Callable ic = CodeFactory::StoreGlobalICInOptimizedCode(
     291          93 :       isolate(), LanguageMode::kStrict);
     292          93 :   StaGlobal(ic);
     293          93 : }
     294             : 
     295             : // LdaContextSlot <context> <slot_index> <depth>
     296             : //
     297             : // Load the object in |slot_index| of the context at |depth| in the context
     298             : // chain starting at |context| into the accumulator.
     299         186 : IGNITION_HANDLER(LdaContextSlot, InterpreterAssembler) {
     300          93 :   Node* reg_index = BytecodeOperandReg(0);
     301          93 :   Node* context = LoadRegister(reg_index);
     302          93 :   Node* slot_index = BytecodeOperandIdx(1);
     303          93 :   Node* depth = BytecodeOperandUImm(2);
     304          93 :   Node* slot_context = GetContextAtDepth(context, depth);
     305         186 :   Node* result = LoadContextElement(slot_context, slot_index);
     306          93 :   SetAccumulator(result);
     307          93 :   Dispatch();
     308          93 : }
     309             : 
     310             : // LdaImmutableContextSlot <context> <slot_index> <depth>
     311             : //
     312             : // Load the object in |slot_index| of the context at |depth| in the context
     313             : // chain starting at |context| into the accumulator.
     314           0 : IGNITION_HANDLER(LdaImmutableContextSlot, InterpreterAssembler) {
     315             :   // Same as LdaContextSlot, should never be called.
     316           0 :   UNREACHABLE();
     317             : }
     318             : 
     319             : // LdaCurrentContextSlot <slot_index>
     320             : //
     321             : // Load the object in |slot_index| of the current context into the accumulator.
     322         186 : IGNITION_HANDLER(LdaCurrentContextSlot, InterpreterAssembler) {
     323          93 :   Node* slot_index = BytecodeOperandIdx(0);
     324          93 :   Node* slot_context = GetContext();
     325         186 :   Node* result = LoadContextElement(slot_context, slot_index);
     326          93 :   SetAccumulator(result);
     327          93 :   Dispatch();
     328          93 : }
     329             : 
     330             : // LdaImmutableCurrentContextSlot <slot_index>
     331             : //
     332             : // Load the object in |slot_index| of the current context into the accumulator.
     333           0 : IGNITION_HANDLER(LdaImmutableCurrentContextSlot, InterpreterAssembler) {
     334             :   // Same as LdaCurrentContextSlot, should never be called.
     335           0 :   UNREACHABLE();
     336             : }
     337             : 
     338             : // StaContextSlot <context> <slot_index> <depth>
     339             : //
     340             : // Stores the object in the accumulator into |slot_index| of the context at
     341             : // |depth| in the context chain starting at |context|.
     342         186 : IGNITION_HANDLER(StaContextSlot, InterpreterAssembler) {
     343          93 :   Node* value = GetAccumulator();
     344          93 :   Node* reg_index = BytecodeOperandReg(0);
     345          93 :   Node* context = LoadRegister(reg_index);
     346          93 :   Node* slot_index = BytecodeOperandIdx(1);
     347          93 :   Node* depth = BytecodeOperandUImm(2);
     348          93 :   Node* slot_context = GetContextAtDepth(context, depth);
     349          93 :   StoreContextElement(slot_context, slot_index, value);
     350          93 :   Dispatch();
     351          93 : }
     352             : 
     353             : // StaCurrentContextSlot <slot_index>
     354             : //
     355             : // Stores the object in the accumulator into |slot_index| of the current
     356             : // context.
     357         186 : IGNITION_HANDLER(StaCurrentContextSlot, InterpreterAssembler) {
     358          93 :   Node* value = GetAccumulator();
     359          93 :   Node* slot_index = BytecodeOperandIdx(0);
     360          93 :   Node* slot_context = GetContext();
     361          93 :   StoreContextElement(slot_context, slot_index, value);
     362          93 :   Dispatch();
     363          93 : }
     364             : 
     365             : // LdaLookupSlot <name_index>
     366             : //
     367             : // Lookup the object with the name in constant pool entry |name_index|
     368             : // dynamically.
     369         186 : IGNITION_HANDLER(LdaLookupSlot, InterpreterAssembler) {
     370          93 :   Node* name_index = BytecodeOperandIdx(0);
     371          93 :   Node* name = LoadConstantPoolEntry(name_index);
     372          93 :   Node* context = GetContext();
     373          93 :   Node* result = CallRuntime(Runtime::kLoadLookupSlot, context, name);
     374          93 :   SetAccumulator(result);
     375          93 :   Dispatch();
     376          93 : }
     377             : 
     378             : // LdaLookupSlotInsideTypeof <name_index>
     379             : //
     380             : // Lookup the object with the name in constant pool entry |name_index|
     381             : // dynamically without causing a NoReferenceError.
     382         186 : IGNITION_HANDLER(LdaLookupSlotInsideTypeof, InterpreterAssembler) {
     383          93 :   Node* name_index = BytecodeOperandIdx(0);
     384          93 :   Node* name = LoadConstantPoolEntry(name_index);
     385          93 :   Node* context = GetContext();
     386             :   Node* result =
     387          93 :       CallRuntime(Runtime::kLoadLookupSlotInsideTypeof, context, name);
     388          93 :   SetAccumulator(result);
     389          93 :   Dispatch();
     390          93 : }
     391             : 
     392         186 : class InterpreterLookupContextSlotAssembler : public InterpreterAssembler {
     393             :  public:
     394             :   InterpreterLookupContextSlotAssembler(CodeAssemblerState* state,
     395             :                                         Bytecode bytecode,
     396             :                                         OperandScale operand_scale)
     397         186 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     398             : 
     399         186 :   void LookupContextSlot(Runtime::FunctionId function_id) {
     400         186 :     Node* context = GetContext();
     401         186 :     Node* name_index = BytecodeOperandIdx(0);
     402         186 :     Node* slot_index = BytecodeOperandIdx(1);
     403         186 :     Node* depth = BytecodeOperandUImm(2);
     404             : 
     405         186 :     Label slowpath(this, Label::kDeferred);
     406             : 
     407             :     // Check for context extensions to allow the fast path.
     408         186 :     GotoIfHasContextExtensionUpToDepth(context, depth, &slowpath);
     409             : 
     410             :     // Fast path does a normal load context.
     411             :     {
     412         186 :       Node* slot_context = GetContextAtDepth(context, depth);
     413         372 :       Node* result = LoadContextElement(slot_context, slot_index);
     414         186 :       SetAccumulator(result);
     415         186 :       Dispatch();
     416             :     }
     417             : 
     418             :     // Slow path when we have to call out to the runtime.
     419         186 :     BIND(&slowpath);
     420             :     {
     421         186 :       Node* name = LoadConstantPoolEntry(name_index);
     422             :       Node* result = CallRuntime(function_id, context, name);
     423         186 :       SetAccumulator(result);
     424         186 :       Dispatch();
     425         186 :     }
     426         186 :   }
     427             : };
     428             : 
     429             : // LdaLookupSlot <name_index>
     430             : //
     431             : // Lookup the object with the name in constant pool entry |name_index|
     432             : // dynamically.
     433         279 : IGNITION_HANDLER(LdaLookupContextSlot, InterpreterLookupContextSlotAssembler) {
     434          93 :   LookupContextSlot(Runtime::kLoadLookupSlot);
     435             : }
     436             : 
     437             : // LdaLookupSlotInsideTypeof <name_index>
     438             : //
     439             : // Lookup the object with the name in constant pool entry |name_index|
     440             : // dynamically without causing a NoReferenceError.
     441         279 : IGNITION_HANDLER(LdaLookupContextSlotInsideTypeof,
     442             :                  InterpreterLookupContextSlotAssembler) {
     443          93 :   LookupContextSlot(Runtime::kLoadLookupSlotInsideTypeof);
     444             : }
     445             : 
     446             : class InterpreterLookupGlobalAssembler : public InterpreterLoadGlobalAssembler {
     447             :  public:
     448             :   InterpreterLookupGlobalAssembler(CodeAssemblerState* state, Bytecode bytecode,
     449             :                                    OperandScale operand_scale)
     450             :       : InterpreterLoadGlobalAssembler(state, bytecode, operand_scale) {}
     451             : 
     452         186 :   void LookupGlobalSlot(Runtime::FunctionId function_id) {
     453         186 :     Node* context = GetContext();
     454         186 :     Node* depth = BytecodeOperandUImm(2);
     455             : 
     456         186 :     Label slowpath(this, Label::kDeferred);
     457             : 
     458             :     // Check for context extensions to allow the fast path
     459         186 :     GotoIfHasContextExtensionUpToDepth(context, depth, &slowpath);
     460             : 
     461             :     // Fast path does a normal load global
     462             :     {
     463             :       static const int kNameOperandIndex = 0;
     464             :       static const int kSlotOperandIndex = 1;
     465             : 
     466             :       TypeofMode typeof_mode =
     467             :           function_id == Runtime::kLoadLookupSlotInsideTypeof
     468             :               ? INSIDE_TYPEOF
     469         186 :               : NOT_INSIDE_TYPEOF;
     470             : 
     471         186 :       LdaGlobal(kSlotOperandIndex, kNameOperandIndex, typeof_mode);
     472             :     }
     473             : 
     474             :     // Slow path when we have to call out to the runtime
     475         186 :     BIND(&slowpath);
     476             :     {
     477         186 :       Node* name_index = BytecodeOperandIdx(0);
     478         186 :       Node* name = LoadConstantPoolEntry(name_index);
     479             :       Node* result = CallRuntime(function_id, context, name);
     480         186 :       SetAccumulator(result);
     481         186 :       Dispatch();
     482         186 :     }
     483         186 :   }
     484             : };
     485             : 
     486             : // LdaLookupGlobalSlot <name_index> <feedback_slot> <depth>
     487             : //
     488             : // Lookup the object with the name in constant pool entry |name_index|
     489             : // dynamically.
     490         279 : IGNITION_HANDLER(LdaLookupGlobalSlot, InterpreterLookupGlobalAssembler) {
     491          93 :   LookupGlobalSlot(Runtime::kLoadLookupSlot);
     492             : }
     493             : 
     494             : // LdaLookupGlobalSlotInsideTypeof <name_index> <feedback_slot> <depth>
     495             : //
     496             : // Lookup the object with the name in constant pool entry |name_index|
     497             : // dynamically without causing a NoReferenceError.
     498         279 : IGNITION_HANDLER(LdaLookupGlobalSlotInsideTypeof,
     499             :                  InterpreterLookupGlobalAssembler) {
     500          93 :   LookupGlobalSlot(Runtime::kLoadLookupSlotInsideTypeof);
     501             : }
     502             : 
     503             : // StaLookupSlotSloppy <name_index> <flags>
     504             : //
     505             : // Store the object in accumulator to the object with the name in constant
     506             : // pool entry |name_index|.
     507         186 : IGNITION_HANDLER(StaLookupSlot, InterpreterAssembler) {
     508          93 :   Node* value = GetAccumulator();
     509          93 :   Node* index = BytecodeOperandIdx(0);
     510          93 :   Node* bytecode_flags = BytecodeOperandFlag(1);
     511          93 :   Node* name = LoadConstantPoolEntry(index);
     512          93 :   Node* context = GetContext();
     513          93 :   Variable var_result(this, MachineRepresentation::kTagged);
     514             : 
     515          93 :   Label sloppy(this), strict(this), end(this);
     516             :   DCHECK_EQ(0, LanguageMode::kSloppy);
     517             :   DCHECK_EQ(1, LanguageMode::kStrict);
     518             :   DCHECK_EQ(0, static_cast<int>(LookupHoistingMode::kNormal));
     519             :   DCHECK_EQ(1, static_cast<int>(LookupHoistingMode::kLegacySloppy));
     520          93 :   Branch(IsSetWord32<StoreLookupSlotFlags::LanguageModeBit>(bytecode_flags),
     521          93 :          &strict, &sloppy);
     522             : 
     523          93 :   BIND(&strict);
     524             :   {
     525             :     CSA_ASSERT(this, IsClearWord32<StoreLookupSlotFlags::LookupHoistingModeBit>(
     526             :                          bytecode_flags));
     527             :     var_result.Bind(
     528          93 :         CallRuntime(Runtime::kStoreLookupSlot_Strict, context, name, value));
     529          93 :     Goto(&end);
     530             :   }
     531             : 
     532          93 :   BIND(&sloppy);
     533             :   {
     534          93 :     Label hoisting(this), ordinary(this);
     535             :     Branch(IsSetWord32<StoreLookupSlotFlags::LookupHoistingModeBit>(
     536             :                bytecode_flags),
     537          93 :            &hoisting, &ordinary);
     538             : 
     539          93 :     BIND(&hoisting);
     540             :     {
     541             :       var_result.Bind(CallRuntime(Runtime::kStoreLookupSlot_SloppyHoisting,
     542          93 :                                   context, name, value));
     543          93 :       Goto(&end);
     544             :     }
     545             : 
     546          93 :     BIND(&ordinary);
     547             :     {
     548             :       var_result.Bind(
     549          93 :           CallRuntime(Runtime::kStoreLookupSlot_Sloppy, context, name, value));
     550          93 :       Goto(&end);
     551          93 :     }
     552             :   }
     553             : 
     554          93 :   BIND(&end);
     555             :   {
     556          93 :     SetAccumulator(var_result.value());
     557          93 :     Dispatch();
     558          93 :   }
     559          93 : }
     560             : 
     561             : // LdaNamedProperty <object> <name_index> <slot>
     562             : //
     563             : // Calls the LoadIC at FeedBackVector slot <slot> for <object> and the name at
     564             : // constant pool entry <name_index>.
     565         186 : IGNITION_HANDLER(LdaNamedProperty, InterpreterAssembler) {
     566          93 :   Node* feedback_vector = LoadFeedbackVector();
     567          93 :   Node* feedback_slot = BytecodeOperandIdx(2);
     568         186 :   Node* smi_slot = SmiTag(feedback_slot);
     569             : 
     570             :   // Load receiver.
     571          93 :   Node* register_index = BytecodeOperandReg(0);
     572          93 :   Node* recv = LoadRegister(register_index);
     573             : 
     574             :   // Load the name.
     575             :   // TODO(jgruber): Not needed for monomorphic smi handler constant/field case.
     576          93 :   Node* constant_index = BytecodeOperandIdx(1);
     577          93 :   Node* name = LoadConstantPoolEntry(constant_index);
     578             : 
     579          93 :   Node* context = GetContext();
     580             : 
     581          93 :   Label done(this);
     582         186 :   Variable var_result(this, MachineRepresentation::kTagged);
     583             :   ExitPoint exit_point(this, &done, &var_result);
     584             : 
     585             :   AccessorAssembler::LoadICParameters params(context, recv, name, smi_slot,
     586             :                                              feedback_vector);
     587             :   AccessorAssembler accessor_asm(state());
     588          93 :   accessor_asm.LoadIC_BytecodeHandler(&params, &exit_point);
     589             : 
     590          93 :   BIND(&done);
     591             :   {
     592          93 :     SetAccumulator(var_result.value());
     593          93 :     Dispatch();
     594          93 :   }
     595          93 : }
     596             : 
     597             : // KeyedLoadIC <object> <slot>
     598             : //
     599             : // Calls the KeyedLoadIC at FeedBackVector slot <slot> for <object> and the key
     600             : // in the accumulator.
     601         186 : IGNITION_HANDLER(LdaKeyedProperty, InterpreterAssembler) {
     602          93 :   Callable ic = Builtins::CallableFor(isolate(), Builtins::kKeyedLoadIC);
     603             :   Node* code_target = HeapConstant(ic.code());
     604          93 :   Node* reg_index = BytecodeOperandReg(0);
     605          93 :   Node* object = LoadRegister(reg_index);
     606          93 :   Node* name = GetAccumulator();
     607          93 :   Node* raw_slot = BytecodeOperandIdx(1);
     608         186 :   Node* smi_slot = SmiTag(raw_slot);
     609          93 :   Node* feedback_vector = LoadFeedbackVector();
     610          93 :   Node* context = GetContext();
     611             :   Node* result = CallStub(ic.descriptor(), code_target, context, object, name,
     612          93 :                           smi_slot, feedback_vector);
     613          93 :   SetAccumulator(result);
     614          93 :   Dispatch();
     615          93 : }
     616             : 
     617         186 : class InterpreterStoreNamedPropertyAssembler : public InterpreterAssembler {
     618             :  public:
     619             :   InterpreterStoreNamedPropertyAssembler(CodeAssemblerState* state,
     620             :                                          Bytecode bytecode,
     621             :                                          OperandScale operand_scale)
     622         186 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     623             : 
     624         186 :   void StaNamedProperty(Callable ic) {
     625         186 :     Node* code_target = HeapConstant(ic.code());
     626         186 :     Node* object_reg_index = BytecodeOperandReg(0);
     627         186 :     Node* object = LoadRegister(object_reg_index);
     628         186 :     Node* constant_index = BytecodeOperandIdx(1);
     629         186 :     Node* name = LoadConstantPoolEntry(constant_index);
     630         186 :     Node* value = GetAccumulator();
     631         186 :     Node* raw_slot = BytecodeOperandIdx(2);
     632         372 :     Node* smi_slot = SmiTag(raw_slot);
     633         186 :     Node* feedback_vector = LoadFeedbackVector();
     634         186 :     Node* context = GetContext();
     635             :     CallStub(ic.descriptor(), code_target, context, object, name, value,
     636         186 :              smi_slot, feedback_vector);
     637         186 :     Dispatch();
     638         186 :   }
     639             : };
     640             : 
     641             : // StaNamedProperty <object> <name_index> <slot>
     642             : //
     643             : // Calls the StoreIC at FeedBackVector slot <slot> for <object> and
     644             : // the name in constant pool entry <name_index> with the value in the
     645             : // accumulator.
     646         372 : IGNITION_HANDLER(StaNamedProperty, InterpreterStoreNamedPropertyAssembler) {
     647          93 :   Callable ic = Builtins::CallableFor(isolate(), Builtins::kStoreIC);
     648          93 :   StaNamedProperty(ic);
     649          93 : }
     650             : 
     651             : // StaNamedOwnProperty <object> <name_index> <slot>
     652             : //
     653             : // Calls the StoreOwnIC at FeedBackVector slot <slot> for <object> and
     654             : // the name in constant pool entry <name_index> with the value in the
     655             : // accumulator.
     656         372 : IGNITION_HANDLER(StaNamedOwnProperty, InterpreterStoreNamedPropertyAssembler) {
     657          93 :   Callable ic = CodeFactory::StoreOwnICInOptimizedCode(isolate());
     658          93 :   StaNamedProperty(ic);
     659          93 : }
     660             : 
     661             : // StaKeyedProperty <object> <key> <slot>
     662             : //
     663             : // Calls the KeyedStoreIC at FeedbackVector slot <slot> for <object> and
     664             : // the key <key> with the value in the accumulator.
     665         186 : IGNITION_HANDLER(StaKeyedProperty, InterpreterAssembler) {
     666          93 :   Callable ic = Builtins::CallableFor(isolate(), Builtins::kKeyedStoreIC);
     667             :   Node* code_target = HeapConstant(ic.code());
     668          93 :   Node* object_reg_index = BytecodeOperandReg(0);
     669          93 :   Node* object = LoadRegister(object_reg_index);
     670          93 :   Node* name_reg_index = BytecodeOperandReg(1);
     671          93 :   Node* name = LoadRegister(name_reg_index);
     672          93 :   Node* value = GetAccumulator();
     673          93 :   Node* raw_slot = BytecodeOperandIdx(2);
     674         186 :   Node* smi_slot = SmiTag(raw_slot);
     675          93 :   Node* feedback_vector = LoadFeedbackVector();
     676          93 :   Node* context = GetContext();
     677             :   CallStub(ic.descriptor(), code_target, context, object, name, value, smi_slot,
     678          93 :            feedback_vector);
     679          93 :   Dispatch();
     680          93 : }
     681             : 
     682             : // StaDataPropertyInLiteral <object> <name> <flags>
     683             : //
     684             : // Define a property <name> with value from the accumulator in <object>.
     685             : // Property attributes and whether set_function_name are stored in
     686             : // DataPropertyInLiteralFlags <flags>.
     687             : //
     688             : // This definition is not observable and is used only for definitions
     689             : // in object or class literals.
     690         186 : IGNITION_HANDLER(StaDataPropertyInLiteral, InterpreterAssembler) {
     691          93 :   Node* object = LoadRegister(BytecodeOperandReg(0));
     692          93 :   Node* name = LoadRegister(BytecodeOperandReg(1));
     693          93 :   Node* value = GetAccumulator();
     694         279 :   Node* flags = SmiFromWord32(BytecodeOperandFlag(2));
     695         279 :   Node* vector_index = SmiTag(BytecodeOperandIdx(3));
     696             : 
     697          93 :   Node* feedback_vector = LoadFeedbackVector();
     698          93 :   Node* context = GetContext();
     699             : 
     700             :   CallRuntime(Runtime::kDefineDataPropertyInLiteral, context, object, name,
     701          93 :               value, flags, feedback_vector, vector_index);
     702          93 :   Dispatch();
     703          93 : }
     704             : 
     705         186 : IGNITION_HANDLER(CollectTypeProfile, InterpreterAssembler) {
     706          93 :   Node* position = BytecodeOperandImmSmi(0);
     707          93 :   Node* value = GetAccumulator();
     708             : 
     709          93 :   Node* feedback_vector = LoadFeedbackVector();
     710          93 :   Node* context = GetContext();
     711             : 
     712             :   CallRuntime(Runtime::kCollectTypeProfile, context, position, value,
     713          93 :               feedback_vector);
     714          93 :   Dispatch();
     715          93 : }
     716             : 
     717             : // LdaModuleVariable <cell_index> <depth>
     718             : //
     719             : // Load the contents of a module variable into the accumulator.  The variable is
     720             : // identified by <cell_index>.  <depth> is the depth of the current context
     721             : // relative to the module context.
     722         186 : IGNITION_HANDLER(LdaModuleVariable, InterpreterAssembler) {
     723          93 :   Node* cell_index = BytecodeOperandImmIntPtr(0);
     724          93 :   Node* depth = BytecodeOperandUImm(1);
     725             : 
     726          93 :   Node* module_context = GetContextAtDepth(GetContext(), depth);
     727         186 :   Node* module = LoadContextElement(module_context, Context::EXTENSION_INDEX);
     728             : 
     729         186 :   Label if_export(this), if_import(this), end(this);
     730         186 :   Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export,
     731         186 :          &if_import);
     732             : 
     733          93 :   BIND(&if_export);
     734             :   {
     735             :     Node* regular_exports =
     736             :         LoadObjectField(module, Module::kRegularExportsOffset);
     737             :     // The actual array index is (cell_index - 1).
     738         279 :     Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1));
     739          93 :     Node* cell = LoadFixedArrayElement(regular_exports, export_index);
     740          93 :     SetAccumulator(LoadObjectField(cell, Cell::kValueOffset));
     741          93 :     Goto(&end);
     742             :   }
     743             : 
     744          93 :   BIND(&if_import);
     745             :   {
     746             :     Node* regular_imports =
     747             :         LoadObjectField(module, Module::kRegularImportsOffset);
     748             :     // The actual array index is (-cell_index - 1).
     749         279 :     Node* import_index = IntPtrSub(IntPtrConstant(-1), cell_index);
     750          93 :     Node* cell = LoadFixedArrayElement(regular_imports, import_index);
     751          93 :     SetAccumulator(LoadObjectField(cell, Cell::kValueOffset));
     752          93 :     Goto(&end);
     753             :   }
     754             : 
     755          93 :   BIND(&end);
     756         186 :   Dispatch();
     757          93 : }
     758             : 
     759             : // StaModuleVariable <cell_index> <depth>
     760             : //
     761             : // Store accumulator to the module variable identified by <cell_index>.
     762             : // <depth> is the depth of the current context relative to the module context.
     763         186 : IGNITION_HANDLER(StaModuleVariable, InterpreterAssembler) {
     764          93 :   Node* value = GetAccumulator();
     765          93 :   Node* cell_index = BytecodeOperandImmIntPtr(0);
     766          93 :   Node* depth = BytecodeOperandUImm(1);
     767             : 
     768          93 :   Node* module_context = GetContextAtDepth(GetContext(), depth);
     769         186 :   Node* module = LoadContextElement(module_context, Context::EXTENSION_INDEX);
     770             : 
     771         186 :   Label if_export(this), if_import(this), end(this);
     772         186 :   Branch(IntPtrGreaterThan(cell_index, IntPtrConstant(0)), &if_export,
     773         186 :          &if_import);
     774             : 
     775          93 :   BIND(&if_export);
     776             :   {
     777             :     Node* regular_exports =
     778             :         LoadObjectField(module, Module::kRegularExportsOffset);
     779             :     // The actual array index is (cell_index - 1).
     780         279 :     Node* export_index = IntPtrSub(cell_index, IntPtrConstant(1));
     781          93 :     Node* cell = LoadFixedArrayElement(regular_exports, export_index);
     782          93 :     StoreObjectField(cell, Cell::kValueOffset, value);
     783          93 :     Goto(&end);
     784             :   }
     785             : 
     786          93 :   BIND(&if_import);
     787             :   {
     788             :     // Not supported (probably never).
     789          93 :     Abort(kUnsupportedModuleOperation);
     790          93 :     Goto(&end);
     791             :   }
     792             : 
     793          93 :   BIND(&end);
     794         186 :   Dispatch();
     795          93 : }
     796             : 
     797             : // PushContext <context>
     798             : //
     799             : // Saves the current context in <context>, and pushes the accumulator as the
     800             : // new current context.
     801         186 : IGNITION_HANDLER(PushContext, InterpreterAssembler) {
     802          93 :   Node* reg_index = BytecodeOperandReg(0);
     803          93 :   Node* new_context = GetAccumulator();
     804          93 :   Node* old_context = GetContext();
     805          93 :   StoreRegister(old_context, reg_index);
     806          93 :   SetContext(new_context);
     807          93 :   Dispatch();
     808          93 : }
     809             : 
     810             : // PopContext <context>
     811             : //
     812             : // Pops the current context and sets <context> as the new context.
     813         186 : IGNITION_HANDLER(PopContext, InterpreterAssembler) {
     814          93 :   Node* reg_index = BytecodeOperandReg(0);
     815          93 :   Node* context = LoadRegister(reg_index);
     816          93 :   SetContext(context);
     817          93 :   Dispatch();
     818          93 : }
     819             : 
     820         930 : class InterpreterBinaryOpAssembler : public InterpreterAssembler {
     821             :  public:
     822             :   InterpreterBinaryOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
     823             :                                OperandScale operand_scale)
     824         930 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     825             : 
     826             :   typedef Node* (BinaryOpAssembler::*BinaryOpGenerator)(Node* context,
     827             :                                                         Node* left, Node* right,
     828             :                                                         Node* slot,
     829             :                                                         Node* vector,
     830             :                                                         bool lhs_is_smi);
     831             : 
     832         465 :   void BinaryOpWithFeedback(BinaryOpGenerator generator) {
     833         465 :     Node* reg_index = BytecodeOperandReg(0);
     834         465 :     Node* lhs = LoadRegister(reg_index);
     835         465 :     Node* rhs = GetAccumulator();
     836         465 :     Node* context = GetContext();
     837         465 :     Node* slot_index = BytecodeOperandIdx(1);
     838         465 :     Node* feedback_vector = LoadFeedbackVector();
     839             : 
     840             :     BinaryOpAssembler binop_asm(state());
     841             :     Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,
     842         465 :                                           feedback_vector, false);
     843         465 :     SetAccumulator(result);
     844         465 :     Dispatch();
     845         465 :   }
     846             : 
     847         465 :   void BinaryOpSmiWithFeedback(BinaryOpGenerator generator) {
     848         465 :     Node* lhs = GetAccumulator();
     849         465 :     Node* rhs = BytecodeOperandImmSmi(0);
     850         465 :     Node* context = GetContext();
     851         465 :     Node* slot_index = BytecodeOperandIdx(1);
     852         465 :     Node* feedback_vector = LoadFeedbackVector();
     853             : 
     854             :     BinaryOpAssembler binop_asm(state());
     855             :     Node* result = (binop_asm.*generator)(context, lhs, rhs, slot_index,
     856         465 :                                           feedback_vector, true);
     857         465 :     SetAccumulator(result);
     858         465 :     Dispatch();
     859         465 :   }
     860             : };
     861             : 
     862             : // Add <src>
     863             : //
     864             : // Add register <src> to accumulator.
     865         279 : IGNITION_HANDLER(Add, InterpreterBinaryOpAssembler) {
     866          93 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
     867             : }
     868             : 
     869             : // Sub <src>
     870             : //
     871             : // Subtract register <src> from accumulator.
     872         279 : IGNITION_HANDLER(Sub, InterpreterBinaryOpAssembler) {
     873          93 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_SubtractWithFeedback);
     874             : }
     875             : 
     876             : // Mul <src>
     877             : //
     878             : // Multiply accumulator by register <src>.
     879         279 : IGNITION_HANDLER(Mul, InterpreterBinaryOpAssembler) {
     880          93 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_MultiplyWithFeedback);
     881             : }
     882             : 
     883             : // Div <src>
     884             : //
     885             : // Divide register <src> by accumulator.
     886         279 : IGNITION_HANDLER(Div, InterpreterBinaryOpAssembler) {
     887          93 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_DivideWithFeedback);
     888             : }
     889             : 
     890             : // Mod <src>
     891             : //
     892             : // Modulo register <src> by accumulator.
     893         279 : IGNITION_HANDLER(Mod, InterpreterBinaryOpAssembler) {
     894          93 :   BinaryOpWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
     895             : }
     896             : 
     897             : // AddSmi <imm>
     898             : //
     899             : // Adds an immediate value <imm> to the value in the accumulator.
     900         279 : IGNITION_HANDLER(AddSmi, InterpreterBinaryOpAssembler) {
     901          93 :   BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_AddWithFeedback);
     902             : }
     903             : 
     904             : // SubSmi <imm>
     905             : //
     906             : // Subtracts an immediate value <imm> from the value in the accumulator.
     907         279 : IGNITION_HANDLER(SubSmi, InterpreterBinaryOpAssembler) {
     908          93 :   BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_SubtractWithFeedback);
     909             : }
     910             : 
     911             : // MulSmi <imm>
     912             : //
     913             : // Multiplies an immediate value <imm> to the value in the accumulator.
     914         279 : IGNITION_HANDLER(MulSmi, InterpreterBinaryOpAssembler) {
     915          93 :   BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_MultiplyWithFeedback);
     916             : }
     917             : 
     918             : // DivSmi <imm>
     919             : //
     920             : // Divides the value in the accumulator by immediate value <imm>.
     921         279 : IGNITION_HANDLER(DivSmi, InterpreterBinaryOpAssembler) {
     922          93 :   BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_DivideWithFeedback);
     923             : }
     924             : 
     925             : // ModSmi <imm>
     926             : //
     927             : // Modulo accumulator by immediate value <imm>.
     928         279 : IGNITION_HANDLER(ModSmi, InterpreterBinaryOpAssembler) {
     929          93 :   BinaryOpSmiWithFeedback(&BinaryOpAssembler::Generate_ModulusWithFeedback);
     930             : }
     931             : 
     932        1116 : class InterpreterBitwiseBinaryOpAssembler : public InterpreterAssembler {
     933             :  public:
     934             :   InterpreterBitwiseBinaryOpAssembler(CodeAssemblerState* state,
     935             :                                       Bytecode bytecode,
     936             :                                       OperandScale operand_scale)
     937        1116 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
     938             : 
     939         558 :   void BitwiseBinaryOpWithFeedback(Token::Value bitwise_op) {
     940         558 :     Node* reg_index = BytecodeOperandReg(0);
     941         558 :     Node* left = LoadRegister(reg_index);
     942         558 :     Node* right = GetAccumulator();
     943         558 :     Node* context = GetContext();
     944         558 :     Node* slot_index = BytecodeOperandIdx(1);
     945         558 :     Node* feedback_vector = LoadFeedbackVector();
     946             : 
     947         558 :     VARIABLE(var_left_feedback, MachineRepresentation::kTaggedSigned);
     948        1116 :     VARIABLE(var_right_feedback, MachineRepresentation::kTaggedSigned);
     949        1116 :     VARIABLE(var_left_word32, MachineRepresentation::kWord32);
     950        1116 :     VARIABLE(var_right_word32, MachineRepresentation::kWord32);
     951        1116 :     VARIABLE(var_left_bigint, MachineRepresentation::kTagged, left);
     952        1116 :     VARIABLE(var_right_bigint, MachineRepresentation::kTagged);
     953         558 :     Label if_left_number(this), do_number_op(this);
     954         558 :     Label if_left_bigint(this), do_bigint_op(this);
     955             : 
     956             :     TaggedToWord32OrBigIntWithFeedback(context, left, &if_left_number,
     957             :                                        &var_left_word32, &if_left_bigint,
     958         558 :                                        &var_left_bigint, &var_left_feedback);
     959         558 :     BIND(&if_left_number);
     960             :     TaggedToWord32OrBigIntWithFeedback(context, right, &do_number_op,
     961             :                                        &var_right_word32, &do_bigint_op,
     962         558 :                                        &var_right_bigint, &var_right_feedback);
     963         558 :     BIND(&do_number_op);
     964             :     Node* result = BitwiseOp(var_left_word32.value(), var_right_word32.value(),
     965         558 :                              bitwise_op);
     966         558 :     Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
     967             :                                           BinaryOperationFeedback::kSignedSmall,
     968        1116 :                                           BinaryOperationFeedback::kNumber);
     969             :     Node* input_feedback =
     970        2232 :         SmiOr(var_left_feedback.value(), var_right_feedback.value());
     971         558 :     UpdateFeedback(SmiOr(result_type, input_feedback), feedback_vector,
     972        1116 :                    slot_index);
     973         558 :     SetAccumulator(result);
     974         558 :     Dispatch();
     975             : 
     976             :     // BigInt cases.
     977         558 :     BIND(&if_left_bigint);
     978             :     TaggedToNumericWithFeedback(context, right, &do_bigint_op,
     979         558 :                                 &var_right_bigint, &var_right_feedback);
     980             : 
     981         558 :     BIND(&do_bigint_op);
     982             :     SetAccumulator(
     983             :         CallRuntime(Runtime::kBigIntBinaryOp, context, var_left_bigint.value(),
     984        1116 :                     var_right_bigint.value(), SmiConstant(bitwise_op)));
     985        1674 :     UpdateFeedback(SmiOr(var_left_feedback.value(), var_right_feedback.value()),
     986        1116 :                    feedback_vector, slot_index);
     987        1116 :     Dispatch();
     988         558 :   }
     989             : 
     990         558 :   void BitwiseBinaryOpWithSmi(Token::Value bitwise_op) {
     991         558 :     Node* left = GetAccumulator();
     992         558 :     Node* right = BytecodeOperandImmSmi(0);
     993         558 :     Node* slot_index = BytecodeOperandIdx(1);
     994         558 :     Node* feedback_vector = LoadFeedbackVector();
     995         558 :     Node* context = GetContext();
     996             : 
     997         558 :     VARIABLE(var_left_feedback, MachineRepresentation::kTaggedSigned);
     998        1116 :     VARIABLE(var_left_word32, MachineRepresentation::kWord32);
     999        1116 :     VARIABLE(var_left_bigint, MachineRepresentation::kTagged);
    1000         558 :     Label do_smi_op(this), if_bigint_mix(this);
    1001             : 
    1002             :     TaggedToWord32OrBigIntWithFeedback(context, left, &do_smi_op,
    1003             :                                        &var_left_word32, &if_bigint_mix,
    1004         558 :                                        &var_left_bigint, &var_left_feedback);
    1005         558 :     BIND(&do_smi_op);
    1006             :     Node* result =
    1007        1116 :         BitwiseOp(var_left_word32.value(), SmiToWord32(right), bitwise_op);
    1008         558 :     Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1009             :                                           BinaryOperationFeedback::kSignedSmall,
    1010        1116 :                                           BinaryOperationFeedback::kNumber);
    1011        1116 :     UpdateFeedback(SmiOr(result_type, var_left_feedback.value()),
    1012        1116 :                    feedback_vector, slot_index);
    1013         558 :     SetAccumulator(result);
    1014         558 :     Dispatch();
    1015             : 
    1016         558 :     BIND(&if_bigint_mix);
    1017         558 :     UpdateFeedback(var_left_feedback.value(), feedback_vector, slot_index);
    1018        1116 :     ThrowTypeError(context, MessageTemplate::kBigIntMixedTypes);
    1019         558 :   }
    1020             : };
    1021             : 
    1022             : // BitwiseOr <src>
    1023             : //
    1024             : // BitwiseOr register <src> to accumulator.
    1025         279 : IGNITION_HANDLER(BitwiseOr, InterpreterBitwiseBinaryOpAssembler) {
    1026          93 :   BitwiseBinaryOpWithFeedback(Token::BIT_OR);
    1027             : }
    1028             : 
    1029             : // BitwiseXor <src>
    1030             : //
    1031             : // BitwiseXor register <src> to accumulator.
    1032         279 : IGNITION_HANDLER(BitwiseXor, InterpreterBitwiseBinaryOpAssembler) {
    1033          93 :   BitwiseBinaryOpWithFeedback(Token::BIT_XOR);
    1034             : }
    1035             : 
    1036             : // BitwiseAnd <src>
    1037             : //
    1038             : // BitwiseAnd register <src> to accumulator.
    1039         279 : IGNITION_HANDLER(BitwiseAnd, InterpreterBitwiseBinaryOpAssembler) {
    1040          93 :   BitwiseBinaryOpWithFeedback(Token::BIT_AND);
    1041             : }
    1042             : 
    1043             : // ShiftLeft <src>
    1044             : //
    1045             : // Left shifts register <src> by the count specified in the accumulator.
    1046             : // Register <src> is converted to an int32 and the accumulator to uint32
    1047             : // before the operation. 5 lsb bits from the accumulator are used as count
    1048             : // i.e. <src> << (accumulator & 0x1F).
    1049         279 : IGNITION_HANDLER(ShiftLeft, InterpreterBitwiseBinaryOpAssembler) {
    1050          93 :   BitwiseBinaryOpWithFeedback(Token::SHL);
    1051             : }
    1052             : 
    1053             : // ShiftRight <src>
    1054             : //
    1055             : // Right shifts register <src> by the count specified in the accumulator.
    1056             : // Result is sign extended. Register <src> is converted to an int32 and the
    1057             : // accumulator to uint32 before the operation. 5 lsb bits from the accumulator
    1058             : // are used as count i.e. <src> >> (accumulator & 0x1F).
    1059         279 : IGNITION_HANDLER(ShiftRight, InterpreterBitwiseBinaryOpAssembler) {
    1060          93 :   BitwiseBinaryOpWithFeedback(Token::SAR);
    1061             : }
    1062             : 
    1063             : // ShiftRightLogical <src>
    1064             : //
    1065             : // Right Shifts register <src> by the count specified in the accumulator.
    1066             : // Result is zero-filled. The accumulator and register <src> are converted to
    1067             : // uint32 before the operation 5 lsb bits from the accumulator are used as
    1068             : // count i.e. <src> << (accumulator & 0x1F).
    1069         279 : IGNITION_HANDLER(ShiftRightLogical, InterpreterBitwiseBinaryOpAssembler) {
    1070          93 :   BitwiseBinaryOpWithFeedback(Token::SHR);
    1071             : }
    1072             : 
    1073             : // BitwiseOrSmi <imm>
    1074             : //
    1075             : // BitwiseOrSmi accumulator with <imm>.
    1076         279 : IGNITION_HANDLER(BitwiseOrSmi, InterpreterBitwiseBinaryOpAssembler) {
    1077          93 :   BitwiseBinaryOpWithSmi(Token::BIT_OR);
    1078             : }
    1079             : 
    1080             : // BitwiseXorSmi <imm>
    1081             : //
    1082             : // BitwiseXorSmi accumulator with <imm>.
    1083         279 : IGNITION_HANDLER(BitwiseXorSmi, InterpreterBitwiseBinaryOpAssembler) {
    1084          93 :   BitwiseBinaryOpWithSmi(Token::BIT_XOR);
    1085             : }
    1086             : 
    1087             : // BitwiseAndSmi <imm>
    1088             : //
    1089             : // BitwiseAndSmi accumulator with <imm>.
    1090         279 : IGNITION_HANDLER(BitwiseAndSmi, InterpreterBitwiseBinaryOpAssembler) {
    1091          93 :   BitwiseBinaryOpWithSmi(Token::BIT_AND);
    1092             : }
    1093             : 
    1094             : // BitwiseNot <feedback_slot>
    1095             : //
    1096             : // Perform bitwise-not on the accumulator.
    1097         186 : IGNITION_HANDLER(BitwiseNot, InterpreterAssembler) {
    1098          93 :   Node* operand = GetAccumulator();
    1099          93 :   Node* slot_index = BytecodeOperandIdx(0);
    1100          93 :   Node* feedback_vector = LoadFeedbackVector();
    1101          93 :   Node* context = GetContext();
    1102             : 
    1103          93 :   VARIABLE(var_word32, MachineRepresentation::kWord32);
    1104         186 :   VARIABLE(var_feedback, MachineRepresentation::kTaggedSigned);
    1105         186 :   VARIABLE(var_bigint, MachineRepresentation::kTagged);
    1106          93 :   Label if_number(this), if_bigint(this);
    1107             :   TaggedToWord32OrBigIntWithFeedback(context, operand, &if_number, &var_word32,
    1108          93 :                                      &if_bigint, &var_bigint, &var_feedback);
    1109             : 
    1110             :   // Number case.
    1111          93 :   BIND(&if_number);
    1112         372 :   Node* result = ChangeInt32ToTagged(Signed(Word32Not(var_word32.value())));
    1113          93 :   Node* result_type = SelectSmiConstant(TaggedIsSmi(result),
    1114             :                                         BinaryOperationFeedback::kSignedSmall,
    1115         186 :                                         BinaryOperationFeedback::kNumber);
    1116         186 :   UpdateFeedback(SmiOr(result_type, var_feedback.value()), feedback_vector,
    1117         186 :                  slot_index);
    1118          93 :   SetAccumulator(result);
    1119          93 :   Dispatch();
    1120             : 
    1121             :   // BigInt case.
    1122          93 :   BIND(&if_bigint);
    1123             :   UpdateFeedback(SmiConstant(BinaryOperationFeedback::kBigInt), feedback_vector,
    1124         186 :                  slot_index);
    1125             :   SetAccumulator(CallRuntime(Runtime::kBigIntUnaryOp, context,
    1126         186 :                              var_bigint.value(), SmiConstant(Token::BIT_NOT)));
    1127         186 :   Dispatch();
    1128          93 : }
    1129             : 
    1130             : // ShiftLeftSmi <imm>
    1131             : //
    1132             : // Left shifts accumulator by the count specified in <imm>.
    1133             : // The accumulator is converted to an int32 before the operation. The 5
    1134             : // lsb bits from <imm> are used as count i.e. <src> << (<imm> & 0x1F).
    1135         279 : IGNITION_HANDLER(ShiftLeftSmi, InterpreterBitwiseBinaryOpAssembler) {
    1136          93 :   BitwiseBinaryOpWithSmi(Token::SHL);
    1137             : }
    1138             : 
    1139             : // ShiftRightSmi <imm>
    1140             : //
    1141             : // Right shifts accumulator by the count specified in <imm>. Result is sign
    1142             : // extended. The accumulator is converted to an int32 before the operation. The
    1143             : // 5 lsb bits from <imm> are used as count i.e. <src> >> (<imm> & 0x1F).
    1144         279 : IGNITION_HANDLER(ShiftRightSmi, InterpreterBitwiseBinaryOpAssembler) {
    1145          93 :   BitwiseBinaryOpWithSmi(Token::SAR);
    1146             : }
    1147             : 
    1148             : // ShiftRightLogicalSmi <imm>
    1149             : //
    1150             : // Right shifts accumulator by the count specified in <imm>. Result is zero
    1151             : // extended. The accumulator is converted to an int32 before the operation. The
    1152             : // 5 lsb bits from <imm> are used as count i.e. <src> >>> (<imm> & 0x1F).
    1153         279 : IGNITION_HANDLER(ShiftRightLogicalSmi, InterpreterBitwiseBinaryOpAssembler) {
    1154          93 :   BitwiseBinaryOpWithSmi(Token::SHR);
    1155             : }
    1156             : 
    1157         279 : class UnaryNumericOpAssembler : public InterpreterAssembler {
    1158             :  public:
    1159             :   UnaryNumericOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
    1160             :                           OperandScale operand_scale)
    1161         279 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    1162             : 
    1163             :   // {smi_op} signature: (Node* smi_value, Variable* var_feedback,
    1164             :   // Label* do_float_op, Variable* var_float) => Node* tagged result.
    1165             :   // {float_op} signature: (Node* float_value) => Node* float_result.
    1166             :   // {bigint_op} signature: (Node* bigint_value) => Node* tagged_result.
    1167         279 :   void UnaryOpWithFeedback(
    1168             :       std::function<Node*(Node*, Variable*, Label*, Variable*)> smi_op,
    1169             :       std::function<Node*(Node*)> float_op,
    1170             :       std::function<Node*(Node*)> bigint_op) {
    1171         279 :     VARIABLE(var_value, MachineRepresentation::kTagged, GetAccumulator());
    1172         279 :     Node* slot_index = BytecodeOperandIdx(0);
    1173         279 :     Node* feedback_vector = LoadFeedbackVector();
    1174             : 
    1175         558 :     VARIABLE(var_result, MachineRepresentation::kTagged);
    1176         558 :     VARIABLE(var_float_value, MachineRepresentation::kFloat64);
    1177         837 :     VARIABLE(var_feedback, MachineRepresentation::kTaggedSigned,
    1178             :              SmiConstant(BinaryOperationFeedback::kNone));
    1179         279 :     Variable* loop_vars[] = {&var_value, &var_feedback};
    1180         558 :     Label start(this, arraysize(loop_vars), loop_vars), end(this);
    1181         279 :     Label do_float_op(this, &var_float_value);
    1182         279 :     Goto(&start);
    1183             :     // We might have to try again after ToNumeric conversion.
    1184         279 :     BIND(&start);
    1185             :     {
    1186         279 :       Label if_smi(this), if_heapnumber(this), if_bigint(this);
    1187         279 :       Label if_oddball(this), if_other(this);
    1188         279 :       Node* value = var_value.value();
    1189         558 :       GotoIf(TaggedIsSmi(value), &if_smi);
    1190         558 :       Node* map = LoadMap(value);
    1191         558 :       GotoIf(IsHeapNumberMap(map), &if_heapnumber);
    1192         558 :       Node* instance_type = LoadMapInstanceType(map);
    1193         558 :       GotoIf(IsBigIntInstanceType(instance_type), &if_bigint);
    1194             :       Branch(InstanceTypeEqual(instance_type, ODDBALL_TYPE), &if_oddball,
    1195         558 :              &if_other);
    1196             : 
    1197         279 :       BIND(&if_smi);
    1198             :       {
    1199             :         var_result.Bind(
    1200         279 :             smi_op(value, &var_feedback, &do_float_op, &var_float_value));
    1201         279 :         Goto(&end);
    1202             :       }
    1203             : 
    1204         279 :       BIND(&if_heapnumber);
    1205             :       {
    1206         558 :         var_float_value.Bind(LoadHeapNumberValue(value));
    1207         279 :         Goto(&do_float_op);
    1208             :       }
    1209             : 
    1210         279 :       BIND(&if_bigint);
    1211             :       {
    1212         279 :         var_result.Bind(bigint_op(value));
    1213             :         var_feedback.Bind(SmiOr(var_feedback.value(),
    1214        1116 :                                 SmiConstant(BinaryOperationFeedback::kBigInt)));
    1215         279 :         Goto(&end);
    1216             :       }
    1217             : 
    1218         279 :       BIND(&if_oddball);
    1219             :       {
    1220             :         // We do not require an Or with earlier feedback here because once we
    1221             :         // convert the value to a number, we cannot reach this path. We can
    1222             :         // only reach this path on the first pass when the feedback is kNone.
    1223             :         CSA_ASSERT(this, SmiEqual(var_feedback.value(),
    1224             :                                   SmiConstant(BinaryOperationFeedback::kNone)));
    1225             :         var_feedback.Bind(
    1226         558 :             SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
    1227         279 :         var_value.Bind(LoadObjectField(value, Oddball::kToNumberOffset));
    1228         279 :         Goto(&start);
    1229             :       }
    1230             : 
    1231         279 :       BIND(&if_other);
    1232             :       {
    1233             :         // We do not require an Or with earlier feedback here because once we
    1234             :         // convert the value to a number, we cannot reach this path. We can
    1235             :         // only reach this path on the first pass when the feedback is kNone.
    1236             :         CSA_ASSERT(this, SmiEqual(var_feedback.value(),
    1237             :                                   SmiConstant(BinaryOperationFeedback::kNone)));
    1238         558 :         var_feedback.Bind(SmiConstant(BinaryOperationFeedback::kAny));
    1239             :         var_value.Bind(
    1240         279 :             CallBuiltin(Builtins::kNonNumberToNumeric, GetContext(), value));
    1241         279 :         Goto(&start);
    1242         279 :       }
    1243             :     }
    1244             : 
    1245         279 :     BIND(&do_float_op);
    1246             :     {
    1247             :       var_feedback.Bind(SmiOr(var_feedback.value(),
    1248        1116 :                               SmiConstant(BinaryOperationFeedback::kNumber)));
    1249             :       var_result.Bind(
    1250         837 :           AllocateHeapNumberWithValue(float_op(var_float_value.value())));
    1251         279 :       Goto(&end);
    1252             :     }
    1253             : 
    1254         279 :     BIND(&end);
    1255         279 :     UpdateFeedback(var_feedback.value(), feedback_vector, slot_index);
    1256         279 :     SetAccumulator(var_result.value());
    1257         558 :     Dispatch();
    1258         279 :   }
    1259             : 
    1260         186 :   void IncDecWithFeedback(Token::Value op) {
    1261             :     DCHECK(op == Token::INC || op == Token::DEC);
    1262             :     UnaryOpWithFeedback(
    1263             :         [=](Node* smi_value, Variable* var_feedback, Label* do_float_op,
    1264         186 :             Variable* var_float) {
    1265             :           // Try fast Smi operation first.
    1266         372 :           Node* value = BitcastTaggedToWord(smi_value);
    1267         558 :           Node* one = BitcastTaggedToWord(SmiConstant(1));
    1268         558 :           Node* pair = op == Token::INC ? IntPtrAddWithOverflow(value, one)
    1269         651 :                                         : IntPtrSubWithOverflow(value, one);
    1270         186 :           Node* overflow = Projection(1, pair);
    1271             : 
    1272             :           // Check if the Smi operation overflowed.
    1273         558 :           Label if_overflow(this), if_notoverflow(this);
    1274         186 :           Branch(overflow, &if_overflow, &if_notoverflow);
    1275             : 
    1276         186 :           BIND(&if_overflow);
    1277             :           {
    1278         372 :             var_float->Bind(SmiToFloat64(smi_value));
    1279         186 :             Goto(do_float_op);
    1280             :           }
    1281             : 
    1282         186 :           BIND(&if_notoverflow);
    1283             :           var_feedback->Bind(
    1284             :               SmiOr(var_feedback->value(),
    1285         744 :                     SmiConstant(BinaryOperationFeedback::kSignedSmall)));
    1286         558 :           return BitcastWordToTaggedSigned(Projection(0, pair));
    1287         186 :         },
    1288         186 :         [=](Node* float_value) {
    1289         186 :           return op == Token::INC
    1290         372 :                      ? Float64Add(float_value, Float64Constant(1.0))
    1291         372 :                      : Float64Sub(float_value, Float64Constant(1.0));
    1292         558 :         },
    1293         186 :         [=](Node* bigint_value) {
    1294             :           return CallRuntime(Runtime::kBigIntUnaryOp, GetContext(),
    1295         186 :                              bigint_value, SmiConstant(op));
    1296         930 :         });
    1297         186 :   }
    1298             : };
    1299             : 
    1300             : // Negate <feedback_slot>
    1301             : //
    1302             : // Perform arithmetic negation on the accumulator.
    1303         372 : IGNITION_HANDLER(Negate, UnaryNumericOpAssembler) {
    1304             :   UnaryOpWithFeedback(
    1305             :       [=](Node* operand, Variable* var_feedback, Label* do_float_op,
    1306          93 :           Variable* var_float) {
    1307          93 :         VARIABLE(var_result, MachineRepresentation::kTagged);
    1308         372 :         Label if_zero(this), if_min_smi(this), end(this);
    1309             :         // Return -0 if operand is 0.
    1310         279 :         GotoIf(SmiEqual(operand, SmiConstant(0)), &if_zero);
    1311             : 
    1312             :         // Special-case the minimum Smi to avoid overflow.
    1313         279 :         GotoIf(SmiEqual(operand, SmiConstant(Smi::kMinValue)), &if_min_smi);
    1314             : 
    1315             :         // Else simply subtract operand from 0.
    1316         186 :         var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kSignedSmall));
    1317         279 :         var_result.Bind(SmiSub(SmiConstant(0), operand));
    1318          93 :         Goto(&end);
    1319             : 
    1320          93 :         BIND(&if_zero);
    1321         186 :         var_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNumber));
    1322         186 :         var_result.Bind(MinusZeroConstant());
    1323          93 :         Goto(&end);
    1324             : 
    1325          93 :         BIND(&if_min_smi);
    1326         186 :         var_float->Bind(SmiToFloat64(operand));
    1327          93 :         Goto(do_float_op);
    1328             : 
    1329          93 :         BIND(&end);
    1330         186 :         return var_result.value();
    1331          93 :       },
    1332          93 :       [=](Node* float_value) { return Float64Neg(float_value); },
    1333          93 :       [=](Node* bigint_value) {
    1334             :         return CallRuntime(Runtime::kBigIntUnaryOp, GetContext(), bigint_value,
    1335          93 :                            SmiConstant(Token::SUB));
    1336         465 :       });
    1337          93 : }
    1338             : 
    1339             : // ToName <dst>
    1340             : //
    1341             : // Convert the object referenced by the accumulator to a name.
    1342         186 : IGNITION_HANDLER(ToName, InterpreterAssembler) {
    1343          93 :   Node* object = GetAccumulator();
    1344          93 :   Node* context = GetContext();
    1345          93 :   Node* result = ToName(context, object);
    1346          93 :   StoreRegister(result, BytecodeOperandReg(0));
    1347          93 :   Dispatch();
    1348          93 : }
    1349             : 
    1350             : // ToNumber <slot>
    1351             : //
    1352             : // Convert the object referenced by the accumulator to a number.
    1353         186 : IGNITION_HANDLER(ToNumber, InterpreterAssembler) {
    1354          93 :   ToNumberOrNumeric(Object::Conversion::kToNumber);
    1355             : }
    1356             : 
    1357             : // ToNumeric <slot>
    1358             : //
    1359             : // Convert the object referenced by the accumulator to a numeric.
    1360         186 : IGNITION_HANDLER(ToNumeric, InterpreterAssembler) {
    1361          93 :   ToNumberOrNumeric(Object::Conversion::kToNumeric);
    1362             : }
    1363             : 
    1364             : // ToObject <dst>
    1365             : //
    1366             : // Convert the object referenced by the accumulator to a JSReceiver.
    1367         186 : IGNITION_HANDLER(ToObject, InterpreterAssembler) {
    1368          93 :   Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject);
    1369             :   Node* target = HeapConstant(callable.code());
    1370          93 :   Node* accumulator = GetAccumulator();
    1371          93 :   Node* context = GetContext();
    1372          93 :   Node* result = CallStub(callable.descriptor(), target, context, accumulator);
    1373          93 :   StoreRegister(result, BytecodeOperandReg(0));
    1374          93 :   Dispatch();
    1375          93 : }
    1376             : 
    1377             : // Inc
    1378             : //
    1379             : // Increments value in the accumulator by one.
    1380         279 : IGNITION_HANDLER(Inc, UnaryNumericOpAssembler) {
    1381          93 :   IncDecWithFeedback(Token::INC);
    1382             : }
    1383             : 
    1384             : // Dec
    1385             : //
    1386             : // Decrements value in the accumulator by one.
    1387         279 : IGNITION_HANDLER(Dec, UnaryNumericOpAssembler) {
    1388          93 :   IncDecWithFeedback(Token::DEC);
    1389             : }
    1390             : 
    1391             : // LogicalNot
    1392             : //
    1393             : // Perform logical-not on the accumulator, first casting the
    1394             : // accumulator to a boolean value if required.
    1395             : // ToBooleanLogicalNot
    1396          62 : IGNITION_HANDLER(ToBooleanLogicalNot, InterpreterAssembler) {
    1397          31 :   Node* value = GetAccumulator();
    1398          31 :   Variable result(this, MachineRepresentation::kTagged);
    1399          31 :   Label if_true(this), if_false(this), end(this);
    1400          62 :   Node* true_value = BooleanConstant(true);
    1401          62 :   Node* false_value = BooleanConstant(false);
    1402          31 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    1403          31 :   BIND(&if_true);
    1404             :   {
    1405          31 :     result.Bind(false_value);
    1406          31 :     Goto(&end);
    1407             :   }
    1408          31 :   BIND(&if_false);
    1409             :   {
    1410          31 :     result.Bind(true_value);
    1411          31 :     Goto(&end);
    1412             :   }
    1413          31 :   BIND(&end);
    1414          31 :   SetAccumulator(result.value());
    1415          62 :   Dispatch();
    1416          31 : }
    1417             : 
    1418             : // LogicalNot
    1419             : //
    1420             : // Perform logical-not on the accumulator, which must already be a boolean
    1421             : // value.
    1422          62 : IGNITION_HANDLER(LogicalNot, InterpreterAssembler) {
    1423          31 :   Node* value = GetAccumulator();
    1424          31 :   Variable result(this, MachineRepresentation::kTagged);
    1425          31 :   Label if_true(this), if_false(this), end(this);
    1426          62 :   Node* true_value = BooleanConstant(true);
    1427          62 :   Node* false_value = BooleanConstant(false);
    1428          62 :   Branch(WordEqual(value, true_value), &if_true, &if_false);
    1429          31 :   BIND(&if_true);
    1430             :   {
    1431          31 :     result.Bind(false_value);
    1432          31 :     Goto(&end);
    1433             :   }
    1434          31 :   BIND(&if_false);
    1435             :   {
    1436          31 :     if (FLAG_debug_code) {
    1437             :       AbortIfWordNotEqual(value, false_value,
    1438           0 :                           BailoutReason::kExpectedBooleanValue);
    1439             :     }
    1440          31 :     result.Bind(true_value);
    1441          31 :     Goto(&end);
    1442             :   }
    1443          31 :   BIND(&end);
    1444          31 :   SetAccumulator(result.value());
    1445          62 :   Dispatch();
    1446          31 : }
    1447             : 
    1448             : // TypeOf
    1449             : //
    1450             : // Load the accumulator with the string representating type of the
    1451             : // object in the accumulator.
    1452          62 : IGNITION_HANDLER(TypeOf, InterpreterAssembler) {
    1453          31 :   Node* value = GetAccumulator();
    1454          31 :   Node* result = Typeof(value);
    1455          31 :   SetAccumulator(result);
    1456          31 :   Dispatch();
    1457          31 : }
    1458             : 
    1459             : // DeletePropertyStrict
    1460             : //
    1461             : // Delete the property specified in the accumulator from the object
    1462             : // referenced by the register operand following strict mode semantics.
    1463         186 : IGNITION_HANDLER(DeletePropertyStrict, InterpreterAssembler) {
    1464          93 :   Node* reg_index = BytecodeOperandReg(0);
    1465          93 :   Node* object = LoadRegister(reg_index);
    1466          93 :   Node* key = GetAccumulator();
    1467          93 :   Node* context = GetContext();
    1468             :   Node* result = CallBuiltin(Builtins::kDeleteProperty, context, object, key,
    1469          93 :                              SmiConstant(Smi::FromEnum(LanguageMode::kStrict)));
    1470          93 :   SetAccumulator(result);
    1471          93 :   Dispatch();
    1472          93 : }
    1473             : 
    1474             : // DeletePropertySloppy
    1475             : //
    1476             : // Delete the property specified in the accumulator from the object
    1477             : // referenced by the register operand following sloppy mode semantics.
    1478         186 : IGNITION_HANDLER(DeletePropertySloppy, InterpreterAssembler) {
    1479          93 :   Node* reg_index = BytecodeOperandReg(0);
    1480          93 :   Node* object = LoadRegister(reg_index);
    1481          93 :   Node* key = GetAccumulator();
    1482          93 :   Node* context = GetContext();
    1483             :   Node* result = CallBuiltin(Builtins::kDeleteProperty, context, object, key,
    1484          93 :                              SmiConstant(Smi::FromEnum(LanguageMode::kSloppy)));
    1485          93 :   SetAccumulator(result);
    1486          93 :   Dispatch();
    1487          93 : }
    1488             : 
    1489             : // GetSuperConstructor
    1490             : //
    1491             : // Get the super constructor from the object referenced by the accumulator.
    1492             : // The result is stored in register |reg|.
    1493         186 : IGNITION_HANDLER(GetSuperConstructor, InterpreterAssembler) {
    1494          93 :   Node* active_function = GetAccumulator();
    1495          93 :   Node* context = GetContext();
    1496          93 :   Node* result = GetSuperConstructor(active_function, context);
    1497          93 :   Node* reg = BytecodeOperandReg(0);
    1498          93 :   StoreRegister(result, reg);
    1499          93 :   Dispatch();
    1500          93 : }
    1501             : 
    1502         837 : class InterpreterJSCallAssembler : public InterpreterAssembler {
    1503             :  public:
    1504             :   InterpreterJSCallAssembler(CodeAssemblerState* state, Bytecode bytecode,
    1505             :                              OperandScale operand_scale)
    1506         837 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    1507             : 
    1508             :   // Generates code to perform a JS call that collects type feedback.
    1509         279 :   void JSCall(ConvertReceiverMode receiver_mode) {
    1510         279 :     Node* function_reg = BytecodeOperandReg(0);
    1511         279 :     Node* function = LoadRegister(function_reg);
    1512         279 :     Node* first_arg_reg = BytecodeOperandReg(1);
    1513         279 :     Node* first_arg = RegisterLocation(first_arg_reg);
    1514         279 :     Node* arg_list_count = BytecodeOperandCount(2);
    1515             :     Node* args_count;
    1516         279 :     if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
    1517             :       // The receiver is implied, so it is not in the argument list.
    1518             :       args_count = arg_list_count;
    1519             :     } else {
    1520             :       // Subtract the receiver from the argument count.
    1521         372 :       Node* receiver_count = Int32Constant(1);
    1522         372 :       args_count = Int32Sub(arg_list_count, receiver_count);
    1523             :     }
    1524         279 :     Node* slot_id = BytecodeOperandIdx(3);
    1525         279 :     Node* feedback_vector = LoadFeedbackVector();
    1526         279 :     Node* context = GetContext();
    1527             : 
    1528             :     // Collect the {function} feedback.
    1529         279 :     CollectCallFeedback(function, context, feedback_vector, slot_id);
    1530             : 
    1531             :     // Call the function and dispatch to the next handler.
    1532         279 :     CallJSAndDispatch(function, context, first_arg, args_count, receiver_mode);
    1533         279 :   }
    1534             : 
    1535             :   // Generates code to perform a JS call with a known number of arguments that
    1536             :   // collects type feedback.
    1537         558 :   void JSCallN(int arg_count, ConvertReceiverMode receiver_mode) {
    1538             :     // Indices and counts of operands on the bytecode.
    1539             :     const int kFirstArgumentOperandIndex = 1;
    1540             :     const int kReceiverOperandCount =
    1541         558 :         (receiver_mode == ConvertReceiverMode::kNullOrUndefined) ? 0 : 1;
    1542         558 :     const int kRecieverAndArgOperandCount = kReceiverOperandCount + arg_count;
    1543             :     const int kSlotOperandIndex =
    1544         558 :         kFirstArgumentOperandIndex + kRecieverAndArgOperandCount;
    1545             : 
    1546         558 :     Node* function_reg = BytecodeOperandReg(0);
    1547         558 :     Node* function = LoadRegister(function_reg);
    1548         558 :     Node* slot_id = BytecodeOperandIdx(kSlotOperandIndex);
    1549         558 :     Node* feedback_vector = LoadFeedbackVector();
    1550         558 :     Node* context = GetContext();
    1551             : 
    1552             :     // Collect the {function} feedback.
    1553         558 :     CollectCallFeedback(function, context, feedback_vector, slot_id);
    1554             : 
    1555         558 :     switch (kRecieverAndArgOperandCount) {
    1556             :       case 0:
    1557          93 :         CallJSAndDispatch(function, context, Int32Constant(arg_count),
    1558         186 :                           receiver_mode);
    1559          93 :         break;
    1560             :       case 1:
    1561             :         CallJSAndDispatch(
    1562         186 :             function, context, Int32Constant(arg_count), receiver_mode,
    1563         558 :             LoadRegister(BytecodeOperandReg(kFirstArgumentOperandIndex)));
    1564         186 :         break;
    1565             :       case 2:
    1566             :         CallJSAndDispatch(
    1567         186 :             function, context, Int32Constant(arg_count), receiver_mode,
    1568             :             LoadRegister(BytecodeOperandReg(kFirstArgumentOperandIndex)),
    1569         558 :             LoadRegister(BytecodeOperandReg(kFirstArgumentOperandIndex + 1)));
    1570         186 :         break;
    1571             :       case 3:
    1572             :         CallJSAndDispatch(
    1573          93 :             function, context, Int32Constant(arg_count), receiver_mode,
    1574             :             LoadRegister(BytecodeOperandReg(kFirstArgumentOperandIndex)),
    1575             :             LoadRegister(BytecodeOperandReg(kFirstArgumentOperandIndex + 1)),
    1576         279 :             LoadRegister(BytecodeOperandReg(kFirstArgumentOperandIndex + 2)));
    1577          93 :         break;
    1578             :       default:
    1579           0 :         UNREACHABLE();
    1580             :     }
    1581         558 :   }
    1582             : };
    1583             : 
    1584             : // Call <callable> <receiver> <arg_count> <feedback_slot_id>
    1585             : //
    1586             : // Call a JSfunction or Callable in |callable| with the |receiver| and
    1587             : // |arg_count| arguments in subsequent registers. Collect type feedback
    1588             : // into |feedback_slot_id|
    1589         279 : IGNITION_HANDLER(CallAnyReceiver, InterpreterJSCallAssembler) {
    1590          93 :   JSCall(ConvertReceiverMode::kAny);
    1591             : }
    1592             : 
    1593         279 : IGNITION_HANDLER(CallProperty, InterpreterJSCallAssembler) {
    1594          93 :   JSCall(ConvertReceiverMode::kNotNullOrUndefined);
    1595             : }
    1596             : 
    1597         279 : IGNITION_HANDLER(CallProperty0, InterpreterJSCallAssembler) {
    1598          93 :   JSCallN(0, ConvertReceiverMode::kNotNullOrUndefined);
    1599             : }
    1600             : 
    1601         279 : IGNITION_HANDLER(CallProperty1, InterpreterJSCallAssembler) {
    1602          93 :   JSCallN(1, ConvertReceiverMode::kNotNullOrUndefined);
    1603             : }
    1604             : 
    1605         279 : IGNITION_HANDLER(CallProperty2, InterpreterJSCallAssembler) {
    1606          93 :   JSCallN(2, ConvertReceiverMode::kNotNullOrUndefined);
    1607             : }
    1608             : 
    1609         279 : IGNITION_HANDLER(CallUndefinedReceiver, InterpreterJSCallAssembler) {
    1610          93 :   JSCall(ConvertReceiverMode::kNullOrUndefined);
    1611             : }
    1612             : 
    1613         279 : IGNITION_HANDLER(CallUndefinedReceiver0, InterpreterJSCallAssembler) {
    1614          93 :   JSCallN(0, ConvertReceiverMode::kNullOrUndefined);
    1615             : }
    1616             : 
    1617         279 : IGNITION_HANDLER(CallUndefinedReceiver1, InterpreterJSCallAssembler) {
    1618          93 :   JSCallN(1, ConvertReceiverMode::kNullOrUndefined);
    1619             : }
    1620             : 
    1621         279 : IGNITION_HANDLER(CallUndefinedReceiver2, InterpreterJSCallAssembler) {
    1622          93 :   JSCallN(2, ConvertReceiverMode::kNullOrUndefined);
    1623             : }
    1624             : 
    1625             : // CallRuntime <function_id> <first_arg> <arg_count>
    1626             : //
    1627             : // Call the runtime function |function_id| with the first argument in
    1628             : // register |first_arg| and |arg_count| arguments in subsequent
    1629             : // registers.
    1630         186 : IGNITION_HANDLER(CallRuntime, InterpreterAssembler) {
    1631          93 :   Node* function_id = BytecodeOperandRuntimeId(0);
    1632          93 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1633          93 :   Node* first_arg = RegisterLocation(first_arg_reg);
    1634          93 :   Node* args_count = BytecodeOperandCount(2);
    1635          93 :   Node* context = GetContext();
    1636          93 :   Node* result = CallRuntimeN(function_id, context, first_arg, args_count);
    1637          93 :   SetAccumulator(result);
    1638          93 :   Dispatch();
    1639          93 : }
    1640             : 
    1641             : // InvokeIntrinsic <function_id> <first_arg> <arg_count>
    1642             : //
    1643             : // Implements the semantic equivalent of calling the runtime function
    1644             : // |function_id| with the first argument in |first_arg| and |arg_count|
    1645             : // arguments in subsequent registers.
    1646         186 : IGNITION_HANDLER(InvokeIntrinsic, InterpreterAssembler) {
    1647          93 :   Node* function_id = BytecodeOperandIntrinsicId(0);
    1648          93 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1649          93 :   Node* arg_count = BytecodeOperandCount(2);
    1650          93 :   Node* context = GetContext();
    1651             :   Node* result = GenerateInvokeIntrinsic(this, function_id, context,
    1652          93 :                                          first_arg_reg, arg_count);
    1653          93 :   SetAccumulator(result);
    1654          93 :   Dispatch();
    1655          93 : }
    1656             : 
    1657             : // CallRuntimeForPair <function_id> <first_arg> <arg_count> <first_return>
    1658             : //
    1659             : // Call the runtime function |function_id| which returns a pair, with the
    1660             : // first argument in register |first_arg| and |arg_count| arguments in
    1661             : // subsequent registers. Returns the result in <first_return> and
    1662             : // <first_return + 1>
    1663         186 : IGNITION_HANDLER(CallRuntimeForPair, InterpreterAssembler) {
    1664             :   // Call the runtime function.
    1665          93 :   Node* function_id = BytecodeOperandRuntimeId(0);
    1666          93 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1667          93 :   Node* first_arg = RegisterLocation(first_arg_reg);
    1668          93 :   Node* args_count = BytecodeOperandCount(2);
    1669          93 :   Node* context = GetContext();
    1670             :   Node* result_pair =
    1671          93 :       CallRuntimeN(function_id, context, first_arg, args_count, 2);
    1672             :   // Store the results in <first_return> and <first_return + 1>
    1673          93 :   Node* first_return_reg = BytecodeOperandReg(3);
    1674          93 :   Node* second_return_reg = NextRegister(first_return_reg);
    1675          93 :   Node* result0 = Projection(0, result_pair);
    1676          93 :   Node* result1 = Projection(1, result_pair);
    1677          93 :   StoreRegister(result0, first_return_reg);
    1678          93 :   StoreRegister(result1, second_return_reg);
    1679          93 :   Dispatch();
    1680          93 : }
    1681             : 
    1682             : // CallJSRuntime <context_index> <receiver> <arg_count>
    1683             : //
    1684             : // Call the JS runtime function that has the |context_index| with the receiver
    1685             : // in register |receiver| and |arg_count| arguments in subsequent registers.
    1686         186 : IGNITION_HANDLER(CallJSRuntime, InterpreterAssembler) {
    1687          93 :   Node* context_index = BytecodeOperandNativeContextIndex(0);
    1688          93 :   Node* receiver_reg = BytecodeOperandReg(1);
    1689          93 :   Node* first_arg = RegisterLocation(receiver_reg);
    1690          93 :   Node* args_count = BytecodeOperandCount(2);
    1691             : 
    1692             :   // Get the function to call from the native context.
    1693          93 :   Node* context = GetContext();
    1694         186 :   Node* native_context = LoadNativeContext(context);
    1695         186 :   Node* function = LoadContextElement(native_context, context_index);
    1696             : 
    1697             :   // Call the function.
    1698             :   CallJSAndDispatch(function, context, first_arg, args_count,
    1699          93 :                     ConvertReceiverMode::kNullOrUndefined);
    1700          93 : }
    1701             : 
    1702             : // CallWithSpread <callable> <first_arg> <arg_count>
    1703             : //
    1704             : // Call a JSfunction or Callable in |callable| with the receiver in
    1705             : // |first_arg| and |arg_count - 1| arguments in subsequent registers. The
    1706             : // final argument is always a spread.
    1707             : //
    1708         186 : IGNITION_HANDLER(CallWithSpread, InterpreterAssembler) {
    1709          93 :   Node* callable_reg = BytecodeOperandReg(0);
    1710          93 :   Node* callable = LoadRegister(callable_reg);
    1711          93 :   Node* receiver_reg = BytecodeOperandReg(1);
    1712          93 :   Node* receiver_arg = RegisterLocation(receiver_reg);
    1713          93 :   Node* receiver_args_count = BytecodeOperandCount(2);
    1714         186 :   Node* receiver_count = Int32Constant(1);
    1715         186 :   Node* args_count = Int32Sub(receiver_args_count, receiver_count);
    1716          93 :   Node* slot_id = BytecodeOperandIdx(3);
    1717          93 :   Node* feedback_vector = LoadFeedbackVector();
    1718          93 :   Node* context = GetContext();
    1719             : 
    1720             :   // Call into Runtime function CallWithSpread which does everything.
    1721             :   CallJSWithSpreadAndDispatch(callable, context, receiver_arg, args_count,
    1722          93 :                               slot_id, feedback_vector);
    1723          93 : }
    1724             : 
    1725             : // ConstructWithSpread <first_arg> <arg_count>
    1726             : //
    1727             : // Call the constructor in |constructor| with the first argument in register
    1728             : // |first_arg| and |arg_count| arguments in subsequent registers. The final
    1729             : // argument is always a spread. The new.target is in the accumulator.
    1730             : //
    1731         186 : IGNITION_HANDLER(ConstructWithSpread, InterpreterAssembler) {
    1732          93 :   Node* new_target = GetAccumulator();
    1733          93 :   Node* constructor_reg = BytecodeOperandReg(0);
    1734          93 :   Node* constructor = LoadRegister(constructor_reg);
    1735          93 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1736          93 :   Node* first_arg = RegisterLocation(first_arg_reg);
    1737          93 :   Node* args_count = BytecodeOperandCount(2);
    1738          93 :   Node* slot_id = BytecodeOperandIdx(3);
    1739          93 :   Node* feedback_vector = LoadFeedbackVector();
    1740          93 :   Node* context = GetContext();
    1741             :   Node* result =
    1742             :       ConstructWithSpread(constructor, context, new_target, first_arg,
    1743          93 :                           args_count, slot_id, feedback_vector);
    1744          93 :   SetAccumulator(result);
    1745          93 :   Dispatch();
    1746          93 : }
    1747             : 
    1748             : // Construct <constructor> <first_arg> <arg_count>
    1749             : //
    1750             : // Call operator construct with |constructor| and the first argument in
    1751             : // register |first_arg| and |arg_count| arguments in subsequent
    1752             : // registers. The new.target is in the accumulator.
    1753             : //
    1754         186 : IGNITION_HANDLER(Construct, InterpreterAssembler) {
    1755          93 :   Node* new_target = GetAccumulator();
    1756          93 :   Node* constructor_reg = BytecodeOperandReg(0);
    1757          93 :   Node* constructor = LoadRegister(constructor_reg);
    1758          93 :   Node* first_arg_reg = BytecodeOperandReg(1);
    1759          93 :   Node* first_arg = RegisterLocation(first_arg_reg);
    1760          93 :   Node* args_count = BytecodeOperandCount(2);
    1761          93 :   Node* slot_id = BytecodeOperandIdx(3);
    1762          93 :   Node* feedback_vector = LoadFeedbackVector();
    1763          93 :   Node* context = GetContext();
    1764             :   Node* result = Construct(constructor, context, new_target, first_arg,
    1765          93 :                            args_count, slot_id, feedback_vector);
    1766          93 :   SetAccumulator(result);
    1767          93 :   Dispatch();
    1768          93 : }
    1769             : 
    1770         558 : class InterpreterCompareOpAssembler : public InterpreterAssembler {
    1771             :  public:
    1772             :   InterpreterCompareOpAssembler(CodeAssemblerState* state, Bytecode bytecode,
    1773             :                                 OperandScale operand_scale)
    1774         558 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    1775             : 
    1776         558 :   void CompareOpWithFeedback(Token::Value compare_op) {
    1777         558 :     Node* reg_index = BytecodeOperandReg(0);
    1778         558 :     Node* lhs = LoadRegister(reg_index);
    1779         558 :     Node* rhs = GetAccumulator();
    1780         558 :     Node* context = GetContext();
    1781             : 
    1782         558 :     Variable var_type_feedback(this, MachineRepresentation::kTagged);
    1783             :     Node* result;
    1784         558 :     switch (compare_op) {
    1785             :       case Token::EQ:
    1786          93 :         result = Equal(lhs, rhs, context, &var_type_feedback);
    1787          93 :         break;
    1788             :       case Token::EQ_STRICT:
    1789          93 :         result = StrictEqual(lhs, rhs, &var_type_feedback);
    1790          93 :         break;
    1791             :       case Token::LT:
    1792             :         result = RelationalComparison(CodeStubAssembler::kLessThan, lhs, rhs,
    1793          93 :                                       context, &var_type_feedback);
    1794          93 :         break;
    1795             :       case Token::GT:
    1796             :         result = RelationalComparison(CodeStubAssembler::kGreaterThan, lhs, rhs,
    1797          93 :                                       context, &var_type_feedback);
    1798          93 :         break;
    1799             :       case Token::LTE:
    1800             :         result = RelationalComparison(CodeStubAssembler::kLessThanOrEqual, lhs,
    1801          93 :                                       rhs, context, &var_type_feedback);
    1802          93 :         break;
    1803             :       case Token::GTE:
    1804             :         result = RelationalComparison(CodeStubAssembler::kGreaterThanOrEqual,
    1805          93 :                                       lhs, rhs, context, &var_type_feedback);
    1806          93 :         break;
    1807             :       default:
    1808           0 :         UNREACHABLE();
    1809             :     }
    1810             : 
    1811         558 :     Node* slot_index = BytecodeOperandIdx(1);
    1812         558 :     Node* feedback_vector = LoadFeedbackVector();
    1813         558 :     UpdateFeedback(var_type_feedback.value(), feedback_vector, slot_index);
    1814         558 :     SetAccumulator(result);
    1815         558 :     Dispatch();
    1816         558 :   }
    1817             : };
    1818             : 
    1819             : // TestEqual <src>
    1820             : //
    1821             : // Test if the value in the <src> register equals the accumulator.
    1822         279 : IGNITION_HANDLER(TestEqual, InterpreterCompareOpAssembler) {
    1823          93 :   CompareOpWithFeedback(Token::Value::EQ);
    1824             : }
    1825             : 
    1826             : // TestEqualStrict <src>
    1827             : //
    1828             : // Test if the value in the <src> register is strictly equal to the accumulator.
    1829         279 : IGNITION_HANDLER(TestEqualStrict, InterpreterCompareOpAssembler) {
    1830          93 :   CompareOpWithFeedback(Token::Value::EQ_STRICT);
    1831             : }
    1832             : 
    1833             : // TestLessThan <src>
    1834             : //
    1835             : // Test if the value in the <src> register is less than the accumulator.
    1836         279 : IGNITION_HANDLER(TestLessThan, InterpreterCompareOpAssembler) {
    1837          93 :   CompareOpWithFeedback(Token::Value::LT);
    1838             : }
    1839             : 
    1840             : // TestGreaterThan <src>
    1841             : //
    1842             : // Test if the value in the <src> register is greater than the accumulator.
    1843         279 : IGNITION_HANDLER(TestGreaterThan, InterpreterCompareOpAssembler) {
    1844          93 :   CompareOpWithFeedback(Token::Value::GT);
    1845             : }
    1846             : 
    1847             : // TestLessThanOrEqual <src>
    1848             : //
    1849             : // Test if the value in the <src> register is less than or equal to the
    1850             : // accumulator.
    1851         279 : IGNITION_HANDLER(TestLessThanOrEqual, InterpreterCompareOpAssembler) {
    1852          93 :   CompareOpWithFeedback(Token::Value::LTE);
    1853             : }
    1854             : 
    1855             : // TestGreaterThanOrEqual <src>
    1856             : //
    1857             : // Test if the value in the <src> register is greater than or equal to the
    1858             : // accumulator.
    1859         279 : IGNITION_HANDLER(TestGreaterThanOrEqual, InterpreterCompareOpAssembler) {
    1860          93 :   CompareOpWithFeedback(Token::Value::GTE);
    1861             : }
    1862             : 
    1863             : // TestEqualStrictNoFeedback <src>
    1864             : //
    1865             : // Test if the value in the <src> register is strictly equal to the accumulator.
    1866             : // Type feedback is not collected.
    1867         186 : IGNITION_HANDLER(TestEqualStrictNoFeedback, InterpreterAssembler) {
    1868          93 :   Node* reg_index = BytecodeOperandReg(0);
    1869          93 :   Node* lhs = LoadRegister(reg_index);
    1870          93 :   Node* rhs = GetAccumulator();
    1871             :   // TODO(5310): This is called only when lhs and rhs are Smis (for ex:
    1872             :   // try-finally or generators) or strings (only when visiting
    1873             :   // ClassLiteralProperties). We should be able to optimize this and not perform
    1874             :   // the full strict equality.
    1875          93 :   Node* result = StrictEqual(lhs, rhs);
    1876          93 :   SetAccumulator(result);
    1877          93 :   Dispatch();
    1878          93 : }
    1879             : 
    1880             : // TestIn <src>
    1881             : //
    1882             : // Test if the object referenced by the register operand is a property of the
    1883             : // object referenced by the accumulator.
    1884         186 : IGNITION_HANDLER(TestIn, InterpreterAssembler) {
    1885          93 :   Node* reg_index = BytecodeOperandReg(0);
    1886          93 :   Node* property = LoadRegister(reg_index);
    1887          93 :   Node* object = GetAccumulator();
    1888          93 :   Node* context = GetContext();
    1889             : 
    1890          93 :   SetAccumulator(HasProperty(object, property, context, kHasProperty));
    1891          93 :   Dispatch();
    1892          93 : }
    1893             : 
    1894             : // TestInstanceOf <src>
    1895             : //
    1896             : // Test if the object referenced by the <src> register is an an instance of type
    1897             : // referenced by the accumulator.
    1898         186 : IGNITION_HANDLER(TestInstanceOf, InterpreterAssembler) {
    1899          93 :   Node* reg_index = BytecodeOperandReg(0);
    1900          93 :   Node* name = LoadRegister(reg_index);
    1901          93 :   Node* object = GetAccumulator();
    1902          93 :   Node* context = GetContext();
    1903          93 :   SetAccumulator(InstanceOf(name, object, context));
    1904          93 :   Dispatch();
    1905          93 : }
    1906             : 
    1907             : // TestUndetectable
    1908             : //
    1909             : // Test if the value in the accumulator is undetectable (null, undefined or
    1910             : // document.all).
    1911          62 : IGNITION_HANDLER(TestUndetectable, InterpreterAssembler) {
    1912          62 :   Label return_false(this), end(this);
    1913          31 :   Node* object = GetAccumulator();
    1914             : 
    1915             :   // If the object is an Smi then return false.
    1916          62 :   SetAccumulator(BooleanConstant(false));
    1917          62 :   GotoIf(TaggedIsSmi(object), &end);
    1918             : 
    1919             :   // If it is a HeapObject, load the map and check for undetectable bit.
    1920          62 :   Node* result = SelectBooleanConstant(IsUndetectableMap(LoadMap(object)));
    1921          31 :   SetAccumulator(result);
    1922          31 :   Goto(&end);
    1923             : 
    1924          31 :   BIND(&end);
    1925          62 :   Dispatch();
    1926          31 : }
    1927             : 
    1928             : // TestNull
    1929             : //
    1930             : // Test if the value in accumulator is strictly equal to null.
    1931          62 : IGNITION_HANDLER(TestNull, InterpreterAssembler) {
    1932          31 :   Node* object = GetAccumulator();
    1933          31 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    1934          62 :   Node* result = SelectBooleanConstant(WordEqual(object, null_value));
    1935          31 :   SetAccumulator(result);
    1936          31 :   Dispatch();
    1937          31 : }
    1938             : 
    1939             : // TestUndefined
    1940             : //
    1941             : // Test if the value in the accumulator is strictly equal to undefined.
    1942          62 : IGNITION_HANDLER(TestUndefined, InterpreterAssembler) {
    1943          31 :   Node* object = GetAccumulator();
    1944          31 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    1945          62 :   Node* result = SelectBooleanConstant(WordEqual(object, undefined_value));
    1946          31 :   SetAccumulator(result);
    1947          31 :   Dispatch();
    1948          31 : }
    1949             : 
    1950             : // TestTypeOf <literal_flag>
    1951             : //
    1952             : // Tests if the object in the <accumulator> is typeof the literal represented
    1953             : // by |literal_flag|.
    1954          62 : IGNITION_HANDLER(TestTypeOf, InterpreterAssembler) {
    1955          31 :   Node* object = GetAccumulator();
    1956          31 :   Node* literal_flag = BytecodeOperandFlag(0);
    1957             : 
    1958             : #define MAKE_LABEL(name, lower_case) Label if_##lower_case(this);
    1959          62 :   TYPEOF_LITERAL_LIST(MAKE_LABEL)
    1960             : #undef MAKE_LABEL
    1961             : 
    1962             : #define LABEL_POINTER(name, lower_case) &if_##lower_case,
    1963          31 :   Label* labels[] = {TYPEOF_LITERAL_LIST(LABEL_POINTER)};
    1964             : #undef LABEL_POINTER
    1965             : 
    1966             : #define CASE(name, lower_case) \
    1967             :   static_cast<int32_t>(TestTypeOfFlags::LiteralFlag::k##name),
    1968          31 :   int32_t cases[] = {TYPEOF_LITERAL_LIST(CASE)};
    1969             : #undef CASE
    1970             : 
    1971          31 :   Label if_true(this), if_false(this), end(this);
    1972             : 
    1973             :   // We juse use the final label as the default and properly CSA_ASSERT
    1974             :   // that the {literal_flag} is valid here; this significantly improves
    1975             :   // the generated code (compared to having a default label that aborts).
    1976             :   unsigned const num_cases = arraysize(cases);
    1977             :   CSA_ASSERT(this, Uint32LessThan(literal_flag, Int32Constant(num_cases)));
    1978          31 :   Switch(literal_flag, labels[num_cases - 1], cases, labels, num_cases - 1);
    1979             : 
    1980          31 :   BIND(&if_number);
    1981             :   {
    1982          31 :     Comment("IfNumber");
    1983          31 :     GotoIfNumber(object, &if_true);
    1984          31 :     Goto(&if_false);
    1985             :   }
    1986          31 :   BIND(&if_string);
    1987             :   {
    1988          31 :     Comment("IfString");
    1989          62 :     GotoIf(TaggedIsSmi(object), &if_false);
    1990          62 :     Branch(IsString(object), &if_true, &if_false);
    1991             :   }
    1992          31 :   BIND(&if_symbol);
    1993             :   {
    1994          31 :     Comment("IfSymbol");
    1995          62 :     GotoIf(TaggedIsSmi(object), &if_false);
    1996          62 :     Branch(IsSymbol(object), &if_true, &if_false);
    1997             :   }
    1998          31 :   BIND(&if_boolean);
    1999             :   {
    2000          31 :     Comment("IfBoolean");
    2001          62 :     GotoIf(WordEqual(object, BooleanConstant(true)), &if_true);
    2002          62 :     Branch(WordEqual(object, BooleanConstant(false)), &if_true, &if_false);
    2003             :   }
    2004          31 :   BIND(&if_undefined);
    2005             :   {
    2006          31 :     Comment("IfUndefined");
    2007          62 :     GotoIf(TaggedIsSmi(object), &if_false);
    2008             :     // Check it is not null and the map has the undetectable bit set.
    2009          62 :     GotoIf(IsNull(object), &if_false);
    2010          93 :     Branch(IsUndetectableMap(LoadMap(object)), &if_true, &if_false);
    2011             :   }
    2012          31 :   BIND(&if_function);
    2013             :   {
    2014          31 :     Comment("IfFunction");
    2015          62 :     GotoIf(TaggedIsSmi(object), &if_false);
    2016             :     // Check if callable bit is set and not undetectable.
    2017          93 :     Node* map_bitfield = LoadMapBitField(LoadMap(object));
    2018             :     Node* callable_undetectable = Word32And(
    2019             :         map_bitfield,
    2020          93 :         Int32Constant(1 << Map::kIsUndetectable | 1 << Map::kIsCallable));
    2021             :     Branch(Word32Equal(callable_undetectable,
    2022          62 :                        Int32Constant(1 << Map::kIsCallable)),
    2023          62 :            &if_true, &if_false);
    2024             :   }
    2025          31 :   BIND(&if_object);
    2026             :   {
    2027          31 :     Comment("IfObject");
    2028          62 :     GotoIf(TaggedIsSmi(object), &if_false);
    2029             : 
    2030             :     // If the object is null then return true.
    2031          62 :     GotoIf(WordEqual(object, NullConstant()), &if_true);
    2032             : 
    2033             :     // Check if the object is a receiver type and is not undefined or callable.
    2034          62 :     Node* map = LoadMap(object);
    2035          62 :     GotoIfNot(IsJSReceiverMap(map), &if_false);
    2036          62 :     Node* map_bitfield = LoadMapBitField(map);
    2037             :     Node* callable_undetectable = Word32And(
    2038             :         map_bitfield,
    2039          93 :         Int32Constant(1 << Map::kIsUndetectable | 1 << Map::kIsCallable));
    2040          62 :     Branch(Word32Equal(callable_undetectable, Int32Constant(0)), &if_true,
    2041          62 :            &if_false);
    2042             :   }
    2043          31 :   BIND(&if_other);
    2044             :   {
    2045             :     // Typeof doesn't return any other string value.
    2046          31 :     Goto(&if_false);
    2047             :   }
    2048             : 
    2049          31 :   BIND(&if_false);
    2050             :   {
    2051          62 :     SetAccumulator(BooleanConstant(false));
    2052          31 :     Goto(&end);
    2053             :   }
    2054          31 :   BIND(&if_true);
    2055             :   {
    2056          62 :     SetAccumulator(BooleanConstant(true));
    2057          31 :     Goto(&end);
    2058             :   }
    2059          31 :   BIND(&end);
    2060          62 :   Dispatch();
    2061          31 : }
    2062             : 
    2063             : // Jump <imm>
    2064             : //
    2065             : // Jump by the number of bytes represented by the immediate operand |imm|.
    2066         186 : IGNITION_HANDLER(Jump, InterpreterAssembler) {
    2067          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2068          93 :   Jump(relative_jump);
    2069          93 : }
    2070             : 
    2071             : // JumpConstant <idx>
    2072             : //
    2073             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2074             : // pool.
    2075         186 : IGNITION_HANDLER(JumpConstant, InterpreterAssembler) {
    2076          93 :   Node* index = BytecodeOperandIdx(0);
    2077          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2078          93 :   Jump(relative_jump);
    2079          93 : }
    2080             : 
    2081             : // JumpIfTrue <imm>
    2082             : //
    2083             : // Jump by the number of bytes represented by an immediate operand if the
    2084             : // accumulator contains true. This only works for boolean inputs, and
    2085             : // will misbehave if passed arbitrary input values.
    2086         186 : IGNITION_HANDLER(JumpIfTrue, InterpreterAssembler) {
    2087          93 :   Node* accumulator = GetAccumulator();
    2088          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2089         186 :   Node* true_value = BooleanConstant(true);
    2090             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2091             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2092          93 :   JumpIfWordEqual(accumulator, true_value, relative_jump);
    2093          93 : }
    2094             : 
    2095             : // JumpIfTrueConstant <idx>
    2096             : //
    2097             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2098             : // pool if the accumulator contains true. This only works for boolean inputs,
    2099             : // and will misbehave if passed arbitrary input values.
    2100         186 : IGNITION_HANDLER(JumpIfTrueConstant, InterpreterAssembler) {
    2101          93 :   Node* accumulator = GetAccumulator();
    2102          93 :   Node* index = BytecodeOperandIdx(0);
    2103          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2104         186 :   Node* true_value = BooleanConstant(true);
    2105             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2106             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2107          93 :   JumpIfWordEqual(accumulator, true_value, relative_jump);
    2108          93 : }
    2109             : 
    2110             : // JumpIfFalse <imm>
    2111             : //
    2112             : // Jump by the number of bytes represented by an immediate operand if the
    2113             : // accumulator contains false. This only works for boolean inputs, and
    2114             : // will misbehave if passed arbitrary input values.
    2115         186 : IGNITION_HANDLER(JumpIfFalse, InterpreterAssembler) {
    2116          93 :   Node* accumulator = GetAccumulator();
    2117          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2118         186 :   Node* false_value = BooleanConstant(false);
    2119             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2120             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2121          93 :   JumpIfWordEqual(accumulator, false_value, relative_jump);
    2122          93 : }
    2123             : 
    2124             : // JumpIfFalseConstant <idx>
    2125             : //
    2126             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2127             : // pool if the accumulator contains false. This only works for boolean inputs,
    2128             : // and will misbehave if passed arbitrary input values.
    2129         186 : IGNITION_HANDLER(JumpIfFalseConstant, InterpreterAssembler) {
    2130          93 :   Node* accumulator = GetAccumulator();
    2131          93 :   Node* index = BytecodeOperandIdx(0);
    2132          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2133         186 :   Node* false_value = BooleanConstant(false);
    2134             :   CSA_ASSERT(this, TaggedIsNotSmi(accumulator));
    2135             :   CSA_ASSERT(this, IsBoolean(accumulator));
    2136          93 :   JumpIfWordEqual(accumulator, false_value, relative_jump);
    2137          93 : }
    2138             : 
    2139             : // JumpIfToBooleanTrue <imm>
    2140             : //
    2141             : // Jump by the number of bytes represented by an immediate operand if the object
    2142             : // referenced by the accumulator is true when the object is cast to boolean.
    2143         186 : IGNITION_HANDLER(JumpIfToBooleanTrue, InterpreterAssembler) {
    2144          93 :   Node* value = GetAccumulator();
    2145          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2146         186 :   Label if_true(this), if_false(this);
    2147          93 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2148          93 :   BIND(&if_true);
    2149          93 :   Jump(relative_jump);
    2150          93 :   BIND(&if_false);
    2151         186 :   Dispatch();
    2152          93 : }
    2153             : 
    2154             : // JumpIfToBooleanTrueConstant <idx>
    2155             : //
    2156             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2157             : // pool if the object referenced by the accumulator is true when the object is
    2158             : // cast to boolean.
    2159         186 : IGNITION_HANDLER(JumpIfToBooleanTrueConstant, InterpreterAssembler) {
    2160          93 :   Node* value = GetAccumulator();
    2161          93 :   Node* index = BytecodeOperandIdx(0);
    2162          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2163         186 :   Label if_true(this), if_false(this);
    2164          93 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2165          93 :   BIND(&if_true);
    2166          93 :   Jump(relative_jump);
    2167          93 :   BIND(&if_false);
    2168         186 :   Dispatch();
    2169          93 : }
    2170             : 
    2171             : // JumpIfToBooleanFalse <imm>
    2172             : //
    2173             : // Jump by the number of bytes represented by an immediate operand if the object
    2174             : // referenced by the accumulator is false when the object is cast to boolean.
    2175         186 : IGNITION_HANDLER(JumpIfToBooleanFalse, InterpreterAssembler) {
    2176          93 :   Node* value = GetAccumulator();
    2177          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2178         186 :   Label if_true(this), if_false(this);
    2179          93 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2180          93 :   BIND(&if_true);
    2181          93 :   Dispatch();
    2182          93 :   BIND(&if_false);
    2183         186 :   Jump(relative_jump);
    2184          93 : }
    2185             : 
    2186             : // JumpIfToBooleanFalseConstant <idx>
    2187             : //
    2188             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2189             : // pool if the object referenced by the accumulator is false when the object is
    2190             : // cast to boolean.
    2191         186 : IGNITION_HANDLER(JumpIfToBooleanFalseConstant, InterpreterAssembler) {
    2192          93 :   Node* value = GetAccumulator();
    2193          93 :   Node* index = BytecodeOperandIdx(0);
    2194          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2195         186 :   Label if_true(this), if_false(this);
    2196          93 :   BranchIfToBooleanIsTrue(value, &if_true, &if_false);
    2197          93 :   BIND(&if_true);
    2198          93 :   Dispatch();
    2199          93 :   BIND(&if_false);
    2200         186 :   Jump(relative_jump);
    2201          93 : }
    2202             : 
    2203             : // JumpIfNull <imm>
    2204             : //
    2205             : // Jump by the number of bytes represented by an immediate operand if the object
    2206             : // referenced by the accumulator is the null constant.
    2207         186 : IGNITION_HANDLER(JumpIfNull, InterpreterAssembler) {
    2208          93 :   Node* accumulator = GetAccumulator();
    2209          93 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2210          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2211          93 :   JumpIfWordEqual(accumulator, null_value, relative_jump);
    2212          93 : }
    2213             : 
    2214             : // JumpIfNullConstant <idx>
    2215             : //
    2216             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2217             : // pool if the object referenced by the accumulator is the null constant.
    2218         186 : IGNITION_HANDLER(JumpIfNullConstant, InterpreterAssembler) {
    2219          93 :   Node* accumulator = GetAccumulator();
    2220          93 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2221          93 :   Node* index = BytecodeOperandIdx(0);
    2222          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2223          93 :   JumpIfWordEqual(accumulator, null_value, relative_jump);
    2224          93 : }
    2225             : 
    2226             : // JumpIfNotNull <imm>
    2227             : //
    2228             : // Jump by the number of bytes represented by an immediate operand if the object
    2229             : // referenced by the accumulator is not the null constant.
    2230         186 : IGNITION_HANDLER(JumpIfNotNull, InterpreterAssembler) {
    2231          93 :   Node* accumulator = GetAccumulator();
    2232          93 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2233          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2234          93 :   JumpIfWordNotEqual(accumulator, null_value, relative_jump);
    2235          93 : }
    2236             : 
    2237             : // JumpIfNotNullConstant <idx>
    2238             : //
    2239             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2240             : // pool if the object referenced by the accumulator is not the null constant.
    2241         186 : IGNITION_HANDLER(JumpIfNotNullConstant, InterpreterAssembler) {
    2242          93 :   Node* accumulator = GetAccumulator();
    2243          93 :   Node* null_value = HeapConstant(isolate()->factory()->null_value());
    2244          93 :   Node* index = BytecodeOperandIdx(0);
    2245          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2246          93 :   JumpIfWordNotEqual(accumulator, null_value, relative_jump);
    2247          93 : }
    2248             : 
    2249             : // JumpIfUndefined <imm>
    2250             : //
    2251             : // Jump by the number of bytes represented by an immediate operand if the object
    2252             : // referenced by the accumulator is the undefined constant.
    2253         186 : IGNITION_HANDLER(JumpIfUndefined, InterpreterAssembler) {
    2254          93 :   Node* accumulator = GetAccumulator();
    2255          93 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2256          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2257          93 :   JumpIfWordEqual(accumulator, undefined_value, relative_jump);
    2258          93 : }
    2259             : 
    2260             : // JumpIfUndefinedConstant <idx>
    2261             : //
    2262             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2263             : // pool if the object referenced by the accumulator is the undefined constant.
    2264         186 : IGNITION_HANDLER(JumpIfUndefinedConstant, InterpreterAssembler) {
    2265          93 :   Node* accumulator = GetAccumulator();
    2266          93 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2267          93 :   Node* index = BytecodeOperandIdx(0);
    2268          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2269          93 :   JumpIfWordEqual(accumulator, undefined_value, relative_jump);
    2270          93 : }
    2271             : 
    2272             : // JumpIfNotUndefined <imm>
    2273             : //
    2274             : // Jump by the number of bytes represented by an immediate operand if the object
    2275             : // referenced by the accumulator is not the undefined constant.
    2276         186 : IGNITION_HANDLER(JumpIfNotUndefined, InterpreterAssembler) {
    2277          93 :   Node* accumulator = GetAccumulator();
    2278          93 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2279          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2280          93 :   JumpIfWordNotEqual(accumulator, undefined_value, relative_jump);
    2281          93 : }
    2282             : 
    2283             : // JumpIfNotUndefinedConstant <idx>
    2284             : //
    2285             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2286             : // pool if the object referenced by the accumulator is not the undefined
    2287             : // constant.
    2288         186 : IGNITION_HANDLER(JumpIfNotUndefinedConstant, InterpreterAssembler) {
    2289          93 :   Node* accumulator = GetAccumulator();
    2290          93 :   Node* undefined_value = HeapConstant(isolate()->factory()->undefined_value());
    2291          93 :   Node* index = BytecodeOperandIdx(0);
    2292          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2293          93 :   JumpIfWordNotEqual(accumulator, undefined_value, relative_jump);
    2294          93 : }
    2295             : 
    2296             : // JumpIfJSReceiver <imm>
    2297             : //
    2298             : // Jump by the number of bytes represented by an immediate operand if the object
    2299             : // referenced by the accumulator is a JSReceiver.
    2300         186 : IGNITION_HANDLER(JumpIfJSReceiver, InterpreterAssembler) {
    2301          93 :   Node* accumulator = GetAccumulator();
    2302          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2303             : 
    2304         186 :   Label if_object(this), if_notobject(this, Label::kDeferred), if_notsmi(this);
    2305         186 :   Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi);
    2306             : 
    2307          93 :   BIND(&if_notsmi);
    2308         186 :   Branch(IsJSReceiver(accumulator), &if_object, &if_notobject);
    2309          93 :   BIND(&if_object);
    2310          93 :   Jump(relative_jump);
    2311             : 
    2312          93 :   BIND(&if_notobject);
    2313         186 :   Dispatch();
    2314          93 : }
    2315             : 
    2316             : // JumpIfJSReceiverConstant <idx>
    2317             : //
    2318             : // Jump by the number of bytes in the Smi in the |idx| entry in the constant
    2319             : // pool if the object referenced by the accumulator is a JSReceiver.
    2320         186 : IGNITION_HANDLER(JumpIfJSReceiverConstant, InterpreterAssembler) {
    2321          93 :   Node* accumulator = GetAccumulator();
    2322          93 :   Node* index = BytecodeOperandIdx(0);
    2323          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(index);
    2324             : 
    2325         186 :   Label if_object(this), if_notobject(this), if_notsmi(this);
    2326         186 :   Branch(TaggedIsSmi(accumulator), &if_notobject, &if_notsmi);
    2327             : 
    2328          93 :   BIND(&if_notsmi);
    2329         186 :   Branch(IsJSReceiver(accumulator), &if_object, &if_notobject);
    2330             : 
    2331          93 :   BIND(&if_object);
    2332          93 :   Jump(relative_jump);
    2333             : 
    2334          93 :   BIND(&if_notobject);
    2335         186 :   Dispatch();
    2336          93 : }
    2337             : 
    2338             : // JumpLoop <imm> <loop_depth>
    2339             : //
    2340             : // Jump by the number of bytes represented by the immediate operand |imm|. Also
    2341             : // performs a loop nesting check and potentially triggers OSR in case the
    2342             : // current OSR level matches (or exceeds) the specified |loop_depth|.
    2343         186 : IGNITION_HANDLER(JumpLoop, InterpreterAssembler) {
    2344          93 :   Node* relative_jump = BytecodeOperandUImmWord(0);
    2345          93 :   Node* loop_depth = BytecodeOperandImm(1);
    2346          93 :   Node* osr_level = LoadOSRNestingLevel();
    2347             : 
    2348             :   // Check if OSR points at the given {loop_depth} are armed by comparing it to
    2349             :   // the current {osr_level} loaded from the header of the BytecodeArray.
    2350         186 :   Label ok(this), osr_armed(this, Label::kDeferred);
    2351         186 :   Node* condition = Int32GreaterThanOrEqual(loop_depth, osr_level);
    2352          93 :   Branch(condition, &ok, &osr_armed);
    2353             : 
    2354          93 :   BIND(&ok);
    2355          93 :   JumpBackward(relative_jump);
    2356             : 
    2357          93 :   BIND(&osr_armed);
    2358             :   {
    2359          93 :     Callable callable = CodeFactory::InterpreterOnStackReplacement(isolate());
    2360             :     Node* target = HeapConstant(callable.code());
    2361          93 :     Node* context = GetContext();
    2362          93 :     CallStub(callable.descriptor(), target, context);
    2363          93 :     JumpBackward(relative_jump);
    2364          93 :   }
    2365          93 : }
    2366             : 
    2367             : // SwitchOnSmiNoFeedback <table_start> <table_length> <case_value_base>
    2368             : //
    2369             : // Jump by the number of bytes defined by a Smi in a table in the constant pool,
    2370             : // where the table starts at |table_start| and has |table_length| entries.
    2371             : // The table is indexed by the accumulator, minus |case_value_base|. If the
    2372             : // case_value falls outside of the table |table_length|, fall-through to the
    2373             : // next bytecode.
    2374         186 : IGNITION_HANDLER(SwitchOnSmiNoFeedback, InterpreterAssembler) {
    2375          93 :   Node* acc = GetAccumulator();
    2376          93 :   Node* table_start = BytecodeOperandIdx(0);
    2377          93 :   Node* table_length = BytecodeOperandUImmWord(1);
    2378          93 :   Node* case_value_base = BytecodeOperandImmIntPtr(2);
    2379             : 
    2380          93 :   Label fall_through(this);
    2381             : 
    2382             :   // The accumulator must be a Smi.
    2383             :   // TODO(leszeks): Add a bytecode with type feedback that allows other
    2384             :   // accumulator values.
    2385             :   CSA_ASSERT(this, TaggedIsSmi(acc));
    2386             : 
    2387         279 :   Node* case_value = IntPtrSub(SmiUntag(acc), case_value_base);
    2388         279 :   GotoIf(IntPtrLessThan(case_value, IntPtrConstant(0)), &fall_through);
    2389         186 :   GotoIf(IntPtrGreaterThanOrEqual(case_value, table_length), &fall_through);
    2390         186 :   Node* entry = IntPtrAdd(table_start, case_value);
    2391          93 :   Node* relative_jump = LoadAndUntagConstantPoolEntry(entry);
    2392          93 :   Jump(relative_jump);
    2393             : 
    2394          93 :   BIND(&fall_through);
    2395          93 :   Dispatch();
    2396          93 : }
    2397             : 
    2398             : // CreateRegExpLiteral <pattern_idx> <literal_idx> <flags>
    2399             : //
    2400             : // Creates a regular expression literal for literal index <literal_idx> with
    2401             : // <flags> and the pattern in <pattern_idx>.
    2402         186 : IGNITION_HANDLER(CreateRegExpLiteral, InterpreterAssembler) {
    2403          93 :   Node* pattern_index = BytecodeOperandIdx(0);
    2404          93 :   Node* pattern = LoadConstantPoolEntry(pattern_index);
    2405          93 :   Node* feedback_vector = LoadFeedbackVector();
    2406          93 :   Node* slot_id = BytecodeOperandIdx(1);
    2407         279 :   Node* flags = SmiFromWord32(BytecodeOperandFlag(2));
    2408          93 :   Node* context = GetContext();
    2409             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    2410             :   Node* result = constructor_assembler.EmitCreateRegExpLiteral(
    2411          93 :       feedback_vector, slot_id, pattern, flags, context);
    2412          93 :   SetAccumulator(result);
    2413          93 :   Dispatch();
    2414          93 : }
    2415             : 
    2416             : // CreateArrayLiteral <element_idx> <literal_idx> <flags>
    2417             : //
    2418             : // Creates an array literal for literal index <literal_idx> with
    2419             : // CreateArrayLiteral flags <flags> and constant elements in <element_idx>.
    2420         186 : IGNITION_HANDLER(CreateArrayLiteral, InterpreterAssembler) {
    2421          93 :   Node* feedback_vector = LoadFeedbackVector();
    2422          93 :   Node* slot_id = BytecodeOperandIdx(1);
    2423          93 :   Node* context = GetContext();
    2424          93 :   Node* bytecode_flags = BytecodeOperandFlag(2);
    2425             : 
    2426         186 :   Label fast_shallow_clone(this), call_runtime(this, Label::kDeferred);
    2427             :   Branch(IsSetWord32<CreateArrayLiteralFlags::FastCloneSupportedBit>(
    2428          93 :              bytecode_flags),
    2429          93 :          &fast_shallow_clone, &call_runtime);
    2430             : 
    2431          93 :   BIND(&fast_shallow_clone);
    2432             :   {
    2433             :     ConstructorBuiltinsAssembler constructor_assembler(state());
    2434             :     Node* result = constructor_assembler.EmitCreateShallowArrayLiteral(
    2435             :         feedback_vector, slot_id, context, &call_runtime,
    2436          93 :         TRACK_ALLOCATION_SITE);
    2437          93 :     SetAccumulator(result);
    2438          93 :     Dispatch();
    2439             :   }
    2440             : 
    2441          93 :   BIND(&call_runtime);
    2442             :   {
    2443             :     Node* flags_raw = DecodeWordFromWord32<CreateArrayLiteralFlags::FlagsBits>(
    2444          93 :         bytecode_flags);
    2445         186 :     Node* flags = SmiTag(flags_raw);
    2446          93 :     Node* index = BytecodeOperandIdx(0);
    2447          93 :     Node* constant_elements = LoadConstantPoolEntry(index);
    2448             :     Node* result =
    2449             :         CallRuntime(Runtime::kCreateArrayLiteral, context, feedback_vector,
    2450         186 :                     SmiTag(slot_id), constant_elements, flags);
    2451          93 :     SetAccumulator(result);
    2452          93 :     Dispatch();
    2453          93 :   }
    2454          93 : }
    2455             : 
    2456             : // CreateEmptyArrayLiteral <literal_idx>
    2457             : //
    2458             : // Creates an empty JSArray literal for literal index <literal_idx>.
    2459         186 : IGNITION_HANDLER(CreateEmptyArrayLiteral, InterpreterAssembler) {
    2460          93 :   Node* feedback_vector = LoadFeedbackVector();
    2461          93 :   Node* slot_id = BytecodeOperandIdx(0);
    2462          93 :   Node* context = GetContext();
    2463             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    2464             :   Node* result = constructor_assembler.EmitCreateEmptyArrayLiteral(
    2465          93 :       feedback_vector, slot_id, context);
    2466          93 :   SetAccumulator(result);
    2467          93 :   Dispatch();
    2468          93 : }
    2469             : 
    2470             : // CreateObjectLiteral <element_idx> <literal_idx> <flags>
    2471             : //
    2472             : // Creates an object literal for literal index <literal_idx> with
    2473             : // CreateObjectLiteralFlags <flags> and constant elements in <element_idx>.
    2474         186 : IGNITION_HANDLER(CreateObjectLiteral, InterpreterAssembler) {
    2475          93 :   Node* feedback_vector = LoadFeedbackVector();
    2476          93 :   Node* slot_id = BytecodeOperandIdx(1);
    2477          93 :   Node* bytecode_flags = BytecodeOperandFlag(2);
    2478             : 
    2479             :   // Check if we can do a fast clone or have to call the runtime.
    2480         186 :   Label if_fast_clone(this), if_not_fast_clone(this, Label::kDeferred);
    2481             :   Branch(IsSetWord32<CreateObjectLiteralFlags::FastCloneSupportedBit>(
    2482          93 :              bytecode_flags),
    2483          93 :          &if_fast_clone, &if_not_fast_clone);
    2484             : 
    2485          93 :   BIND(&if_fast_clone);
    2486             :   {
    2487             :     // If we can do a fast clone do the fast-path in CreateShallowObjectLiteral.
    2488             :     ConstructorBuiltinsAssembler constructor_assembler(state());
    2489             :     Node* result = constructor_assembler.EmitCreateShallowObjectLiteral(
    2490          93 :         feedback_vector, slot_id, &if_not_fast_clone);
    2491          93 :     StoreRegister(result, BytecodeOperandReg(3));
    2492          93 :     Dispatch();
    2493             :   }
    2494             : 
    2495          93 :   BIND(&if_not_fast_clone);
    2496             :   {
    2497             :     // If we can't do a fast clone, call into the runtime.
    2498          93 :     Node* index = BytecodeOperandIdx(0);
    2499          93 :     Node* boilerplate_description = LoadConstantPoolEntry(index);
    2500          93 :     Node* context = GetContext();
    2501             : 
    2502             :     Node* flags_raw = DecodeWordFromWord32<CreateObjectLiteralFlags::FlagsBits>(
    2503          93 :         bytecode_flags);
    2504         186 :     Node* flags = SmiTag(flags_raw);
    2505             : 
    2506             :     Node* result =
    2507             :         CallRuntime(Runtime::kCreateObjectLiteral, context, feedback_vector,
    2508         186 :                     SmiTag(slot_id), boilerplate_description, flags);
    2509          93 :     StoreRegister(result, BytecodeOperandReg(3));
    2510             :     // TODO(klaasb) build a single dispatch once the call is inlined
    2511          93 :     Dispatch();
    2512          93 :   }
    2513          93 : }
    2514             : 
    2515             : // CreateEmptyObjectLiteral
    2516             : //
    2517             : // Creates an empty JSObject literal.
    2518          62 : IGNITION_HANDLER(CreateEmptyObjectLiteral, InterpreterAssembler) {
    2519          31 :   Node* context = GetContext();
    2520             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    2521          31 :   Node* result = constructor_assembler.EmitCreateEmptyObjectLiteral(context);
    2522          31 :   SetAccumulator(result);
    2523          31 :   Dispatch();
    2524          31 : }
    2525             : 
    2526             : // GetTemplateObject
    2527             : //
    2528             : // Creates the template to pass for tagged templates and returns it in the
    2529             : // accumulator, creating and caching the site object on-demand as per the
    2530             : // specification.
    2531         186 : IGNITION_HANDLER(GetTemplateObject, InterpreterAssembler) {
    2532          93 :   Node* description_index = BytecodeOperandIdx(0);
    2533          93 :   Node* description = LoadConstantPoolEntry(description_index);
    2534          93 :   Node* context = GetContext();
    2535             : 
    2536          93 :   Node* result = CallRuntime(Runtime::kGetTemplateObject, context, description);
    2537          93 :   SetAccumulator(result);
    2538          93 :   Dispatch();
    2539          93 : }
    2540             : 
    2541             : // CreateClosure <index> <slot> <tenured>
    2542             : //
    2543             : // Creates a new closure for SharedFunctionInfo at position |index| in the
    2544             : // constant pool and with the PretenureFlag <tenured>.
    2545         186 : IGNITION_HANDLER(CreateClosure, InterpreterAssembler) {
    2546          93 :   Node* index = BytecodeOperandIdx(0);
    2547          93 :   Node* shared = LoadConstantPoolEntry(index);
    2548          93 :   Node* flags = BytecodeOperandFlag(2);
    2549          93 :   Node* context = GetContext();
    2550             : 
    2551          93 :   Label call_runtime(this, Label::kDeferred);
    2552          93 :   GotoIfNot(IsSetWord32<CreateClosureFlags::FastNewClosureBit>(flags),
    2553          93 :             &call_runtime);
    2554             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    2555          93 :   Node* vector_index = BytecodeOperandIdx(1);
    2556         186 :   vector_index = SmiTag(vector_index);
    2557          93 :   Node* feedback_vector = LoadFeedbackVector();
    2558             :   SetAccumulator(constructor_assembler.EmitFastNewClosure(
    2559          93 :       shared, feedback_vector, vector_index, context));
    2560          93 :   Dispatch();
    2561             : 
    2562          93 :   BIND(&call_runtime);
    2563             :   {
    2564             :     Node* tenured_raw =
    2565          93 :         DecodeWordFromWord32<CreateClosureFlags::PretenuredBit>(flags);
    2566         186 :     Node* tenured = SmiTag(tenured_raw);
    2567          93 :     feedback_vector = LoadFeedbackVector();
    2568          93 :     vector_index = BytecodeOperandIdx(1);
    2569         186 :     vector_index = SmiTag(vector_index);
    2570             :     Node* result = CallRuntime(Runtime::kInterpreterNewClosure, context, shared,
    2571             :                                feedback_vector, vector_index, tenured);
    2572          93 :     SetAccumulator(result);
    2573          93 :     Dispatch();
    2574          93 :   }
    2575          93 : }
    2576             : 
    2577             : // CreateBlockContext <index>
    2578             : //
    2579             : // Creates a new block context with the scope info constant at |index| and the
    2580             : // closure in the accumulator.
    2581         186 : IGNITION_HANDLER(CreateBlockContext, InterpreterAssembler) {
    2582          93 :   Node* index = BytecodeOperandIdx(0);
    2583          93 :   Node* scope_info = LoadConstantPoolEntry(index);
    2584          93 :   Node* closure = GetAccumulator();
    2585          93 :   Node* context = GetContext();
    2586             :   SetAccumulator(
    2587         186 :       CallRuntime(Runtime::kPushBlockContext, context, scope_info, closure));
    2588          93 :   Dispatch();
    2589          93 : }
    2590             : 
    2591             : // CreateCatchContext <exception> <name_idx> <scope_info_idx>
    2592             : //
    2593             : // Creates a new context for a catch block with the |exception| in a register,
    2594             : // the variable name at |name_idx|, the ScopeInfo at |scope_info_idx|, and the
    2595             : // closure in the accumulator.
    2596         186 : IGNITION_HANDLER(CreateCatchContext, InterpreterAssembler) {
    2597          93 :   Node* exception_reg = BytecodeOperandReg(0);
    2598          93 :   Node* exception = LoadRegister(exception_reg);
    2599          93 :   Node* name_idx = BytecodeOperandIdx(1);
    2600          93 :   Node* name = LoadConstantPoolEntry(name_idx);
    2601          93 :   Node* scope_info_idx = BytecodeOperandIdx(2);
    2602          93 :   Node* scope_info = LoadConstantPoolEntry(scope_info_idx);
    2603          93 :   Node* closure = GetAccumulator();
    2604          93 :   Node* context = GetContext();
    2605             :   SetAccumulator(CallRuntime(Runtime::kPushCatchContext, context, name,
    2606         186 :                              exception, scope_info, closure));
    2607          93 :   Dispatch();
    2608          93 : }
    2609             : 
    2610             : // CreateFunctionContext <slots>
    2611             : //
    2612             : // Creates a new context with number of |slots| for the function closure.
    2613         186 : IGNITION_HANDLER(CreateFunctionContext, InterpreterAssembler) {
    2614          93 :   Node* closure = LoadRegister(Register::function_closure());
    2615          93 :   Node* slots = BytecodeOperandUImm(0);
    2616          93 :   Node* context = GetContext();
    2617             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    2618             :   SetAccumulator(constructor_assembler.EmitFastNewFunctionContext(
    2619          93 :       closure, slots, context, FUNCTION_SCOPE));
    2620          93 :   Dispatch();
    2621          93 : }
    2622             : 
    2623             : // CreateEvalContext <slots>
    2624             : //
    2625             : // Creates a new context with number of |slots| for an eval closure.
    2626         186 : IGNITION_HANDLER(CreateEvalContext, InterpreterAssembler) {
    2627          93 :   Node* closure = LoadRegister(Register::function_closure());
    2628          93 :   Node* slots = BytecodeOperandUImm(0);
    2629          93 :   Node* context = GetContext();
    2630             :   ConstructorBuiltinsAssembler constructor_assembler(state());
    2631             :   SetAccumulator(constructor_assembler.EmitFastNewFunctionContext(
    2632          93 :       closure, slots, context, EVAL_SCOPE));
    2633          93 :   Dispatch();
    2634          93 : }
    2635             : 
    2636             : // CreateWithContext <register> <scope_info_idx>
    2637             : //
    2638             : // Creates a new context with the ScopeInfo at |scope_info_idx| for a
    2639             : // with-statement with the object in |register| and the closure in the
    2640             : // accumulator.
    2641         186 : IGNITION_HANDLER(CreateWithContext, InterpreterAssembler) {
    2642          93 :   Node* reg_index = BytecodeOperandReg(0);
    2643          93 :   Node* object = LoadRegister(reg_index);
    2644          93 :   Node* scope_info_idx = BytecodeOperandIdx(1);
    2645          93 :   Node* scope_info = LoadConstantPoolEntry(scope_info_idx);
    2646          93 :   Node* closure = GetAccumulator();
    2647          93 :   Node* context = GetContext();
    2648             :   SetAccumulator(CallRuntime(Runtime::kPushWithContext, context, object,
    2649         186 :                              scope_info, closure));
    2650          93 :   Dispatch();
    2651          93 : }
    2652             : 
    2653             : // CreateMappedArguments
    2654             : //
    2655             : // Creates a new mapped arguments object.
    2656          62 : IGNITION_HANDLER(CreateMappedArguments, InterpreterAssembler) {
    2657          31 :   Node* closure = LoadRegister(Register::function_closure());
    2658          31 :   Node* context = GetContext();
    2659             : 
    2660          31 :   Label if_duplicate_parameters(this, Label::kDeferred);
    2661          31 :   Label if_not_duplicate_parameters(this);
    2662             : 
    2663             :   // Check if function has duplicate parameters.
    2664             :   // TODO(rmcilroy): Remove this check when FastNewSloppyArgumentsStub supports
    2665             :   // duplicate parameters.
    2666             :   Node* shared_info =
    2667          31 :       LoadObjectField(closure, JSFunction::kSharedFunctionInfoOffset);
    2668             :   Node* compiler_hints =
    2669             :       LoadObjectField(shared_info, SharedFunctionInfo::kCompilerHintsOffset,
    2670          31 :                       MachineType::Uint32());
    2671             :   Node* has_duplicate_parameters =
    2672             :       IsSetWord32<SharedFunctionInfo::HasDuplicateParametersBit>(
    2673             :           compiler_hints);
    2674             :   Branch(has_duplicate_parameters, &if_duplicate_parameters,
    2675          31 :          &if_not_duplicate_parameters);
    2676             : 
    2677          31 :   BIND(&if_not_duplicate_parameters);
    2678             :   {
    2679             :     ArgumentsBuiltinsAssembler constructor_assembler(state());
    2680             :     Node* result =
    2681          31 :         constructor_assembler.EmitFastNewSloppyArguments(context, closure);
    2682          31 :     SetAccumulator(result);
    2683          31 :     Dispatch();
    2684             :   }
    2685             : 
    2686          31 :   BIND(&if_duplicate_parameters);
    2687             :   {
    2688             :     Node* result =
    2689             :         CallRuntime(Runtime::kNewSloppyArguments_Generic, context, closure);
    2690          31 :     SetAccumulator(result);
    2691          31 :     Dispatch();
    2692          31 :   }
    2693          31 : }
    2694             : 
    2695             : // CreateUnmappedArguments
    2696             : //
    2697             : // Creates a new unmapped arguments object.
    2698          62 : IGNITION_HANDLER(CreateUnmappedArguments, InterpreterAssembler) {
    2699          31 :   Node* context = GetContext();
    2700          31 :   Node* closure = LoadRegister(Register::function_closure());
    2701             :   ArgumentsBuiltinsAssembler builtins_assembler(state());
    2702             :   Node* result =
    2703          31 :       builtins_assembler.EmitFastNewStrictArguments(context, closure);
    2704          31 :   SetAccumulator(result);
    2705          31 :   Dispatch();
    2706          31 : }
    2707             : 
    2708             : // CreateRestParameter
    2709             : //
    2710             : // Creates a new rest parameter array.
    2711          62 : IGNITION_HANDLER(CreateRestParameter, InterpreterAssembler) {
    2712          31 :   Node* closure = LoadRegister(Register::function_closure());
    2713          31 :   Node* context = GetContext();
    2714             :   ArgumentsBuiltinsAssembler builtins_assembler(state());
    2715          31 :   Node* result = builtins_assembler.EmitFastNewRestParameter(context, closure);
    2716          31 :   SetAccumulator(result);
    2717          31 :   Dispatch();
    2718          31 : }
    2719             : 
    2720             : // StackCheck
    2721             : //
    2722             : // Performs a stack guard check.
    2723          62 : IGNITION_HANDLER(StackCheck, InterpreterAssembler) {
    2724          62 :   Label ok(this), stack_check_interrupt(this, Label::kDeferred);
    2725             : 
    2726          31 :   Node* interrupt = StackCheckTriggeredInterrupt();
    2727          31 :   Branch(interrupt, &stack_check_interrupt, &ok);
    2728             : 
    2729          31 :   BIND(&ok);
    2730          31 :   Dispatch();
    2731             : 
    2732          31 :   BIND(&stack_check_interrupt);
    2733             :   {
    2734          31 :     Node* context = GetContext();
    2735             :     CallRuntime(Runtime::kStackGuard, context);
    2736          31 :     Dispatch();
    2737          31 :   }
    2738          31 : }
    2739             : 
    2740             : // SetPendingMessage
    2741             : //
    2742             : // Sets the pending message to the value in the accumulator, and returns the
    2743             : // previous pending message in the accumulator.
    2744          62 : IGNITION_HANDLER(SetPendingMessage, InterpreterAssembler) {
    2745             :   Node* pending_message = ExternalConstant(
    2746          62 :       ExternalReference::address_of_pending_message_obj(isolate()));
    2747          31 :   Node* previous_message = Load(MachineType::TaggedPointer(), pending_message);
    2748          31 :   Node* new_message = GetAccumulator();
    2749             :   StoreNoWriteBarrier(MachineRepresentation::kTaggedPointer, pending_message,
    2750          31 :                       new_message);
    2751          31 :   SetAccumulator(previous_message);
    2752          31 :   Dispatch();
    2753          31 : }
    2754             : 
    2755             : // Throw
    2756             : //
    2757             : // Throws the exception in the accumulator.
    2758          62 : IGNITION_HANDLER(Throw, InterpreterAssembler) {
    2759          31 :   Node* exception = GetAccumulator();
    2760          31 :   Node* context = GetContext();
    2761          31 :   CallRuntime(Runtime::kThrow, context, exception);
    2762             :   // We shouldn't ever return from a throw.
    2763          31 :   Abort(kUnexpectedReturnFromThrow);
    2764          31 : }
    2765             : 
    2766             : // ReThrow
    2767             : //
    2768             : // Re-throws the exception in the accumulator.
    2769          62 : IGNITION_HANDLER(ReThrow, InterpreterAssembler) {
    2770          31 :   Node* exception = GetAccumulator();
    2771          31 :   Node* context = GetContext();
    2772          31 :   CallRuntime(Runtime::kReThrow, context, exception);
    2773             :   // We shouldn't ever return from a throw.
    2774          31 :   Abort(kUnexpectedReturnFromThrow);
    2775          31 : }
    2776             : 
    2777             : // Abort <bailout_reason>
    2778             : //
    2779             : // Aborts execution (via a call to the runtime function).
    2780         186 : IGNITION_HANDLER(Abort, InterpreterAssembler) {
    2781          93 :   Node* reason = BytecodeOperandIdx(0);
    2782         186 :   CallRuntime(Runtime::kAbort, NoContextConstant(), SmiTag(reason));
    2783          93 :   Unreachable();
    2784          93 : }
    2785             : 
    2786             : // Return
    2787             : //
    2788             : // Return the value in the accumulator.
    2789          62 : IGNITION_HANDLER(Return, InterpreterAssembler) {
    2790          31 :   UpdateInterruptBudgetOnReturn();
    2791          31 :   Node* accumulator = GetAccumulator();
    2792          31 :   Return(accumulator);
    2793          31 : }
    2794             : 
    2795             : // ThrowReferenceErrorIfHole <variable_name>
    2796             : //
    2797             : // Throws an exception if the value in the accumulator is TheHole.
    2798         186 : IGNITION_HANDLER(ThrowReferenceErrorIfHole, InterpreterAssembler) {
    2799          93 :   Node* value = GetAccumulator();
    2800          93 :   Node* the_hole_value = HeapConstant(isolate()->factory()->the_hole_value());
    2801             : 
    2802             :   Label throw_error(this, Label::kDeferred);
    2803         186 :   GotoIf(WordEqual(value, the_hole_value), &throw_error);
    2804          93 :   Dispatch();
    2805             : 
    2806          93 :   BIND(&throw_error);
    2807             :   {
    2808          93 :     Node* name = LoadConstantPoolEntry(BytecodeOperandIdx(0));
    2809          93 :     CallRuntime(Runtime::kThrowReferenceError, GetContext(), name);
    2810             :     // We shouldn't ever return from a throw.
    2811          93 :     Abort(kUnexpectedReturnFromThrow);
    2812          93 :   }
    2813          93 : }
    2814             : 
    2815             : // ThrowSuperNotCalledIfHole
    2816             : //
    2817             : // Throws an exception if the value in the accumulator is TheHole.
    2818          62 : IGNITION_HANDLER(ThrowSuperNotCalledIfHole, InterpreterAssembler) {
    2819          31 :   Node* value = GetAccumulator();
    2820          31 :   Node* the_hole_value = HeapConstant(isolate()->factory()->the_hole_value());
    2821             : 
    2822             :   Label throw_error(this, Label::kDeferred);
    2823          62 :   GotoIf(WordEqual(value, the_hole_value), &throw_error);
    2824          31 :   Dispatch();
    2825             : 
    2826          31 :   BIND(&throw_error);
    2827             :   {
    2828          31 :     CallRuntime(Runtime::kThrowSuperNotCalled, GetContext());
    2829             :     // We shouldn't ever return from a throw.
    2830          31 :     Abort(kUnexpectedReturnFromThrow);
    2831          31 :   }
    2832          31 : }
    2833             : 
    2834             : // ThrowSuperAlreadyCalledIfNotHole
    2835             : //
    2836             : // Throws SuperAleradyCalled exception if the value in the accumulator is not
    2837             : // TheHole.
    2838          62 : IGNITION_HANDLER(ThrowSuperAlreadyCalledIfNotHole, InterpreterAssembler) {
    2839          31 :   Node* value = GetAccumulator();
    2840          31 :   Node* the_hole_value = HeapConstant(isolate()->factory()->the_hole_value());
    2841             : 
    2842             :   Label throw_error(this, Label::kDeferred);
    2843          62 :   GotoIf(WordNotEqual(value, the_hole_value), &throw_error);
    2844          31 :   Dispatch();
    2845             : 
    2846          31 :   BIND(&throw_error);
    2847             :   {
    2848          31 :     CallRuntime(Runtime::kThrowSuperAlreadyCalledError, GetContext());
    2849             :     // We shouldn't ever return from a throw.
    2850          31 :     Abort(kUnexpectedReturnFromThrow);
    2851          31 :   }
    2852          31 : }
    2853             : 
    2854             : // Debugger
    2855             : //
    2856             : // Call runtime to handle debugger statement.
    2857          62 : IGNITION_HANDLER(Debugger, InterpreterAssembler) {
    2858          31 :   Node* context = GetContext();
    2859          62 :   CallStub(CodeFactory::HandleDebuggerStatement(isolate()), context);
    2860          31 :   Dispatch();
    2861          31 : }
    2862             : 
    2863             : // DebugBreak
    2864             : //
    2865             : // Call runtime to handle a debug break.
    2866             : #define DEBUG_BREAK(Name, ...)                                             \
    2867             :   IGNITION_HANDLER(Name, InterpreterAssembler) {                           \
    2868             :     Node* context = GetContext();                                          \
    2869             :     Node* accumulator = GetAccumulator();                                  \
    2870             :     Node* original_handler =                                               \
    2871             :         CallRuntime(Runtime::kDebugBreakOnBytecode, context, accumulator); \
    2872             :     MaybeDropFrames(context);                                              \
    2873             :     DispatchToBytecodeHandler(original_handler);                           \
    2874             :   }
    2875        1953 : DEBUG_BREAK_BYTECODE_LIST(DEBUG_BREAK);
    2876             : #undef DEBUG_BREAK
    2877             : 
    2878             : // IncBlockCounter <slot>
    2879             : //
    2880             : // Increment the execution count for the given slot. Used for block code
    2881             : // coverage.
    2882         186 : IGNITION_HANDLER(IncBlockCounter, InterpreterAssembler) {
    2883          93 :   Node* closure = LoadRegister(Register::function_closure());
    2884          93 :   Node* coverage_array_slot = BytecodeOperandIdxSmi(0);
    2885          93 :   Node* context = GetContext();
    2886             : 
    2887          93 :   CallRuntime(Runtime::kIncBlockCounter, context, closure, coverage_array_slot);
    2888             : 
    2889          93 :   Dispatch();
    2890          93 : }
    2891             : 
    2892          93 : class InterpreterForInPrepareAssembler : public InterpreterAssembler {
    2893             :  public:
    2894             :   InterpreterForInPrepareAssembler(CodeAssemblerState* state, Bytecode bytecode,
    2895             :                                    OperandScale operand_scale)
    2896          93 :       : InterpreterAssembler(state, bytecode, operand_scale) {}
    2897             : 
    2898         186 :   void BuildForInPrepareResult(Node* output_register, Node* cache_type,
    2899             :                                Node* cache_array, Node* cache_length) {
    2900         186 :     StoreRegister(cache_type, output_register);
    2901         186 :     output_register = NextRegister(output_register);
    2902         186 :     StoreRegister(cache_array, output_register);
    2903         186 :     output_register = NextRegister(output_register);
    2904         186 :     StoreRegister(cache_length, output_register);
    2905         186 :   }
    2906             : };
    2907             : 
    2908             : // ForInEnumerate <receiver>
    2909             : //
    2910             : // Enumerates the enumerable keys of the |receiver| and either returns the
    2911             : // map of the |receiver| if it has a usable enum cache or a fixed array
    2912             : // with the keys to enumerate in the accumulator.
    2913         186 : IGNITION_HANDLER(ForInEnumerate, InterpreterAssembler) {
    2914          93 :   Node* receiver_register = BytecodeOperandReg(0);
    2915          93 :   Node* receiver = LoadRegister(receiver_register);
    2916          93 :   Node* context = GetContext();
    2917             : 
    2918         186 :   Label if_empty(this), if_runtime(this, Label::kDeferred);
    2919          93 :   Node* receiver_map = CheckEnumCache(receiver, &if_empty, &if_runtime);
    2920          93 :   SetAccumulator(receiver_map);
    2921          93 :   Dispatch();
    2922             : 
    2923          93 :   BIND(&if_empty);
    2924             :   {
    2925         186 :     Node* result = EmptyFixedArrayConstant();
    2926          93 :     SetAccumulator(result);
    2927          93 :     Dispatch();
    2928             :   }
    2929             : 
    2930          93 :   BIND(&if_runtime);
    2931             :   {
    2932             :     Node* result = CallRuntime(Runtime::kForInEnumerate, context, receiver);
    2933          93 :     SetAccumulator(result);
    2934          93 :     Dispatch();
    2935          93 :   }
    2936          93 : }
    2937             : 
    2938             : // ForInPrepare <cache_info_triple>
    2939             : //
    2940             : // Returns state for for..in loop execution based on the enumerator in
    2941             : // the accumulator register, which is the result of calling ForInEnumerate
    2942             : // on a JSReceiver object.
    2943             : // The result is output in registers |cache_info_triple| to
    2944             : // |cache_info_triple + 2|, with the registers holding cache_type, cache_array,
    2945             : // and cache_length respectively.
    2946         372 : IGNITION_HANDLER(ForInPrepare, InterpreterForInPrepareAssembler) {
    2947          93 :   Node* enumerator = GetAccumulator();
    2948          93 :   Node* output_register = BytecodeOperandReg(0);
    2949          93 :   Node* vector_index = BytecodeOperandIdx(1);
    2950          93 :   Node* feedback_vector = LoadFeedbackVector();
    2951             : 
    2952             :   // The {enumerator} is either a Map or a FixedArray.
    2953             :   CSA_ASSERT(this, TaggedIsNotSmi(enumerator));
    2954             : 
    2955             :   // Check if we're using an enum cache.
    2956         186 :   Label if_fast(this), if_slow(this);
    2957         186 :   Branch(IsMap(enumerator), &if_fast, &if_slow);
    2958             : 
    2959          93 :   BIND(&if_fast);
    2960             :   {
    2961             :     // Load the enumeration length and cache from the {enumerator}.
    2962          93 :     Node* enum_length = LoadMapEnumLength(enumerator);
    2963             :     CSA_ASSERT(this, WordNotEqual(enum_length,
    2964             :                                   IntPtrConstant(kInvalidEnumCacheSentinel)));
    2965         186 :     Node* descriptors = LoadMapDescriptors(enumerator);
    2966             :     Node* enum_cache =
    2967             :         LoadObjectField(descriptors, DescriptorArray::kEnumCacheOffset);
    2968             :     Node* enum_keys = LoadObjectField(enum_cache, EnumCache::kKeysOffset);
    2969             : 
    2970             :     // Check if we have enum indices available.
    2971             :     Node* enum_indices = LoadObjectField(enum_cache, EnumCache::kIndicesOffset);
    2972         186 :     Node* enum_indices_length = LoadAndUntagFixedArrayBaseLength(enum_indices);
    2973             :     Node* feedback = SelectSmiConstant(
    2974          93 :         IntPtrLessThanOrEqual(enum_length, enum_indices_length),
    2975         186 :         ForInFeedback::kEnumCacheKeysAndIndices, ForInFeedback::kEnumCacheKeys);
    2976          93 :     UpdateFeedback(feedback, feedback_vector, vector_index);
    2977             : 
    2978             :     // Construct the cache info triple.
    2979             :     Node* cache_type = enumerator;
    2980             :     Node* cache_array = enum_keys;
    2981         186 :     Node* cache_length = SmiTag(enum_length);
    2982             :     BuildForInPrepareResult(output_register, cache_type, cache_array,
    2983          93 :                             cache_length);
    2984          93 :     Dispatch();
    2985             :   }
    2986             : 
    2987          93 :   BIND(&if_slow);
    2988             :   {
    2989             :     // The {enumerator} is a FixedArray with all the keys to iterate.
    2990             :     CSA_ASSERT(this, IsFixedArray(enumerator));
    2991             : 
    2992             :     // Record the fact that we hit the for-in slow-path.
    2993             :     UpdateFeedback(SmiConstant(ForInFeedback::kAny), feedback_vector,
    2994         186 :                    vector_index);
    2995             : 
    2996             :     // Construct the cache info triple.
    2997             :     Node* cache_type = enumerator;
    2998             :     Node* cache_array = enumerator;
    2999         186 :     Node* cache_length = LoadFixedArrayBaseLength(enumerator);
    3000             :     BuildForInPrepareResult(output_register, cache_type, cache_array,
    3001          93 :                             cache_length);
    3002          93 :     Dispatch();
    3003          93 :   }
    3004          93 : }
    3005             : 
    3006             : // ForInNext <receiver> <index> <cache_info_pair>
    3007             : //
    3008             : // Returns the next enumerable property in the the accumulator.
    3009         186 : IGNITION_HANDLER(ForInNext, InterpreterAssembler) {
    3010          93 :   Node* receiver_reg = BytecodeOperandReg(0);
    3011          93 :   Node* receiver = LoadRegister(receiver_reg);
    3012          93 :   Node* index_reg = BytecodeOperandReg(1);
    3013          93 :   Node* index = LoadRegister(index_reg);
    3014          93 :   Node* cache_type_reg = BytecodeOperandReg(2);
    3015          93 :   Node* cache_type = LoadRegister(cache_type_reg);
    3016          93 :   Node* cache_array_reg = NextRegister(cache_type_reg);
    3017          93 :   Node* cache_array = LoadRegister(cache_array_reg);
    3018          93 :   Node* vector_index = BytecodeOperandIdx(3);
    3019          93 :   Node* feedback_vector = LoadFeedbackVector();
    3020             : 
    3021             :   // Load the next key from the enumeration array.
    3022             :   Node* key = LoadFixedArrayElement(cache_array, index, 0,
    3023          93 :                                     CodeStubAssembler::SMI_PARAMETERS);
    3024             : 
    3025             :   // Check if we can use the for-in fast path potentially using the enum cache.
    3026         186 :   Label if_fast(this), if_slow(this, Label::kDeferred);
    3027         186 :   Node* receiver_map = LoadMap(receiver);
    3028         186 :   Branch(WordEqual(receiver_map, cache_type), &if_fast, &if_slow);
    3029          93 :   BIND(&if_fast);
    3030             :   {
    3031             :     // Enum cache in use for {receiver}, the {key} is definitely valid.
    3032          93 :     SetAccumulator(key);
    3033          93 :     Dispatch();
    3034             :   }
    3035          93 :   BIND(&if_slow);
    3036             :   {
    3037             :     // Record the fact that we hit the for-in slow-path.
    3038             :     UpdateFeedback(SmiConstant(ForInFeedback::kAny), feedback_vector,
    3039         186 :                    vector_index);
    3040             : 
    3041             :     // Need to filter the {key} for the {receiver}.
    3042          93 :     Node* context = GetContext();
    3043          93 :     Node* result = CallBuiltin(Builtins::kForInFilter, context, key, receiver);
    3044          93 :     SetAccumulator(result);
    3045          93 :     Dispatch();
    3046          93 :   }
    3047          93 : }
    3048             : 
    3049             : // ForInContinue <index> <cache_length>
    3050             : //
    3051             : // Returns false if the end of the enumerable properties has been reached.
    3052         186 : IGNITION_HANDLER(ForInContinue, InterpreterAssembler) {
    3053          93 :   Node* index_reg = BytecodeOperandReg(0);
    3054          93 :   Node* index = LoadRegister(index_reg);
    3055          93 :   Node* cache_length_reg = BytecodeOperandReg(1);
    3056          93 :   Node* cache_length = LoadRegister(cache_length_reg);
    3057             : 
    3058             :   // Check if {index} is at {cache_length} already.
    3059         186 :   Label if_true(this), if_false(this), end(this);
    3060         186 :   Branch(WordEqual(index, cache_length), &if_true, &if_false);
    3061          93 :   BIND(&if_true);
    3062             :   {
    3063         186 :     SetAccumulator(BooleanConstant(false));
    3064          93 :     Goto(&end);
    3065             :   }
    3066          93 :   BIND(&if_false);
    3067             :   {
    3068         186 :     SetAccumulator(BooleanConstant(true));
    3069          93 :     Goto(&end);
    3070             :   }
    3071          93 :   BIND(&end);
    3072         186 :   Dispatch();
    3073          93 : }
    3074             : 
    3075             : // ForInStep <index>
    3076             : //
    3077             : // Increments the loop counter in register |index| and stores the result
    3078             : // in the accumulator.
    3079         186 : IGNITION_HANDLER(ForInStep, InterpreterAssembler) {
    3080          93 :   Node* index_reg = BytecodeOperandReg(0);
    3081          93 :   Node* index = LoadRegister(index_reg);
    3082         186 :   Node* one = SmiConstant(1);
    3083         186 :   Node* result = SmiAdd(index, one);
    3084          93 :   SetAccumulator(result);
    3085          93 :   Dispatch();
    3086          93 : }
    3087             : 
    3088             : // Wide
    3089             : //
    3090             : // Prefix bytecode indicating next bytecode has wide (16-bit) operands.
    3091          62 : IGNITION_HANDLER(Wide, InterpreterAssembler) {
    3092          31 :   DispatchWide(OperandScale::kDouble);
    3093             : }
    3094             : 
    3095             : // ExtraWide
    3096             : //
    3097             : // Prefix bytecode indicating next bytecode has extra-wide (32-bit) operands.
    3098          62 : IGNITION_HANDLER(ExtraWide, InterpreterAssembler) {
    3099          31 :   DispatchWide(OperandScale::kQuadruple);
    3100             : }
    3101             : 
    3102             : // Illegal
    3103             : //
    3104             : // An invalid bytecode aborting execution if dispatched.
    3105          31 : IGNITION_HANDLER(Illegal, InterpreterAssembler) { Abort(kInvalidBytecode); }
    3106             : 
    3107             : // SuspendGenerator <generator> <first input register> <register count>
    3108             : // <suspend_id>
    3109             : //
    3110             : // Exports the register file and stores it into the generator.  Also stores the
    3111             : // current context, |suspend_id|, and the current bytecode offset (for debugging
    3112             : // purposes) into the generator.
    3113         186 : IGNITION_HANDLER(SuspendGenerator, InterpreterAssembler) {
    3114          93 :   Node* generator_reg = BytecodeOperandReg(0);
    3115             : 
    3116          93 :   Node* generator = LoadRegister(generator_reg);
    3117             : 
    3118         186 :   Label if_stepping(this, Label::kDeferred), ok(this);
    3119             :   Node* step_action_address = ExternalConstant(
    3120         186 :       ExternalReference::debug_last_step_action_address(isolate()));
    3121          93 :   Node* step_action = Load(MachineType::Int8(), step_action_address);
    3122             :   STATIC_ASSERT(StepIn > StepNext);
    3123             :   STATIC_ASSERT(LastStepAction == StepIn);
    3124         186 :   Node* step_next = Int32Constant(StepNext);
    3125         186 :   Branch(Int32LessThanOrEqual(step_next, step_action), &if_stepping, &ok);
    3126          93 :   BIND(&ok);
    3127             : 
    3128             :   Node* array =
    3129             :       LoadObjectField(generator, JSGeneratorObject::kRegisterFileOffset);
    3130          93 :   Node* context = GetContext();
    3131          93 :   Node* suspend_id = BytecodeOperandUImmSmi(3);
    3132             : 
    3133             :   // Bytecode operand 1 should be always 0 (we are always store registers
    3134             :   // from the beginning).
    3135             :   CSA_ASSERT(this, WordEqual(BytecodeOperandReg(1),
    3136             :                              IntPtrConstant(Register(0).ToOperand())));
    3137             :   // Bytecode operand 2 is the number of registers to store to the generator.
    3138         279 :   Node* register_count = ChangeUint32ToWord(BytecodeOperandCount(2));
    3139          93 :   ExportRegisterFile(array, register_count);
    3140          93 :   StoreObjectField(generator, JSGeneratorObject::kContextOffset, context);
    3141             :   StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
    3142          93 :                    suspend_id);
    3143             : 
    3144             :   // Store the bytecode offset in the [input_or_debug_pos] field, to be used by
    3145             :   // the inspector.
    3146         279 :   Node* offset = SmiTag(BytecodeOffset());
    3147             :   StoreObjectField(generator, JSGeneratorObject::kInputOrDebugPosOffset,
    3148          93 :                    offset);
    3149          93 :   Dispatch();
    3150             : 
    3151          93 :   BIND(&if_stepping);
    3152             :   {
    3153          93 :     Node* context = GetContext();
    3154             :     CallRuntime(Runtime::kDebugRecordGenerator, context, generator);
    3155          93 :     Goto(&ok);
    3156          93 :   }
    3157          93 : }
    3158             : 
    3159             : // RestoreGeneratorState <generator>
    3160             : //
    3161             : // Loads the generator's state and stores it in the accumulator,
    3162             : // before overwriting it with kGeneratorExecuting.
    3163         186 : IGNITION_HANDLER(RestoreGeneratorState, InterpreterAssembler) {
    3164          93 :   Node* generator_reg = BytecodeOperandReg(0);
    3165          93 :   Node* generator = LoadRegister(generator_reg);
    3166             : 
    3167             :   Node* old_state =
    3168          93 :       LoadObjectField(generator, JSGeneratorObject::kContinuationOffset);
    3169         186 :   Node* new_state = Int32Constant(JSGeneratorObject::kGeneratorExecuting);
    3170             :   StoreObjectField(generator, JSGeneratorObject::kContinuationOffset,
    3171         186 :                    SmiTag(new_state));
    3172          93 :   SetAccumulator(old_state);
    3173             : 
    3174          93 :   Dispatch();
    3175          93 : }
    3176             : 
    3177             : // RestoreGeneratorRegisters <generator> <first output register> <register
    3178             : // count>
    3179             : //
    3180             : // Imports the register file stored in the generator.
    3181         186 : IGNITION_HANDLER(RestoreGeneratorRegisters, InterpreterAssembler) {
    3182          93 :   Node* generator_reg = BytecodeOperandReg(0);
    3183             :   // Bytecode operand 1 is the start register. It should always be 0, so let's
    3184             :   // ignore it.
    3185             :   CSA_ASSERT(this, WordEqual(BytecodeOperandReg(1),
    3186             :                              IntPtrConstant(Register(0).ToOperand())));
    3187             :   // Bytecode operand 2 is the number of registers to store to the generator.
    3188         279 :   Node* register_count = ChangeUint32ToWord(BytecodeOperandCount(2));
    3189             : 
    3190          93 :   Node* generator = LoadRegister(generator_reg);
    3191             : 
    3192             :   ImportRegisterFile(
    3193          93 :       LoadObjectField(generator, JSGeneratorObject::kRegisterFileOffset),
    3194          93 :       register_count);
    3195             : 
    3196          93 :   Dispatch();
    3197          93 : }
    3198             : 
    3199             : }  // namespace
    3200             : 
    3201       13888 : Handle<Code> GenerateBytecodeHandler(Isolate* isolate, Bytecode bytecode,
    3202             :                                      OperandScale operand_scale) {
    3203       13888 :   Zone zone(isolate->allocator(), ZONE_NAME);
    3204       13888 :   InterpreterDispatchDescriptor descriptor(isolate);
    3205             :   compiler::CodeAssemblerState state(
    3206             :       isolate, &zone, descriptor, Code::BYTECODE_HANDLER,
    3207       27776 :       Bytecodes::ToString(bytecode), Bytecodes::ReturnCount(bytecode));
    3208             : 
    3209       13888 :   switch (bytecode) {
    3210             : #define CALL_GENERATOR(Name, ...)                     \
    3211             :   case Bytecode::k##Name:                             \
    3212             :     Name##Assembler::Generate(&state, operand_scale); \
    3213             :     break;
    3214          31 :     BYTECODE_LIST(CALL_GENERATOR);
    3215             : #undef CALL_GENERATOR
    3216             :   }
    3217             : 
    3218       13888 :   Handle<Code> code = compiler::CodeAssembler::GenerateCode(&state);
    3219       41664 :   PROFILE(isolate, CodeCreateEvent(
    3220             :                        CodeEventListener::BYTECODE_HANDLER_TAG,
    3221             :                        AbstractCode::cast(*code),
    3222             :                        Bytecodes::ToString(bytecode, operand_scale).c_str()));
    3223             : #ifdef ENABLE_DISASSEMBLER
    3224             :   if (FLAG_trace_ignition_codegen) {
    3225             :     OFStream os(stdout);
    3226             :     code->Disassemble(Bytecodes::ToString(bytecode), os);
    3227             :     os << std::flush;
    3228             :   }
    3229             : #endif  // ENABLE_DISASSEMBLER
    3230       27776 :   return code;
    3231             : }
    3232             : 
    3233             : }  // namespace interpreter
    3234             : }  // namespace internal
    3235             : }  // namespace v8

Generated by: LCOV version 1.10