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)), ¬_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(¬_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