Home | History | Annotate | Download | only in interpreter
      1 // Copyright 2015 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-assembler.h"
      6 
      7 #include <limits>
      8 #include <ostream>
      9 
     10 #include "src/code-factory.h"
     11 #include "src/frames.h"
     12 #include "src/interface-descriptors.h"
     13 #include "src/interpreter/bytecodes.h"
     14 #include "src/interpreter/interpreter.h"
     15 #include "src/machine-type.h"
     16 #include "src/macro-assembler.h"
     17 #include "src/objects-inl.h"
     18 #include "src/zone/zone.h"
     19 
     20 namespace v8 {
     21 namespace internal {
     22 namespace interpreter {
     23 
     24 using compiler::CodeAssemblerState;
     25 using compiler::Node;
     26 
     27 InterpreterAssembler::InterpreterAssembler(CodeAssemblerState* state,
     28                                            Bytecode bytecode,
     29                                            OperandScale operand_scale)
     30     : CodeStubAssembler(state),
     31       bytecode_(bytecode),
     32       operand_scale_(operand_scale),
     33       bytecode_offset_(this, MachineType::PointerRepresentation()),
     34       interpreted_frame_pointer_(this, MachineType::PointerRepresentation()),
     35       bytecode_array_(this, MachineRepresentation::kTagged),
     36       dispatch_table_(this, MachineType::PointerRepresentation()),
     37       accumulator_(this, MachineRepresentation::kTagged),
     38       accumulator_use_(AccumulatorUse::kNone),
     39       made_call_(false),
     40       reloaded_frame_ptr_(false),
     41       saved_bytecode_offset_(false),
     42       disable_stack_check_across_call_(false),
     43       stack_pointer_before_call_(nullptr) {
     44   accumulator_.Bind(Parameter(InterpreterDispatchDescriptor::kAccumulator));
     45   bytecode_offset_.Bind(
     46       Parameter(InterpreterDispatchDescriptor::kBytecodeOffset));
     47   bytecode_array_.Bind(
     48       Parameter(InterpreterDispatchDescriptor::kBytecodeArray));
     49   dispatch_table_.Bind(
     50       Parameter(InterpreterDispatchDescriptor::kDispatchTable));
     51 
     52   if (FLAG_trace_ignition) {
     53     TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
     54   }
     55   RegisterCallGenerationCallbacks([this] { CallPrologue(); },
     56                                   [this] { CallEpilogue(); });
     57 }
     58 
     59 InterpreterAssembler::~InterpreterAssembler() {
     60   // If the following check fails the handler does not use the
     61   // accumulator in the way described in the bytecode definitions in
     62   // bytecodes.h.
     63   DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_));
     64   UnregisterCallGenerationCallbacks();
     65 }
     66 
     67 Node* InterpreterAssembler::GetInterpretedFramePointer() {
     68   if (!interpreted_frame_pointer_.IsBound()) {
     69     interpreted_frame_pointer_.Bind(LoadParentFramePointer());
     70   } else if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
     71              !reloaded_frame_ptr_) {
     72     interpreted_frame_pointer_.Bind(LoadParentFramePointer());
     73     reloaded_frame_ptr_ = true;
     74   }
     75   return interpreted_frame_pointer_.value();
     76 }
     77 
     78 Node* InterpreterAssembler::GetAccumulatorUnchecked() {
     79   return accumulator_.value();
     80 }
     81 
     82 Node* InterpreterAssembler::GetAccumulator() {
     83   DCHECK(Bytecodes::ReadsAccumulator(bytecode_));
     84   accumulator_use_ = accumulator_use_ | AccumulatorUse::kRead;
     85   return GetAccumulatorUnchecked();
     86 }
     87 
     88 void InterpreterAssembler::SetAccumulator(Node* value) {
     89   DCHECK(Bytecodes::WritesAccumulator(bytecode_));
     90   accumulator_use_ = accumulator_use_ | AccumulatorUse::kWrite;
     91   accumulator_.Bind(value);
     92 }
     93 
     94 Node* InterpreterAssembler::GetContext() {
     95   return LoadRegister(Register::current_context());
     96 }
     97 
     98 void InterpreterAssembler::SetContext(Node* value) {
     99   StoreRegister(value, Register::current_context());
    100 }
    101 
    102 Node* InterpreterAssembler::GetContextAtDepth(Node* context, Node* depth) {
    103   Variable cur_context(this, MachineRepresentation::kTaggedPointer);
    104   cur_context.Bind(context);
    105 
    106   Variable cur_depth(this, MachineRepresentation::kWord32);
    107   cur_depth.Bind(depth);
    108 
    109   Label context_found(this);
    110 
    111   Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context};
    112   Label context_search(this, 2, context_search_loop_variables);
    113 
    114   // Fast path if the depth is 0.
    115   Branch(Word32Equal(depth, Int32Constant(0)), &context_found, &context_search);
    116 
    117   // Loop until the depth is 0.
    118   Bind(&context_search);
    119   {
    120     cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1)));
    121     cur_context.Bind(
    122         LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX));
    123 
    124     Branch(Word32Equal(cur_depth.value(), Int32Constant(0)), &context_found,
    125            &context_search);
    126   }
    127 
    128   Bind(&context_found);
    129   return cur_context.value();
    130 }
    131 
    132 void InterpreterAssembler::GotoIfHasContextExtensionUpToDepth(Node* context,
    133                                                               Node* depth,
    134                                                               Label* target) {
    135   Variable cur_context(this, MachineRepresentation::kTaggedPointer);
    136   cur_context.Bind(context);
    137 
    138   Variable cur_depth(this, MachineRepresentation::kWord32);
    139   cur_depth.Bind(depth);
    140 
    141   Variable* context_search_loop_variables[2] = {&cur_depth, &cur_context};
    142   Label context_search(this, 2, context_search_loop_variables);
    143 
    144   // Loop until the depth is 0.
    145   Goto(&context_search);
    146   Bind(&context_search);
    147   {
    148     // TODO(leszeks): We only need to do this check if the context had a sloppy
    149     // eval, we could pass in a context chain bitmask to figure out which
    150     // contexts actually need to be checked.
    151 
    152     Node* extension_slot =
    153         LoadContextElement(cur_context.value(), Context::EXTENSION_INDEX);
    154 
    155     // Jump to the target if the extension slot is not a hole.
    156     GotoIf(WordNotEqual(extension_slot, TheHoleConstant()), target);
    157 
    158     cur_depth.Bind(Int32Sub(cur_depth.value(), Int32Constant(1)));
    159     cur_context.Bind(
    160         LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX));
    161 
    162     GotoIf(Word32NotEqual(cur_depth.value(), Int32Constant(0)),
    163            &context_search);
    164   }
    165 }
    166 
    167 Node* InterpreterAssembler::BytecodeOffset() {
    168   if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
    169       (bytecode_offset_.value() ==
    170        Parameter(InterpreterDispatchDescriptor::kBytecodeOffset))) {
    171     bytecode_offset_.Bind(LoadAndUntagRegister(Register::bytecode_offset()));
    172   }
    173   return bytecode_offset_.value();
    174 }
    175 
    176 Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
    177   // Force a re-load of the bytecode array after every call in case the debugger
    178   // has been activated.
    179   if (made_call_ &&
    180       (bytecode_array_.value() ==
    181        Parameter(InterpreterDispatchDescriptor::kBytecodeArray))) {
    182     bytecode_array_.Bind(LoadRegister(Register::bytecode_array()));
    183   }
    184   return bytecode_array_.value();
    185 }
    186 
    187 Node* InterpreterAssembler::DispatchTableRawPointer() {
    188   if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
    189       (dispatch_table_.value() ==
    190        Parameter(InterpreterDispatchDescriptor::kDispatchTable))) {
    191     dispatch_table_.Bind(ExternalConstant(
    192         ExternalReference::interpreter_dispatch_table_address(isolate())));
    193   }
    194   return dispatch_table_.value();
    195 }
    196 
    197 Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
    198   return IntPtrAdd(GetInterpretedFramePointer(),
    199                    RegisterFrameOffset(reg_index));
    200 }
    201 
    202 Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
    203   return WordShl(index, kPointerSizeLog2);
    204 }
    205 
    206 Node* InterpreterAssembler::LoadRegister(Register reg) {
    207   return Load(MachineType::AnyTagged(), GetInterpretedFramePointer(),
    208               IntPtrConstant(reg.ToOperand() << kPointerSizeLog2));
    209 }
    210 
    211 Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
    212   return Load(MachineType::AnyTagged(), GetInterpretedFramePointer(),
    213               RegisterFrameOffset(reg_index));
    214 }
    215 
    216 Node* InterpreterAssembler::LoadAndUntagRegister(Register reg) {
    217   return LoadAndUntagSmi(GetInterpretedFramePointer(), reg.ToOperand()
    218                                                            << kPointerSizeLog2);
    219 }
    220 
    221 Node* InterpreterAssembler::StoreRegister(Node* value, Register reg) {
    222   return StoreNoWriteBarrier(
    223       MachineRepresentation::kTagged, GetInterpretedFramePointer(),
    224       IntPtrConstant(reg.ToOperand() << kPointerSizeLog2), value);
    225 }
    226 
    227 Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
    228   return StoreNoWriteBarrier(MachineRepresentation::kTagged,
    229                              GetInterpretedFramePointer(),
    230                              RegisterFrameOffset(reg_index), value);
    231 }
    232 
    233 Node* InterpreterAssembler::StoreAndTagRegister(compiler::Node* value,
    234                                                 Register reg) {
    235   int offset = reg.ToOperand() << kPointerSizeLog2;
    236   return StoreAndTagSmi(GetInterpretedFramePointer(), offset, value);
    237 }
    238 
    239 Node* InterpreterAssembler::NextRegister(Node* reg_index) {
    240   // Register indexes are negative, so the next index is minus one.
    241   return IntPtrAdd(reg_index, IntPtrConstant(-1));
    242 }
    243 
    244 Node* InterpreterAssembler::OperandOffset(int operand_index) {
    245   return IntPtrConstant(
    246       Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()));
    247 }
    248 
    249 Node* InterpreterAssembler::BytecodeOperandUnsignedByte(int operand_index) {
    250   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
    251   DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize(
    252                                     bytecode_, operand_index, operand_scale()));
    253   Node* operand_offset = OperandOffset(operand_index);
    254   return Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(),
    255               IntPtrAdd(BytecodeOffset(), operand_offset));
    256 }
    257 
    258 Node* InterpreterAssembler::BytecodeOperandSignedByte(int operand_index) {
    259   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
    260   DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize(
    261                                     bytecode_, operand_index, operand_scale()));
    262   Node* operand_offset = OperandOffset(operand_index);
    263   return Load(MachineType::Int8(), BytecodeArrayTaggedPointer(),
    264               IntPtrAdd(BytecodeOffset(), operand_offset));
    265 }
    266 
    267 compiler::Node* InterpreterAssembler::BytecodeOperandReadUnaligned(
    268     int relative_offset, MachineType result_type) {
    269   static const int kMaxCount = 4;
    270   DCHECK(!TargetSupportsUnalignedAccess());
    271 
    272   int count;
    273   switch (result_type.representation()) {
    274     case MachineRepresentation::kWord16:
    275       count = 2;
    276       break;
    277     case MachineRepresentation::kWord32:
    278       count = 4;
    279       break;
    280     default:
    281       UNREACHABLE();
    282       break;
    283   }
    284   MachineType msb_type =
    285       result_type.IsSigned() ? MachineType::Int8() : MachineType::Uint8();
    286 
    287 #if V8_TARGET_LITTLE_ENDIAN
    288   const int kStep = -1;
    289   int msb_offset = count - 1;
    290 #elif V8_TARGET_BIG_ENDIAN
    291   const int kStep = 1;
    292   int msb_offset = 0;
    293 #else
    294 #error "Unknown Architecture"
    295 #endif
    296 
    297   // Read the most signicant bytecode into bytes[0] and then in order
    298   // down to least significant in bytes[count - 1].
    299   DCHECK(count <= kMaxCount);
    300   compiler::Node* bytes[kMaxCount];
    301   for (int i = 0; i < count; i++) {
    302     MachineType machine_type = (i == 0) ? msb_type : MachineType::Uint8();
    303     Node* offset = IntPtrConstant(relative_offset + msb_offset + i * kStep);
    304     Node* array_offset = IntPtrAdd(BytecodeOffset(), offset);
    305     bytes[i] = Load(machine_type, BytecodeArrayTaggedPointer(), array_offset);
    306   }
    307 
    308   // Pack LSB to MSB.
    309   Node* result = bytes[--count];
    310   for (int i = 1; --count >= 0; i++) {
    311     Node* shift = Int32Constant(i * kBitsPerByte);
    312     Node* value = Word32Shl(bytes[count], shift);
    313     result = Word32Or(value, result);
    314   }
    315   return result;
    316 }
    317 
    318 Node* InterpreterAssembler::BytecodeOperandUnsignedShort(int operand_index) {
    319   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
    320   DCHECK_EQ(
    321       OperandSize::kShort,
    322       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()));
    323   int operand_offset =
    324       Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
    325   if (TargetSupportsUnalignedAccess()) {
    326     return Load(MachineType::Uint16(), BytecodeArrayTaggedPointer(),
    327                 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
    328   } else {
    329     return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint16());
    330   }
    331 }
    332 
    333 Node* InterpreterAssembler::BytecodeOperandSignedShort(int operand_index) {
    334   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
    335   DCHECK_EQ(
    336       OperandSize::kShort,
    337       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()));
    338   int operand_offset =
    339       Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
    340   if (TargetSupportsUnalignedAccess()) {
    341     return Load(MachineType::Int16(), BytecodeArrayTaggedPointer(),
    342                 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
    343   } else {
    344     return BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16());
    345   }
    346 }
    347 
    348 Node* InterpreterAssembler::BytecodeOperandUnsignedQuad(int operand_index) {
    349   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
    350   DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize(
    351                                     bytecode_, operand_index, operand_scale()));
    352   int operand_offset =
    353       Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
    354   if (TargetSupportsUnalignedAccess()) {
    355     return Load(MachineType::Uint32(), BytecodeArrayTaggedPointer(),
    356                 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
    357   } else {
    358     return BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32());
    359   }
    360 }
    361 
    362 Node* InterpreterAssembler::BytecodeOperandSignedQuad(int operand_index) {
    363   DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
    364   DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize(
    365                                     bytecode_, operand_index, operand_scale()));
    366   int operand_offset =
    367       Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
    368   if (TargetSupportsUnalignedAccess()) {
    369     return Load(MachineType::Int32(), BytecodeArrayTaggedPointer(),
    370                 IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
    371   } else {
    372     return BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32());
    373   }
    374 }
    375 
    376 Node* InterpreterAssembler::BytecodeSignedOperand(int operand_index,
    377                                                   OperandSize operand_size) {
    378   DCHECK(!Bytecodes::IsUnsignedOperandType(
    379       Bytecodes::GetOperandType(bytecode_, operand_index)));
    380   switch (operand_size) {
    381     case OperandSize::kByte:
    382       return BytecodeOperandSignedByte(operand_index);
    383     case OperandSize::kShort:
    384       return BytecodeOperandSignedShort(operand_index);
    385     case OperandSize::kQuad:
    386       return BytecodeOperandSignedQuad(operand_index);
    387     case OperandSize::kNone:
    388       UNREACHABLE();
    389   }
    390   return nullptr;
    391 }
    392 
    393 Node* InterpreterAssembler::BytecodeUnsignedOperand(int operand_index,
    394                                                     OperandSize operand_size) {
    395   DCHECK(Bytecodes::IsUnsignedOperandType(
    396       Bytecodes::GetOperandType(bytecode_, operand_index)));
    397   switch (operand_size) {
    398     case OperandSize::kByte:
    399       return BytecodeOperandUnsignedByte(operand_index);
    400     case OperandSize::kShort:
    401       return BytecodeOperandUnsignedShort(operand_index);
    402     case OperandSize::kQuad:
    403       return BytecodeOperandUnsignedQuad(operand_index);
    404     case OperandSize::kNone:
    405       UNREACHABLE();
    406   }
    407   return nullptr;
    408 }
    409 
    410 Node* InterpreterAssembler::BytecodeOperandCount(int operand_index) {
    411   DCHECK_EQ(OperandType::kRegCount,
    412             Bytecodes::GetOperandType(bytecode_, operand_index));
    413   OperandSize operand_size =
    414       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    415   return BytecodeUnsignedOperand(operand_index, operand_size);
    416 }
    417 
    418 Node* InterpreterAssembler::BytecodeOperandFlag(int operand_index) {
    419   DCHECK_EQ(OperandType::kFlag8,
    420             Bytecodes::GetOperandType(bytecode_, operand_index));
    421   OperandSize operand_size =
    422       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    423   DCHECK_EQ(operand_size, OperandSize::kByte);
    424   return BytecodeUnsignedOperand(operand_index, operand_size);
    425 }
    426 
    427 Node* InterpreterAssembler::BytecodeOperandUImm(int operand_index) {
    428   DCHECK_EQ(OperandType::kUImm,
    429             Bytecodes::GetOperandType(bytecode_, operand_index));
    430   OperandSize operand_size =
    431       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    432   return BytecodeUnsignedOperand(operand_index, operand_size);
    433 }
    434 
    435 Node* InterpreterAssembler::BytecodeOperandUImmWord(int operand_index) {
    436   return ChangeUint32ToWord(BytecodeOperandUImm(operand_index));
    437 }
    438 
    439 Node* InterpreterAssembler::BytecodeOperandImm(int operand_index) {
    440   DCHECK_EQ(OperandType::kImm,
    441             Bytecodes::GetOperandType(bytecode_, operand_index));
    442   OperandSize operand_size =
    443       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    444   return BytecodeSignedOperand(operand_index, operand_size);
    445 }
    446 
    447 Node* InterpreterAssembler::BytecodeOperandImmIntPtr(int operand_index) {
    448   return ChangeInt32ToIntPtr(BytecodeOperandImm(operand_index));
    449 }
    450 
    451 Node* InterpreterAssembler::BytecodeOperandImmSmi(int operand_index) {
    452   return SmiFromWord32(BytecodeOperandImm(operand_index));
    453 }
    454 
    455 Node* InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
    456   DCHECK(OperandType::kIdx ==
    457          Bytecodes::GetOperandType(bytecode_, operand_index));
    458   OperandSize operand_size =
    459       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    460   return ChangeUint32ToWord(
    461       BytecodeUnsignedOperand(operand_index, operand_size));
    462 }
    463 
    464 Node* InterpreterAssembler::BytecodeOperandIdxSmi(int operand_index) {
    465   return SmiTag(BytecodeOperandIdx(operand_index));
    466 }
    467 
    468 Node* InterpreterAssembler::BytecodeOperandReg(int operand_index) {
    469   DCHECK(Bytecodes::IsRegisterOperandType(
    470       Bytecodes::GetOperandType(bytecode_, operand_index)));
    471   OperandSize operand_size =
    472       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    473   return ChangeInt32ToIntPtr(
    474       BytecodeSignedOperand(operand_index, operand_size));
    475 }
    476 
    477 Node* InterpreterAssembler::BytecodeOperandRuntimeId(int operand_index) {
    478   DCHECK(OperandType::kRuntimeId ==
    479          Bytecodes::GetOperandType(bytecode_, operand_index));
    480   OperandSize operand_size =
    481       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    482   DCHECK_EQ(operand_size, OperandSize::kShort);
    483   return BytecodeUnsignedOperand(operand_index, operand_size);
    484 }
    485 
    486 Node* InterpreterAssembler::BytecodeOperandIntrinsicId(int operand_index) {
    487   DCHECK(OperandType::kIntrinsicId ==
    488          Bytecodes::GetOperandType(bytecode_, operand_index));
    489   OperandSize operand_size =
    490       Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
    491   DCHECK_EQ(operand_size, OperandSize::kByte);
    492   return BytecodeUnsignedOperand(operand_index, operand_size);
    493 }
    494 
    495 Node* InterpreterAssembler::LoadConstantPoolEntry(Node* index) {
    496   Node* constant_pool = LoadObjectField(BytecodeArrayTaggedPointer(),
    497                                         BytecodeArray::kConstantPoolOffset);
    498   return LoadFixedArrayElement(constant_pool, index);
    499 }
    500 
    501 Node* InterpreterAssembler::LoadAndUntagConstantPoolEntry(Node* index) {
    502   return SmiUntag(LoadConstantPoolEntry(index));
    503 }
    504 
    505 Node* InterpreterAssembler::LoadFeedbackVector() {
    506   Node* function = LoadRegister(Register::function_closure());
    507   Node* cell = LoadObjectField(function, JSFunction::kFeedbackVectorOffset);
    508   Node* vector = LoadObjectField(cell, Cell::kValueOffset);
    509   return vector;
    510 }
    511 
    512 void InterpreterAssembler::SaveBytecodeOffset() {
    513   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    514   StoreAndTagRegister(BytecodeOffset(), Register::bytecode_offset());
    515   saved_bytecode_offset_ = true;
    516 }
    517 
    518 void InterpreterAssembler::CallPrologue() {
    519   if (!saved_bytecode_offset_) {
    520     // If there are multiple calls in the bytecode handler, you need to spill
    521     // before each of them, unless SaveBytecodeOffset has explicitly been called
    522     // in a path that dominates _all_ of those calls. Therefore don't set
    523     // saved_bytecode_offset_ to true or call SaveBytecodeOffset.
    524     StoreAndTagRegister(BytecodeOffset(), Register::bytecode_offset());
    525   }
    526 
    527   if (FLAG_debug_code && !disable_stack_check_across_call_) {
    528     DCHECK(stack_pointer_before_call_ == nullptr);
    529     stack_pointer_before_call_ = LoadStackPointer();
    530   }
    531   made_call_ = true;
    532 }
    533 
    534 void InterpreterAssembler::CallEpilogue() {
    535   if (FLAG_debug_code && !disable_stack_check_across_call_) {
    536     Node* stack_pointer_after_call = LoadStackPointer();
    537     Node* stack_pointer_before_call = stack_pointer_before_call_;
    538     stack_pointer_before_call_ = nullptr;
    539     AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
    540                         kUnexpectedStackPointer);
    541   }
    542 }
    543 
    544 Node* InterpreterAssembler::IncrementCallCount(Node* feedback_vector,
    545                                                Node* slot_id) {
    546   Comment("increment call count");
    547   Node* call_count_slot = IntPtrAdd(slot_id, IntPtrConstant(1));
    548   Node* call_count = LoadFixedArrayElement(feedback_vector, call_count_slot);
    549   Node* new_count = SmiAdd(call_count, SmiConstant(1));
    550   // Count is Smi, so we don't need a write barrier.
    551   return StoreFixedArrayElement(feedback_vector, call_count_slot, new_count,
    552                                 SKIP_WRITE_BARRIER);
    553 }
    554 
    555 Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
    556                                                Node* first_arg, Node* arg_count,
    557                                                Node* slot_id,
    558                                                Node* feedback_vector,
    559                                                TailCallMode tail_call_mode) {
    560   // Static checks to assert it is safe to examine the type feedback element.
    561   // We don't know that we have a weak cell. We might have a private symbol
    562   // or an AllocationSite, but the memory is safe to examine.
    563   // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
    564   // FixedArray.
    565   // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
    566   // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
    567   // computed, meaning that it can't appear to be a pointer. If the low bit is
    568   // 0, then hash is computed, but the 0 bit prevents the field from appearing
    569   // to be a pointer.
    570   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    571   DCHECK(Bytecodes::IsCallOrConstruct(bytecode_));
    572   STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
    573   STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
    574                     WeakCell::kValueOffset &&
    575                 WeakCell::kValueOffset == Symbol::kHashFieldSlot);
    576 
    577   Variable return_value(this, MachineRepresentation::kTagged);
    578   Label call_function(this), extra_checks(this, Label::kDeferred), call(this),
    579       end(this);
    580 
    581   // The checks. First, does function match the recorded monomorphic target?
    582   Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id);
    583   Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element);
    584   Node* is_monomorphic = WordEqual(function, feedback_value);
    585   GotoIfNot(is_monomorphic, &extra_checks);
    586 
    587   // The compare above could have been a SMI/SMI comparison. Guard against
    588   // this convincing us that we have a monomorphic JSFunction.
    589   Node* is_smi = TaggedIsSmi(function);
    590   Branch(is_smi, &extra_checks, &call_function);
    591 
    592   Bind(&call_function);
    593   {
    594     // Increment the call count.
    595     IncrementCallCount(feedback_vector, slot_id);
    596 
    597     // Call using call function builtin.
    598     Callable callable = CodeFactory::InterpreterPushArgsAndCall(
    599         isolate(), tail_call_mode, InterpreterPushArgsMode::kJSFunction);
    600     Node* code_target = HeapConstant(callable.code());
    601     Node* ret_value = CallStub(callable.descriptor(), code_target, context,
    602                                arg_count, first_arg, function);
    603     return_value.Bind(ret_value);
    604     Goto(&end);
    605   }
    606 
    607   Bind(&extra_checks);
    608   {
    609     Label check_initialized(this), mark_megamorphic(this),
    610         create_allocation_site(this);
    611 
    612     Comment("check if megamorphic");
    613     // Check if it is a megamorphic target.
    614     Node* is_megamorphic =
    615         WordEqual(feedback_element,
    616                   HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())));
    617     GotoIf(is_megamorphic, &call);
    618 
    619     Comment("check if it is an allocation site");
    620     GotoIfNot(IsAllocationSiteMap(LoadMap(feedback_element)),
    621               &check_initialized);
    622 
    623     // If it is not the Array() function, mark megamorphic.
    624     Node* context_slot = LoadContextElement(LoadNativeContext(context),
    625                                             Context::ARRAY_FUNCTION_INDEX);
    626     Node* is_array_function = WordEqual(context_slot, function);
    627     GotoIfNot(is_array_function, &mark_megamorphic);
    628 
    629     // It is a monomorphic Array function. Increment the call count.
    630     IncrementCallCount(feedback_vector, slot_id);
    631 
    632     // Call ArrayConstructorStub.
    633     Callable callable_call =
    634         CodeFactory::InterpreterPushArgsAndConstructArray(isolate());
    635     Node* code_target_call = HeapConstant(callable_call.code());
    636     Node* ret_value =
    637         CallStub(callable_call.descriptor(), code_target_call, context,
    638                  arg_count, function, feedback_element, first_arg);
    639     return_value.Bind(ret_value);
    640     Goto(&end);
    641 
    642     Bind(&check_initialized);
    643     {
    644       Comment("check if uninitialized");
    645       // Check if it is uninitialized target first.
    646       Node* is_uninitialized = WordEqual(
    647           feedback_element,
    648           HeapConstant(FeedbackVector::UninitializedSentinel(isolate())));
    649       GotoIfNot(is_uninitialized, &mark_megamorphic);
    650 
    651       Comment("handle_unitinitialized");
    652       // If it is not a JSFunction mark it as megamorphic.
    653       Node* is_smi = TaggedIsSmi(function);
    654       GotoIf(is_smi, &mark_megamorphic);
    655 
    656       // Check if function is an object of JSFunction type.
    657       Node* instance_type = LoadInstanceType(function);
    658       Node* is_js_function =
    659           Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE));
    660       GotoIfNot(is_js_function, &mark_megamorphic);
    661 
    662       // Check if it is the Array() function.
    663       Node* context_slot = LoadContextElement(LoadNativeContext(context),
    664                                               Context::ARRAY_FUNCTION_INDEX);
    665       Node* is_array_function = WordEqual(context_slot, function);
    666       GotoIf(is_array_function, &create_allocation_site);
    667 
    668       // Check if the function belongs to the same native context.
    669       Node* native_context = LoadNativeContext(
    670           LoadObjectField(function, JSFunction::kContextOffset));
    671       Node* is_same_native_context =
    672           WordEqual(native_context, LoadNativeContext(context));
    673       GotoIfNot(is_same_native_context, &mark_megamorphic);
    674 
    675       CreateWeakCellInFeedbackVector(feedback_vector, SmiTag(slot_id),
    676                                      function);
    677 
    678       // Call using call function builtin.
    679       Goto(&call_function);
    680     }
    681 
    682     Bind(&create_allocation_site);
    683     {
    684       CreateAllocationSiteInFeedbackVector(feedback_vector, SmiTag(slot_id));
    685 
    686       // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state.
    687       // They start collecting feedback only when a call is executed the second
    688       // time. So, do not pass any feedback here.
    689       Goto(&call_function);
    690     }
    691 
    692     Bind(&mark_megamorphic);
    693     {
    694       // Mark it as a megamorphic.
    695       // MegamorphicSentinel is created as a part of Heap::InitialObjects
    696       // and will not move during a GC. So it is safe to skip write barrier.
    697       DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
    698       StoreFixedArrayElement(
    699           feedback_vector, slot_id,
    700           HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
    701           SKIP_WRITE_BARRIER);
    702       Goto(&call);
    703     }
    704   }
    705 
    706   Bind(&call);
    707   {
    708     Comment("Increment call count and call using Call builtin");
    709     // Increment the call count.
    710     IncrementCallCount(feedback_vector, slot_id);
    711 
    712     // Call using call builtin.
    713     Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
    714         isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
    715     Node* code_target_call = HeapConstant(callable_call.code());
    716     Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
    717                                context, arg_count, first_arg, function);
    718     return_value.Bind(ret_value);
    719     Goto(&end);
    720   }
    721 
    722   Bind(&end);
    723   return return_value.value();
    724 }
    725 
    726 Node* InterpreterAssembler::CallJS(Node* function, Node* context,
    727                                    Node* first_arg, Node* arg_count,
    728                                    TailCallMode tail_call_mode) {
    729   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    730   DCHECK(Bytecodes::IsCallOrConstruct(bytecode_));
    731   Callable callable = CodeFactory::InterpreterPushArgsAndCall(
    732       isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
    733   Node* code_target = HeapConstant(callable.code());
    734 
    735   return CallStub(callable.descriptor(), code_target, context, arg_count,
    736                   first_arg, function);
    737 }
    738 
    739 Node* InterpreterAssembler::CallJSWithSpread(Node* function, Node* context,
    740                                              Node* first_arg, Node* arg_count) {
    741   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    742   Callable callable = CodeFactory::InterpreterPushArgsAndCall(
    743       isolate(), TailCallMode::kDisallow,
    744       InterpreterPushArgsMode::kWithFinalSpread);
    745   Node* code_target = HeapConstant(callable.code());
    746 
    747   return CallStub(callable.descriptor(), code_target, context, arg_count,
    748                   first_arg, function);
    749 }
    750 
    751 Node* InterpreterAssembler::Construct(Node* constructor, Node* context,
    752                                       Node* new_target, Node* first_arg,
    753                                       Node* arg_count, Node* slot_id,
    754                                       Node* feedback_vector) {
    755   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    756   Variable return_value(this, MachineRepresentation::kTagged);
    757   Variable allocation_feedback(this, MachineRepresentation::kTagged);
    758   Label call_construct_function(this, &allocation_feedback),
    759       extra_checks(this, Label::kDeferred), call_construct(this), end(this);
    760 
    761   // Slot id of 0 is used to indicate no type feedback is available.
    762   STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
    763   Node* is_feedback_unavailable = WordEqual(slot_id, IntPtrConstant(0));
    764   GotoIf(is_feedback_unavailable, &call_construct);
    765 
    766   // Check that the constructor is not a smi.
    767   Node* is_smi = TaggedIsSmi(constructor);
    768   GotoIf(is_smi, &call_construct);
    769 
    770   // Check that constructor is a JSFunction.
    771   Node* instance_type = LoadInstanceType(constructor);
    772   Node* is_js_function =
    773       Word32Equal(instance_type, Int32Constant(JS_FUNCTION_TYPE));
    774   GotoIfNot(is_js_function, &call_construct);
    775 
    776   // Check if it is a monomorphic constructor.
    777   Node* feedback_element = LoadFixedArrayElement(feedback_vector, slot_id);
    778   Node* feedback_value = LoadWeakCellValueUnchecked(feedback_element);
    779   Node* is_monomorphic = WordEqual(constructor, feedback_value);
    780   allocation_feedback.Bind(UndefinedConstant());
    781   Branch(is_monomorphic, &call_construct_function, &extra_checks);
    782 
    783   Bind(&call_construct_function);
    784   {
    785     Comment("call using ConstructFunction");
    786     IncrementCallCount(feedback_vector, slot_id);
    787     Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct(
    788         isolate(), InterpreterPushArgsMode::kJSFunction);
    789     return_value.Bind(CallStub(callable_function.descriptor(),
    790                                HeapConstant(callable_function.code()), context,
    791                                arg_count, new_target, constructor,
    792                                allocation_feedback.value(), first_arg));
    793     Goto(&end);
    794   }
    795 
    796   Bind(&extra_checks);
    797   {
    798     Label check_allocation_site(this), check_initialized(this),
    799         initialize(this), mark_megamorphic(this);
    800 
    801     // Check if it is a megamorphic target.
    802     Comment("check if megamorphic");
    803     Node* is_megamorphic =
    804         WordEqual(feedback_element,
    805                   HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())));
    806     GotoIf(is_megamorphic, &call_construct_function);
    807 
    808     Comment("check if weak cell");
    809     Node* is_weak_cell = WordEqual(LoadMap(feedback_element),
    810                                    LoadRoot(Heap::kWeakCellMapRootIndex));
    811     GotoIfNot(is_weak_cell, &check_allocation_site);
    812 
    813     // If the weak cell is cleared, we have a new chance to become
    814     // monomorphic.
    815     Comment("check if weak cell is cleared");
    816     Node* is_smi = TaggedIsSmi(feedback_value);
    817     Branch(is_smi, &initialize, &mark_megamorphic);
    818 
    819     Bind(&check_allocation_site);
    820     {
    821       Comment("check if it is an allocation site");
    822       Node* is_allocation_site =
    823           WordEqual(LoadObjectField(feedback_element, 0),
    824                     LoadRoot(Heap::kAllocationSiteMapRootIndex));
    825       GotoIfNot(is_allocation_site, &check_initialized);
    826 
    827       // Make sure the function is the Array() function.
    828       Node* context_slot = LoadContextElement(LoadNativeContext(context),
    829                                               Context::ARRAY_FUNCTION_INDEX);
    830       Node* is_array_function = WordEqual(context_slot, constructor);
    831       GotoIfNot(is_array_function, &mark_megamorphic);
    832 
    833       allocation_feedback.Bind(feedback_element);
    834       Goto(&call_construct_function);
    835     }
    836 
    837     Bind(&check_initialized);
    838     {
    839       // Check if it is uninitialized.
    840       Comment("check if uninitialized");
    841       Node* is_uninitialized = WordEqual(
    842           feedback_element, LoadRoot(Heap::kuninitialized_symbolRootIndex));
    843       Branch(is_uninitialized, &initialize, &mark_megamorphic);
    844     }
    845 
    846     Bind(&initialize);
    847     {
    848       Label create_allocation_site(this), create_weak_cell(this);
    849       Comment("initialize the feedback element");
    850       // Create an allocation site if the function is an array function,
    851       // otherwise create a weak cell.
    852       Node* context_slot = LoadContextElement(LoadNativeContext(context),
    853                                               Context::ARRAY_FUNCTION_INDEX);
    854       Node* is_array_function = WordEqual(context_slot, constructor);
    855       Branch(is_array_function, &create_allocation_site, &create_weak_cell);
    856 
    857       Bind(&create_allocation_site);
    858       {
    859         Node* site = CreateAllocationSiteInFeedbackVector(feedback_vector,
    860                                                           SmiTag(slot_id));
    861         allocation_feedback.Bind(site);
    862         Goto(&call_construct_function);
    863       }
    864 
    865       Bind(&create_weak_cell);
    866       {
    867         CreateWeakCellInFeedbackVector(feedback_vector, SmiTag(slot_id),
    868                                        constructor);
    869         Goto(&call_construct_function);
    870       }
    871     }
    872 
    873     Bind(&mark_megamorphic);
    874     {
    875       // MegamorphicSentinel is an immortal immovable object so
    876       // write-barrier is not needed.
    877       Comment("transition to megamorphic");
    878       DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
    879       StoreFixedArrayElement(
    880           feedback_vector, slot_id,
    881           HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
    882           SKIP_WRITE_BARRIER);
    883       Goto(&call_construct_function);
    884     }
    885   }
    886 
    887   Bind(&call_construct);
    888   {
    889     Comment("call using Construct builtin");
    890     Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
    891         isolate(), InterpreterPushArgsMode::kOther);
    892     Node* code_target = HeapConstant(callable.code());
    893     return_value.Bind(CallStub(callable.descriptor(), code_target, context,
    894                                arg_count, new_target, constructor,
    895                                UndefinedConstant(), first_arg));
    896     Goto(&end);
    897   }
    898 
    899   Bind(&end);
    900   return return_value.value();
    901 }
    902 
    903 Node* InterpreterAssembler::ConstructWithSpread(Node* constructor,
    904                                                 Node* context, Node* new_target,
    905                                                 Node* first_arg,
    906                                                 Node* arg_count) {
    907   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    908   Variable return_value(this, MachineRepresentation::kTagged);
    909   Comment("call using ConstructWithSpread");
    910   Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
    911       isolate(), InterpreterPushArgsMode::kWithFinalSpread);
    912   Node* code_target = HeapConstant(callable.code());
    913   return_value.Bind(CallStub(callable.descriptor(), code_target, context,
    914                              arg_count, new_target, constructor,
    915                              UndefinedConstant(), first_arg));
    916 
    917   return return_value.value();
    918 }
    919 
    920 Node* InterpreterAssembler::CallRuntimeN(Node* function_id, Node* context,
    921                                          Node* first_arg, Node* arg_count,
    922                                          int result_size) {
    923   DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
    924   DCHECK(Bytecodes::IsCallRuntime(bytecode_));
    925   Callable callable = CodeFactory::InterpreterCEntry(isolate(), result_size);
    926   Node* code_target = HeapConstant(callable.code());
    927 
    928   // Get the function entry from the function id.
    929   Node* function_table = ExternalConstant(
    930       ExternalReference::runtime_function_table_address(isolate()));
    931   Node* function_offset =
    932       Int32Mul(function_id, Int32Constant(sizeof(Runtime::Function)));
    933   Node* function =
    934       IntPtrAdd(function_table, ChangeUint32ToWord(function_offset));
    935   Node* function_entry =
    936       Load(MachineType::Pointer(), function,
    937            IntPtrConstant(offsetof(Runtime::Function, entry)));
    938 
    939   return CallStubR(callable.descriptor(), result_size, code_target, context,
    940                    arg_count, first_arg, function_entry);
    941 }
    942 
    943 void InterpreterAssembler::UpdateInterruptBudget(Node* weight, bool backward) {
    944   Label ok(this), interrupt_check(this, Label::kDeferred), end(this);
    945   Node* budget_offset =
    946       IntPtrConstant(BytecodeArray::kInterruptBudgetOffset - kHeapObjectTag);
    947 
    948   // Update budget by |weight| and check if it reaches zero.
    949   Variable new_budget(this, MachineRepresentation::kWord32);
    950   Node* old_budget =
    951       Load(MachineType::Int32(), BytecodeArrayTaggedPointer(), budget_offset);
    952   if (backward) {
    953     new_budget.Bind(Int32Sub(old_budget, weight));
    954   } else {
    955     new_budget.Bind(Int32Add(old_budget, weight));
    956   }
    957   Node* condition =
    958       Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0));
    959   Branch(condition, &ok, &interrupt_check);
    960 
    961   // Perform interrupt and reset budget.
    962   Bind(&interrupt_check);
    963   {
    964     CallRuntime(Runtime::kInterrupt, GetContext());
    965     new_budget.Bind(Int32Constant(Interpreter::InterruptBudget()));
    966     Goto(&ok);
    967   }
    968 
    969   // Update budget.
    970   Bind(&ok);
    971   StoreNoWriteBarrier(MachineRepresentation::kWord32,
    972                       BytecodeArrayTaggedPointer(), budget_offset,
    973                       new_budget.value());
    974 }
    975 
    976 Node* InterpreterAssembler::Advance() {
    977   return Advance(Bytecodes::Size(bytecode_, operand_scale_));
    978 }
    979 
    980 Node* InterpreterAssembler::Advance(int delta) {
    981   return Advance(IntPtrConstant(delta));
    982 }
    983 
    984 Node* InterpreterAssembler::Advance(Node* delta, bool backward) {
    985   if (FLAG_trace_ignition) {
    986     TraceBytecode(Runtime::kInterpreterTraceBytecodeExit);
    987   }
    988   Node* next_offset = backward ? IntPtrSub(BytecodeOffset(), delta)
    989                                : IntPtrAdd(BytecodeOffset(), delta);
    990   bytecode_offset_.Bind(next_offset);
    991   return next_offset;
    992 }
    993 
    994 Node* InterpreterAssembler::Jump(Node* delta, bool backward) {
    995   DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_));
    996 
    997   UpdateInterruptBudget(TruncateWordToWord32(delta), backward);
    998   Node* new_bytecode_offset = Advance(delta, backward);
    999   Node* target_bytecode = LoadBytecode(new_bytecode_offset);
   1000   return DispatchToBytecode(target_bytecode, new_bytecode_offset);
   1001 }
   1002 
   1003 Node* InterpreterAssembler::Jump(Node* delta) { return Jump(delta, false); }
   1004 
   1005 Node* InterpreterAssembler::JumpBackward(Node* delta) {
   1006   return Jump(delta, true);
   1007 }
   1008 
   1009 void InterpreterAssembler::JumpConditional(Node* condition, Node* delta) {
   1010   Label match(this), no_match(this);
   1011 
   1012   Branch(condition, &match, &no_match);
   1013   Bind(&match);
   1014   Jump(delta);
   1015   Bind(&no_match);
   1016   Dispatch();
   1017 }
   1018 
   1019 void InterpreterAssembler::JumpIfWordEqual(Node* lhs, Node* rhs, Node* delta) {
   1020   JumpConditional(WordEqual(lhs, rhs), delta);
   1021 }
   1022 
   1023 void InterpreterAssembler::JumpIfWordNotEqual(Node* lhs, Node* rhs,
   1024                                               Node* delta) {
   1025   JumpConditional(WordNotEqual(lhs, rhs), delta);
   1026 }
   1027 
   1028 Node* InterpreterAssembler::LoadBytecode(compiler::Node* bytecode_offset) {
   1029   Node* bytecode =
   1030       Load(MachineType::Uint8(), BytecodeArrayTaggedPointer(), bytecode_offset);
   1031   return ChangeUint32ToWord(bytecode);
   1032 }
   1033 
   1034 Node* InterpreterAssembler::StarDispatchLookahead(Node* target_bytecode) {
   1035   Label do_inline_star(this), done(this);
   1036 
   1037   Variable var_bytecode(this, MachineType::PointerRepresentation());
   1038   var_bytecode.Bind(target_bytecode);
   1039 
   1040   Node* star_bytecode = IntPtrConstant(static_cast<int>(Bytecode::kStar));
   1041   Node* is_star = WordEqual(target_bytecode, star_bytecode);
   1042   Branch(is_star, &do_inline_star, &done);
   1043 
   1044   Bind(&do_inline_star);
   1045   {
   1046     InlineStar();
   1047     var_bytecode.Bind(LoadBytecode(BytecodeOffset()));
   1048     Goto(&done);
   1049   }
   1050   Bind(&done);
   1051   return var_bytecode.value();
   1052 }
   1053 
   1054 void InterpreterAssembler::InlineStar() {
   1055   Bytecode previous_bytecode = bytecode_;
   1056   AccumulatorUse previous_acc_use = accumulator_use_;
   1057 
   1058   bytecode_ = Bytecode::kStar;
   1059   accumulator_use_ = AccumulatorUse::kNone;
   1060 
   1061   if (FLAG_trace_ignition) {
   1062     TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
   1063   }
   1064   StoreRegister(GetAccumulator(), BytecodeOperandReg(0));
   1065 
   1066   DCHECK_EQ(accumulator_use_, Bytecodes::GetAccumulatorUse(bytecode_));
   1067 
   1068   Advance();
   1069   bytecode_ = previous_bytecode;
   1070   accumulator_use_ = previous_acc_use;
   1071 }
   1072 
   1073 Node* InterpreterAssembler::Dispatch() {
   1074   Comment("========= Dispatch");
   1075   DCHECK_IMPLIES(Bytecodes::MakesCallAlongCriticalPath(bytecode_), made_call_);
   1076   Node* target_offset = Advance();
   1077   Node* target_bytecode = LoadBytecode(target_offset);
   1078 
   1079   if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) {
   1080     target_bytecode = StarDispatchLookahead(target_bytecode);
   1081   }
   1082   return DispatchToBytecode(target_bytecode, BytecodeOffset());
   1083 }
   1084 
   1085 Node* InterpreterAssembler::DispatchToBytecode(Node* target_bytecode,
   1086                                                Node* new_bytecode_offset) {
   1087   if (FLAG_trace_ignition_dispatches) {
   1088     TraceBytecodeDispatch(target_bytecode);
   1089   }
   1090 
   1091   Node* target_code_entry =
   1092       Load(MachineType::Pointer(), DispatchTableRawPointer(),
   1093            WordShl(target_bytecode, IntPtrConstant(kPointerSizeLog2)));
   1094 
   1095   return DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset);
   1096 }
   1097 
   1098 Node* InterpreterAssembler::DispatchToBytecodeHandler(Node* handler,
   1099                                                       Node* bytecode_offset) {
   1100   // TODO(ishell): Add CSA::CodeEntryPoint(code).
   1101   Node* handler_entry =
   1102       IntPtrAdd(BitcastTaggedToWord(handler),
   1103                 IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
   1104   return DispatchToBytecodeHandlerEntry(handler_entry, bytecode_offset);
   1105 }
   1106 
   1107 Node* InterpreterAssembler::DispatchToBytecodeHandlerEntry(
   1108     Node* handler_entry, Node* bytecode_offset) {
   1109   InterpreterDispatchDescriptor descriptor(isolate());
   1110   return TailCallBytecodeDispatch(
   1111       descriptor, handler_entry, GetAccumulatorUnchecked(), bytecode_offset,
   1112       BytecodeArrayTaggedPointer(), DispatchTableRawPointer());
   1113 }
   1114 
   1115 void InterpreterAssembler::DispatchWide(OperandScale operand_scale) {
   1116   // Dispatching a wide bytecode requires treating the prefix
   1117   // bytecode a base pointer into the dispatch table and dispatching
   1118   // the bytecode that follows relative to this base.
   1119   //
   1120   //   Indices 0-255 correspond to bytecodes with operand_scale == 0
   1121   //   Indices 256-511 correspond to bytecodes with operand_scale == 1
   1122   //   Indices 512-767 correspond to bytecodes with operand_scale == 2
   1123   DCHECK_IMPLIES(Bytecodes::MakesCallAlongCriticalPath(bytecode_), made_call_);
   1124   Node* next_bytecode_offset = Advance(1);
   1125   Node* next_bytecode = LoadBytecode(next_bytecode_offset);
   1126 
   1127   if (FLAG_trace_ignition_dispatches) {
   1128     TraceBytecodeDispatch(next_bytecode);
   1129   }
   1130 
   1131   Node* base_index;
   1132   switch (operand_scale) {
   1133     case OperandScale::kDouble:
   1134       base_index = IntPtrConstant(1 << kBitsPerByte);
   1135       break;
   1136     case OperandScale::kQuadruple:
   1137       base_index = IntPtrConstant(2 << kBitsPerByte);
   1138       break;
   1139     default:
   1140       UNREACHABLE();
   1141       base_index = nullptr;
   1142   }
   1143   Node* target_index = IntPtrAdd(base_index, next_bytecode);
   1144   Node* target_code_entry =
   1145       Load(MachineType::Pointer(), DispatchTableRawPointer(),
   1146            WordShl(target_index, kPointerSizeLog2));
   1147 
   1148   DispatchToBytecodeHandlerEntry(target_code_entry, next_bytecode_offset);
   1149 }
   1150 
   1151 Node* InterpreterAssembler::TruncateTaggedToWord32WithFeedback(
   1152     Node* context, Node* value, Variable* var_type_feedback) {
   1153   // We might need to loop once due to ToNumber conversion.
   1154   Variable var_value(this, MachineRepresentation::kTagged),
   1155       var_result(this, MachineRepresentation::kWord32);
   1156   Variable* loop_vars[] = {&var_value, var_type_feedback};
   1157   Label loop(this, 2, loop_vars), done_loop(this, &var_result);
   1158   var_value.Bind(value);
   1159   var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kNone));
   1160   Goto(&loop);
   1161   Bind(&loop);
   1162   {
   1163     // Load the current {value}.
   1164     value = var_value.value();
   1165 
   1166     // Check if the {value} is a Smi or a HeapObject.
   1167     Label if_valueissmi(this), if_valueisnotsmi(this);
   1168     Branch(TaggedIsSmi(value), &if_valueissmi, &if_valueisnotsmi);
   1169 
   1170     Bind(&if_valueissmi);
   1171     {
   1172       // Convert the Smi {value}.
   1173       var_result.Bind(SmiToWord32(value));
   1174       var_type_feedback->Bind(
   1175           SmiOr(var_type_feedback->value(),
   1176                 SmiConstant(BinaryOperationFeedback::kSignedSmall)));
   1177       Goto(&done_loop);
   1178     }
   1179 
   1180     Bind(&if_valueisnotsmi);
   1181     {
   1182       // Check if {value} is a HeapNumber.
   1183       Label if_valueisheapnumber(this),
   1184           if_valueisnotheapnumber(this, Label::kDeferred);
   1185       Node* value_map = LoadMap(value);
   1186       Branch(IsHeapNumberMap(value_map), &if_valueisheapnumber,
   1187              &if_valueisnotheapnumber);
   1188 
   1189       Bind(&if_valueisheapnumber);
   1190       {
   1191         // Truncate the floating point value.
   1192         var_result.Bind(TruncateHeapNumberValueToWord32(value));
   1193         var_type_feedback->Bind(
   1194             SmiOr(var_type_feedback->value(),
   1195                   SmiConstant(BinaryOperationFeedback::kNumber)));
   1196         Goto(&done_loop);
   1197       }
   1198 
   1199       Bind(&if_valueisnotheapnumber);
   1200       {
   1201         // We do not require an Or with earlier feedback here because once we
   1202         // convert the value to a number, we cannot reach this path. We can
   1203         // only reach this path on the first pass when the feedback is kNone.
   1204         CSA_ASSERT(this, SmiEqual(var_type_feedback->value(),
   1205                                   SmiConstant(BinaryOperationFeedback::kNone)));
   1206 
   1207         Label if_valueisoddball(this),
   1208             if_valueisnotoddball(this, Label::kDeferred);
   1209         Node* is_oddball = Word32Equal(LoadMapInstanceType(value_map),
   1210                                        Int32Constant(ODDBALL_TYPE));
   1211         Branch(is_oddball, &if_valueisoddball, &if_valueisnotoddball);
   1212 
   1213         Bind(&if_valueisoddball);
   1214         {
   1215           // Convert Oddball to a Number and perform checks again.
   1216           var_value.Bind(LoadObjectField(value, Oddball::kToNumberOffset));
   1217           var_type_feedback->Bind(
   1218               SmiConstant(BinaryOperationFeedback::kNumberOrOddball));
   1219           Goto(&loop);
   1220         }
   1221 
   1222         Bind(&if_valueisnotoddball);
   1223         {
   1224           // Convert the {value} to a Number first.
   1225           Callable callable = CodeFactory::NonNumberToNumber(isolate());
   1226           var_value.Bind(CallStub(callable, context, value));
   1227           var_type_feedback->Bind(SmiConstant(BinaryOperationFeedback::kAny));
   1228           Goto(&loop);
   1229         }
   1230       }
   1231     }
   1232   }
   1233   Bind(&done_loop);
   1234   return var_result.value();
   1235 }
   1236 
   1237 void InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
   1238   // TODO(rmcilroy): Investigate whether it is worth supporting self
   1239   // optimization of primitive functions like FullCodegen.
   1240 
   1241   // Update profiling count by -BytecodeOffset to simulate backedge to start of
   1242   // function.
   1243   Node* profiling_weight =
   1244       Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize),
   1245                TruncateWordToWord32(BytecodeOffset()));
   1246   UpdateInterruptBudget(profiling_weight, false);
   1247 }
   1248 
   1249 Node* InterpreterAssembler::StackCheckTriggeredInterrupt() {
   1250   Node* sp = LoadStackPointer();
   1251   Node* stack_limit = Load(
   1252       MachineType::Pointer(),
   1253       ExternalConstant(ExternalReference::address_of_stack_limit(isolate())));
   1254   return UintPtrLessThan(sp, stack_limit);
   1255 }
   1256 
   1257 Node* InterpreterAssembler::LoadOSRNestingLevel() {
   1258   return LoadObjectField(BytecodeArrayTaggedPointer(),
   1259                          BytecodeArray::kOSRNestingLevelOffset,
   1260                          MachineType::Int8());
   1261 }
   1262 
   1263 void InterpreterAssembler::Abort(BailoutReason bailout_reason) {
   1264   disable_stack_check_across_call_ = true;
   1265   Node* abort_id = SmiTag(Int32Constant(bailout_reason));
   1266   CallRuntime(Runtime::kAbort, GetContext(), abort_id);
   1267   disable_stack_check_across_call_ = false;
   1268 }
   1269 
   1270 void InterpreterAssembler::AbortIfWordNotEqual(Node* lhs, Node* rhs,
   1271                                                BailoutReason bailout_reason) {
   1272   Label ok(this), abort(this, Label::kDeferred);
   1273   Branch(WordEqual(lhs, rhs), &ok, &abort);
   1274 
   1275   Bind(&abort);
   1276   Abort(bailout_reason);
   1277   Goto(&ok);
   1278 
   1279   Bind(&ok);
   1280 }
   1281 
   1282 void InterpreterAssembler::MaybeDropFrames(Node* context) {
   1283   Node* restart_fp_address =
   1284       ExternalConstant(ExternalReference::debug_restart_fp_address(isolate()));
   1285 
   1286   Node* restart_fp = Load(MachineType::Pointer(), restart_fp_address);
   1287   Node* null = IntPtrConstant(0);
   1288 
   1289   Label ok(this), drop_frames(this);
   1290   Branch(IntPtrEqual(restart_fp, null), &ok, &drop_frames);
   1291 
   1292   Bind(&drop_frames);
   1293   // We don't expect this call to return since the frame dropper tears down
   1294   // the stack and jumps into the function on the target frame to restart it.
   1295   CallStub(CodeFactory::FrameDropperTrampoline(isolate()), context, restart_fp);
   1296   Abort(kUnexpectedReturnFromFrameDropper);
   1297   Goto(&ok);
   1298 
   1299   Bind(&ok);
   1300 }
   1301 
   1302 void InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) {
   1303   CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(),
   1304               SmiTag(BytecodeOffset()), GetAccumulatorUnchecked());
   1305 }
   1306 
   1307 void InterpreterAssembler::TraceBytecodeDispatch(Node* target_bytecode) {
   1308   Node* counters_table = ExternalConstant(
   1309       ExternalReference::interpreter_dispatch_counters(isolate()));
   1310   Node* source_bytecode_table_index = IntPtrConstant(
   1311       static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1));
   1312 
   1313   Node* counter_offset =
   1314       WordShl(IntPtrAdd(source_bytecode_table_index, target_bytecode),
   1315               IntPtrConstant(kPointerSizeLog2));
   1316   Node* old_counter =
   1317       Load(MachineType::IntPtr(), counters_table, counter_offset);
   1318 
   1319   Label counter_ok(this), counter_saturated(this, Label::kDeferred);
   1320 
   1321   Node* counter_reached_max = WordEqual(
   1322       old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max()));
   1323   Branch(counter_reached_max, &counter_saturated, &counter_ok);
   1324 
   1325   Bind(&counter_ok);
   1326   {
   1327     Node* new_counter = IntPtrAdd(old_counter, IntPtrConstant(1));
   1328     StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table,
   1329                         counter_offset, new_counter);
   1330     Goto(&counter_saturated);
   1331   }
   1332 
   1333   Bind(&counter_saturated);
   1334 }
   1335 
   1336 // static
   1337 bool InterpreterAssembler::TargetSupportsUnalignedAccess() {
   1338 #if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64
   1339   return false;
   1340 #elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_X87 || \
   1341     V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || \
   1342     V8_TARGET_ARCH_PPC
   1343   return true;
   1344 #else
   1345 #error "Unknown Architecture"
   1346 #endif
   1347 }
   1348 
   1349 Node* InterpreterAssembler::RegisterCount() {
   1350   Node* bytecode_array = LoadRegister(Register::bytecode_array());
   1351   Node* frame_size = LoadObjectField(
   1352       bytecode_array, BytecodeArray::kFrameSizeOffset, MachineType::Uint32());
   1353   return WordShr(ChangeUint32ToWord(frame_size),
   1354                  IntPtrConstant(kPointerSizeLog2));
   1355 }
   1356 
   1357 Node* InterpreterAssembler::ExportRegisterFile(Node* array) {
   1358   Node* register_count = RegisterCount();
   1359   if (FLAG_debug_code) {
   1360     Node* array_size = LoadAndUntagFixedArrayBaseLength(array);
   1361     AbortIfWordNotEqual(array_size, register_count,
   1362                         kInvalidRegisterFileInGenerator);
   1363   }
   1364 
   1365   Variable var_index(this, MachineType::PointerRepresentation());
   1366   var_index.Bind(IntPtrConstant(0));
   1367 
   1368   // Iterate over register file and write values into array.
   1369   // The mapping of register to array index must match that used in
   1370   // BytecodeGraphBuilder::VisitResumeGenerator.
   1371   Label loop(this, &var_index), done_loop(this);
   1372   Goto(&loop);
   1373   Bind(&loop);
   1374   {
   1375     Node* index = var_index.value();
   1376     GotoIfNot(UintPtrLessThan(index, register_count), &done_loop);
   1377 
   1378     Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index);
   1379     Node* value = LoadRegister(reg_index);
   1380 
   1381     StoreFixedArrayElement(array, index, value);
   1382 
   1383     var_index.Bind(IntPtrAdd(index, IntPtrConstant(1)));
   1384     Goto(&loop);
   1385   }
   1386   Bind(&done_loop);
   1387 
   1388   return array;
   1389 }
   1390 
   1391 Node* InterpreterAssembler::ImportRegisterFile(Node* array) {
   1392   Node* register_count = RegisterCount();
   1393   if (FLAG_debug_code) {
   1394     Node* array_size = LoadAndUntagFixedArrayBaseLength(array);
   1395     AbortIfWordNotEqual(array_size, register_count,
   1396                         kInvalidRegisterFileInGenerator);
   1397   }
   1398 
   1399   Variable var_index(this, MachineType::PointerRepresentation());
   1400   var_index.Bind(IntPtrConstant(0));
   1401 
   1402   // Iterate over array and write values into register file.  Also erase the
   1403   // array contents to not keep them alive artificially.
   1404   Label loop(this, &var_index), done_loop(this);
   1405   Goto(&loop);
   1406   Bind(&loop);
   1407   {
   1408     Node* index = var_index.value();
   1409     GotoIfNot(UintPtrLessThan(index, register_count), &done_loop);
   1410 
   1411     Node* value = LoadFixedArrayElement(array, index);
   1412 
   1413     Node* reg_index = IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index);
   1414     StoreRegister(value, reg_index);
   1415 
   1416     StoreFixedArrayElement(array, index, StaleRegisterConstant());
   1417 
   1418     var_index.Bind(IntPtrAdd(index, IntPtrConstant(1)));
   1419     Goto(&loop);
   1420   }
   1421   Bind(&done_loop);
   1422 
   1423   return array;
   1424 }
   1425 
   1426 }  // namespace interpreter
   1427 }  // namespace internal
   1428 }  // namespace v8
   1429