LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1636 1638 99.9 %
Date: 2019-01-20 Functions: 328 340 96.5 %

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

Generated by: LCOV version 1.10