11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/interpreter/interpreter-assembler.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <limits>
81cb0ef41Sopenharmony_ci#include <ostream>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/codegen/code-factory.h"
111cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors-inl.h"
121cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h"
131cb0ef41Sopenharmony_ci#include "src/execution/frames.h"
141cb0ef41Sopenharmony_ci#include "src/interpreter/bytecodes.h"
151cb0ef41Sopenharmony_ci#include "src/interpreter/interpreter.h"
161cb0ef41Sopenharmony_ci#include "src/objects/objects-inl.h"
171cb0ef41Sopenharmony_ci#include "src/zone/zone.h"
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace v8 {
201cb0ef41Sopenharmony_cinamespace internal {
211cb0ef41Sopenharmony_cinamespace interpreter {
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ciusing compiler::CodeAssemblerState;
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciInterpreterAssembler::InterpreterAssembler(CodeAssemblerState* state,
261cb0ef41Sopenharmony_ci                                           Bytecode bytecode,
271cb0ef41Sopenharmony_ci                                           OperandScale operand_scale)
281cb0ef41Sopenharmony_ci    : CodeStubAssembler(state),
291cb0ef41Sopenharmony_ci      bytecode_(bytecode),
301cb0ef41Sopenharmony_ci      operand_scale_(operand_scale),
311cb0ef41Sopenharmony_ci      TVARIABLE_CONSTRUCTOR(interpreted_frame_pointer_),
321cb0ef41Sopenharmony_ci      TVARIABLE_CONSTRUCTOR(bytecode_array_,
331cb0ef41Sopenharmony_ci                            Parameter<BytecodeArray>(
341cb0ef41Sopenharmony_ci                                InterpreterDispatchDescriptor::kBytecodeArray)),
351cb0ef41Sopenharmony_ci      TVARIABLE_CONSTRUCTOR(
361cb0ef41Sopenharmony_ci          bytecode_offset_,
371cb0ef41Sopenharmony_ci          UncheckedParameter<IntPtrT>(
381cb0ef41Sopenharmony_ci              InterpreterDispatchDescriptor::kBytecodeOffset)),
391cb0ef41Sopenharmony_ci      TVARIABLE_CONSTRUCTOR(dispatch_table_,
401cb0ef41Sopenharmony_ci                            UncheckedParameter<ExternalReference>(
411cb0ef41Sopenharmony_ci                                InterpreterDispatchDescriptor::kDispatchTable)),
421cb0ef41Sopenharmony_ci      TVARIABLE_CONSTRUCTOR(
431cb0ef41Sopenharmony_ci          accumulator_,
441cb0ef41Sopenharmony_ci          Parameter<Object>(InterpreterDispatchDescriptor::kAccumulator)),
451cb0ef41Sopenharmony_ci      implicit_register_use_(ImplicitRegisterUse::kNone),
461cb0ef41Sopenharmony_ci      made_call_(false),
471cb0ef41Sopenharmony_ci      reloaded_frame_ptr_(false),
481cb0ef41Sopenharmony_ci      bytecode_array_valid_(true) {
491cb0ef41Sopenharmony_ci#ifdef V8_TRACE_UNOPTIMIZED
501cb0ef41Sopenharmony_ci  TraceBytecode(Runtime::kTraceUnoptimizedBytecodeEntry);
511cb0ef41Sopenharmony_ci#endif
521cb0ef41Sopenharmony_ci  RegisterCallGenerationCallbacks([this] { CallPrologue(); },
531cb0ef41Sopenharmony_ci                                  [this] { CallEpilogue(); });
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  // Save the bytecode offset immediately if bytecode will make a call along
561cb0ef41Sopenharmony_ci  // the critical path, or it is a return bytecode.
571cb0ef41Sopenharmony_ci  if (Bytecodes::MakesCallAlongCriticalPath(bytecode) ||
581cb0ef41Sopenharmony_ci      Bytecodes::Returns(bytecode)) {
591cb0ef41Sopenharmony_ci    SaveBytecodeOffset();
601cb0ef41Sopenharmony_ci  }
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciInterpreterAssembler::~InterpreterAssembler() {
641cb0ef41Sopenharmony_ci  // If the following check fails the handler does not use the
651cb0ef41Sopenharmony_ci  // accumulator in the way described in the bytecode definitions in
661cb0ef41Sopenharmony_ci  // bytecodes.h.
671cb0ef41Sopenharmony_ci  DCHECK_EQ(implicit_register_use_,
681cb0ef41Sopenharmony_ci            Bytecodes::GetImplicitRegisterUse(bytecode_));
691cb0ef41Sopenharmony_ci  UnregisterCallGenerationCallbacks();
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciTNode<RawPtrT> InterpreterAssembler::GetInterpretedFramePointer() {
731cb0ef41Sopenharmony_ci  if (!interpreted_frame_pointer_.IsBound()) {
741cb0ef41Sopenharmony_ci    interpreted_frame_pointer_ = LoadParentFramePointer();
751cb0ef41Sopenharmony_ci  } else if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
761cb0ef41Sopenharmony_ci             !reloaded_frame_ptr_) {
771cb0ef41Sopenharmony_ci    interpreted_frame_pointer_ = LoadParentFramePointer();
781cb0ef41Sopenharmony_ci    reloaded_frame_ptr_ = true;
791cb0ef41Sopenharmony_ci  }
801cb0ef41Sopenharmony_ci  return interpreted_frame_pointer_.value();
811cb0ef41Sopenharmony_ci}
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::BytecodeOffset() {
841cb0ef41Sopenharmony_ci  if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
851cb0ef41Sopenharmony_ci      (bytecode_offset_.value() ==
861cb0ef41Sopenharmony_ci       UncheckedParameter<IntPtrT>(
871cb0ef41Sopenharmony_ci           InterpreterDispatchDescriptor::kBytecodeOffset))) {
881cb0ef41Sopenharmony_ci    bytecode_offset_ = ReloadBytecodeOffset();
891cb0ef41Sopenharmony_ci  }
901cb0ef41Sopenharmony_ci  return bytecode_offset_.value();
911cb0ef41Sopenharmony_ci}
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::ReloadBytecodeOffset() {
941cb0ef41Sopenharmony_ci  TNode<IntPtrT> offset = LoadAndUntagRegister(Register::bytecode_offset());
951cb0ef41Sopenharmony_ci  if (operand_scale() != OperandScale::kSingle) {
961cb0ef41Sopenharmony_ci    // Add one to the offset such that it points to the actual bytecode rather
971cb0ef41Sopenharmony_ci    // than the Wide / ExtraWide prefix bytecode.
981cb0ef41Sopenharmony_ci    offset = IntPtrAdd(offset, IntPtrConstant(1));
991cb0ef41Sopenharmony_ci  }
1001cb0ef41Sopenharmony_ci  return offset;
1011cb0ef41Sopenharmony_ci}
1021cb0ef41Sopenharmony_ci
1031cb0ef41Sopenharmony_civoid InterpreterAssembler::SaveBytecodeOffset() {
1041cb0ef41Sopenharmony_ci  TNode<IntPtrT> bytecode_offset = BytecodeOffset();
1051cb0ef41Sopenharmony_ci  if (operand_scale() != OperandScale::kSingle) {
1061cb0ef41Sopenharmony_ci    // Subtract one from the bytecode_offset such that it points to the Wide /
1071cb0ef41Sopenharmony_ci    // ExtraWide prefix bytecode.
1081cb0ef41Sopenharmony_ci    bytecode_offset = IntPtrSub(BytecodeOffset(), IntPtrConstant(1));
1091cb0ef41Sopenharmony_ci  }
1101cb0ef41Sopenharmony_ci  int store_offset =
1111cb0ef41Sopenharmony_ci      Register::bytecode_offset().ToOperand() * kSystemPointerSize;
1121cb0ef41Sopenharmony_ci  TNode<RawPtrT> base = GetInterpretedFramePointer();
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  if (SmiValuesAre32Bits()) {
1151cb0ef41Sopenharmony_ci    int zero_offset = store_offset + 4;
1161cb0ef41Sopenharmony_ci    int payload_offset = store_offset;
1171cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN
1181cb0ef41Sopenharmony_ci    std::swap(zero_offset, payload_offset);
1191cb0ef41Sopenharmony_ci#endif
1201cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineRepresentation::kWord32, base,
1211cb0ef41Sopenharmony_ci                        IntPtrConstant(zero_offset), Int32Constant(0));
1221cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineRepresentation::kWord32, base,
1231cb0ef41Sopenharmony_ci                        IntPtrConstant(payload_offset),
1241cb0ef41Sopenharmony_ci                        TruncateIntPtrToInt32(bytecode_offset));
1251cb0ef41Sopenharmony_ci  } else {
1261cb0ef41Sopenharmony_ci    StoreFullTaggedNoWriteBarrier(base, IntPtrConstant(store_offset),
1271cb0ef41Sopenharmony_ci                                  SmiTag(bytecode_offset));
1281cb0ef41Sopenharmony_ci  }
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ciTNode<BytecodeArray> InterpreterAssembler::BytecodeArrayTaggedPointer() {
1321cb0ef41Sopenharmony_ci  // Force a re-load of the bytecode array after every call in case the debugger
1331cb0ef41Sopenharmony_ci  // has been activated.
1341cb0ef41Sopenharmony_ci  if (!bytecode_array_valid_) {
1351cb0ef41Sopenharmony_ci    bytecode_array_ = CAST(LoadRegister(Register::bytecode_array()));
1361cb0ef41Sopenharmony_ci    bytecode_array_valid_ = true;
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci  return bytecode_array_.value();
1391cb0ef41Sopenharmony_ci}
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ciTNode<ExternalReference> InterpreterAssembler::DispatchTablePointer() {
1421cb0ef41Sopenharmony_ci  if (Bytecodes::MakesCallAlongCriticalPath(bytecode_) && made_call_ &&
1431cb0ef41Sopenharmony_ci      (dispatch_table_.value() ==
1441cb0ef41Sopenharmony_ci       UncheckedParameter<ExternalReference>(
1451cb0ef41Sopenharmony_ci           InterpreterDispatchDescriptor::kDispatchTable))) {
1461cb0ef41Sopenharmony_ci    dispatch_table_ = ExternalConstant(
1471cb0ef41Sopenharmony_ci        ExternalReference::interpreter_dispatch_table_address(isolate()));
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci  return dispatch_table_.value();
1501cb0ef41Sopenharmony_ci}
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::GetAccumulatorUnchecked() {
1531cb0ef41Sopenharmony_ci  return accumulator_.value();
1541cb0ef41Sopenharmony_ci}
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::GetAccumulator() {
1571cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::ReadsAccumulator(bytecode_));
1581cb0ef41Sopenharmony_ci  implicit_register_use_ =
1591cb0ef41Sopenharmony_ci      implicit_register_use_ | ImplicitRegisterUse::kReadAccumulator;
1601cb0ef41Sopenharmony_ci  return GetAccumulatorUnchecked();
1611cb0ef41Sopenharmony_ci}
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_civoid InterpreterAssembler::SetAccumulator(TNode<Object> value) {
1641cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::WritesAccumulator(bytecode_));
1651cb0ef41Sopenharmony_ci  implicit_register_use_ =
1661cb0ef41Sopenharmony_ci      implicit_register_use_ | ImplicitRegisterUse::kWriteAccumulator;
1671cb0ef41Sopenharmony_ci  accumulator_ = value;
1681cb0ef41Sopenharmony_ci}
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ciTNode<Context> InterpreterAssembler::GetContext() {
1711cb0ef41Sopenharmony_ci  return CAST(LoadRegister(Register::current_context()));
1721cb0ef41Sopenharmony_ci}
1731cb0ef41Sopenharmony_ci
1741cb0ef41Sopenharmony_civoid InterpreterAssembler::SetContext(TNode<Context> value) {
1751cb0ef41Sopenharmony_ci  StoreRegister(value, Register::current_context());
1761cb0ef41Sopenharmony_ci}
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ciTNode<Context> InterpreterAssembler::GetContextAtDepth(TNode<Context> context,
1791cb0ef41Sopenharmony_ci                                                       TNode<Uint32T> depth) {
1801cb0ef41Sopenharmony_ci  TVARIABLE(Context, cur_context, context);
1811cb0ef41Sopenharmony_ci  TVARIABLE(Uint32T, cur_depth, depth);
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  Label context_found(this);
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci  Label context_search(this, {&cur_depth, &cur_context});
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci  // Fast path if the depth is 0.
1881cb0ef41Sopenharmony_ci  Branch(Word32Equal(depth, Int32Constant(0)), &context_found, &context_search);
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  // Loop until the depth is 0.
1911cb0ef41Sopenharmony_ci  BIND(&context_search);
1921cb0ef41Sopenharmony_ci  {
1931cb0ef41Sopenharmony_ci    cur_depth = Unsigned(Int32Sub(cur_depth.value(), Int32Constant(1)));
1941cb0ef41Sopenharmony_ci    cur_context =
1951cb0ef41Sopenharmony_ci        CAST(LoadContextElement(cur_context.value(), Context::PREVIOUS_INDEX));
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci    Branch(Word32Equal(cur_depth.value(), Int32Constant(0)), &context_found,
1981cb0ef41Sopenharmony_ci           &context_search);
1991cb0ef41Sopenharmony_ci  }
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci  BIND(&context_found);
2021cb0ef41Sopenharmony_ci  return cur_context.value();
2031cb0ef41Sopenharmony_ci}
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::RegisterLocation(
2061cb0ef41Sopenharmony_ci    TNode<IntPtrT> reg_index) {
2071cb0ef41Sopenharmony_ci  return Signed(
2081cb0ef41Sopenharmony_ci      IntPtrAdd(GetInterpretedFramePointer(), RegisterFrameOffset(reg_index)));
2091cb0ef41Sopenharmony_ci}
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::RegisterLocation(Register reg) {
2121cb0ef41Sopenharmony_ci  return RegisterLocation(IntPtrConstant(reg.ToOperand()));
2131cb0ef41Sopenharmony_ci}
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::RegisterFrameOffset(TNode<IntPtrT> index) {
2161cb0ef41Sopenharmony_ci  return TimesSystemPointerSize(index);
2171cb0ef41Sopenharmony_ci}
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::LoadRegister(TNode<IntPtrT> reg_index) {
2201cb0ef41Sopenharmony_ci  return LoadFullTagged(GetInterpretedFramePointer(),
2211cb0ef41Sopenharmony_ci                        RegisterFrameOffset(reg_index));
2221cb0ef41Sopenharmony_ci}
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::LoadRegister(Register reg) {
2251cb0ef41Sopenharmony_ci  return LoadFullTagged(GetInterpretedFramePointer(),
2261cb0ef41Sopenharmony_ci                        IntPtrConstant(reg.ToOperand() * kSystemPointerSize));
2271cb0ef41Sopenharmony_ci}
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::LoadAndUntagRegister(Register reg) {
2301cb0ef41Sopenharmony_ci  TNode<RawPtrT> base = GetInterpretedFramePointer();
2311cb0ef41Sopenharmony_ci  int index = reg.ToOperand() * kSystemPointerSize;
2321cb0ef41Sopenharmony_ci  if (SmiValuesAre32Bits()) {
2331cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN
2341cb0ef41Sopenharmony_ci    index += 4;
2351cb0ef41Sopenharmony_ci#endif
2361cb0ef41Sopenharmony_ci    return ChangeInt32ToIntPtr(Load<Int32T>(base, IntPtrConstant(index)));
2371cb0ef41Sopenharmony_ci  } else {
2381cb0ef41Sopenharmony_ci    return SmiToIntPtr(CAST(LoadFullTagged(base, IntPtrConstant(index))));
2391cb0ef41Sopenharmony_ci  }
2401cb0ef41Sopenharmony_ci}
2411cb0ef41Sopenharmony_ci
2421cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::LoadRegisterAtOperandIndex(
2431cb0ef41Sopenharmony_ci    int operand_index) {
2441cb0ef41Sopenharmony_ci  return LoadRegister(BytecodeOperandReg(operand_index));
2451cb0ef41Sopenharmony_ci}
2461cb0ef41Sopenharmony_ci
2471cb0ef41Sopenharmony_cistd::pair<TNode<Object>, TNode<Object>>
2481cb0ef41Sopenharmony_ciInterpreterAssembler::LoadRegisterPairAtOperandIndex(int operand_index) {
2491cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kRegPair,
2501cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
2511cb0ef41Sopenharmony_ci  TNode<IntPtrT> first_reg_index = BytecodeOperandReg(operand_index);
2521cb0ef41Sopenharmony_ci  TNode<IntPtrT> second_reg_index = NextRegister(first_reg_index);
2531cb0ef41Sopenharmony_ci  return std::make_pair(LoadRegister(first_reg_index),
2541cb0ef41Sopenharmony_ci                        LoadRegister(second_reg_index));
2551cb0ef41Sopenharmony_ci}
2561cb0ef41Sopenharmony_ci
2571cb0ef41Sopenharmony_ciInterpreterAssembler::RegListNodePair
2581cb0ef41Sopenharmony_ciInterpreterAssembler::GetRegisterListAtOperandIndex(int operand_index) {
2591cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsRegisterListOperandType(
2601cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(bytecode_, operand_index)));
2611cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kRegCount,
2621cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index + 1));
2631cb0ef41Sopenharmony_ci  TNode<IntPtrT> base_reg = RegisterLocation(BytecodeOperandReg(operand_index));
2641cb0ef41Sopenharmony_ci  TNode<Uint32T> reg_count = BytecodeOperandCount(operand_index + 1);
2651cb0ef41Sopenharmony_ci  return RegListNodePair(base_reg, reg_count);
2661cb0ef41Sopenharmony_ci}
2671cb0ef41Sopenharmony_ci
2681cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::LoadRegisterFromRegisterList(
2691cb0ef41Sopenharmony_ci    const RegListNodePair& reg_list, int index) {
2701cb0ef41Sopenharmony_ci  TNode<IntPtrT> location = RegisterLocationInRegisterList(reg_list, index);
2711cb0ef41Sopenharmony_ci  return LoadFullTagged(location);
2721cb0ef41Sopenharmony_ci}
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::RegisterLocationInRegisterList(
2751cb0ef41Sopenharmony_ci    const RegListNodePair& reg_list, int index) {
2761cb0ef41Sopenharmony_ci  CSA_DCHECK(this,
2771cb0ef41Sopenharmony_ci             Uint32GreaterThan(reg_list.reg_count(), Int32Constant(index)));
2781cb0ef41Sopenharmony_ci  TNode<IntPtrT> offset = RegisterFrameOffset(IntPtrConstant(index));
2791cb0ef41Sopenharmony_ci  // Register indexes are negative, so subtract index from base location to get
2801cb0ef41Sopenharmony_ci  // location.
2811cb0ef41Sopenharmony_ci  return Signed(IntPtrSub(reg_list.base_reg_location(), offset));
2821cb0ef41Sopenharmony_ci}
2831cb0ef41Sopenharmony_ci
2841cb0ef41Sopenharmony_civoid InterpreterAssembler::StoreRegister(TNode<Object> value, Register reg) {
2851cb0ef41Sopenharmony_ci  StoreFullTaggedNoWriteBarrier(
2861cb0ef41Sopenharmony_ci      GetInterpretedFramePointer(),
2871cb0ef41Sopenharmony_ci      IntPtrConstant(reg.ToOperand() * kSystemPointerSize), value);
2881cb0ef41Sopenharmony_ci}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_civoid InterpreterAssembler::StoreRegister(TNode<Object> value,
2911cb0ef41Sopenharmony_ci                                         TNode<IntPtrT> reg_index) {
2921cb0ef41Sopenharmony_ci  StoreFullTaggedNoWriteBarrier(GetInterpretedFramePointer(),
2931cb0ef41Sopenharmony_ci                                RegisterFrameOffset(reg_index), value);
2941cb0ef41Sopenharmony_ci}
2951cb0ef41Sopenharmony_ci
2961cb0ef41Sopenharmony_civoid InterpreterAssembler::StoreRegisterForShortStar(TNode<Object> value,
2971cb0ef41Sopenharmony_ci                                                     TNode<WordT> opcode) {
2981cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsShortStar(bytecode_));
2991cb0ef41Sopenharmony_ci  implicit_register_use_ =
3001cb0ef41Sopenharmony_ci      implicit_register_use_ | ImplicitRegisterUse::kWriteShortStar;
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci  CSA_DCHECK(
3031cb0ef41Sopenharmony_ci      this, UintPtrGreaterThanOrEqual(opcode, UintPtrConstant(static_cast<int>(
3041cb0ef41Sopenharmony_ci                                                  Bytecode::kFirstShortStar))));
3051cb0ef41Sopenharmony_ci  CSA_DCHECK(
3061cb0ef41Sopenharmony_ci      this,
3071cb0ef41Sopenharmony_ci      UintPtrLessThanOrEqual(
3081cb0ef41Sopenharmony_ci          opcode, UintPtrConstant(static_cast<int>(Bytecode::kLastShortStar))));
3091cb0ef41Sopenharmony_ci
3101cb0ef41Sopenharmony_ci  // Compute the constant that we can add to a Bytecode value to map the range
3111cb0ef41Sopenharmony_ci  // [Bytecode::kStar15, Bytecode::kStar0] to the range
3121cb0ef41Sopenharmony_ci  // [Register(15).ToOperand(), Register(0).ToOperand()].
3131cb0ef41Sopenharmony_ci  constexpr int short_star_to_operand =
3141cb0ef41Sopenharmony_ci      Register(0).ToOperand() - static_cast<int>(Bytecode::kStar0);
3151cb0ef41Sopenharmony_ci  // Make sure the values count in the right direction.
3161cb0ef41Sopenharmony_ci  STATIC_ASSERT(short_star_to_operand ==
3171cb0ef41Sopenharmony_ci                Register(1).ToOperand() - static_cast<int>(Bytecode::kStar1));
3181cb0ef41Sopenharmony_ci
3191cb0ef41Sopenharmony_ci  TNode<IntPtrT> offset =
3201cb0ef41Sopenharmony_ci      IntPtrAdd(RegisterFrameOffset(Signed(opcode)),
3211cb0ef41Sopenharmony_ci                IntPtrConstant(short_star_to_operand * kSystemPointerSize));
3221cb0ef41Sopenharmony_ci  StoreFullTaggedNoWriteBarrier(GetInterpretedFramePointer(), offset, value);
3231cb0ef41Sopenharmony_ci}
3241cb0ef41Sopenharmony_ci
3251cb0ef41Sopenharmony_civoid InterpreterAssembler::StoreRegisterAtOperandIndex(TNode<Object> value,
3261cb0ef41Sopenharmony_ci                                                       int operand_index) {
3271cb0ef41Sopenharmony_ci  StoreRegister(value, BytecodeOperandReg(operand_index));
3281cb0ef41Sopenharmony_ci}
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_civoid InterpreterAssembler::StoreRegisterPairAtOperandIndex(TNode<Object> value1,
3311cb0ef41Sopenharmony_ci                                                           TNode<Object> value2,
3321cb0ef41Sopenharmony_ci                                                           int operand_index) {
3331cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kRegOutPair,
3341cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
3351cb0ef41Sopenharmony_ci  TNode<IntPtrT> first_reg_index = BytecodeOperandReg(operand_index);
3361cb0ef41Sopenharmony_ci  StoreRegister(value1, first_reg_index);
3371cb0ef41Sopenharmony_ci  TNode<IntPtrT> second_reg_index = NextRegister(first_reg_index);
3381cb0ef41Sopenharmony_ci  StoreRegister(value2, second_reg_index);
3391cb0ef41Sopenharmony_ci}
3401cb0ef41Sopenharmony_ci
3411cb0ef41Sopenharmony_civoid InterpreterAssembler::StoreRegisterTripleAtOperandIndex(
3421cb0ef41Sopenharmony_ci    TNode<Object> value1, TNode<Object> value2, TNode<Object> value3,
3431cb0ef41Sopenharmony_ci    int operand_index) {
3441cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kRegOutTriple,
3451cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
3461cb0ef41Sopenharmony_ci  TNode<IntPtrT> first_reg_index = BytecodeOperandReg(operand_index);
3471cb0ef41Sopenharmony_ci  StoreRegister(value1, first_reg_index);
3481cb0ef41Sopenharmony_ci  TNode<IntPtrT> second_reg_index = NextRegister(first_reg_index);
3491cb0ef41Sopenharmony_ci  StoreRegister(value2, second_reg_index);
3501cb0ef41Sopenharmony_ci  TNode<IntPtrT> third_reg_index = NextRegister(second_reg_index);
3511cb0ef41Sopenharmony_ci  StoreRegister(value3, third_reg_index);
3521cb0ef41Sopenharmony_ci}
3531cb0ef41Sopenharmony_ci
3541cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::NextRegister(TNode<IntPtrT> reg_index) {
3551cb0ef41Sopenharmony_ci  // Register indexes are negative, so the next index is minus one.
3561cb0ef41Sopenharmony_ci  return Signed(IntPtrAdd(reg_index, IntPtrConstant(-1)));
3571cb0ef41Sopenharmony_ci}
3581cb0ef41Sopenharmony_ci
3591cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::OperandOffset(int operand_index) {
3601cb0ef41Sopenharmony_ci  return IntPtrConstant(
3611cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale()));
3621cb0ef41Sopenharmony_ci}
3631cb0ef41Sopenharmony_ci
3641cb0ef41Sopenharmony_ciTNode<Uint8T> InterpreterAssembler::BytecodeOperandUnsignedByte(
3651cb0ef41Sopenharmony_ci    int operand_index) {
3661cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
3671cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize(
3681cb0ef41Sopenharmony_ci                                    bytecode_, operand_index, operand_scale()));
3691cb0ef41Sopenharmony_ci  TNode<IntPtrT> operand_offset = OperandOffset(operand_index);
3701cb0ef41Sopenharmony_ci  return Load<Uint8T>(BytecodeArrayTaggedPointer(),
3711cb0ef41Sopenharmony_ci                      IntPtrAdd(BytecodeOffset(), operand_offset));
3721cb0ef41Sopenharmony_ci}
3731cb0ef41Sopenharmony_ci
3741cb0ef41Sopenharmony_ciTNode<Int8T> InterpreterAssembler::BytecodeOperandSignedByte(
3751cb0ef41Sopenharmony_ci    int operand_index) {
3761cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
3771cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandSize::kByte, Bytecodes::GetOperandSize(
3781cb0ef41Sopenharmony_ci                                    bytecode_, operand_index, operand_scale()));
3791cb0ef41Sopenharmony_ci  TNode<IntPtrT> operand_offset = OperandOffset(operand_index);
3801cb0ef41Sopenharmony_ci  return Load<Int8T>(BytecodeArrayTaggedPointer(),
3811cb0ef41Sopenharmony_ci                     IntPtrAdd(BytecodeOffset(), operand_offset));
3821cb0ef41Sopenharmony_ci}
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ciTNode<Word32T> InterpreterAssembler::BytecodeOperandReadUnaligned(
3851cb0ef41Sopenharmony_ci    int relative_offset, MachineType result_type) {
3861cb0ef41Sopenharmony_ci  static const int kMaxCount = 4;
3871cb0ef41Sopenharmony_ci  DCHECK(!TargetSupportsUnalignedAccess());
3881cb0ef41Sopenharmony_ci
3891cb0ef41Sopenharmony_ci  int count;
3901cb0ef41Sopenharmony_ci  switch (result_type.representation()) {
3911cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord16:
3921cb0ef41Sopenharmony_ci      count = 2;
3931cb0ef41Sopenharmony_ci      break;
3941cb0ef41Sopenharmony_ci    case MachineRepresentation::kWord32:
3951cb0ef41Sopenharmony_ci      count = 4;
3961cb0ef41Sopenharmony_ci      break;
3971cb0ef41Sopenharmony_ci    default:
3981cb0ef41Sopenharmony_ci      UNREACHABLE();
3991cb0ef41Sopenharmony_ci  }
4001cb0ef41Sopenharmony_ci  MachineType msb_type =
4011cb0ef41Sopenharmony_ci      result_type.IsSigned() ? MachineType::Int8() : MachineType::Uint8();
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci#if V8_TARGET_LITTLE_ENDIAN
4041cb0ef41Sopenharmony_ci  const int kStep = -1;
4051cb0ef41Sopenharmony_ci  int msb_offset = count - 1;
4061cb0ef41Sopenharmony_ci#elif V8_TARGET_BIG_ENDIAN
4071cb0ef41Sopenharmony_ci  const int kStep = 1;
4081cb0ef41Sopenharmony_ci  int msb_offset = 0;
4091cb0ef41Sopenharmony_ci#else
4101cb0ef41Sopenharmony_ci#error "Unknown Architecture"
4111cb0ef41Sopenharmony_ci#endif
4121cb0ef41Sopenharmony_ci
4131cb0ef41Sopenharmony_ci  // Read the most signicant bytecode into bytes[0] and then in order
4141cb0ef41Sopenharmony_ci  // down to least significant in bytes[count - 1].
4151cb0ef41Sopenharmony_ci  DCHECK_LE(count, kMaxCount);
4161cb0ef41Sopenharmony_ci  TNode<Word32T> bytes[kMaxCount];
4171cb0ef41Sopenharmony_ci  for (int i = 0; i < count; i++) {
4181cb0ef41Sopenharmony_ci    MachineType machine_type = (i == 0) ? msb_type : MachineType::Uint8();
4191cb0ef41Sopenharmony_ci    TNode<IntPtrT> offset =
4201cb0ef41Sopenharmony_ci        IntPtrConstant(relative_offset + msb_offset + i * kStep);
4211cb0ef41Sopenharmony_ci    TNode<IntPtrT> array_offset = IntPtrAdd(BytecodeOffset(), offset);
4221cb0ef41Sopenharmony_ci    bytes[i] = UncheckedCast<Word32T>(
4231cb0ef41Sopenharmony_ci        Load(machine_type, BytecodeArrayTaggedPointer(), array_offset));
4241cb0ef41Sopenharmony_ci  }
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci  // Pack LSB to MSB.
4271cb0ef41Sopenharmony_ci  TNode<Word32T> result = bytes[--count];
4281cb0ef41Sopenharmony_ci  for (int i = 1; --count >= 0; i++) {
4291cb0ef41Sopenharmony_ci    TNode<Int32T> shift = Int32Constant(i * kBitsPerByte);
4301cb0ef41Sopenharmony_ci    TNode<Word32T> value = Word32Shl(bytes[count], shift);
4311cb0ef41Sopenharmony_ci    result = Word32Or(value, result);
4321cb0ef41Sopenharmony_ci  }
4331cb0ef41Sopenharmony_ci  return result;
4341cb0ef41Sopenharmony_ci}
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ciTNode<Uint16T> InterpreterAssembler::BytecodeOperandUnsignedShort(
4371cb0ef41Sopenharmony_ci    int operand_index) {
4381cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
4391cb0ef41Sopenharmony_ci  DCHECK_EQ(
4401cb0ef41Sopenharmony_ci      OperandSize::kShort,
4411cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()));
4421cb0ef41Sopenharmony_ci  int operand_offset =
4431cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
4441cb0ef41Sopenharmony_ci  if (TargetSupportsUnalignedAccess()) {
4451cb0ef41Sopenharmony_ci    return Load<Uint16T>(
4461cb0ef41Sopenharmony_ci        BytecodeArrayTaggedPointer(),
4471cb0ef41Sopenharmony_ci        IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
4481cb0ef41Sopenharmony_ci  } else {
4491cb0ef41Sopenharmony_ci    return UncheckedCast<Uint16T>(
4501cb0ef41Sopenharmony_ci        BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint16()));
4511cb0ef41Sopenharmony_ci  }
4521cb0ef41Sopenharmony_ci}
4531cb0ef41Sopenharmony_ci
4541cb0ef41Sopenharmony_ciTNode<Int16T> InterpreterAssembler::BytecodeOperandSignedShort(
4551cb0ef41Sopenharmony_ci    int operand_index) {
4561cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
4571cb0ef41Sopenharmony_ci  DCHECK_EQ(
4581cb0ef41Sopenharmony_ci      OperandSize::kShort,
4591cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale()));
4601cb0ef41Sopenharmony_ci  int operand_offset =
4611cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
4621cb0ef41Sopenharmony_ci  if (TargetSupportsUnalignedAccess()) {
4631cb0ef41Sopenharmony_ci    return Load<Int16T>(
4641cb0ef41Sopenharmony_ci        BytecodeArrayTaggedPointer(),
4651cb0ef41Sopenharmony_ci        IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
4661cb0ef41Sopenharmony_ci  } else {
4671cb0ef41Sopenharmony_ci    return UncheckedCast<Int16T>(
4681cb0ef41Sopenharmony_ci        BytecodeOperandReadUnaligned(operand_offset, MachineType::Int16()));
4691cb0ef41Sopenharmony_ci  }
4701cb0ef41Sopenharmony_ci}
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandUnsignedQuad(
4731cb0ef41Sopenharmony_ci    int operand_index) {
4741cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
4751cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize(
4761cb0ef41Sopenharmony_ci                                    bytecode_, operand_index, operand_scale()));
4771cb0ef41Sopenharmony_ci  int operand_offset =
4781cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
4791cb0ef41Sopenharmony_ci  if (TargetSupportsUnalignedAccess()) {
4801cb0ef41Sopenharmony_ci    return Load<Uint32T>(
4811cb0ef41Sopenharmony_ci        BytecodeArrayTaggedPointer(),
4821cb0ef41Sopenharmony_ci        IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
4831cb0ef41Sopenharmony_ci  } else {
4841cb0ef41Sopenharmony_ci    return UncheckedCast<Uint32T>(
4851cb0ef41Sopenharmony_ci        BytecodeOperandReadUnaligned(operand_offset, MachineType::Uint32()));
4861cb0ef41Sopenharmony_ci  }
4871cb0ef41Sopenharmony_ci}
4881cb0ef41Sopenharmony_ci
4891cb0ef41Sopenharmony_ciTNode<Int32T> InterpreterAssembler::BytecodeOperandSignedQuad(
4901cb0ef41Sopenharmony_ci    int operand_index) {
4911cb0ef41Sopenharmony_ci  DCHECK_LT(operand_index, Bytecodes::NumberOfOperands(bytecode_));
4921cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandSize::kQuad, Bytecodes::GetOperandSize(
4931cb0ef41Sopenharmony_ci                                    bytecode_, operand_index, operand_scale()));
4941cb0ef41Sopenharmony_ci  int operand_offset =
4951cb0ef41Sopenharmony_ci      Bytecodes::GetOperandOffset(bytecode_, operand_index, operand_scale());
4961cb0ef41Sopenharmony_ci  if (TargetSupportsUnalignedAccess()) {
4971cb0ef41Sopenharmony_ci    return Load<Int32T>(
4981cb0ef41Sopenharmony_ci        BytecodeArrayTaggedPointer(),
4991cb0ef41Sopenharmony_ci        IntPtrAdd(BytecodeOffset(), IntPtrConstant(operand_offset)));
5001cb0ef41Sopenharmony_ci  } else {
5011cb0ef41Sopenharmony_ci    return UncheckedCast<Int32T>(
5021cb0ef41Sopenharmony_ci        BytecodeOperandReadUnaligned(operand_offset, MachineType::Int32()));
5031cb0ef41Sopenharmony_ci  }
5041cb0ef41Sopenharmony_ci}
5051cb0ef41Sopenharmony_ci
5061cb0ef41Sopenharmony_ciTNode<Int32T> InterpreterAssembler::BytecodeSignedOperand(
5071cb0ef41Sopenharmony_ci    int operand_index, OperandSize operand_size) {
5081cb0ef41Sopenharmony_ci  DCHECK(!Bytecodes::IsUnsignedOperandType(
5091cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(bytecode_, operand_index)));
5101cb0ef41Sopenharmony_ci  switch (operand_size) {
5111cb0ef41Sopenharmony_ci    case OperandSize::kByte:
5121cb0ef41Sopenharmony_ci      return BytecodeOperandSignedByte(operand_index);
5131cb0ef41Sopenharmony_ci    case OperandSize::kShort:
5141cb0ef41Sopenharmony_ci      return BytecodeOperandSignedShort(operand_index);
5151cb0ef41Sopenharmony_ci    case OperandSize::kQuad:
5161cb0ef41Sopenharmony_ci      return BytecodeOperandSignedQuad(operand_index);
5171cb0ef41Sopenharmony_ci    case OperandSize::kNone:
5181cb0ef41Sopenharmony_ci      UNREACHABLE();
5191cb0ef41Sopenharmony_ci  }
5201cb0ef41Sopenharmony_ci}
5211cb0ef41Sopenharmony_ci
5221cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeUnsignedOperand(
5231cb0ef41Sopenharmony_ci    int operand_index, OperandSize operand_size) {
5241cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsUnsignedOperandType(
5251cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(bytecode_, operand_index)));
5261cb0ef41Sopenharmony_ci  switch (operand_size) {
5271cb0ef41Sopenharmony_ci    case OperandSize::kByte:
5281cb0ef41Sopenharmony_ci      return BytecodeOperandUnsignedByte(operand_index);
5291cb0ef41Sopenharmony_ci    case OperandSize::kShort:
5301cb0ef41Sopenharmony_ci      return BytecodeOperandUnsignedShort(operand_index);
5311cb0ef41Sopenharmony_ci    case OperandSize::kQuad:
5321cb0ef41Sopenharmony_ci      return BytecodeOperandUnsignedQuad(operand_index);
5331cb0ef41Sopenharmony_ci    case OperandSize::kNone:
5341cb0ef41Sopenharmony_ci      UNREACHABLE();
5351cb0ef41Sopenharmony_ci  }
5361cb0ef41Sopenharmony_ci}
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandCount(int operand_index) {
5391cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kRegCount,
5401cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
5411cb0ef41Sopenharmony_ci  OperandSize operand_size =
5421cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
5431cb0ef41Sopenharmony_ci  return BytecodeUnsignedOperand(operand_index, operand_size);
5441cb0ef41Sopenharmony_ci}
5451cb0ef41Sopenharmony_ci
5461cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandFlag(int operand_index) {
5471cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kFlag8,
5481cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
5491cb0ef41Sopenharmony_ci  OperandSize operand_size =
5501cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
5511cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_size, OperandSize::kByte);
5521cb0ef41Sopenharmony_ci  return BytecodeUnsignedOperand(operand_index, operand_size);
5531cb0ef41Sopenharmony_ci}
5541cb0ef41Sopenharmony_ci
5551cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandUImm(int operand_index) {
5561cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kUImm,
5571cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
5581cb0ef41Sopenharmony_ci  OperandSize operand_size =
5591cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
5601cb0ef41Sopenharmony_ci  return BytecodeUnsignedOperand(operand_index, operand_size);
5611cb0ef41Sopenharmony_ci}
5621cb0ef41Sopenharmony_ci
5631cb0ef41Sopenharmony_ciTNode<UintPtrT> InterpreterAssembler::BytecodeOperandUImmWord(
5641cb0ef41Sopenharmony_ci    int operand_index) {
5651cb0ef41Sopenharmony_ci  return ChangeUint32ToWord(BytecodeOperandUImm(operand_index));
5661cb0ef41Sopenharmony_ci}
5671cb0ef41Sopenharmony_ci
5681cb0ef41Sopenharmony_ciTNode<Smi> InterpreterAssembler::BytecodeOperandUImmSmi(int operand_index) {
5691cb0ef41Sopenharmony_ci  return SmiFromUint32(BytecodeOperandUImm(operand_index));
5701cb0ef41Sopenharmony_ci}
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ciTNode<Int32T> InterpreterAssembler::BytecodeOperandImm(int operand_index) {
5731cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kImm,
5741cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
5751cb0ef41Sopenharmony_ci  OperandSize operand_size =
5761cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
5771cb0ef41Sopenharmony_ci  return BytecodeSignedOperand(operand_index, operand_size);
5781cb0ef41Sopenharmony_ci}
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::BytecodeOperandImmIntPtr(
5811cb0ef41Sopenharmony_ci    int operand_index) {
5821cb0ef41Sopenharmony_ci  return ChangeInt32ToIntPtr(BytecodeOperandImm(operand_index));
5831cb0ef41Sopenharmony_ci}
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ciTNode<Smi> InterpreterAssembler::BytecodeOperandImmSmi(int operand_index) {
5861cb0ef41Sopenharmony_ci  return SmiFromInt32(BytecodeOperandImm(operand_index));
5871cb0ef41Sopenharmony_ci}
5881cb0ef41Sopenharmony_ci
5891cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandIdxInt32(
5901cb0ef41Sopenharmony_ci    int operand_index) {
5911cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kIdx,
5921cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
5931cb0ef41Sopenharmony_ci  OperandSize operand_size =
5941cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
5951cb0ef41Sopenharmony_ci  return BytecodeUnsignedOperand(operand_index, operand_size);
5961cb0ef41Sopenharmony_ci}
5971cb0ef41Sopenharmony_ci
5981cb0ef41Sopenharmony_ciTNode<UintPtrT> InterpreterAssembler::BytecodeOperandIdx(int operand_index) {
5991cb0ef41Sopenharmony_ci  return ChangeUint32ToWord(BytecodeOperandIdxInt32(operand_index));
6001cb0ef41Sopenharmony_ci}
6011cb0ef41Sopenharmony_ci
6021cb0ef41Sopenharmony_ciTNode<Smi> InterpreterAssembler::BytecodeOperandIdxSmi(int operand_index) {
6031cb0ef41Sopenharmony_ci  return SmiTag(Signed(BytecodeOperandIdx(operand_index)));
6041cb0ef41Sopenharmony_ci}
6051cb0ef41Sopenharmony_ci
6061cb0ef41Sopenharmony_ciTNode<TaggedIndex> InterpreterAssembler::BytecodeOperandIdxTaggedIndex(
6071cb0ef41Sopenharmony_ci    int operand_index) {
6081cb0ef41Sopenharmony_ci  TNode<IntPtrT> index =
6091cb0ef41Sopenharmony_ci      ChangeInt32ToIntPtr(Signed(BytecodeOperandIdxInt32(operand_index)));
6101cb0ef41Sopenharmony_ci  return IntPtrToTaggedIndex(index);
6111cb0ef41Sopenharmony_ci}
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ciTNode<UintPtrT> InterpreterAssembler::BytecodeOperandConstantPoolIdx(
6141cb0ef41Sopenharmony_ci    int operand_index) {
6151cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kIdx,
6161cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
6171cb0ef41Sopenharmony_ci  OperandSize operand_size =
6181cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
6191cb0ef41Sopenharmony_ci  return ChangeUint32ToWord(
6201cb0ef41Sopenharmony_ci      BytecodeUnsignedOperand(operand_index, operand_size));
6211cb0ef41Sopenharmony_ci}
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::BytecodeOperandReg(int operand_index) {
6241cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsRegisterOperandType(
6251cb0ef41Sopenharmony_ci      Bytecodes::GetOperandType(bytecode_, operand_index)));
6261cb0ef41Sopenharmony_ci  OperandSize operand_size =
6271cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
6281cb0ef41Sopenharmony_ci  return ChangeInt32ToIntPtr(
6291cb0ef41Sopenharmony_ci      BytecodeSignedOperand(operand_index, operand_size));
6301cb0ef41Sopenharmony_ci}
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandRuntimeId(
6331cb0ef41Sopenharmony_ci    int operand_index) {
6341cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kRuntimeId,
6351cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
6361cb0ef41Sopenharmony_ci  OperandSize operand_size =
6371cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
6381cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_size, OperandSize::kShort);
6391cb0ef41Sopenharmony_ci  return BytecodeUnsignedOperand(operand_index, operand_size);
6401cb0ef41Sopenharmony_ci}
6411cb0ef41Sopenharmony_ci
6421cb0ef41Sopenharmony_ciTNode<UintPtrT> InterpreterAssembler::BytecodeOperandNativeContextIndex(
6431cb0ef41Sopenharmony_ci    int operand_index) {
6441cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kNativeContextIndex,
6451cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
6461cb0ef41Sopenharmony_ci  OperandSize operand_size =
6471cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
6481cb0ef41Sopenharmony_ci  return ChangeUint32ToWord(
6491cb0ef41Sopenharmony_ci      BytecodeUnsignedOperand(operand_index, operand_size));
6501cb0ef41Sopenharmony_ci}
6511cb0ef41Sopenharmony_ci
6521cb0ef41Sopenharmony_ciTNode<Uint32T> InterpreterAssembler::BytecodeOperandIntrinsicId(
6531cb0ef41Sopenharmony_ci    int operand_index) {
6541cb0ef41Sopenharmony_ci  DCHECK_EQ(OperandType::kIntrinsicId,
6551cb0ef41Sopenharmony_ci            Bytecodes::GetOperandType(bytecode_, operand_index));
6561cb0ef41Sopenharmony_ci  OperandSize operand_size =
6571cb0ef41Sopenharmony_ci      Bytecodes::GetOperandSize(bytecode_, operand_index, operand_scale());
6581cb0ef41Sopenharmony_ci  DCHECK_EQ(operand_size, OperandSize::kByte);
6591cb0ef41Sopenharmony_ci  return BytecodeUnsignedOperand(operand_index, operand_size);
6601cb0ef41Sopenharmony_ci}
6611cb0ef41Sopenharmony_ci
6621cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::LoadConstantPoolEntry(TNode<WordT> index) {
6631cb0ef41Sopenharmony_ci  TNode<FixedArray> constant_pool = CAST(LoadObjectField(
6641cb0ef41Sopenharmony_ci      BytecodeArrayTaggedPointer(), BytecodeArray::kConstantPoolOffset));
6651cb0ef41Sopenharmony_ci  return UnsafeLoadFixedArrayElement(constant_pool,
6661cb0ef41Sopenharmony_ci                                     UncheckedCast<IntPtrT>(index), 0);
6671cb0ef41Sopenharmony_ci}
6681cb0ef41Sopenharmony_ci
6691cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::LoadAndUntagConstantPoolEntry(
6701cb0ef41Sopenharmony_ci    TNode<WordT> index) {
6711cb0ef41Sopenharmony_ci  return SmiUntag(CAST(LoadConstantPoolEntry(index)));
6721cb0ef41Sopenharmony_ci}
6731cb0ef41Sopenharmony_ci
6741cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::LoadConstantPoolEntryAtOperandIndex(
6751cb0ef41Sopenharmony_ci    int operand_index) {
6761cb0ef41Sopenharmony_ci  TNode<UintPtrT> index = BytecodeOperandConstantPoolIdx(operand_index);
6771cb0ef41Sopenharmony_ci  return LoadConstantPoolEntry(index);
6781cb0ef41Sopenharmony_ci}
6791cb0ef41Sopenharmony_ci
6801cb0ef41Sopenharmony_ciTNode<IntPtrT>
6811cb0ef41Sopenharmony_ciInterpreterAssembler::LoadAndUntagConstantPoolEntryAtOperandIndex(
6821cb0ef41Sopenharmony_ci    int operand_index) {
6831cb0ef41Sopenharmony_ci  return SmiUntag(CAST(LoadConstantPoolEntryAtOperandIndex(operand_index)));
6841cb0ef41Sopenharmony_ci}
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ciTNode<HeapObject> InterpreterAssembler::LoadFeedbackVector() {
6871cb0ef41Sopenharmony_ci  TNode<JSFunction> function = CAST(LoadRegister(Register::function_closure()));
6881cb0ef41Sopenharmony_ci  return CodeStubAssembler::LoadFeedbackVector(function);
6891cb0ef41Sopenharmony_ci}
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_civoid InterpreterAssembler::CallPrologue() {
6921cb0ef41Sopenharmony_ci  if (!Bytecodes::MakesCallAlongCriticalPath(bytecode_)) {
6931cb0ef41Sopenharmony_ci    // Bytecodes that make a call along the critical path save the bytecode
6941cb0ef41Sopenharmony_ci    // offset in the bytecode handler's prologue. For other bytecodes, if
6951cb0ef41Sopenharmony_ci    // there are multiple calls in the bytecode handler, you need to spill
6961cb0ef41Sopenharmony_ci    // before each of them, unless SaveBytecodeOffset has explicitly been called
6971cb0ef41Sopenharmony_ci    // in a path that dominates _all_ of those calls (which we don't track).
6981cb0ef41Sopenharmony_ci    SaveBytecodeOffset();
6991cb0ef41Sopenharmony_ci  }
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci  bytecode_array_valid_ = false;
7021cb0ef41Sopenharmony_ci  made_call_ = true;
7031cb0ef41Sopenharmony_ci}
7041cb0ef41Sopenharmony_ci
7051cb0ef41Sopenharmony_civoid InterpreterAssembler::CallEpilogue() {}
7061cb0ef41Sopenharmony_ci
7071cb0ef41Sopenharmony_civoid InterpreterAssembler::CallJSAndDispatch(
7081cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Context> context, const RegListNodePair& args,
7091cb0ef41Sopenharmony_ci    ConvertReceiverMode receiver_mode) {
7101cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
7111cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsCallOrConstruct(bytecode_) ||
7121cb0ef41Sopenharmony_ci         bytecode_ == Bytecode::kInvokeIntrinsic);
7131cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), receiver_mode);
7141cb0ef41Sopenharmony_ci
7151cb0ef41Sopenharmony_ci  TNode<Word32T> args_count = args.reg_count();
7161cb0ef41Sopenharmony_ci  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
7171cb0ef41Sopenharmony_ci    // Add receiver. It is not included in args as it is implicit.
7181cb0ef41Sopenharmony_ci    args_count = Int32Add(args_count, Int32Constant(kJSArgcReceiverSlots));
7191cb0ef41Sopenharmony_ci  }
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  Callable callable = CodeFactory::InterpreterPushArgsThenCall(
7221cb0ef41Sopenharmony_ci      isolate(), receiver_mode, InterpreterPushArgsMode::kOther);
7231cb0ef41Sopenharmony_ci  TNode<CodeT> code_target = HeapConstant(callable.code());
7241cb0ef41Sopenharmony_ci
7251cb0ef41Sopenharmony_ci  TailCallStubThenBytecodeDispatch(callable.descriptor(), code_target, context,
7261cb0ef41Sopenharmony_ci                                   args_count, args.base_reg_location(),
7271cb0ef41Sopenharmony_ci                                   function);
7281cb0ef41Sopenharmony_ci  // TailCallStubThenDispatch updates accumulator with result.
7291cb0ef41Sopenharmony_ci  implicit_register_use_ =
7301cb0ef41Sopenharmony_ci      implicit_register_use_ | ImplicitRegisterUse::kWriteAccumulator;
7311cb0ef41Sopenharmony_ci}
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_citemplate <class... TArgs>
7341cb0ef41Sopenharmony_civoid InterpreterAssembler::CallJSAndDispatch(TNode<Object> function,
7351cb0ef41Sopenharmony_ci                                             TNode<Context> context,
7361cb0ef41Sopenharmony_ci                                             TNode<Word32T> arg_count,
7371cb0ef41Sopenharmony_ci                                             ConvertReceiverMode receiver_mode,
7381cb0ef41Sopenharmony_ci                                             TArgs... args) {
7391cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
7401cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsCallOrConstruct(bytecode_) ||
7411cb0ef41Sopenharmony_ci         bytecode_ == Bytecode::kInvokeIntrinsic);
7421cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), receiver_mode);
7431cb0ef41Sopenharmony_ci  Callable callable = CodeFactory::Call(isolate());
7441cb0ef41Sopenharmony_ci  TNode<CodeT> code_target = HeapConstant(callable.code());
7451cb0ef41Sopenharmony_ci
7461cb0ef41Sopenharmony_ci  arg_count = JSParameterCount(arg_count);
7471cb0ef41Sopenharmony_ci  if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) {
7481cb0ef41Sopenharmony_ci    // The first argument parameter (the receiver) is implied to be undefined.
7491cb0ef41Sopenharmony_ci    TailCallStubThenBytecodeDispatch(callable.descriptor(), code_target,
7501cb0ef41Sopenharmony_ci                                     context, function, arg_count, args...,
7511cb0ef41Sopenharmony_ci                                     UndefinedConstant());
7521cb0ef41Sopenharmony_ci  } else {
7531cb0ef41Sopenharmony_ci    TailCallStubThenBytecodeDispatch(callable.descriptor(), code_target,
7541cb0ef41Sopenharmony_ci                                     context, function, arg_count, args...);
7551cb0ef41Sopenharmony_ci  }
7561cb0ef41Sopenharmony_ci  // TailCallStubThenDispatch updates accumulator with result.
7571cb0ef41Sopenharmony_ci  implicit_register_use_ =
7581cb0ef41Sopenharmony_ci      implicit_register_use_ | ImplicitRegisterUse::kWriteAccumulator;
7591cb0ef41Sopenharmony_ci}
7601cb0ef41Sopenharmony_ci
7611cb0ef41Sopenharmony_ci// Instantiate CallJSAndDispatch() for argument counts used by interpreter
7621cb0ef41Sopenharmony_ci// generator.
7631cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE void InterpreterAssembler::CallJSAndDispatch(
7641cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Context> context, TNode<Word32T> arg_count,
7651cb0ef41Sopenharmony_ci    ConvertReceiverMode receiver_mode);
7661cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE void InterpreterAssembler::CallJSAndDispatch(
7671cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Context> context, TNode<Word32T> arg_count,
7681cb0ef41Sopenharmony_ci    ConvertReceiverMode receiver_mode, TNode<Object>);
7691cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE void InterpreterAssembler::CallJSAndDispatch(
7701cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Context> context, TNode<Word32T> arg_count,
7711cb0ef41Sopenharmony_ci    ConvertReceiverMode receiver_mode, TNode<Object>, TNode<Object>);
7721cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE void InterpreterAssembler::CallJSAndDispatch(
7731cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Context> context, TNode<Word32T> arg_count,
7741cb0ef41Sopenharmony_ci    ConvertReceiverMode receiver_mode, TNode<Object>, TNode<Object>,
7751cb0ef41Sopenharmony_ci    TNode<Object>);
7761cb0ef41Sopenharmony_ci
7771cb0ef41Sopenharmony_civoid InterpreterAssembler::CallJSWithSpreadAndDispatch(
7781cb0ef41Sopenharmony_ci    TNode<Object> function, TNode<Context> context, const RegListNodePair& args,
7791cb0ef41Sopenharmony_ci    TNode<UintPtrT> slot_id, TNode<HeapObject> maybe_feedback_vector) {
7801cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
7811cb0ef41Sopenharmony_ci  DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), ConvertReceiverMode::kAny);
7821cb0ef41Sopenharmony_ci  LazyNode<Object> receiver = [=] { return LoadRegisterAtOperandIndex(1); };
7831cb0ef41Sopenharmony_ci  CollectCallFeedback(function, receiver, context, maybe_feedback_vector,
7841cb0ef41Sopenharmony_ci                      slot_id);
7851cb0ef41Sopenharmony_ci  Comment("call using CallWithSpread builtin");
7861cb0ef41Sopenharmony_ci  Callable callable = CodeFactory::InterpreterPushArgsThenCall(
7871cb0ef41Sopenharmony_ci      isolate(), ConvertReceiverMode::kAny,
7881cb0ef41Sopenharmony_ci      InterpreterPushArgsMode::kWithFinalSpread);
7891cb0ef41Sopenharmony_ci  TNode<CodeT> code_target = HeapConstant(callable.code());
7901cb0ef41Sopenharmony_ci
7911cb0ef41Sopenharmony_ci  TNode<Word32T> args_count = args.reg_count();
7921cb0ef41Sopenharmony_ci  TailCallStubThenBytecodeDispatch(callable.descriptor(), code_target, context,
7931cb0ef41Sopenharmony_ci                                   args_count, args.base_reg_location(),
7941cb0ef41Sopenharmony_ci                                   function);
7951cb0ef41Sopenharmony_ci  // TailCallStubThenDispatch updates accumulator with result.
7961cb0ef41Sopenharmony_ci  implicit_register_use_ =
7971cb0ef41Sopenharmony_ci      implicit_register_use_ | ImplicitRegisterUse::kWriteAccumulator;
7981cb0ef41Sopenharmony_ci}
7991cb0ef41Sopenharmony_ci
8001cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::Construct(
8011cb0ef41Sopenharmony_ci    TNode<Object> target, TNode<Context> context, TNode<Object> new_target,
8021cb0ef41Sopenharmony_ci    const RegListNodePair& args, TNode<UintPtrT> slot_id,
8031cb0ef41Sopenharmony_ci    TNode<HeapObject> maybe_feedback_vector) {
8041cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
8051cb0ef41Sopenharmony_ci  TVARIABLE(Object, var_result);
8061cb0ef41Sopenharmony_ci  TVARIABLE(AllocationSite, var_site);
8071cb0ef41Sopenharmony_ci  Label return_result(this), construct_generic(this),
8081cb0ef41Sopenharmony_ci      construct_array(this, &var_site);
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci  TNode<Word32T> args_count = JSParameterCount(args.reg_count());
8111cb0ef41Sopenharmony_ci  CollectConstructFeedback(context, target, new_target, maybe_feedback_vector,
8121cb0ef41Sopenharmony_ci                           slot_id, UpdateFeedbackMode::kOptionalFeedback,
8131cb0ef41Sopenharmony_ci                           &construct_generic, &construct_array, &var_site);
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_ci  BIND(&construct_generic);
8161cb0ef41Sopenharmony_ci  {
8171cb0ef41Sopenharmony_ci    // TODO(bmeurer): Remove the generic type_info parameter from the Construct.
8181cb0ef41Sopenharmony_ci    Comment("call using Construct builtin");
8191cb0ef41Sopenharmony_ci    Callable callable = CodeFactory::InterpreterPushArgsThenConstruct(
8201cb0ef41Sopenharmony_ci        isolate(), InterpreterPushArgsMode::kOther);
8211cb0ef41Sopenharmony_ci    var_result =
8221cb0ef41Sopenharmony_ci        CallStub(callable, context, args_count, args.base_reg_location(),
8231cb0ef41Sopenharmony_ci                 target, new_target, UndefinedConstant());
8241cb0ef41Sopenharmony_ci    Goto(&return_result);
8251cb0ef41Sopenharmony_ci  }
8261cb0ef41Sopenharmony_ci
8271cb0ef41Sopenharmony_ci  BIND(&construct_array);
8281cb0ef41Sopenharmony_ci  {
8291cb0ef41Sopenharmony_ci    // TODO(bmeurer): Introduce a dedicated builtin to deal with the Array
8301cb0ef41Sopenharmony_ci    // constructor feedback collection inside of Ignition.
8311cb0ef41Sopenharmony_ci    Comment("call using ConstructArray builtin");
8321cb0ef41Sopenharmony_ci    Callable callable = CodeFactory::InterpreterPushArgsThenConstruct(
8331cb0ef41Sopenharmony_ci        isolate(), InterpreterPushArgsMode::kArrayFunction);
8341cb0ef41Sopenharmony_ci    var_result =
8351cb0ef41Sopenharmony_ci        CallStub(callable, context, args_count, args.base_reg_location(),
8361cb0ef41Sopenharmony_ci                 target, new_target, var_site.value());
8371cb0ef41Sopenharmony_ci    Goto(&return_result);
8381cb0ef41Sopenharmony_ci  }
8391cb0ef41Sopenharmony_ci
8401cb0ef41Sopenharmony_ci  BIND(&return_result);
8411cb0ef41Sopenharmony_ci  return var_result.value();
8421cb0ef41Sopenharmony_ci}
8431cb0ef41Sopenharmony_ci
8441cb0ef41Sopenharmony_ciTNode<Object> InterpreterAssembler::ConstructWithSpread(
8451cb0ef41Sopenharmony_ci    TNode<Object> target, TNode<Context> context, TNode<Object> new_target,
8461cb0ef41Sopenharmony_ci    const RegListNodePair& args, TNode<UintPtrT> slot_id,
8471cb0ef41Sopenharmony_ci    TNode<HeapObject> maybe_feedback_vector) {
8481cb0ef41Sopenharmony_ci  // TODO(bmeurer): Unify this with the Construct bytecode feedback
8491cb0ef41Sopenharmony_ci  // above once we have a way to pass the AllocationSite to the Array
8501cb0ef41Sopenharmony_ci  // constructor _and_ spread the last argument at the same time.
8511cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
8521cb0ef41Sopenharmony_ci  Label extra_checks(this, Label::kDeferred), construct(this);
8531cb0ef41Sopenharmony_ci  GotoIf(IsUndefined(maybe_feedback_vector), &construct);
8541cb0ef41Sopenharmony_ci
8551cb0ef41Sopenharmony_ci  TNode<FeedbackVector> feedback_vector = CAST(maybe_feedback_vector);
8561cb0ef41Sopenharmony_ci
8571cb0ef41Sopenharmony_ci  // Increment the call count.
8581cb0ef41Sopenharmony_ci  IncrementCallCount(feedback_vector, slot_id);
8591cb0ef41Sopenharmony_ci
8601cb0ef41Sopenharmony_ci  // Check if we have monomorphic {new_target} feedback already.
8611cb0ef41Sopenharmony_ci  TNode<MaybeObject> feedback =
8621cb0ef41Sopenharmony_ci      LoadFeedbackVectorSlot(feedback_vector, slot_id);
8631cb0ef41Sopenharmony_ci  Branch(IsWeakReferenceToObject(feedback, new_target), &construct,
8641cb0ef41Sopenharmony_ci         &extra_checks);
8651cb0ef41Sopenharmony_ci
8661cb0ef41Sopenharmony_ci  BIND(&extra_checks);
8671cb0ef41Sopenharmony_ci  {
8681cb0ef41Sopenharmony_ci    Label check_initialized(this), initialize(this), mark_megamorphic(this);
8691cb0ef41Sopenharmony_ci
8701cb0ef41Sopenharmony_ci    // Check if it is a megamorphic {new_target}.
8711cb0ef41Sopenharmony_ci    Comment("check if megamorphic");
8721cb0ef41Sopenharmony_ci    TNode<BoolT> is_megamorphic = TaggedEqual(
8731cb0ef41Sopenharmony_ci        feedback, HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())));
8741cb0ef41Sopenharmony_ci    GotoIf(is_megamorphic, &construct);
8751cb0ef41Sopenharmony_ci
8761cb0ef41Sopenharmony_ci    Comment("check if weak reference");
8771cb0ef41Sopenharmony_ci    GotoIfNot(IsWeakOrCleared(feedback), &check_initialized);
8781cb0ef41Sopenharmony_ci
8791cb0ef41Sopenharmony_ci    // If the weak reference is cleared, we have a new chance to become
8801cb0ef41Sopenharmony_ci    // monomorphic.
8811cb0ef41Sopenharmony_ci    Comment("check if weak reference is cleared");
8821cb0ef41Sopenharmony_ci    Branch(IsCleared(feedback), &initialize, &mark_megamorphic);
8831cb0ef41Sopenharmony_ci
8841cb0ef41Sopenharmony_ci    BIND(&check_initialized);
8851cb0ef41Sopenharmony_ci    {
8861cb0ef41Sopenharmony_ci      // Check if it is uninitialized.
8871cb0ef41Sopenharmony_ci      Comment("check if uninitialized");
8881cb0ef41Sopenharmony_ci      TNode<BoolT> is_uninitialized =
8891cb0ef41Sopenharmony_ci          TaggedEqual(feedback, UninitializedSymbolConstant());
8901cb0ef41Sopenharmony_ci      Branch(is_uninitialized, &initialize, &mark_megamorphic);
8911cb0ef41Sopenharmony_ci    }
8921cb0ef41Sopenharmony_ci
8931cb0ef41Sopenharmony_ci    BIND(&initialize);
8941cb0ef41Sopenharmony_ci    {
8951cb0ef41Sopenharmony_ci      Comment("check if function in same native context");
8961cb0ef41Sopenharmony_ci      GotoIf(TaggedIsSmi(new_target), &mark_megamorphic);
8971cb0ef41Sopenharmony_ci      // Check if the {new_target} is a JSFunction or JSBoundFunction
8981cb0ef41Sopenharmony_ci      // in the current native context.
8991cb0ef41Sopenharmony_ci      TVARIABLE(HeapObject, var_current, CAST(new_target));
9001cb0ef41Sopenharmony_ci      Label loop(this, &var_current), done_loop(this);
9011cb0ef41Sopenharmony_ci      Goto(&loop);
9021cb0ef41Sopenharmony_ci      BIND(&loop);
9031cb0ef41Sopenharmony_ci      {
9041cb0ef41Sopenharmony_ci        Label if_boundfunction(this), if_function(this);
9051cb0ef41Sopenharmony_ci        TNode<HeapObject> current = var_current.value();
9061cb0ef41Sopenharmony_ci        TNode<Uint16T> current_instance_type = LoadInstanceType(current);
9071cb0ef41Sopenharmony_ci        GotoIf(InstanceTypeEqual(current_instance_type, JS_BOUND_FUNCTION_TYPE),
9081cb0ef41Sopenharmony_ci               &if_boundfunction);
9091cb0ef41Sopenharmony_ci        Branch(IsJSFunctionInstanceType(current_instance_type), &if_function,
9101cb0ef41Sopenharmony_ci               &mark_megamorphic);
9111cb0ef41Sopenharmony_ci
9121cb0ef41Sopenharmony_ci        BIND(&if_function);
9131cb0ef41Sopenharmony_ci        {
9141cb0ef41Sopenharmony_ci          // Check that the JSFunction {current} is in the current native
9151cb0ef41Sopenharmony_ci          // context.
9161cb0ef41Sopenharmony_ci          TNode<Context> current_context =
9171cb0ef41Sopenharmony_ci              CAST(LoadObjectField(current, JSFunction::kContextOffset));
9181cb0ef41Sopenharmony_ci          TNode<NativeContext> current_native_context =
9191cb0ef41Sopenharmony_ci              LoadNativeContext(current_context);
9201cb0ef41Sopenharmony_ci          Branch(
9211cb0ef41Sopenharmony_ci              TaggedEqual(LoadNativeContext(context), current_native_context),
9221cb0ef41Sopenharmony_ci              &done_loop, &mark_megamorphic);
9231cb0ef41Sopenharmony_ci        }
9241cb0ef41Sopenharmony_ci
9251cb0ef41Sopenharmony_ci        BIND(&if_boundfunction);
9261cb0ef41Sopenharmony_ci        {
9271cb0ef41Sopenharmony_ci          // Continue with the [[BoundTargetFunction]] of {current}.
9281cb0ef41Sopenharmony_ci          var_current = LoadObjectField<HeapObject>(
9291cb0ef41Sopenharmony_ci              current, JSBoundFunction::kBoundTargetFunctionOffset);
9301cb0ef41Sopenharmony_ci          Goto(&loop);
9311cb0ef41Sopenharmony_ci        }
9321cb0ef41Sopenharmony_ci      }
9331cb0ef41Sopenharmony_ci      BIND(&done_loop);
9341cb0ef41Sopenharmony_ci      StoreWeakReferenceInFeedbackVector(feedback_vector, slot_id,
9351cb0ef41Sopenharmony_ci                                         CAST(new_target));
9361cb0ef41Sopenharmony_ci      ReportFeedbackUpdate(feedback_vector, slot_id,
9371cb0ef41Sopenharmony_ci                           "ConstructWithSpread:Initialize");
9381cb0ef41Sopenharmony_ci      Goto(&construct);
9391cb0ef41Sopenharmony_ci    }
9401cb0ef41Sopenharmony_ci
9411cb0ef41Sopenharmony_ci    BIND(&mark_megamorphic);
9421cb0ef41Sopenharmony_ci    {
9431cb0ef41Sopenharmony_ci      // MegamorphicSentinel is an immortal immovable object so
9441cb0ef41Sopenharmony_ci      // write-barrier is not needed.
9451cb0ef41Sopenharmony_ci      Comment("transition to megamorphic");
9461cb0ef41Sopenharmony_ci      DCHECK(RootsTable::IsImmortalImmovable(RootIndex::kmegamorphic_symbol));
9471cb0ef41Sopenharmony_ci      StoreFeedbackVectorSlot(
9481cb0ef41Sopenharmony_ci          feedback_vector, slot_id,
9491cb0ef41Sopenharmony_ci          HeapConstant(FeedbackVector::MegamorphicSentinel(isolate())),
9501cb0ef41Sopenharmony_ci          SKIP_WRITE_BARRIER);
9511cb0ef41Sopenharmony_ci      ReportFeedbackUpdate(feedback_vector, slot_id,
9521cb0ef41Sopenharmony_ci                           "ConstructWithSpread:TransitionMegamorphic");
9531cb0ef41Sopenharmony_ci      Goto(&construct);
9541cb0ef41Sopenharmony_ci    }
9551cb0ef41Sopenharmony_ci  }
9561cb0ef41Sopenharmony_ci
9571cb0ef41Sopenharmony_ci  BIND(&construct);
9581cb0ef41Sopenharmony_ci  Comment("call using ConstructWithSpread builtin");
9591cb0ef41Sopenharmony_ci  Callable callable = CodeFactory::InterpreterPushArgsThenConstruct(
9601cb0ef41Sopenharmony_ci      isolate(), InterpreterPushArgsMode::kWithFinalSpread);
9611cb0ef41Sopenharmony_ci  TNode<Word32T> args_count = JSParameterCount(args.reg_count());
9621cb0ef41Sopenharmony_ci  return CallStub(callable, context, args_count, args.base_reg_location(),
9631cb0ef41Sopenharmony_ci                  target, new_target, UndefinedConstant());
9641cb0ef41Sopenharmony_ci}
9651cb0ef41Sopenharmony_ci
9661cb0ef41Sopenharmony_citemplate <class T>
9671cb0ef41Sopenharmony_ciTNode<T> InterpreterAssembler::CallRuntimeN(TNode<Uint32T> function_id,
9681cb0ef41Sopenharmony_ci                                            TNode<Context> context,
9691cb0ef41Sopenharmony_ci                                            const RegListNodePair& args,
9701cb0ef41Sopenharmony_ci                                            int return_count) {
9711cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
9721cb0ef41Sopenharmony_ci  DCHECK(Bytecodes::IsCallRuntime(bytecode_));
9731cb0ef41Sopenharmony_ci  Callable callable = CodeFactory::InterpreterCEntry(isolate(), return_count);
9741cb0ef41Sopenharmony_ci  TNode<CodeT> code_target = HeapConstant(callable.code());
9751cb0ef41Sopenharmony_ci
9761cb0ef41Sopenharmony_ci  // Get the function entry from the function id.
9771cb0ef41Sopenharmony_ci  TNode<RawPtrT> function_table = ReinterpretCast<RawPtrT>(ExternalConstant(
9781cb0ef41Sopenharmony_ci      ExternalReference::runtime_function_table_address(isolate())));
9791cb0ef41Sopenharmony_ci  TNode<Word32T> function_offset =
9801cb0ef41Sopenharmony_ci      Int32Mul(function_id, Int32Constant(sizeof(Runtime::Function)));
9811cb0ef41Sopenharmony_ci  TNode<WordT> function =
9821cb0ef41Sopenharmony_ci      IntPtrAdd(function_table, ChangeUint32ToWord(function_offset));
9831cb0ef41Sopenharmony_ci  TNode<RawPtrT> function_entry = Load<RawPtrT>(
9841cb0ef41Sopenharmony_ci      function, IntPtrConstant(offsetof(Runtime::Function, entry)));
9851cb0ef41Sopenharmony_ci
9861cb0ef41Sopenharmony_ci  return CallStub<T>(callable.descriptor(), code_target, context,
9871cb0ef41Sopenharmony_ci                     args.reg_count(), args.base_reg_location(),
9881cb0ef41Sopenharmony_ci                     function_entry);
9891cb0ef41Sopenharmony_ci}
9901cb0ef41Sopenharmony_ci
9911cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE TNode<Object> InterpreterAssembler::CallRuntimeN(
9921cb0ef41Sopenharmony_ci    TNode<Uint32T> function_id, TNode<Context> context,
9931cb0ef41Sopenharmony_ci    const RegListNodePair& args, int return_count);
9941cb0ef41Sopenharmony_citemplate V8_EXPORT_PRIVATE TNode<PairT<Object, Object>>
9951cb0ef41Sopenharmony_ciInterpreterAssembler::CallRuntimeN(TNode<Uint32T> function_id,
9961cb0ef41Sopenharmony_ci                                   TNode<Context> context,
9971cb0ef41Sopenharmony_ci                                   const RegListNodePair& args,
9981cb0ef41Sopenharmony_ci                                   int return_count);
9991cb0ef41Sopenharmony_ci
10001cb0ef41Sopenharmony_civoid InterpreterAssembler::UpdateInterruptBudget(TNode<Int32T> weight,
10011cb0ef41Sopenharmony_ci                                                 bool backward) {
10021cb0ef41Sopenharmony_ci  Comment("[ UpdateInterruptBudget");
10031cb0ef41Sopenharmony_ci
10041cb0ef41Sopenharmony_ci  // Assert that the weight is positive (negative weights should be implemented
10051cb0ef41Sopenharmony_ci  // as backward updates).
10061cb0ef41Sopenharmony_ci  CSA_DCHECK(this, Int32GreaterThanOrEqual(weight, Int32Constant(0)));
10071cb0ef41Sopenharmony_ci
10081cb0ef41Sopenharmony_ci  Label load_budget_from_bytecode(this), load_budget_done(this);
10091cb0ef41Sopenharmony_ci  TNode<JSFunction> function = CAST(LoadRegister(Register::function_closure()));
10101cb0ef41Sopenharmony_ci  TNode<FeedbackCell> feedback_cell =
10111cb0ef41Sopenharmony_ci      LoadObjectField<FeedbackCell>(function, JSFunction::kFeedbackCellOffset);
10121cb0ef41Sopenharmony_ci  TNode<Int32T> old_budget = LoadObjectField<Int32T>(
10131cb0ef41Sopenharmony_ci      feedback_cell, FeedbackCell::kInterruptBudgetOffset);
10141cb0ef41Sopenharmony_ci
10151cb0ef41Sopenharmony_ci  // Make sure we include the current bytecode in the budget calculation.
10161cb0ef41Sopenharmony_ci  TNode<Int32T> budget_after_bytecode =
10171cb0ef41Sopenharmony_ci      Int32Sub(old_budget, Int32Constant(CurrentBytecodeSize()));
10181cb0ef41Sopenharmony_ci
10191cb0ef41Sopenharmony_ci  Label done(this);
10201cb0ef41Sopenharmony_ci  TVARIABLE(Int32T, new_budget);
10211cb0ef41Sopenharmony_ci  if (backward) {
10221cb0ef41Sopenharmony_ci    // Update budget by |weight| and check if it reaches zero.
10231cb0ef41Sopenharmony_ci    new_budget = Int32Sub(budget_after_bytecode, weight);
10241cb0ef41Sopenharmony_ci    TNode<BoolT> condition =
10251cb0ef41Sopenharmony_ci        Int32GreaterThanOrEqual(new_budget.value(), Int32Constant(0));
10261cb0ef41Sopenharmony_ci    Label ok(this), interrupt_check(this, Label::kDeferred);
10271cb0ef41Sopenharmony_ci    Branch(condition, &ok, &interrupt_check);
10281cb0ef41Sopenharmony_ci
10291cb0ef41Sopenharmony_ci    BIND(&interrupt_check);
10301cb0ef41Sopenharmony_ci    // JumpLoop should do a stack check as part of the interrupt.
10311cb0ef41Sopenharmony_ci    CallRuntime(bytecode() == Bytecode::kJumpLoop
10321cb0ef41Sopenharmony_ci                    ? Runtime::kBytecodeBudgetInterruptWithStackCheck
10331cb0ef41Sopenharmony_ci                    : Runtime::kBytecodeBudgetInterrupt,
10341cb0ef41Sopenharmony_ci                GetContext(), function);
10351cb0ef41Sopenharmony_ci    Goto(&done);
10361cb0ef41Sopenharmony_ci
10371cb0ef41Sopenharmony_ci    BIND(&ok);
10381cb0ef41Sopenharmony_ci  } else {
10391cb0ef41Sopenharmony_ci    // For a forward jump, we know we only increase the interrupt budget, so
10401cb0ef41Sopenharmony_ci    // no need to check if it's below zero.
10411cb0ef41Sopenharmony_ci    new_budget = Int32Add(budget_after_bytecode, weight);
10421cb0ef41Sopenharmony_ci  }
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci  // Update budget.
10451cb0ef41Sopenharmony_ci  StoreObjectFieldNoWriteBarrier(
10461cb0ef41Sopenharmony_ci      feedback_cell, FeedbackCell::kInterruptBudgetOffset, new_budget.value());
10471cb0ef41Sopenharmony_ci  Goto(&done);
10481cb0ef41Sopenharmony_ci  BIND(&done);
10491cb0ef41Sopenharmony_ci  Comment("] UpdateInterruptBudget");
10501cb0ef41Sopenharmony_ci}
10511cb0ef41Sopenharmony_ci
10521cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::Advance() {
10531cb0ef41Sopenharmony_ci  return Advance(CurrentBytecodeSize());
10541cb0ef41Sopenharmony_ci}
10551cb0ef41Sopenharmony_ci
10561cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::Advance(int delta) {
10571cb0ef41Sopenharmony_ci  return Advance(IntPtrConstant(delta));
10581cb0ef41Sopenharmony_ci}
10591cb0ef41Sopenharmony_ci
10601cb0ef41Sopenharmony_ciTNode<IntPtrT> InterpreterAssembler::Advance(TNode<IntPtrT> delta,
10611cb0ef41Sopenharmony_ci                                             bool backward) {
10621cb0ef41Sopenharmony_ci#ifdef V8_TRACE_UNOPTIMIZED
10631cb0ef41Sopenharmony_ci  TraceBytecode(Runtime::kTraceUnoptimizedBytecodeExit);
10641cb0ef41Sopenharmony_ci#endif
10651cb0ef41Sopenharmony_ci  TNode<IntPtrT> next_offset = backward ? IntPtrSub(BytecodeOffset(), delta)
10661cb0ef41Sopenharmony_ci                                        : IntPtrAdd(BytecodeOffset(), delta);
10671cb0ef41Sopenharmony_ci  bytecode_offset_ = next_offset;
10681cb0ef41Sopenharmony_ci  return next_offset;
10691cb0ef41Sopenharmony_ci}
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_civoid InterpreterAssembler::Jump(TNode<IntPtrT> jump_offset, bool backward) {
10721cb0ef41Sopenharmony_ci  DCHECK(!Bytecodes::IsStarLookahead(bytecode_, operand_scale_));
10731cb0ef41Sopenharmony_ci
10741cb0ef41Sopenharmony_ci  UpdateInterruptBudget(TruncateIntPtrToInt32(jump_offset), backward);
10751cb0ef41Sopenharmony_ci  TNode<IntPtrT> new_bytecode_offset = Advance(jump_offset, backward);
10761cb0ef41Sopenharmony_ci  TNode<RawPtrT> target_bytecode =
10771cb0ef41Sopenharmony_ci      UncheckedCast<RawPtrT>(LoadBytecode(new_bytecode_offset));
10781cb0ef41Sopenharmony_ci  DispatchToBytecode(target_bytecode, new_bytecode_offset);
10791cb0ef41Sopenharmony_ci}
10801cb0ef41Sopenharmony_ci
10811cb0ef41Sopenharmony_civoid InterpreterAssembler::Jump(TNode<IntPtrT> jump_offset) {
10821cb0ef41Sopenharmony_ci  Jump(jump_offset, false);
10831cb0ef41Sopenharmony_ci}
10841cb0ef41Sopenharmony_ci
10851cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpBackward(TNode<IntPtrT> jump_offset) {
10861cb0ef41Sopenharmony_ci  Jump(jump_offset, true);
10871cb0ef41Sopenharmony_ci}
10881cb0ef41Sopenharmony_ci
10891cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpConditional(TNode<BoolT> condition,
10901cb0ef41Sopenharmony_ci                                           TNode<IntPtrT> jump_offset) {
10911cb0ef41Sopenharmony_ci  Label match(this), no_match(this);
10921cb0ef41Sopenharmony_ci
10931cb0ef41Sopenharmony_ci  Branch(condition, &match, &no_match);
10941cb0ef41Sopenharmony_ci  BIND(&match);
10951cb0ef41Sopenharmony_ci  Jump(jump_offset);
10961cb0ef41Sopenharmony_ci  BIND(&no_match);
10971cb0ef41Sopenharmony_ci  Dispatch();
10981cb0ef41Sopenharmony_ci}
10991cb0ef41Sopenharmony_ci
11001cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpConditionalByImmediateOperand(
11011cb0ef41Sopenharmony_ci    TNode<BoolT> condition, int operand_index) {
11021cb0ef41Sopenharmony_ci  Label match(this), no_match(this);
11031cb0ef41Sopenharmony_ci
11041cb0ef41Sopenharmony_ci  Branch(condition, &match, &no_match);
11051cb0ef41Sopenharmony_ci  BIND(&match);
11061cb0ef41Sopenharmony_ci  TNode<IntPtrT> jump_offset = Signed(BytecodeOperandUImmWord(operand_index));
11071cb0ef41Sopenharmony_ci  Jump(jump_offset);
11081cb0ef41Sopenharmony_ci  BIND(&no_match);
11091cb0ef41Sopenharmony_ci  Dispatch();
11101cb0ef41Sopenharmony_ci}
11111cb0ef41Sopenharmony_ci
11121cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpConditionalByConstantOperand(
11131cb0ef41Sopenharmony_ci    TNode<BoolT> condition, int operand_index) {
11141cb0ef41Sopenharmony_ci  Label match(this), no_match(this);
11151cb0ef41Sopenharmony_ci
11161cb0ef41Sopenharmony_ci  Branch(condition, &match, &no_match);
11171cb0ef41Sopenharmony_ci  BIND(&match);
11181cb0ef41Sopenharmony_ci  TNode<IntPtrT> jump_offset =
11191cb0ef41Sopenharmony_ci      LoadAndUntagConstantPoolEntryAtOperandIndex(operand_index);
11201cb0ef41Sopenharmony_ci  Jump(jump_offset);
11211cb0ef41Sopenharmony_ci  BIND(&no_match);
11221cb0ef41Sopenharmony_ci  Dispatch();
11231cb0ef41Sopenharmony_ci}
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpIfTaggedEqual(TNode<Object> lhs,
11261cb0ef41Sopenharmony_ci                                             TNode<Object> rhs,
11271cb0ef41Sopenharmony_ci                                             TNode<IntPtrT> jump_offset) {
11281cb0ef41Sopenharmony_ci  JumpConditional(TaggedEqual(lhs, rhs), jump_offset);
11291cb0ef41Sopenharmony_ci}
11301cb0ef41Sopenharmony_ci
11311cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpIfTaggedEqual(TNode<Object> lhs,
11321cb0ef41Sopenharmony_ci                                             TNode<Object> rhs,
11331cb0ef41Sopenharmony_ci                                             int operand_index) {
11341cb0ef41Sopenharmony_ci  JumpConditionalByImmediateOperand(TaggedEqual(lhs, rhs), operand_index);
11351cb0ef41Sopenharmony_ci}
11361cb0ef41Sopenharmony_ci
11371cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpIfTaggedEqualConstant(TNode<Object> lhs,
11381cb0ef41Sopenharmony_ci                                                     TNode<Object> rhs,
11391cb0ef41Sopenharmony_ci                                                     int operand_index) {
11401cb0ef41Sopenharmony_ci  JumpConditionalByConstantOperand(TaggedEqual(lhs, rhs), operand_index);
11411cb0ef41Sopenharmony_ci}
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpIfTaggedNotEqual(TNode<Object> lhs,
11441cb0ef41Sopenharmony_ci                                                TNode<Object> rhs,
11451cb0ef41Sopenharmony_ci                                                TNode<IntPtrT> jump_offset) {
11461cb0ef41Sopenharmony_ci  JumpConditional(TaggedNotEqual(lhs, rhs), jump_offset);
11471cb0ef41Sopenharmony_ci}
11481cb0ef41Sopenharmony_ci
11491cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpIfTaggedNotEqual(TNode<Object> lhs,
11501cb0ef41Sopenharmony_ci                                                TNode<Object> rhs,
11511cb0ef41Sopenharmony_ci                                                int operand_index) {
11521cb0ef41Sopenharmony_ci  JumpConditionalByImmediateOperand(TaggedNotEqual(lhs, rhs), operand_index);
11531cb0ef41Sopenharmony_ci}
11541cb0ef41Sopenharmony_ci
11551cb0ef41Sopenharmony_civoid InterpreterAssembler::JumpIfTaggedNotEqualConstant(TNode<Object> lhs,
11561cb0ef41Sopenharmony_ci                                                        TNode<Object> rhs,
11571cb0ef41Sopenharmony_ci                                                        int operand_index) {
11581cb0ef41Sopenharmony_ci  JumpConditionalByConstantOperand(TaggedNotEqual(lhs, rhs), operand_index);
11591cb0ef41Sopenharmony_ci}
11601cb0ef41Sopenharmony_ci
11611cb0ef41Sopenharmony_ciTNode<WordT> InterpreterAssembler::LoadBytecode(
11621cb0ef41Sopenharmony_ci    TNode<IntPtrT> bytecode_offset) {
11631cb0ef41Sopenharmony_ci  TNode<Uint8T> bytecode =
11641cb0ef41Sopenharmony_ci      Load<Uint8T>(BytecodeArrayTaggedPointer(), bytecode_offset);
11651cb0ef41Sopenharmony_ci  return ChangeUint32ToWord(bytecode);
11661cb0ef41Sopenharmony_ci}
11671cb0ef41Sopenharmony_ci
11681cb0ef41Sopenharmony_civoid InterpreterAssembler::StarDispatchLookahead(TNode<WordT> target_bytecode) {
11691cb0ef41Sopenharmony_ci  Label do_inline_star(this), done(this);
11701cb0ef41Sopenharmony_ci
11711cb0ef41Sopenharmony_ci  // Check whether the following opcode is one of the short Star codes. All
11721cb0ef41Sopenharmony_ci  // opcodes higher than the short Star variants are invalid, and invalid
11731cb0ef41Sopenharmony_ci  // opcodes are never deliberately written, so we can use a one-sided check.
11741cb0ef41Sopenharmony_ci  // This is no less secure than the normal-length Star handler, which performs
11751cb0ef41Sopenharmony_ci  // no validation on its operand.
11761cb0ef41Sopenharmony_ci  STATIC_ASSERT(static_cast<int>(Bytecode::kLastShortStar) + 1 ==
11771cb0ef41Sopenharmony_ci                static_cast<int>(Bytecode::kIllegal));
11781cb0ef41Sopenharmony_ci  STATIC_ASSERT(Bytecode::kIllegal == Bytecode::kLast);
11791cb0ef41Sopenharmony_ci  TNode<Int32T> first_short_star_bytecode =
11801cb0ef41Sopenharmony_ci      Int32Constant(static_cast<int>(Bytecode::kFirstShortStar));
11811cb0ef41Sopenharmony_ci  TNode<BoolT> is_star = Uint32GreaterThanOrEqual(
11821cb0ef41Sopenharmony_ci      TruncateWordToInt32(target_bytecode), first_short_star_bytecode);
11831cb0ef41Sopenharmony_ci  Branch(is_star, &do_inline_star, &done);
11841cb0ef41Sopenharmony_ci
11851cb0ef41Sopenharmony_ci  BIND(&do_inline_star);
11861cb0ef41Sopenharmony_ci  {
11871cb0ef41Sopenharmony_ci    InlineShortStar(target_bytecode);
11881cb0ef41Sopenharmony_ci
11891cb0ef41Sopenharmony_ci    // Rather than merging control flow to a single indirect jump, we can get
11901cb0ef41Sopenharmony_ci    // better branch prediction by duplicating it. This is because the
11911cb0ef41Sopenharmony_ci    // instruction following a merged X + StarN is a bad predictor of the
11921cb0ef41Sopenharmony_ci    // instruction following a non-merged X, and vice versa.
11931cb0ef41Sopenharmony_ci    DispatchToBytecode(LoadBytecode(BytecodeOffset()), BytecodeOffset());
11941cb0ef41Sopenharmony_ci  }
11951cb0ef41Sopenharmony_ci  BIND(&done);
11961cb0ef41Sopenharmony_ci}
11971cb0ef41Sopenharmony_ci
11981cb0ef41Sopenharmony_civoid InterpreterAssembler::InlineShortStar(TNode<WordT> target_bytecode) {
11991cb0ef41Sopenharmony_ci  Bytecode previous_bytecode = bytecode_;
12001cb0ef41Sopenharmony_ci  ImplicitRegisterUse previous_acc_use = implicit_register_use_;
12011cb0ef41Sopenharmony_ci
12021cb0ef41Sopenharmony_ci  // At this point we don't know statically what bytecode we're executing, but
12031cb0ef41Sopenharmony_ci  // kStar0 has the right attributes (namely, no operands) for any of the short
12041cb0ef41Sopenharmony_ci  // Star codes.
12051cb0ef41Sopenharmony_ci  bytecode_ = Bytecode::kStar0;
12061cb0ef41Sopenharmony_ci  implicit_register_use_ = ImplicitRegisterUse::kNone;
12071cb0ef41Sopenharmony_ci
12081cb0ef41Sopenharmony_ci#ifdef V8_TRACE_UNOPTIMIZED
12091cb0ef41Sopenharmony_ci  TraceBytecode(Runtime::kTraceUnoptimizedBytecodeEntry);
12101cb0ef41Sopenharmony_ci#endif
12111cb0ef41Sopenharmony_ci
12121cb0ef41Sopenharmony_ci  StoreRegisterForShortStar(GetAccumulator(), target_bytecode);
12131cb0ef41Sopenharmony_ci
12141cb0ef41Sopenharmony_ci  DCHECK_EQ(implicit_register_use_,
12151cb0ef41Sopenharmony_ci            Bytecodes::GetImplicitRegisterUse(bytecode_));
12161cb0ef41Sopenharmony_ci
12171cb0ef41Sopenharmony_ci  Advance();
12181cb0ef41Sopenharmony_ci  bytecode_ = previous_bytecode;
12191cb0ef41Sopenharmony_ci  implicit_register_use_ = previous_acc_use;
12201cb0ef41Sopenharmony_ci}
12211cb0ef41Sopenharmony_ci
12221cb0ef41Sopenharmony_civoid InterpreterAssembler::Dispatch() {
12231cb0ef41Sopenharmony_ci  Comment("========= Dispatch");
12241cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(Bytecodes::MakesCallAlongCriticalPath(bytecode_), made_call_);
12251cb0ef41Sopenharmony_ci  TNode<IntPtrT> target_offset = Advance();
12261cb0ef41Sopenharmony_ci  TNode<WordT> target_bytecode = LoadBytecode(target_offset);
12271cb0ef41Sopenharmony_ci  DispatchToBytecodeWithOptionalStarLookahead(target_bytecode);
12281cb0ef41Sopenharmony_ci}
12291cb0ef41Sopenharmony_ci
12301cb0ef41Sopenharmony_civoid InterpreterAssembler::DispatchToBytecodeWithOptionalStarLookahead(
12311cb0ef41Sopenharmony_ci    TNode<WordT> target_bytecode) {
12321cb0ef41Sopenharmony_ci  if (Bytecodes::IsStarLookahead(bytecode_, operand_scale_)) {
12331cb0ef41Sopenharmony_ci    StarDispatchLookahead(target_bytecode);
12341cb0ef41Sopenharmony_ci  }
12351cb0ef41Sopenharmony_ci  DispatchToBytecode(target_bytecode, BytecodeOffset());
12361cb0ef41Sopenharmony_ci}
12371cb0ef41Sopenharmony_ci
12381cb0ef41Sopenharmony_civoid InterpreterAssembler::DispatchToBytecode(
12391cb0ef41Sopenharmony_ci    TNode<WordT> target_bytecode, TNode<IntPtrT> new_bytecode_offset) {
12401cb0ef41Sopenharmony_ci  if (V8_IGNITION_DISPATCH_COUNTING_BOOL) {
12411cb0ef41Sopenharmony_ci    TraceBytecodeDispatch(target_bytecode);
12421cb0ef41Sopenharmony_ci  }
12431cb0ef41Sopenharmony_ci
12441cb0ef41Sopenharmony_ci  TNode<RawPtrT> target_code_entry = Load<RawPtrT>(
12451cb0ef41Sopenharmony_ci      DispatchTablePointer(), TimesSystemPointerSize(target_bytecode));
12461cb0ef41Sopenharmony_ci
12471cb0ef41Sopenharmony_ci  DispatchToBytecodeHandlerEntry(target_code_entry, new_bytecode_offset);
12481cb0ef41Sopenharmony_ci}
12491cb0ef41Sopenharmony_ci
12501cb0ef41Sopenharmony_civoid InterpreterAssembler::DispatchToBytecodeHandlerEntry(
12511cb0ef41Sopenharmony_ci    TNode<RawPtrT> handler_entry, TNode<IntPtrT> bytecode_offset) {
12521cb0ef41Sopenharmony_ci  TailCallBytecodeDispatch(
12531cb0ef41Sopenharmony_ci      InterpreterDispatchDescriptor{}, handler_entry, GetAccumulatorUnchecked(),
12541cb0ef41Sopenharmony_ci      bytecode_offset, BytecodeArrayTaggedPointer(), DispatchTablePointer());
12551cb0ef41Sopenharmony_ci}
12561cb0ef41Sopenharmony_ci
12571cb0ef41Sopenharmony_civoid InterpreterAssembler::DispatchWide(OperandScale operand_scale) {
12581cb0ef41Sopenharmony_ci  // Dispatching a wide bytecode requires treating the prefix
12591cb0ef41Sopenharmony_ci  // bytecode a base pointer into the dispatch table and dispatching
12601cb0ef41Sopenharmony_ci  // the bytecode that follows relative to this base.
12611cb0ef41Sopenharmony_ci  //
12621cb0ef41Sopenharmony_ci  //   Indices 0-255 correspond to bytecodes with operand_scale == 0
12631cb0ef41Sopenharmony_ci  //   Indices 256-511 correspond to bytecodes with operand_scale == 1
12641cb0ef41Sopenharmony_ci  //   Indices 512-767 correspond to bytecodes with operand_scale == 2
12651cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(Bytecodes::MakesCallAlongCriticalPath(bytecode_), made_call_);
12661cb0ef41Sopenharmony_ci  TNode<IntPtrT> next_bytecode_offset = Advance(1);
12671cb0ef41Sopenharmony_ci  TNode<WordT> next_bytecode = LoadBytecode(next_bytecode_offset);
12681cb0ef41Sopenharmony_ci
12691cb0ef41Sopenharmony_ci  if (V8_IGNITION_DISPATCH_COUNTING_BOOL) {
12701cb0ef41Sopenharmony_ci    TraceBytecodeDispatch(next_bytecode);
12711cb0ef41Sopenharmony_ci  }
12721cb0ef41Sopenharmony_ci
12731cb0ef41Sopenharmony_ci  TNode<IntPtrT> base_index;
12741cb0ef41Sopenharmony_ci  switch (operand_scale) {
12751cb0ef41Sopenharmony_ci    case OperandScale::kDouble:
12761cb0ef41Sopenharmony_ci      base_index = IntPtrConstant(1 << kBitsPerByte);
12771cb0ef41Sopenharmony_ci      break;
12781cb0ef41Sopenharmony_ci    case OperandScale::kQuadruple:
12791cb0ef41Sopenharmony_ci      base_index = IntPtrConstant(2 << kBitsPerByte);
12801cb0ef41Sopenharmony_ci      break;
12811cb0ef41Sopenharmony_ci    default:
12821cb0ef41Sopenharmony_ci      UNREACHABLE();
12831cb0ef41Sopenharmony_ci  }
12841cb0ef41Sopenharmony_ci  TNode<WordT> target_index = IntPtrAdd(base_index, next_bytecode);
12851cb0ef41Sopenharmony_ci  TNode<RawPtrT> target_code_entry = Load<RawPtrT>(
12861cb0ef41Sopenharmony_ci      DispatchTablePointer(), TimesSystemPointerSize(target_index));
12871cb0ef41Sopenharmony_ci
12881cb0ef41Sopenharmony_ci  DispatchToBytecodeHandlerEntry(target_code_entry, next_bytecode_offset);
12891cb0ef41Sopenharmony_ci}
12901cb0ef41Sopenharmony_ci
12911cb0ef41Sopenharmony_civoid InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
12921cb0ef41Sopenharmony_ci  // TODO(rmcilroy): Investigate whether it is worth supporting self
12931cb0ef41Sopenharmony_ci  // optimization of primitive functions like FullCodegen.
12941cb0ef41Sopenharmony_ci
12951cb0ef41Sopenharmony_ci  // Update profiling count by the number of bytes between the end of the
12961cb0ef41Sopenharmony_ci  // current bytecode and the start of the first one, to simulate backedge to
12971cb0ef41Sopenharmony_ci  // start of function.
12981cb0ef41Sopenharmony_ci  //
12991cb0ef41Sopenharmony_ci  // With headers and current offset, the bytecode array layout looks like:
13001cb0ef41Sopenharmony_ci  //
13011cb0ef41Sopenharmony_ci  //           <---------- simulated backedge ----------
13021cb0ef41Sopenharmony_ci  // | header | first bytecode | .... | return bytecode |
13031cb0ef41Sopenharmony_ci  //  |<------ current offset ------->
13041cb0ef41Sopenharmony_ci  //  ^ tagged bytecode array pointer
13051cb0ef41Sopenharmony_ci  //
13061cb0ef41Sopenharmony_ci  // UpdateInterruptBudget already handles adding the bytecode size to the
13071cb0ef41Sopenharmony_ci  // length of the back-edge, so we just have to correct for the non-zero offset
13081cb0ef41Sopenharmony_ci  // of the first bytecode.
13091cb0ef41Sopenharmony_ci
13101cb0ef41Sopenharmony_ci  TNode<Int32T> profiling_weight =
13111cb0ef41Sopenharmony_ci      Int32Sub(TruncateIntPtrToInt32(BytecodeOffset()),
13121cb0ef41Sopenharmony_ci               Int32Constant(kFirstBytecodeOffset));
13131cb0ef41Sopenharmony_ci  UpdateInterruptBudget(profiling_weight, true);
13141cb0ef41Sopenharmony_ci}
13151cb0ef41Sopenharmony_ci
13161cb0ef41Sopenharmony_ciTNode<Int16T> InterpreterAssembler::LoadOsrUrgencyAndInstallTarget() {
13171cb0ef41Sopenharmony_ci  // We're loading a 16-bit field, mask it.
13181cb0ef41Sopenharmony_ci  return UncheckedCast<Int16T>(Word32And(
13191cb0ef41Sopenharmony_ci      LoadObjectField<Int16T>(BytecodeArrayTaggedPointer(),
13201cb0ef41Sopenharmony_ci                              BytecodeArray::kOsrUrgencyAndInstallTargetOffset),
13211cb0ef41Sopenharmony_ci      0xFFFF));
13221cb0ef41Sopenharmony_ci}
13231cb0ef41Sopenharmony_ci
13241cb0ef41Sopenharmony_civoid InterpreterAssembler::Abort(AbortReason abort_reason) {
13251cb0ef41Sopenharmony_ci  TNode<Smi> abort_id = SmiConstant(abort_reason);
13261cb0ef41Sopenharmony_ci  CallRuntime(Runtime::kAbort, GetContext(), abort_id);
13271cb0ef41Sopenharmony_ci}
13281cb0ef41Sopenharmony_ci
13291cb0ef41Sopenharmony_civoid InterpreterAssembler::AbortIfWordNotEqual(TNode<WordT> lhs,
13301cb0ef41Sopenharmony_ci                                               TNode<WordT> rhs,
13311cb0ef41Sopenharmony_ci                                               AbortReason abort_reason) {
13321cb0ef41Sopenharmony_ci  Label ok(this), abort(this, Label::kDeferred);
13331cb0ef41Sopenharmony_ci  Branch(WordEqual(lhs, rhs), &ok, &abort);
13341cb0ef41Sopenharmony_ci
13351cb0ef41Sopenharmony_ci  BIND(&abort);
13361cb0ef41Sopenharmony_ci  Abort(abort_reason);
13371cb0ef41Sopenharmony_ci  Goto(&ok);
13381cb0ef41Sopenharmony_ci
13391cb0ef41Sopenharmony_ci  BIND(&ok);
13401cb0ef41Sopenharmony_ci}
13411cb0ef41Sopenharmony_ci
13421cb0ef41Sopenharmony_civoid InterpreterAssembler::OnStackReplacement(TNode<Context> context,
13431cb0ef41Sopenharmony_ci                                              TNode<IntPtrT> relative_jump) {
13441cb0ef41Sopenharmony_ci  TNode<JSFunction> function = CAST(LoadRegister(Register::function_closure()));
13451cb0ef41Sopenharmony_ci  TNode<HeapObject> shared_info = LoadJSFunctionSharedFunctionInfo(function);
13461cb0ef41Sopenharmony_ci  TNode<Object> sfi_data =
13471cb0ef41Sopenharmony_ci      LoadObjectField(shared_info, SharedFunctionInfo::kFunctionDataOffset);
13481cb0ef41Sopenharmony_ci  TNode<Uint16T> data_type = LoadInstanceType(CAST(sfi_data));
13491cb0ef41Sopenharmony_ci
13501cb0ef41Sopenharmony_ci  Label baseline(this);
13511cb0ef41Sopenharmony_ci  GotoIf(InstanceTypeEqual(data_type, CODET_TYPE), &baseline);
13521cb0ef41Sopenharmony_ci  {
13531cb0ef41Sopenharmony_ci    Callable callable = CodeFactory::InterpreterOnStackReplacement(isolate());
13541cb0ef41Sopenharmony_ci    CallStub(callable, context);
13551cb0ef41Sopenharmony_ci    JumpBackward(relative_jump);
13561cb0ef41Sopenharmony_ci  }
13571cb0ef41Sopenharmony_ci
13581cb0ef41Sopenharmony_ci  BIND(&baseline);
13591cb0ef41Sopenharmony_ci  {
13601cb0ef41Sopenharmony_ci    Callable callable =
13611cb0ef41Sopenharmony_ci        CodeFactory::InterpreterOnStackReplacement_ToBaseline(isolate());
13621cb0ef41Sopenharmony_ci    // We already compiled the baseline code, so we don't need to handle failed
13631cb0ef41Sopenharmony_ci    // compilation as in the Ignition -> Turbofan case. Therefore we can just
13641cb0ef41Sopenharmony_ci    // tailcall to the OSR builtin.
13651cb0ef41Sopenharmony_ci    SaveBytecodeOffset();
13661cb0ef41Sopenharmony_ci    TailCallStub(callable, context);
13671cb0ef41Sopenharmony_ci  }
13681cb0ef41Sopenharmony_ci}
13691cb0ef41Sopenharmony_ci
13701cb0ef41Sopenharmony_civoid InterpreterAssembler::TraceBytecode(Runtime::FunctionId function_id) {
13711cb0ef41Sopenharmony_ci  CallRuntime(function_id, GetContext(), BytecodeArrayTaggedPointer(),
13721cb0ef41Sopenharmony_ci              SmiTag(BytecodeOffset()), GetAccumulatorUnchecked());
13731cb0ef41Sopenharmony_ci}
13741cb0ef41Sopenharmony_ci
13751cb0ef41Sopenharmony_civoid InterpreterAssembler::TraceBytecodeDispatch(TNode<WordT> target_bytecode) {
13761cb0ef41Sopenharmony_ci  TNode<ExternalReference> counters_table = ExternalConstant(
13771cb0ef41Sopenharmony_ci      ExternalReference::interpreter_dispatch_counters(isolate()));
13781cb0ef41Sopenharmony_ci  TNode<IntPtrT> source_bytecode_table_index = IntPtrConstant(
13791cb0ef41Sopenharmony_ci      static_cast<int>(bytecode_) * (static_cast<int>(Bytecode::kLast) + 1));
13801cb0ef41Sopenharmony_ci
13811cb0ef41Sopenharmony_ci  TNode<WordT> counter_offset = TimesSystemPointerSize(
13821cb0ef41Sopenharmony_ci      IntPtrAdd(source_bytecode_table_index, target_bytecode));
13831cb0ef41Sopenharmony_ci  TNode<IntPtrT> old_counter = Load<IntPtrT>(counters_table, counter_offset);
13841cb0ef41Sopenharmony_ci
13851cb0ef41Sopenharmony_ci  Label counter_ok(this), counter_saturated(this, Label::kDeferred);
13861cb0ef41Sopenharmony_ci
13871cb0ef41Sopenharmony_ci  TNode<BoolT> counter_reached_max = WordEqual(
13881cb0ef41Sopenharmony_ci      old_counter, IntPtrConstant(std::numeric_limits<uintptr_t>::max()));
13891cb0ef41Sopenharmony_ci  Branch(counter_reached_max, &counter_saturated, &counter_ok);
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_ci  BIND(&counter_ok);
13921cb0ef41Sopenharmony_ci  {
13931cb0ef41Sopenharmony_ci    TNode<IntPtrT> new_counter = IntPtrAdd(old_counter, IntPtrConstant(1));
13941cb0ef41Sopenharmony_ci    StoreNoWriteBarrier(MachineType::PointerRepresentation(), counters_table,
13951cb0ef41Sopenharmony_ci                        counter_offset, new_counter);
13961cb0ef41Sopenharmony_ci    Goto(&counter_saturated);
13971cb0ef41Sopenharmony_ci  }
13981cb0ef41Sopenharmony_ci
13991cb0ef41Sopenharmony_ci  BIND(&counter_saturated);
14001cb0ef41Sopenharmony_ci}
14011cb0ef41Sopenharmony_ci
14021cb0ef41Sopenharmony_ci// static
14031cb0ef41Sopenharmony_cibool InterpreterAssembler::TargetSupportsUnalignedAccess() {
14041cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_MIPS || V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_RISCV64
14051cb0ef41Sopenharmony_ci  return false;
14061cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_S390 || \
14071cb0ef41Sopenharmony_ci    V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_PPC ||   \
14081cb0ef41Sopenharmony_ci    V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_LOONG64
14091cb0ef41Sopenharmony_ci  return true;
14101cb0ef41Sopenharmony_ci#else
14111cb0ef41Sopenharmony_ci#error "Unknown Architecture"
14121cb0ef41Sopenharmony_ci#endif
14131cb0ef41Sopenharmony_ci}
14141cb0ef41Sopenharmony_ci
14151cb0ef41Sopenharmony_civoid InterpreterAssembler::AbortIfRegisterCountInvalid(
14161cb0ef41Sopenharmony_ci    TNode<FixedArrayBase> parameters_and_registers,
14171cb0ef41Sopenharmony_ci    TNode<IntPtrT> formal_parameter_count, TNode<UintPtrT> register_count) {
14181cb0ef41Sopenharmony_ci  TNode<IntPtrT> array_size =
14191cb0ef41Sopenharmony_ci      LoadAndUntagFixedArrayBaseLength(parameters_and_registers);
14201cb0ef41Sopenharmony_ci
14211cb0ef41Sopenharmony_ci  Label ok(this), abort(this, Label::kDeferred);
14221cb0ef41Sopenharmony_ci  Branch(UintPtrLessThanOrEqual(
14231cb0ef41Sopenharmony_ci             IntPtrAdd(formal_parameter_count, register_count), array_size),
14241cb0ef41Sopenharmony_ci         &ok, &abort);
14251cb0ef41Sopenharmony_ci
14261cb0ef41Sopenharmony_ci  BIND(&abort);
14271cb0ef41Sopenharmony_ci  Abort(AbortReason::kInvalidParametersAndRegistersInGenerator);
14281cb0ef41Sopenharmony_ci  Goto(&ok);
14291cb0ef41Sopenharmony_ci
14301cb0ef41Sopenharmony_ci  BIND(&ok);
14311cb0ef41Sopenharmony_ci}
14321cb0ef41Sopenharmony_ci
14331cb0ef41Sopenharmony_ciTNode<FixedArray> InterpreterAssembler::ExportParametersAndRegisterFile(
14341cb0ef41Sopenharmony_ci    TNode<FixedArray> array, const RegListNodePair& registers,
14351cb0ef41Sopenharmony_ci    TNode<Int32T> formal_parameter_count) {
14361cb0ef41Sopenharmony_ci  // Store the formal parameters (without receiver) followed by the
14371cb0ef41Sopenharmony_ci  // registers into the generator's internal parameters_and_registers field.
14381cb0ef41Sopenharmony_ci  TNode<IntPtrT> formal_parameter_count_intptr =
14391cb0ef41Sopenharmony_ci      Signed(ChangeUint32ToWord(formal_parameter_count));
14401cb0ef41Sopenharmony_ci  TNode<UintPtrT> register_count = ChangeUint32ToWord(registers.reg_count());
14411cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
14421cb0ef41Sopenharmony_ci    CSA_DCHECK(this, IntPtrEqual(registers.base_reg_location(),
14431cb0ef41Sopenharmony_ci                                 RegisterLocation(Register(0))));
14441cb0ef41Sopenharmony_ci    AbortIfRegisterCountInvalid(array, formal_parameter_count_intptr,
14451cb0ef41Sopenharmony_ci                                register_count);
14461cb0ef41Sopenharmony_ci  }
14471cb0ef41Sopenharmony_ci
14481cb0ef41Sopenharmony_ci  {
14491cb0ef41Sopenharmony_ci    TVARIABLE(IntPtrT, var_index);
14501cb0ef41Sopenharmony_ci    var_index = IntPtrConstant(0);
14511cb0ef41Sopenharmony_ci
14521cb0ef41Sopenharmony_ci    // Iterate over parameters and write them into the array.
14531cb0ef41Sopenharmony_ci    Label loop(this, &var_index), done_loop(this);
14541cb0ef41Sopenharmony_ci
14551cb0ef41Sopenharmony_ci    TNode<IntPtrT> reg_base =
14561cb0ef41Sopenharmony_ci        IntPtrConstant(Register::FromParameterIndex(0).ToOperand() + 1);
14571cb0ef41Sopenharmony_ci
14581cb0ef41Sopenharmony_ci    Goto(&loop);
14591cb0ef41Sopenharmony_ci    BIND(&loop);
14601cb0ef41Sopenharmony_ci    {
14611cb0ef41Sopenharmony_ci      TNode<IntPtrT> index = var_index.value();
14621cb0ef41Sopenharmony_ci      GotoIfNot(UintPtrLessThan(index, formal_parameter_count_intptr),
14631cb0ef41Sopenharmony_ci                &done_loop);
14641cb0ef41Sopenharmony_ci
14651cb0ef41Sopenharmony_ci      TNode<IntPtrT> reg_index = IntPtrAdd(reg_base, index);
14661cb0ef41Sopenharmony_ci      TNode<Object> value = LoadRegister(reg_index);
14671cb0ef41Sopenharmony_ci
14681cb0ef41Sopenharmony_ci      StoreFixedArrayElement(array, index, value);
14691cb0ef41Sopenharmony_ci
14701cb0ef41Sopenharmony_ci      var_index = IntPtrAdd(index, IntPtrConstant(1));
14711cb0ef41Sopenharmony_ci      Goto(&loop);
14721cb0ef41Sopenharmony_ci    }
14731cb0ef41Sopenharmony_ci    BIND(&done_loop);
14741cb0ef41Sopenharmony_ci  }
14751cb0ef41Sopenharmony_ci
14761cb0ef41Sopenharmony_ci  {
14771cb0ef41Sopenharmony_ci    // Iterate over register file and write values into array.
14781cb0ef41Sopenharmony_ci    // The mapping of register to array index must match that used in
14791cb0ef41Sopenharmony_ci    // BytecodeGraphBuilder::VisitResumeGenerator.
14801cb0ef41Sopenharmony_ci    TVARIABLE(IntPtrT, var_index);
14811cb0ef41Sopenharmony_ci    var_index = IntPtrConstant(0);
14821cb0ef41Sopenharmony_ci
14831cb0ef41Sopenharmony_ci    Label loop(this, &var_index), done_loop(this);
14841cb0ef41Sopenharmony_ci    Goto(&loop);
14851cb0ef41Sopenharmony_ci    BIND(&loop);
14861cb0ef41Sopenharmony_ci    {
14871cb0ef41Sopenharmony_ci      TNode<IntPtrT> index = var_index.value();
14881cb0ef41Sopenharmony_ci      GotoIfNot(UintPtrLessThan(index, register_count), &done_loop);
14891cb0ef41Sopenharmony_ci
14901cb0ef41Sopenharmony_ci      TNode<IntPtrT> reg_index =
14911cb0ef41Sopenharmony_ci          IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index);
14921cb0ef41Sopenharmony_ci      TNode<Object> value = LoadRegister(reg_index);
14931cb0ef41Sopenharmony_ci
14941cb0ef41Sopenharmony_ci      TNode<IntPtrT> array_index =
14951cb0ef41Sopenharmony_ci          IntPtrAdd(formal_parameter_count_intptr, index);
14961cb0ef41Sopenharmony_ci      StoreFixedArrayElement(array, array_index, value);
14971cb0ef41Sopenharmony_ci
14981cb0ef41Sopenharmony_ci      var_index = IntPtrAdd(index, IntPtrConstant(1));
14991cb0ef41Sopenharmony_ci      Goto(&loop);
15001cb0ef41Sopenharmony_ci    }
15011cb0ef41Sopenharmony_ci    BIND(&done_loop);
15021cb0ef41Sopenharmony_ci  }
15031cb0ef41Sopenharmony_ci
15041cb0ef41Sopenharmony_ci  return array;
15051cb0ef41Sopenharmony_ci}
15061cb0ef41Sopenharmony_ci
15071cb0ef41Sopenharmony_ciTNode<FixedArray> InterpreterAssembler::ImportRegisterFile(
15081cb0ef41Sopenharmony_ci    TNode<FixedArray> array, const RegListNodePair& registers,
15091cb0ef41Sopenharmony_ci    TNode<Int32T> formal_parameter_count) {
15101cb0ef41Sopenharmony_ci  TNode<IntPtrT> formal_parameter_count_intptr =
15111cb0ef41Sopenharmony_ci      Signed(ChangeUint32ToWord(formal_parameter_count));
15121cb0ef41Sopenharmony_ci  TNode<UintPtrT> register_count = ChangeUint32ToWord(registers.reg_count());
15131cb0ef41Sopenharmony_ci  if (FLAG_debug_code) {
15141cb0ef41Sopenharmony_ci    CSA_DCHECK(this, IntPtrEqual(registers.base_reg_location(),
15151cb0ef41Sopenharmony_ci                                 RegisterLocation(Register(0))));
15161cb0ef41Sopenharmony_ci    AbortIfRegisterCountInvalid(array, formal_parameter_count_intptr,
15171cb0ef41Sopenharmony_ci                                register_count);
15181cb0ef41Sopenharmony_ci  }
15191cb0ef41Sopenharmony_ci
15201cb0ef41Sopenharmony_ci  TVARIABLE(IntPtrT, var_index, IntPtrConstant(0));
15211cb0ef41Sopenharmony_ci
15221cb0ef41Sopenharmony_ci  // Iterate over array and write values into register file.  Also erase the
15231cb0ef41Sopenharmony_ci  // array contents to not keep them alive artificially.
15241cb0ef41Sopenharmony_ci  Label loop(this, &var_index), done_loop(this);
15251cb0ef41Sopenharmony_ci  Goto(&loop);
15261cb0ef41Sopenharmony_ci  BIND(&loop);
15271cb0ef41Sopenharmony_ci  {
15281cb0ef41Sopenharmony_ci    TNode<IntPtrT> index = var_index.value();
15291cb0ef41Sopenharmony_ci    GotoIfNot(UintPtrLessThan(index, register_count), &done_loop);
15301cb0ef41Sopenharmony_ci
15311cb0ef41Sopenharmony_ci    TNode<IntPtrT> array_index =
15321cb0ef41Sopenharmony_ci        IntPtrAdd(formal_parameter_count_intptr, index);
15331cb0ef41Sopenharmony_ci    TNode<Object> value = LoadFixedArrayElement(array, array_index);
15341cb0ef41Sopenharmony_ci
15351cb0ef41Sopenharmony_ci    TNode<IntPtrT> reg_index =
15361cb0ef41Sopenharmony_ci        IntPtrSub(IntPtrConstant(Register(0).ToOperand()), index);
15371cb0ef41Sopenharmony_ci    StoreRegister(value, reg_index);
15381cb0ef41Sopenharmony_ci
15391cb0ef41Sopenharmony_ci    StoreFixedArrayElement(array, array_index, StaleRegisterConstant());
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_ci    var_index = IntPtrAdd(index, IntPtrConstant(1));
15421cb0ef41Sopenharmony_ci    Goto(&loop);
15431cb0ef41Sopenharmony_ci  }
15441cb0ef41Sopenharmony_ci  BIND(&done_loop);
15451cb0ef41Sopenharmony_ci
15461cb0ef41Sopenharmony_ci  return array;
15471cb0ef41Sopenharmony_ci}
15481cb0ef41Sopenharmony_ci
15491cb0ef41Sopenharmony_ciint InterpreterAssembler::CurrentBytecodeSize() const {
15501cb0ef41Sopenharmony_ci  return Bytecodes::Size(bytecode_, operand_scale_);
15511cb0ef41Sopenharmony_ci}
15521cb0ef41Sopenharmony_ci
15531cb0ef41Sopenharmony_civoid InterpreterAssembler::ToNumberOrNumeric(Object::Conversion mode) {
15541cb0ef41Sopenharmony_ci  TNode<Object> object = GetAccumulator();
15551cb0ef41Sopenharmony_ci  TNode<Context> context = GetContext();
15561cb0ef41Sopenharmony_ci
15571cb0ef41Sopenharmony_ci  TVARIABLE(Smi, var_type_feedback);
15581cb0ef41Sopenharmony_ci  TVARIABLE(Numeric, var_result);
15591cb0ef41Sopenharmony_ci  Label if_done(this), if_objectissmi(this), if_objectisheapnumber(this),
15601cb0ef41Sopenharmony_ci      if_objectisother(this, Label::kDeferred);
15611cb0ef41Sopenharmony_ci
15621cb0ef41Sopenharmony_ci  GotoIf(TaggedIsSmi(object), &if_objectissmi);
15631cb0ef41Sopenharmony_ci  Branch(IsHeapNumber(CAST(object)), &if_objectisheapnumber, &if_objectisother);
15641cb0ef41Sopenharmony_ci
15651cb0ef41Sopenharmony_ci  BIND(&if_objectissmi);
15661cb0ef41Sopenharmony_ci  {
15671cb0ef41Sopenharmony_ci    var_result = CAST(object);
15681cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kSignedSmall);
15691cb0ef41Sopenharmony_ci    Goto(&if_done);
15701cb0ef41Sopenharmony_ci  }
15711cb0ef41Sopenharmony_ci
15721cb0ef41Sopenharmony_ci  BIND(&if_objectisheapnumber);
15731cb0ef41Sopenharmony_ci  {
15741cb0ef41Sopenharmony_ci    var_result = CAST(object);
15751cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kNumber);
15761cb0ef41Sopenharmony_ci    Goto(&if_done);
15771cb0ef41Sopenharmony_ci  }
15781cb0ef41Sopenharmony_ci
15791cb0ef41Sopenharmony_ci  BIND(&if_objectisother);
15801cb0ef41Sopenharmony_ci  {
15811cb0ef41Sopenharmony_ci    auto builtin = Builtin::kNonNumberToNumber;
15821cb0ef41Sopenharmony_ci    if (mode == Object::Conversion::kToNumeric) {
15831cb0ef41Sopenharmony_ci      builtin = Builtin::kNonNumberToNumeric;
15841cb0ef41Sopenharmony_ci      // Special case for collecting BigInt feedback.
15851cb0ef41Sopenharmony_ci      Label not_bigint(this);
15861cb0ef41Sopenharmony_ci      GotoIfNot(IsBigInt(CAST(object)), &not_bigint);
15871cb0ef41Sopenharmony_ci      {
15881cb0ef41Sopenharmony_ci        var_result = CAST(object);
15891cb0ef41Sopenharmony_ci        var_type_feedback = SmiConstant(BinaryOperationFeedback::kBigInt);
15901cb0ef41Sopenharmony_ci        Goto(&if_done);
15911cb0ef41Sopenharmony_ci      }
15921cb0ef41Sopenharmony_ci      BIND(&not_bigint);
15931cb0ef41Sopenharmony_ci    }
15941cb0ef41Sopenharmony_ci
15951cb0ef41Sopenharmony_ci    // Convert {object} by calling out to the appropriate builtin.
15961cb0ef41Sopenharmony_ci    var_result = CAST(CallBuiltin(builtin, context, object));
15971cb0ef41Sopenharmony_ci    var_type_feedback = SmiConstant(BinaryOperationFeedback::kAny);
15981cb0ef41Sopenharmony_ci    Goto(&if_done);
15991cb0ef41Sopenharmony_ci  }
16001cb0ef41Sopenharmony_ci
16011cb0ef41Sopenharmony_ci  BIND(&if_done);
16021cb0ef41Sopenharmony_ci
16031cb0ef41Sopenharmony_ci  // Record the type feedback collected for {object}.
16041cb0ef41Sopenharmony_ci  TNode<UintPtrT> slot_index = BytecodeOperandIdx(0);
16051cb0ef41Sopenharmony_ci  TNode<HeapObject> maybe_feedback_vector = LoadFeedbackVector();
16061cb0ef41Sopenharmony_ci
16071cb0ef41Sopenharmony_ci  MaybeUpdateFeedback(var_type_feedback.value(), maybe_feedback_vector,
16081cb0ef41Sopenharmony_ci                      slot_index);
16091cb0ef41Sopenharmony_ci
16101cb0ef41Sopenharmony_ci  SetAccumulator(var_result.value());
16111cb0ef41Sopenharmony_ci  Dispatch();
16121cb0ef41Sopenharmony_ci}
16131cb0ef41Sopenharmony_ci
16141cb0ef41Sopenharmony_ci}  // namespace interpreter
16151cb0ef41Sopenharmony_ci}  // namespace internal
16161cb0ef41Sopenharmony_ci}  // namespace v8
1617