11cb0ef41Sopenharmony_ci// Copyright 2021 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#ifndef V8_BASELINE_BASELINE_ASSEMBLER_H_ 61cb0ef41Sopenharmony_ci#define V8_BASELINE_BASELINE_ASSEMBLER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci// TODO(v8:11421): Remove #if once baseline compiler is ported to other 91cb0ef41Sopenharmony_ci// architectures. 101cb0ef41Sopenharmony_ci#include "src/flags/flags.h" 111cb0ef41Sopenharmony_ci#if ENABLE_SPARKPLUG 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ci#include "src/codegen/macro-assembler.h" 141cb0ef41Sopenharmony_ci#include "src/objects/tagged-index.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_cinamespace v8 { 171cb0ef41Sopenharmony_cinamespace internal { 181cb0ef41Sopenharmony_cinamespace baseline { 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_cienum class Condition : uint32_t; 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ciclass BaselineAssembler { 231cb0ef41Sopenharmony_ci public: 241cb0ef41Sopenharmony_ci class ScratchRegisterScope; 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_ci explicit BaselineAssembler(MacroAssembler* masm) : masm_(masm) {} 271cb0ef41Sopenharmony_ci inline static MemOperand RegisterFrameOperand( 281cb0ef41Sopenharmony_ci interpreter::Register interpreter_register); 291cb0ef41Sopenharmony_ci inline void RegisterFrameAddress(interpreter::Register interpreter_register, 301cb0ef41Sopenharmony_ci Register rscratch); 311cb0ef41Sopenharmony_ci inline MemOperand ContextOperand(); 321cb0ef41Sopenharmony_ci inline MemOperand FunctionOperand(); 331cb0ef41Sopenharmony_ci inline MemOperand FeedbackVectorOperand(); 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci inline void GetCode(Isolate* isolate, CodeDesc* desc); 361cb0ef41Sopenharmony_ci inline int pc_offset() const; 371cb0ef41Sopenharmony_ci inline void CodeEntry() const; 381cb0ef41Sopenharmony_ci inline void ExceptionHandler() const; 391cb0ef41Sopenharmony_ci V8_INLINE void RecordComment(const char* string); 401cb0ef41Sopenharmony_ci inline void Trap(); 411cb0ef41Sopenharmony_ci inline void DebugBreak(); 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_ci inline void Bind(Label* label); 441cb0ef41Sopenharmony_ci // Binds the label without marking it as a valid jump target. 451cb0ef41Sopenharmony_ci // This is only useful, when the position is already marked as a valid jump 461cb0ef41Sopenharmony_ci // target (i.e. at the beginning of the bytecode). 471cb0ef41Sopenharmony_ci inline void BindWithoutJumpTarget(Label* label); 481cb0ef41Sopenharmony_ci // Marks the current position as a valid jump target on CFI enabled 491cb0ef41Sopenharmony_ci // architectures. 501cb0ef41Sopenharmony_ci inline void JumpTarget(); 511cb0ef41Sopenharmony_ci inline void Jump(Label* target, Label::Distance distance = Label::kFar); 521cb0ef41Sopenharmony_ci inline void JumpIfRoot(Register value, RootIndex index, Label* target, 531cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 541cb0ef41Sopenharmony_ci inline void JumpIfNotRoot(Register value, RootIndex index, Label* target, 551cb0ef41Sopenharmony_ci Label ::Distance distance = Label::kFar); 561cb0ef41Sopenharmony_ci inline void JumpIfSmi(Register value, Label* target, 571cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 581cb0ef41Sopenharmony_ci inline void JumpIfNotSmi(Register value, Label* target, 591cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci inline void TestAndBranch(Register value, int mask, Condition cc, 621cb0ef41Sopenharmony_ci Label* target, 631cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci inline void JumpIf(Condition cc, Register lhs, const Operand& rhs, 661cb0ef41Sopenharmony_ci Label* target, Label::Distance distance = Label::kFar); 671cb0ef41Sopenharmony_ci inline void JumpIfObjectType(Condition cc, Register object, 681cb0ef41Sopenharmony_ci InstanceType instance_type, Register map, 691cb0ef41Sopenharmony_ci Label* target, 701cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 711cb0ef41Sopenharmony_ci inline void JumpIfInstanceType(Condition cc, Register map, 721cb0ef41Sopenharmony_ci InstanceType instance_type, Label* target, 731cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 741cb0ef41Sopenharmony_ci inline void JumpIfPointer(Condition cc, Register value, MemOperand operand, 751cb0ef41Sopenharmony_ci Label* target, 761cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 771cb0ef41Sopenharmony_ci inline Condition CheckSmi(Register value); 781cb0ef41Sopenharmony_ci inline void JumpIfSmi(Condition cc, Register value, Smi smi, Label* target, 791cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 801cb0ef41Sopenharmony_ci inline void JumpIfSmi(Condition cc, Register lhs, Register rhs, Label* target, 811cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 821cb0ef41Sopenharmony_ci inline void JumpIfImmediate(Condition cc, Register left, int right, 831cb0ef41Sopenharmony_ci Label* target, 841cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 851cb0ef41Sopenharmony_ci inline void JumpIfTagged(Condition cc, Register value, MemOperand operand, 861cb0ef41Sopenharmony_ci Label* target, 871cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 881cb0ef41Sopenharmony_ci inline void JumpIfTagged(Condition cc, MemOperand operand, Register value, 891cb0ef41Sopenharmony_ci Label* target, 901cb0ef41Sopenharmony_ci Label::Distance distance = Label::kFar); 911cb0ef41Sopenharmony_ci inline void JumpIfByte(Condition cc, Register value, int32_t byte, 921cb0ef41Sopenharmony_ci Label* target, Label::Distance distance = Label::kFar); 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci inline void LoadMap(Register output, Register value); 951cb0ef41Sopenharmony_ci inline void LoadRoot(Register output, RootIndex index); 961cb0ef41Sopenharmony_ci inline void LoadNativeContextSlot(Register output, uint32_t index); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci inline void Move(Register output, Register source); 991cb0ef41Sopenharmony_ci inline void Move(Register output, MemOperand operand); 1001cb0ef41Sopenharmony_ci inline void Move(Register output, Smi value); 1011cb0ef41Sopenharmony_ci inline void Move(Register output, TaggedIndex value); 1021cb0ef41Sopenharmony_ci inline void Move(Register output, interpreter::Register source); 1031cb0ef41Sopenharmony_ci inline void Move(interpreter::Register output, Register source); 1041cb0ef41Sopenharmony_ci inline void Move(Register output, RootIndex source); 1051cb0ef41Sopenharmony_ci inline void Move(MemOperand output, Register source); 1061cb0ef41Sopenharmony_ci inline void Move(Register output, ExternalReference reference); 1071cb0ef41Sopenharmony_ci inline void Move(Register output, Handle<HeapObject> value); 1081cb0ef41Sopenharmony_ci inline void Move(Register output, int32_t immediate); 1091cb0ef41Sopenharmony_ci inline void MoveMaybeSmi(Register output, Register source); 1101cb0ef41Sopenharmony_ci inline void MoveSmi(Register output, Register source); 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci // Push the given values, in the given order. If the stack needs alignment 1131cb0ef41Sopenharmony_ci // (looking at you Arm64), the stack is padded from the front (i.e. before the 1141cb0ef41Sopenharmony_ci // first value is pushed). 1151cb0ef41Sopenharmony_ci // 1161cb0ef41Sopenharmony_ci // This supports pushing a RegisterList as the last value -- the list is 1171cb0ef41Sopenharmony_ci // iterated and each interpreter Register is pushed. 1181cb0ef41Sopenharmony_ci // 1191cb0ef41Sopenharmony_ci // The total number of values pushed is returned. Note that this might be 1201cb0ef41Sopenharmony_ci // different from sizeof(T...), specifically if there was a RegisterList. 1211cb0ef41Sopenharmony_ci template <typename... T> 1221cb0ef41Sopenharmony_ci inline int Push(T... vals); 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci // Like Push(vals...), but pushes in reverse order, to support our reversed 1251cb0ef41Sopenharmony_ci // order argument JS calling convention. Doesn't return the number of 1261cb0ef41Sopenharmony_ci // arguments pushed though. 1271cb0ef41Sopenharmony_ci // 1281cb0ef41Sopenharmony_ci // Note that padding is still inserted before the first pushed value (i.e. the 1291cb0ef41Sopenharmony_ci // last value). 1301cb0ef41Sopenharmony_ci template <typename... T> 1311cb0ef41Sopenharmony_ci inline void PushReverse(T... vals); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci // Pop values off the stack into the given registers. 1341cb0ef41Sopenharmony_ci // 1351cb0ef41Sopenharmony_ci // Note that this inserts into registers in the given order, i.e. in reverse 1361cb0ef41Sopenharmony_ci // order if the registers were pushed. This means that to spill registers, 1371cb0ef41Sopenharmony_ci // push and pop have to be in reverse order, e.g. 1381cb0ef41Sopenharmony_ci // 1391cb0ef41Sopenharmony_ci // Push(r1, r2, ..., rN); 1401cb0ef41Sopenharmony_ci // ClobberRegisters(); 1411cb0ef41Sopenharmony_ci // Pop(rN, ..., r2, r1); 1421cb0ef41Sopenharmony_ci // 1431cb0ef41Sopenharmony_ci // On stack-alignment architectures, any padding is popped off after the last 1441cb0ef41Sopenharmony_ci // register. This the behaviour of Push, which means that the above code still 1451cb0ef41Sopenharmony_ci // works even if the number of registers doesn't match stack alignment. 1461cb0ef41Sopenharmony_ci template <typename... T> 1471cb0ef41Sopenharmony_ci inline void Pop(T... registers); 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci inline void CallBuiltin(Builtin builtin); 1501cb0ef41Sopenharmony_ci inline void TailCallBuiltin(Builtin builtin); 1511cb0ef41Sopenharmony_ci inline void CallRuntime(Runtime::FunctionId function, int nargs); 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci inline void LoadTaggedPointerField(Register output, Register source, 1541cb0ef41Sopenharmony_ci int offset); 1551cb0ef41Sopenharmony_ci inline void LoadTaggedSignedField(Register output, Register source, 1561cb0ef41Sopenharmony_ci int offset); 1571cb0ef41Sopenharmony_ci inline void LoadTaggedAnyField(Register output, Register source, int offset); 1581cb0ef41Sopenharmony_ci inline void LoadWord16FieldZeroExtend(Register output, Register source, 1591cb0ef41Sopenharmony_ci int offset); 1601cb0ef41Sopenharmony_ci inline void LoadWord8Field(Register output, Register source, int offset); 1611cb0ef41Sopenharmony_ci inline void StoreTaggedSignedField(Register target, int offset, Smi value); 1621cb0ef41Sopenharmony_ci inline void StoreTaggedFieldWithWriteBarrier(Register target, int offset, 1631cb0ef41Sopenharmony_ci Register value); 1641cb0ef41Sopenharmony_ci inline void StoreTaggedFieldNoWriteBarrier(Register target, int offset, 1651cb0ef41Sopenharmony_ci Register value); 1661cb0ef41Sopenharmony_ci inline void LoadFixedArrayElement(Register output, Register array, 1671cb0ef41Sopenharmony_ci int32_t index); 1681cb0ef41Sopenharmony_ci inline void LoadPrototype(Register prototype, Register object); 1691cb0ef41Sopenharmony_ci 1701cb0ef41Sopenharmony_ci // Loads the feedback cell from the function, and sets flags on add so that 1711cb0ef41Sopenharmony_ci // we can compare afterward. 1721cb0ef41Sopenharmony_ci inline void AddToInterruptBudgetAndJumpIfNotExceeded( 1731cb0ef41Sopenharmony_ci int32_t weight, Label* skip_interrupt_label); 1741cb0ef41Sopenharmony_ci inline void AddToInterruptBudgetAndJumpIfNotExceeded( 1751cb0ef41Sopenharmony_ci Register weight, Label* skip_interrupt_label); 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci inline void AddSmi(Register lhs, Smi rhs); 1781cb0ef41Sopenharmony_ci inline void SmiUntag(Register value); 1791cb0ef41Sopenharmony_ci inline void SmiUntag(Register output, Register value); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci inline void Word32And(Register output, Register lhs, int rhs); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci inline void Switch(Register reg, int case_value_base, Label** labels, 1841cb0ef41Sopenharmony_ci int num_labels); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci // Register operands. 1871cb0ef41Sopenharmony_ci inline void LoadRegister(Register output, interpreter::Register source); 1881cb0ef41Sopenharmony_ci inline void StoreRegister(interpreter::Register output, Register value); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci // Frame values 1911cb0ef41Sopenharmony_ci inline void LoadFunction(Register output); 1921cb0ef41Sopenharmony_ci inline void LoadContext(Register output); 1931cb0ef41Sopenharmony_ci inline void StoreContext(Register context); 1941cb0ef41Sopenharmony_ci 1951cb0ef41Sopenharmony_ci inline static void EmitReturn(MacroAssembler* masm); 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci MacroAssembler* masm() { return masm_; } 1981cb0ef41Sopenharmony_ci 1991cb0ef41Sopenharmony_ci private: 2001cb0ef41Sopenharmony_ci MacroAssembler* masm_; 2011cb0ef41Sopenharmony_ci ScratchRegisterScope* scratch_register_scope_ = nullptr; 2021cb0ef41Sopenharmony_ci}; 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ciclass SaveAccumulatorScope final { 2051cb0ef41Sopenharmony_ci public: 2061cb0ef41Sopenharmony_ci inline explicit SaveAccumulatorScope(BaselineAssembler* assembler); 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci inline ~SaveAccumulatorScope(); 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci private: 2111cb0ef41Sopenharmony_ci BaselineAssembler* assembler_; 2121cb0ef41Sopenharmony_ci}; 2131cb0ef41Sopenharmony_ci 2141cb0ef41Sopenharmony_ciclass EnsureAccumulatorPreservedScope final { 2151cb0ef41Sopenharmony_ci public: 2161cb0ef41Sopenharmony_ci inline explicit EnsureAccumulatorPreservedScope(BaselineAssembler* assembler); 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ci inline ~EnsureAccumulatorPreservedScope(); 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci private: 2211cb0ef41Sopenharmony_ci inline void AssertEqualToAccumulator(Register reg); 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci BaselineAssembler* assembler_; 2241cb0ef41Sopenharmony_ci#ifdef V8_CODE_COMMENTS 2251cb0ef41Sopenharmony_ci Assembler::CodeComment comment_; 2261cb0ef41Sopenharmony_ci#endif 2271cb0ef41Sopenharmony_ci}; 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci} // namespace baseline 2301cb0ef41Sopenharmony_ci} // namespace internal 2311cb0ef41Sopenharmony_ci} // namespace v8 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci#endif 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci#endif // V8_BASELINE_BASELINE_ASSEMBLER_H_ 236