LCOV - code coverage report
Current view: top level - src/interpreter - interpreter-generator.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1607 1609 99.9 %
Date: 2019-04-19 Functions: 327 337 97.0 %

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

Generated by: LCOV version 1.10