LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1729 1731 99.9 %
Date: 2019-02-19 Functions: 770 776 99.2 %

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

Generated by: LCOV version 1.10