LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1762 1764 99.9 %
Date: 2019-03-21 Functions: 770 775 99.4 %

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

Generated by: LCOV version 1.10