11cb0ef41Sopenharmony_ci// Copyright 2012 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 INCLUDED_FROM_MACRO_ASSEMBLER_H 61cb0ef41Sopenharmony_ci#error This header must be included via macro-assembler.h 71cb0ef41Sopenharmony_ci#endif 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#ifndef V8_CODEGEN_X64_MACRO_ASSEMBLER_X64_H_ 101cb0ef41Sopenharmony_ci#define V8_CODEGEN_X64_MACRO_ASSEMBLER_X64_H_ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include "src/base/flags.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/bailout-reason.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/shared-ia32-x64/macro-assembler-shared-ia32-x64.h" 151cb0ef41Sopenharmony_ci#include "src/codegen/x64/assembler-x64.h" 161cb0ef41Sopenharmony_ci#include "src/common/globals.h" 171cb0ef41Sopenharmony_ci#include "src/execution/isolate-data.h" 181cb0ef41Sopenharmony_ci#include "src/objects/contexts.h" 191cb0ef41Sopenharmony_ci#include "src/objects/tagged-index.h" 201cb0ef41Sopenharmony_ci 211cb0ef41Sopenharmony_cinamespace v8 { 221cb0ef41Sopenharmony_cinamespace internal { 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ci// Convenience for platform-independent signatures. 251cb0ef41Sopenharmony_ciusing MemOperand = Operand; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_ciclass StringConstantBase; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_cistruct SmiIndex { 301cb0ef41Sopenharmony_ci SmiIndex(Register index_register, ScaleFactor scale) 311cb0ef41Sopenharmony_ci : reg(index_register), scale(scale) {} 321cb0ef41Sopenharmony_ci Register reg; 331cb0ef41Sopenharmony_ci ScaleFactor scale; 341cb0ef41Sopenharmony_ci}; 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci// TODO(victorgomes): Move definition to macro-assembler.h, once all other 371cb0ef41Sopenharmony_ci// platforms are updated. 381cb0ef41Sopenharmony_cienum class StackLimitKind { kInterruptStackLimit, kRealStackLimit }; 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci// Convenient class to access arguments below the stack pointer. 411cb0ef41Sopenharmony_ciclass StackArgumentsAccessor { 421cb0ef41Sopenharmony_ci public: 431cb0ef41Sopenharmony_ci // argc = the number of arguments not including the receiver. 441cb0ef41Sopenharmony_ci explicit StackArgumentsAccessor(Register argc) : argc_(argc) { 451cb0ef41Sopenharmony_ci DCHECK_NE(argc_, no_reg); 461cb0ef41Sopenharmony_ci } 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci // Argument 0 is the receiver (despite argc not including the receiver). 491cb0ef41Sopenharmony_ci Operand operator[](int index) const { return GetArgumentOperand(index); } 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci Operand GetArgumentOperand(int index) const; 521cb0ef41Sopenharmony_ci Operand GetReceiverOperand() const { return GetArgumentOperand(0); } 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_ci private: 551cb0ef41Sopenharmony_ci const Register argc_; 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_ci DISALLOW_IMPLICIT_CONSTRUCTORS(StackArgumentsAccessor); 581cb0ef41Sopenharmony_ci}; 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE TurboAssembler 611cb0ef41Sopenharmony_ci : public SharedTurboAssemblerBase<TurboAssembler> { 621cb0ef41Sopenharmony_ci public: 631cb0ef41Sopenharmony_ci using SharedTurboAssemblerBase<TurboAssembler>::SharedTurboAssemblerBase; 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci void PushReturnAddressFrom(Register src) { pushq(src); } 661cb0ef41Sopenharmony_ci void PopReturnAddressTo(Register dst) { popq(dst); } 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci void Ret(); 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_ci // Call incsspq with {number_of_words} only if the cpu supports it. 711cb0ef41Sopenharmony_ci // NOTE: This shouldn't be embedded in optimized code, since the check 721cb0ef41Sopenharmony_ci // for CPU support would be redundant (we could check at compiler time). 731cb0ef41Sopenharmony_ci void IncsspqIfSupported(Register number_of_words, Register scratch); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci // Return and drop arguments from stack, where the number of arguments 761cb0ef41Sopenharmony_ci // may be bigger than 2^16 - 1. Requires a scratch register. 771cb0ef41Sopenharmony_ci void Ret(int bytes_dropped, Register scratch); 781cb0ef41Sopenharmony_ci 791cb0ef41Sopenharmony_ci // Operations on roots in the root-array. 801cb0ef41Sopenharmony_ci Operand RootAsOperand(RootIndex index); 811cb0ef41Sopenharmony_ci void LoadRoot(Register destination, RootIndex index) final; 821cb0ef41Sopenharmony_ci void LoadRoot(Operand destination, RootIndex index) { 831cb0ef41Sopenharmony_ci LoadRoot(kScratchRegister, index); 841cb0ef41Sopenharmony_ci movq(destination, kScratchRegister); 851cb0ef41Sopenharmony_ci } 861cb0ef41Sopenharmony_ci 871cb0ef41Sopenharmony_ci void Push(Register src); 881cb0ef41Sopenharmony_ci void Push(Operand src); 891cb0ef41Sopenharmony_ci void Push(Immediate value); 901cb0ef41Sopenharmony_ci void Push(Smi smi); 911cb0ef41Sopenharmony_ci void Push(TaggedIndex index) { 921cb0ef41Sopenharmony_ci Push(Immediate(static_cast<uint32_t>(index.ptr()))); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci void Push(Handle<HeapObject> source); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci enum class PushArrayOrder { kNormal, kReverse }; 971cb0ef41Sopenharmony_ci // `array` points to the first element (the lowest address). 981cb0ef41Sopenharmony_ci // `array` and `size` are not modified. 991cb0ef41Sopenharmony_ci void PushArray(Register array, Register size, Register scratch, 1001cb0ef41Sopenharmony_ci PushArrayOrder order = PushArrayOrder::kNormal); 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci // Before calling a C-function from generated code, align arguments on stack. 1031cb0ef41Sopenharmony_ci // After aligning the frame, arguments must be stored in rsp[0], rsp[8], 1041cb0ef41Sopenharmony_ci // etc., not pushed. The argument count assumes all arguments are word sized. 1051cb0ef41Sopenharmony_ci // The number of slots reserved for arguments depends on platform. On Windows 1061cb0ef41Sopenharmony_ci // stack slots are reserved for the arguments passed in registers. On other 1071cb0ef41Sopenharmony_ci // platforms stack slots are only reserved for the arguments actually passed 1081cb0ef41Sopenharmony_ci // on the stack. 1091cb0ef41Sopenharmony_ci void PrepareCallCFunction(int num_arguments); 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci // Calls a C function and cleans up the space for arguments allocated 1121cb0ef41Sopenharmony_ci // by PrepareCallCFunction. The called function is not allowed to trigger a 1131cb0ef41Sopenharmony_ci // garbage collection, since that might move the code and invalidate the 1141cb0ef41Sopenharmony_ci // return address (unless this is somehow accounted for by the called 1151cb0ef41Sopenharmony_ci // function). 1161cb0ef41Sopenharmony_ci void CallCFunction(ExternalReference function, int num_arguments); 1171cb0ef41Sopenharmony_ci void CallCFunction(Register function, int num_arguments); 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci // Calculate the number of stack slots to reserve for arguments when calling a 1201cb0ef41Sopenharmony_ci // C function. 1211cb0ef41Sopenharmony_ci int ArgumentStackSlotsForCFunctionCall(int num_arguments); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci void CheckPageFlag(Register object, Register scratch, int mask, Condition cc, 1241cb0ef41Sopenharmony_ci Label* condition_met, 1251cb0ef41Sopenharmony_ci Label::Distance condition_met_distance = Label::kFar); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci // Define movq here instead of using AVX_OP. movq is defined using templates 1281cb0ef41Sopenharmony_ci // and there is a function template `void movq(P1)`, while technically 1291cb0ef41Sopenharmony_ci // impossible, will be selected when deducing the arguments for AvxHelper. 1301cb0ef41Sopenharmony_ci void Movq(XMMRegister dst, Register src); 1311cb0ef41Sopenharmony_ci void Movq(Register dst, XMMRegister src); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci void Cvtss2sd(XMMRegister dst, XMMRegister src); 1341cb0ef41Sopenharmony_ci void Cvtss2sd(XMMRegister dst, Operand src); 1351cb0ef41Sopenharmony_ci void Cvtsd2ss(XMMRegister dst, XMMRegister src); 1361cb0ef41Sopenharmony_ci void Cvtsd2ss(XMMRegister dst, Operand src); 1371cb0ef41Sopenharmony_ci void Cvttsd2si(Register dst, XMMRegister src); 1381cb0ef41Sopenharmony_ci void Cvttsd2si(Register dst, Operand src); 1391cb0ef41Sopenharmony_ci void Cvttsd2siq(Register dst, XMMRegister src); 1401cb0ef41Sopenharmony_ci void Cvttsd2siq(Register dst, Operand src); 1411cb0ef41Sopenharmony_ci void Cvttss2si(Register dst, XMMRegister src); 1421cb0ef41Sopenharmony_ci void Cvttss2si(Register dst, Operand src); 1431cb0ef41Sopenharmony_ci void Cvttss2siq(Register dst, XMMRegister src); 1441cb0ef41Sopenharmony_ci void Cvttss2siq(Register dst, Operand src); 1451cb0ef41Sopenharmony_ci void Cvtlui2ss(XMMRegister dst, Register src); 1461cb0ef41Sopenharmony_ci void Cvtlui2ss(XMMRegister dst, Operand src); 1471cb0ef41Sopenharmony_ci void Cvtlui2sd(XMMRegister dst, Register src); 1481cb0ef41Sopenharmony_ci void Cvtlui2sd(XMMRegister dst, Operand src); 1491cb0ef41Sopenharmony_ci void Cvtqui2ss(XMMRegister dst, Register src); 1501cb0ef41Sopenharmony_ci void Cvtqui2ss(XMMRegister dst, Operand src); 1511cb0ef41Sopenharmony_ci void Cvtqui2sd(XMMRegister dst, Register src); 1521cb0ef41Sopenharmony_ci void Cvtqui2sd(XMMRegister dst, Operand src); 1531cb0ef41Sopenharmony_ci void Cvttsd2uiq(Register dst, Operand src, Label* fail = nullptr); 1541cb0ef41Sopenharmony_ci void Cvttsd2uiq(Register dst, XMMRegister src, Label* fail = nullptr); 1551cb0ef41Sopenharmony_ci void Cvttss2uiq(Register dst, Operand src, Label* fail = nullptr); 1561cb0ef41Sopenharmony_ci void Cvttss2uiq(Register dst, XMMRegister src, Label* fail = nullptr); 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci // cvtsi2sd and cvtsi2ss instructions only write to the low 64/32-bit of dst 1591cb0ef41Sopenharmony_ci // register, which hinders register renaming and makes dependence chains 1601cb0ef41Sopenharmony_ci // longer. So we use xorpd to clear the dst register before cvtsi2sd for 1611cb0ef41Sopenharmony_ci // non-AVX and a scratch XMM register as first src for AVX to solve this 1621cb0ef41Sopenharmony_ci // issue. 1631cb0ef41Sopenharmony_ci void Cvtqsi2ss(XMMRegister dst, Register src); 1641cb0ef41Sopenharmony_ci void Cvtqsi2ss(XMMRegister dst, Operand src); 1651cb0ef41Sopenharmony_ci void Cvtqsi2sd(XMMRegister dst, Register src); 1661cb0ef41Sopenharmony_ci void Cvtqsi2sd(XMMRegister dst, Operand src); 1671cb0ef41Sopenharmony_ci void Cvtlsi2ss(XMMRegister dst, Register src); 1681cb0ef41Sopenharmony_ci void Cvtlsi2ss(XMMRegister dst, Operand src); 1691cb0ef41Sopenharmony_ci void Cvtlsi2sd(XMMRegister dst, Register src); 1701cb0ef41Sopenharmony_ci void Cvtlsi2sd(XMMRegister dst, Operand src); 1711cb0ef41Sopenharmony_ci 1721cb0ef41Sopenharmony_ci void Cmpeqss(XMMRegister dst, XMMRegister src); 1731cb0ef41Sopenharmony_ci void Cmpeqsd(XMMRegister dst, XMMRegister src); 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci void PextrdPreSse41(Register dst, XMMRegister src, uint8_t imm8); 1761cb0ef41Sopenharmony_ci void Pextrq(Register dst, XMMRegister src, int8_t imm8); 1771cb0ef41Sopenharmony_ci 1781cb0ef41Sopenharmony_ci void PinsrdPreSse41(XMMRegister dst, Register src2, uint8_t imm8, 1791cb0ef41Sopenharmony_ci uint32_t* load_pc_offset = nullptr); 1801cb0ef41Sopenharmony_ci void PinsrdPreSse41(XMMRegister dst, Operand src2, uint8_t imm8, 1811cb0ef41Sopenharmony_ci uint32_t* load_pc_offset = nullptr); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci void Pinsrq(XMMRegister dst, XMMRegister src1, Register src2, uint8_t imm8, 1841cb0ef41Sopenharmony_ci uint32_t* load_pc_offset = nullptr); 1851cb0ef41Sopenharmony_ci void Pinsrq(XMMRegister dst, XMMRegister src1, Operand src2, uint8_t imm8, 1861cb0ef41Sopenharmony_ci uint32_t* load_pc_offset = nullptr); 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci void Lzcntq(Register dst, Register src); 1891cb0ef41Sopenharmony_ci void Lzcntq(Register dst, Operand src); 1901cb0ef41Sopenharmony_ci void Lzcntl(Register dst, Register src); 1911cb0ef41Sopenharmony_ci void Lzcntl(Register dst, Operand src); 1921cb0ef41Sopenharmony_ci void Tzcntq(Register dst, Register src); 1931cb0ef41Sopenharmony_ci void Tzcntq(Register dst, Operand src); 1941cb0ef41Sopenharmony_ci void Tzcntl(Register dst, Register src); 1951cb0ef41Sopenharmony_ci void Tzcntl(Register dst, Operand src); 1961cb0ef41Sopenharmony_ci void Popcntl(Register dst, Register src); 1971cb0ef41Sopenharmony_ci void Popcntl(Register dst, Operand src); 1981cb0ef41Sopenharmony_ci void Popcntq(Register dst, Register src); 1991cb0ef41Sopenharmony_ci void Popcntq(Register dst, Operand src); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci void Cmp(Register dst, Smi src); 2021cb0ef41Sopenharmony_ci void Cmp(Operand dst, Smi src); 2031cb0ef41Sopenharmony_ci void Cmp(Register dst, int32_t src); 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 2061cb0ef41Sopenharmony_ci // Conversions between tagged smi values and non-tagged integer values. 2071cb0ef41Sopenharmony_ci 2081cb0ef41Sopenharmony_ci // Tag an word-size value. The result must be known to be a valid smi value. 2091cb0ef41Sopenharmony_ci void SmiTag(Register reg); 2101cb0ef41Sopenharmony_ci // Requires dst != src 2111cb0ef41Sopenharmony_ci void SmiTag(Register dst, Register src); 2121cb0ef41Sopenharmony_ci 2131cb0ef41Sopenharmony_ci // Simple comparison of smis. Both sides must be known smis to use these, 2141cb0ef41Sopenharmony_ci // otherwise use Cmp. 2151cb0ef41Sopenharmony_ci void SmiCompare(Register smi1, Register smi2); 2161cb0ef41Sopenharmony_ci void SmiCompare(Register dst, Smi src); 2171cb0ef41Sopenharmony_ci void SmiCompare(Register dst, Operand src); 2181cb0ef41Sopenharmony_ci void SmiCompare(Operand dst, Register src); 2191cb0ef41Sopenharmony_ci void SmiCompare(Operand dst, Smi src); 2201cb0ef41Sopenharmony_ci 2211cb0ef41Sopenharmony_ci // Functions performing a check on a known or potential smi. Returns 2221cb0ef41Sopenharmony_ci // a condition that is satisfied if the check is successful. 2231cb0ef41Sopenharmony_ci Condition CheckSmi(Register src); 2241cb0ef41Sopenharmony_ci Condition CheckSmi(Operand src); 2251cb0ef41Sopenharmony_ci 2261cb0ef41Sopenharmony_ci // Abort execution if argument is a smi, enabled via --debug-code. 2271cb0ef41Sopenharmony_ci void AssertNotSmi(Register object); 2281cb0ef41Sopenharmony_ci 2291cb0ef41Sopenharmony_ci // Abort execution if argument is not a smi, enabled via --debug-code. 2301cb0ef41Sopenharmony_ci void AssertSmi(Register object); 2311cb0ef41Sopenharmony_ci void AssertSmi(Operand object); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci // Test-and-jump functions. Typically combines a check function 2341cb0ef41Sopenharmony_ci // above with a conditional jump. 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci // Jump to label if the value is a tagged smi. 2371cb0ef41Sopenharmony_ci void JumpIfSmi(Register src, Label* on_smi, 2381cb0ef41Sopenharmony_ci Label::Distance near_jump = Label::kFar); 2391cb0ef41Sopenharmony_ci 2401cb0ef41Sopenharmony_ci // Jump to label if the value is not a tagged smi. 2411cb0ef41Sopenharmony_ci void JumpIfNotSmi(Register src, Label* on_not_smi, 2421cb0ef41Sopenharmony_ci Label::Distance near_jump = Label::kFar); 2431cb0ef41Sopenharmony_ci 2441cb0ef41Sopenharmony_ci // Jump to label if the value is not a tagged smi. 2451cb0ef41Sopenharmony_ci void JumpIfNotSmi(Operand src, Label* on_not_smi, 2461cb0ef41Sopenharmony_ci Label::Distance near_jump = Label::kFar); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci // Operations on tagged smi values. 2491cb0ef41Sopenharmony_ci 2501cb0ef41Sopenharmony_ci // Smis represent a subset of integers. The subset is always equivalent to 2511cb0ef41Sopenharmony_ci // a two's complement interpretation of a fixed number of bits. 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci // Add an integer constant to a tagged smi, giving a tagged smi as result. 2541cb0ef41Sopenharmony_ci // No overflow testing on the result is done. 2551cb0ef41Sopenharmony_ci void SmiAddConstant(Operand dst, Smi constant); 2561cb0ef41Sopenharmony_ci 2571cb0ef41Sopenharmony_ci // Specialized operations 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci // Converts, if necessary, a smi to a combination of number and 2601cb0ef41Sopenharmony_ci // multiplier to be used as a scaled index. 2611cb0ef41Sopenharmony_ci // The src register contains a *positive* smi value. The shift is the 2621cb0ef41Sopenharmony_ci // power of two to multiply the index value by (e.g. to index by 2631cb0ef41Sopenharmony_ci // smi-value * kSystemPointerSize, pass the smi and kSystemPointerSizeLog2). 2641cb0ef41Sopenharmony_ci // The returned index register may be either src or dst, depending 2651cb0ef41Sopenharmony_ci // on what is most efficient. If src and dst are different registers, 2661cb0ef41Sopenharmony_ci // src is always unchanged. 2671cb0ef41Sopenharmony_ci SmiIndex SmiToIndex(Register dst, Register src, int shift); 2681cb0ef41Sopenharmony_ci 2691cb0ef41Sopenharmony_ci void JumpIfEqual(Register a, int32_t b, Label* dest) { 2701cb0ef41Sopenharmony_ci cmpl(a, Immediate(b)); 2711cb0ef41Sopenharmony_ci j(equal, dest); 2721cb0ef41Sopenharmony_ci } 2731cb0ef41Sopenharmony_ci 2741cb0ef41Sopenharmony_ci void JumpIfLessThan(Register a, int32_t b, Label* dest) { 2751cb0ef41Sopenharmony_ci cmpl(a, Immediate(b)); 2761cb0ef41Sopenharmony_ci j(less, dest); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci 2791cb0ef41Sopenharmony_ci#ifdef V8_MAP_PACKING 2801cb0ef41Sopenharmony_ci void UnpackMapWord(Register r); 2811cb0ef41Sopenharmony_ci#endif 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci void LoadMap(Register destination, Register object); 2841cb0ef41Sopenharmony_ci 2851cb0ef41Sopenharmony_ci void Move(Register dst, intptr_t x) { 2861cb0ef41Sopenharmony_ci if (x == 0) { 2871cb0ef41Sopenharmony_ci xorl(dst, dst); 2881cb0ef41Sopenharmony_ci // The following shorter sequence for uint8 causes performance 2891cb0ef41Sopenharmony_ci // regressions: 2901cb0ef41Sopenharmony_ci // xorl(dst, dst); movb(dst, 2911cb0ef41Sopenharmony_ci // Immediate(static_cast<uint32_t>(x))); 2921cb0ef41Sopenharmony_ci } else if (is_uint32(x)) { 2931cb0ef41Sopenharmony_ci movl(dst, Immediate(static_cast<uint32_t>(x))); 2941cb0ef41Sopenharmony_ci } else if (is_int32(x)) { 2951cb0ef41Sopenharmony_ci // "movq reg64, imm32" is sign extending. 2961cb0ef41Sopenharmony_ci movq(dst, Immediate(static_cast<int32_t>(x))); 2971cb0ef41Sopenharmony_ci } else { 2981cb0ef41Sopenharmony_ci movq(dst, Immediate64(x)); 2991cb0ef41Sopenharmony_ci } 3001cb0ef41Sopenharmony_ci } 3011cb0ef41Sopenharmony_ci void Move(Operand dst, intptr_t x); 3021cb0ef41Sopenharmony_ci void Move(Register dst, Smi source); 3031cb0ef41Sopenharmony_ci 3041cb0ef41Sopenharmony_ci void Move(Operand dst, Smi source) { 3051cb0ef41Sopenharmony_ci Register constant = GetSmiConstant(source); 3061cb0ef41Sopenharmony_ci movq(dst, constant); 3071cb0ef41Sopenharmony_ci } 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci void Move(Register dst, TaggedIndex source) { Move(dst, source.ptr()); } 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci void Move(Operand dst, TaggedIndex source) { Move(dst, source.ptr()); } 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci void Move(Register dst, ExternalReference ext); 3141cb0ef41Sopenharmony_ci 3151cb0ef41Sopenharmony_ci void Move(XMMRegister dst, uint32_t src); 3161cb0ef41Sopenharmony_ci void Move(XMMRegister dst, uint64_t src); 3171cb0ef41Sopenharmony_ci void Move(XMMRegister dst, float src) { Move(dst, bit_cast<uint32_t>(src)); } 3181cb0ef41Sopenharmony_ci void Move(XMMRegister dst, double src) { Move(dst, bit_cast<uint64_t>(src)); } 3191cb0ef41Sopenharmony_ci void Move(XMMRegister dst, uint64_t high, uint64_t low); 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci // Move if the registers are not identical. 3221cb0ef41Sopenharmony_ci void Move(Register target, Register source); 3231cb0ef41Sopenharmony_ci void Move(XMMRegister target, XMMRegister source); 3241cb0ef41Sopenharmony_ci 3251cb0ef41Sopenharmony_ci void Move(Register target, Operand source); 3261cb0ef41Sopenharmony_ci void Move(Register target, Immediate source); 3271cb0ef41Sopenharmony_ci 3281cb0ef41Sopenharmony_ci void Move(Register dst, Handle<HeapObject> source, 3291cb0ef41Sopenharmony_ci RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT); 3301cb0ef41Sopenharmony_ci void Move(Operand dst, Handle<HeapObject> source, 3311cb0ef41Sopenharmony_ci RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT); 3321cb0ef41Sopenharmony_ci 3331cb0ef41Sopenharmony_ci // Loads a pointer into a register with a relocation mode. 3341cb0ef41Sopenharmony_ci void Move(Register dst, Address ptr, RelocInfo::Mode rmode) { 3351cb0ef41Sopenharmony_ci // This method must not be used with heap object references. The stored 3361cb0ef41Sopenharmony_ci // address is not GC safe. Use the handle version instead. 3371cb0ef41Sopenharmony_ci DCHECK(rmode == RelocInfo::NO_INFO || rmode > RelocInfo::LAST_GCED_ENUM); 3381cb0ef41Sopenharmony_ci movq(dst, Immediate64(ptr, rmode)); 3391cb0ef41Sopenharmony_ci } 3401cb0ef41Sopenharmony_ci 3411cb0ef41Sopenharmony_ci // Move src0 to dst0 and src1 to dst1, handling possible overlaps. 3421cb0ef41Sopenharmony_ci void MovePair(Register dst0, Register src0, Register dst1, Register src1); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci void MoveStringConstant( 3451cb0ef41Sopenharmony_ci Register result, const StringConstantBase* string, 3461cb0ef41Sopenharmony_ci RelocInfo::Mode rmode = RelocInfo::FULL_EMBEDDED_OBJECT); 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci // Convert smi to word-size sign-extended value. 3491cb0ef41Sopenharmony_ci void SmiUntag(Register reg); 3501cb0ef41Sopenharmony_ci // Requires dst != src 3511cb0ef41Sopenharmony_ci void SmiUntag(Register dst, Register src); 3521cb0ef41Sopenharmony_ci void SmiUntag(Register dst, Operand src); 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci // Convert smi to 32-bit value. 3551cb0ef41Sopenharmony_ci void SmiToInt32(Register reg); 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci // Loads the address of the external reference into the destination 3581cb0ef41Sopenharmony_ci // register. 3591cb0ef41Sopenharmony_ci void LoadAddress(Register destination, ExternalReference source); 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci void LoadFromConstantsTable(Register destination, int constant_index) final; 3621cb0ef41Sopenharmony_ci void LoadRootRegisterOffset(Register destination, intptr_t offset) final; 3631cb0ef41Sopenharmony_ci void LoadRootRelative(Register destination, int32_t offset) final; 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci // Operand pointing to an external reference. 3661cb0ef41Sopenharmony_ci // May emit code to set up the scratch register. The operand is 3671cb0ef41Sopenharmony_ci // only guaranteed to be correct as long as the scratch register 3681cb0ef41Sopenharmony_ci // isn't changed. 3691cb0ef41Sopenharmony_ci // If the operand is used more than once, use a scratch register 3701cb0ef41Sopenharmony_ci // that is guaranteed not to be clobbered. 3711cb0ef41Sopenharmony_ci Operand ExternalReferenceAsOperand(ExternalReference reference, 3721cb0ef41Sopenharmony_ci Register scratch = kScratchRegister); 3731cb0ef41Sopenharmony_ci 3741cb0ef41Sopenharmony_ci void Call(Register reg) { call(reg); } 3751cb0ef41Sopenharmony_ci void Call(Operand op); 3761cb0ef41Sopenharmony_ci void Call(Handle<CodeT> code_object, RelocInfo::Mode rmode); 3771cb0ef41Sopenharmony_ci void Call(Address destination, RelocInfo::Mode rmode); 3781cb0ef41Sopenharmony_ci void Call(ExternalReference ext); 3791cb0ef41Sopenharmony_ci void Call(Label* target) { call(target); } 3801cb0ef41Sopenharmony_ci 3811cb0ef41Sopenharmony_ci Operand EntryFromBuiltinAsOperand(Builtin builtin_index); 3821cb0ef41Sopenharmony_ci Operand EntryFromBuiltinIndexAsOperand(Register builtin_index); 3831cb0ef41Sopenharmony_ci void CallBuiltinByIndex(Register builtin_index); 3841cb0ef41Sopenharmony_ci void CallBuiltin(Builtin builtin); 3851cb0ef41Sopenharmony_ci void TailCallBuiltin(Builtin builtin); 3861cb0ef41Sopenharmony_ci 3871cb0ef41Sopenharmony_ci void LoadCodeObjectEntry(Register destination, Register code_object); 3881cb0ef41Sopenharmony_ci void CallCodeObject(Register code_object); 3891cb0ef41Sopenharmony_ci void JumpCodeObject(Register code_object, 3901cb0ef41Sopenharmony_ci JumpMode jump_mode = JumpMode::kJump); 3911cb0ef41Sopenharmony_ci 3921cb0ef41Sopenharmony_ci // Load code entry point from the CodeDataContainer object. 3931cb0ef41Sopenharmony_ci void LoadCodeDataContainerEntry(Register destination, 3941cb0ef41Sopenharmony_ci Register code_data_container_object); 3951cb0ef41Sopenharmony_ci // Load code entry point from the CodeDataContainer object and compute 3961cb0ef41Sopenharmony_ci // Code object pointer out of it. Must not be used for CodeDataContainers 3971cb0ef41Sopenharmony_ci // corresponding to builtins, because their entry points values point to 3981cb0ef41Sopenharmony_ci // the embedded instruction stream in .text section. 3991cb0ef41Sopenharmony_ci void LoadCodeDataContainerCodeNonBuiltin(Register destination, 4001cb0ef41Sopenharmony_ci Register code_data_container_object); 4011cb0ef41Sopenharmony_ci void CallCodeDataContainerObject(Register code_data_container_object); 4021cb0ef41Sopenharmony_ci void JumpCodeDataContainerObject(Register code_data_container_object, 4031cb0ef41Sopenharmony_ci JumpMode jump_mode = JumpMode::kJump); 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci // Helper functions that dispatch either to Call/JumpCodeObject or to 4061cb0ef41Sopenharmony_ci // Call/JumpCodeDataContainerObject. 4071cb0ef41Sopenharmony_ci // TODO(v8:11880): remove since CodeT targets are now default. 4081cb0ef41Sopenharmony_ci void LoadCodeTEntry(Register destination, Register code); 4091cb0ef41Sopenharmony_ci void CallCodeTObject(Register code); 4101cb0ef41Sopenharmony_ci void JumpCodeTObject(Register code, JumpMode jump_mode = JumpMode::kJump); 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci void Jump(Address destination, RelocInfo::Mode rmode); 4131cb0ef41Sopenharmony_ci void Jump(const ExternalReference& reference); 4141cb0ef41Sopenharmony_ci void Jump(Operand op); 4151cb0ef41Sopenharmony_ci void Jump(Handle<CodeT> code_object, RelocInfo::Mode rmode, 4161cb0ef41Sopenharmony_ci Condition cc = always); 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci void BailoutIfDeoptimized(Register scratch); 4191cb0ef41Sopenharmony_ci void CallForDeoptimization(Builtin target, int deopt_id, Label* exit, 4201cb0ef41Sopenharmony_ci DeoptimizeKind kind, Label* ret, 4211cb0ef41Sopenharmony_ci Label* jump_deoptimization_entry_label); 4221cb0ef41Sopenharmony_ci 4231cb0ef41Sopenharmony_ci void Trap(); 4241cb0ef41Sopenharmony_ci void DebugBreak(); 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci void CompareRoot(Register with, RootIndex index); 4271cb0ef41Sopenharmony_ci void CompareRoot(Operand with, RootIndex index); 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci // Generates function and stub prologue code. 4301cb0ef41Sopenharmony_ci void StubPrologue(StackFrame::Type type); 4311cb0ef41Sopenharmony_ci void Prologue(); 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci // Helpers for argument handling 4341cb0ef41Sopenharmony_ci enum ArgumentsCountMode { kCountIncludesReceiver, kCountExcludesReceiver }; 4351cb0ef41Sopenharmony_ci enum ArgumentsCountType { kCountIsInteger, kCountIsSmi, kCountIsBytes }; 4361cb0ef41Sopenharmony_ci void DropArguments(Register count, Register scratch, ArgumentsCountType type, 4371cb0ef41Sopenharmony_ci ArgumentsCountMode mode); 4381cb0ef41Sopenharmony_ci void DropArgumentsAndPushNewReceiver(Register argc, Register receiver, 4391cb0ef41Sopenharmony_ci Register scratch, 4401cb0ef41Sopenharmony_ci ArgumentsCountType type, 4411cb0ef41Sopenharmony_ci ArgumentsCountMode mode); 4421cb0ef41Sopenharmony_ci void DropArgumentsAndPushNewReceiver(Register argc, Operand receiver, 4431cb0ef41Sopenharmony_ci Register scratch, 4441cb0ef41Sopenharmony_ci ArgumentsCountType type, 4451cb0ef41Sopenharmony_ci ArgumentsCountMode mode); 4461cb0ef41Sopenharmony_ci 4471cb0ef41Sopenharmony_ci // Calls Abort(msg) if the condition cc is not satisfied. 4481cb0ef41Sopenharmony_ci // Use --debug_code to enable. 4491cb0ef41Sopenharmony_ci void Assert(Condition cc, AbortReason reason); 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci // Like Assert(), but without condition. 4521cb0ef41Sopenharmony_ci // Use --debug_code to enable. 4531cb0ef41Sopenharmony_ci void AssertUnreachable(AbortReason reason); 4541cb0ef41Sopenharmony_ci 4551cb0ef41Sopenharmony_ci // Abort execution if a 64 bit register containing a 32 bit payload does not 4561cb0ef41Sopenharmony_ci // have zeros in the top 32 bits, enabled via --debug-code. 4571cb0ef41Sopenharmony_ci void AssertZeroExtended(Register reg); 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci // Like Assert(), but always enabled. 4601cb0ef41Sopenharmony_ci void Check(Condition cc, AbortReason reason); 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci // Print a message to stdout and abort execution. 4631cb0ef41Sopenharmony_ci void Abort(AbortReason msg); 4641cb0ef41Sopenharmony_ci 4651cb0ef41Sopenharmony_ci // Check that the stack is aligned. 4661cb0ef41Sopenharmony_ci void CheckStackAlignment(); 4671cb0ef41Sopenharmony_ci 4681cb0ef41Sopenharmony_ci // Activation support. 4691cb0ef41Sopenharmony_ci void EnterFrame(StackFrame::Type type); 4701cb0ef41Sopenharmony_ci void EnterFrame(StackFrame::Type type, bool load_constant_pool_pointer_reg) { 4711cb0ef41Sopenharmony_ci // Out-of-line constant pool not implemented on x64. 4721cb0ef41Sopenharmony_ci UNREACHABLE(); 4731cb0ef41Sopenharmony_ci } 4741cb0ef41Sopenharmony_ci void LeaveFrame(StackFrame::Type type); 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci// Allocate stack space of given size (i.e. decrement {rsp} by the value 4771cb0ef41Sopenharmony_ci// stored in the given register, or by a constant). If you need to perform a 4781cb0ef41Sopenharmony_ci// stack check, do it before calling this function because this function may 4791cb0ef41Sopenharmony_ci// write into the newly allocated space. It may also overwrite the given 4801cb0ef41Sopenharmony_ci// register's value, in the version that takes a register. 4811cb0ef41Sopenharmony_ci#if defined(V8_TARGET_OS_WIN) || defined(V8_TARGET_OS_MACOS) 4821cb0ef41Sopenharmony_ci void AllocateStackSpace(Register bytes_scratch); 4831cb0ef41Sopenharmony_ci void AllocateStackSpace(int bytes); 4841cb0ef41Sopenharmony_ci#else 4851cb0ef41Sopenharmony_ci void AllocateStackSpace(Register bytes) { subq(rsp, bytes); } 4861cb0ef41Sopenharmony_ci void AllocateStackSpace(int bytes) { 4871cb0ef41Sopenharmony_ci DCHECK_GE(bytes, 0); 4881cb0ef41Sopenharmony_ci if (bytes == 0) return; 4891cb0ef41Sopenharmony_ci subq(rsp, Immediate(bytes)); 4901cb0ef41Sopenharmony_ci } 4911cb0ef41Sopenharmony_ci#endif 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci void InitializeRootRegister() { 4941cb0ef41Sopenharmony_ci ExternalReference isolate_root = ExternalReference::isolate_root(isolate()); 4951cb0ef41Sopenharmony_ci Move(kRootRegister, isolate_root); 4961cb0ef41Sopenharmony_ci#ifdef V8_COMPRESS_POINTERS_IN_SHARED_CAGE 4971cb0ef41Sopenharmony_ci LoadRootRelative(kPtrComprCageBaseRegister, 4981cb0ef41Sopenharmony_ci IsolateData::cage_base_offset()); 4991cb0ef41Sopenharmony_ci#endif 5001cb0ef41Sopenharmony_ci } 5011cb0ef41Sopenharmony_ci 5021cb0ef41Sopenharmony_ci void MaybeSaveRegisters(RegList registers); 5031cb0ef41Sopenharmony_ci void MaybeRestoreRegisters(RegList registers); 5041cb0ef41Sopenharmony_ci 5051cb0ef41Sopenharmony_ci void CallEphemeronKeyBarrier(Register object, Register slot_address, 5061cb0ef41Sopenharmony_ci SaveFPRegsMode fp_mode); 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci void CallRecordWriteStubSaveRegisters( 5091cb0ef41Sopenharmony_ci Register object, Register slot_address, 5101cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, 5111cb0ef41Sopenharmony_ci StubCallMode mode = StubCallMode::kCallBuiltinPointer); 5121cb0ef41Sopenharmony_ci void CallRecordWriteStub( 5131cb0ef41Sopenharmony_ci Register object, Register slot_address, 5141cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action, SaveFPRegsMode fp_mode, 5151cb0ef41Sopenharmony_ci StubCallMode mode = StubCallMode::kCallBuiltinPointer); 5161cb0ef41Sopenharmony_ci 5171cb0ef41Sopenharmony_ci#ifdef V8_IS_TSAN 5181cb0ef41Sopenharmony_ci void CallTSANStoreStub(Register address, Register value, 5191cb0ef41Sopenharmony_ci SaveFPRegsMode fp_mode, int size, StubCallMode mode, 5201cb0ef41Sopenharmony_ci std::memory_order order); 5211cb0ef41Sopenharmony_ci void CallTSANRelaxedLoadStub(Register address, SaveFPRegsMode fp_mode, 5221cb0ef41Sopenharmony_ci int size, StubCallMode mode); 5231cb0ef41Sopenharmony_ci#endif // V8_IS_TSAN 5241cb0ef41Sopenharmony_ci 5251cb0ef41Sopenharmony_ci void MoveNumber(Register dst, double value); 5261cb0ef41Sopenharmony_ci void MoveNonSmi(Register dst, double value); 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci // Calculate how much stack space (in bytes) are required to store caller 5291cb0ef41Sopenharmony_ci // registers excluding those specified in the arguments. 5301cb0ef41Sopenharmony_ci int RequiredStackSizeForCallerSaved(SaveFPRegsMode fp_mode, 5311cb0ef41Sopenharmony_ci Register exclusion1 = no_reg, 5321cb0ef41Sopenharmony_ci Register exclusion2 = no_reg, 5331cb0ef41Sopenharmony_ci Register exclusion3 = no_reg) const; 5341cb0ef41Sopenharmony_ci 5351cb0ef41Sopenharmony_ci // PushCallerSaved and PopCallerSaved do not arrange the registers in any 5361cb0ef41Sopenharmony_ci // particular order so they are not useful for calls that can cause a GC. 5371cb0ef41Sopenharmony_ci // The caller can exclude up to 3 registers that do not need to be saved and 5381cb0ef41Sopenharmony_ci // restored. 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ci // Push caller saved registers on the stack, and return the number of bytes 5411cb0ef41Sopenharmony_ci // stack pointer is adjusted. 5421cb0ef41Sopenharmony_ci int PushCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg, 5431cb0ef41Sopenharmony_ci Register exclusion2 = no_reg, 5441cb0ef41Sopenharmony_ci Register exclusion3 = no_reg); 5451cb0ef41Sopenharmony_ci // Restore caller saved registers from the stack, and return the number of 5461cb0ef41Sopenharmony_ci // bytes stack pointer is adjusted. 5471cb0ef41Sopenharmony_ci int PopCallerSaved(SaveFPRegsMode fp_mode, Register exclusion1 = no_reg, 5481cb0ef41Sopenharmony_ci Register exclusion2 = no_reg, 5491cb0ef41Sopenharmony_ci Register exclusion3 = no_reg); 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci // Compute the start of the generated instruction stream from the current PC. 5521cb0ef41Sopenharmony_ci // This is an alternative to embedding the {CodeObject} handle as a reference. 5531cb0ef41Sopenharmony_ci void ComputeCodeStartAddress(Register dst); 5541cb0ef41Sopenharmony_ci 5551cb0ef41Sopenharmony_ci // Control-flow integrity: 5561cb0ef41Sopenharmony_ci 5571cb0ef41Sopenharmony_ci // Define a function entrypoint. This doesn't emit any code for this 5581cb0ef41Sopenharmony_ci // architecture, as control-flow integrity is not supported for it. 5591cb0ef41Sopenharmony_ci void CodeEntry() {} 5601cb0ef41Sopenharmony_ci // Define an exception handler. 5611cb0ef41Sopenharmony_ci void ExceptionHandler() {} 5621cb0ef41Sopenharmony_ci // Define an exception handler and bind a label. 5631cb0ef41Sopenharmony_ci void BindExceptionHandler(Label* label) { bind(label); } 5641cb0ef41Sopenharmony_ci 5651cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 5661cb0ef41Sopenharmony_ci // Pointer compression support 5671cb0ef41Sopenharmony_ci 5681cb0ef41Sopenharmony_ci // Loads a field containing a HeapObject and decompresses it if pointer 5691cb0ef41Sopenharmony_ci // compression is enabled. 5701cb0ef41Sopenharmony_ci void LoadTaggedPointerField(Register destination, Operand field_operand); 5711cb0ef41Sopenharmony_ci 5721cb0ef41Sopenharmony_ci // Loads a field containing a Smi and decompresses it if pointer compression 5731cb0ef41Sopenharmony_ci // is enabled. 5741cb0ef41Sopenharmony_ci void LoadTaggedSignedField(Register destination, Operand field_operand); 5751cb0ef41Sopenharmony_ci 5761cb0ef41Sopenharmony_ci // Loads a field containing any tagged value and decompresses it if necessary. 5771cb0ef41Sopenharmony_ci void LoadAnyTaggedField(Register destination, Operand field_operand); 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci // Loads a field containing a HeapObject, decompresses it if necessary and 5801cb0ef41Sopenharmony_ci // pushes full pointer to the stack. When pointer compression is enabled, 5811cb0ef41Sopenharmony_ci // uses |scratch| to decompress the value. 5821cb0ef41Sopenharmony_ci void PushTaggedPointerField(Operand field_operand, Register scratch); 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ci // Loads a field containing any tagged value, decompresses it if necessary and 5851cb0ef41Sopenharmony_ci // pushes the full pointer to the stack. When pointer compression is enabled, 5861cb0ef41Sopenharmony_ci // uses |scratch| to decompress the value. 5871cb0ef41Sopenharmony_ci void PushTaggedAnyField(Operand field_operand, Register scratch); 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci // Loads a field containing smi value and untags it. 5901cb0ef41Sopenharmony_ci void SmiUntagField(Register dst, Operand src); 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_ci // Compresses tagged value if necessary and stores it to given on-heap 5931cb0ef41Sopenharmony_ci // location. 5941cb0ef41Sopenharmony_ci void StoreTaggedField(Operand dst_field_operand, Immediate immediate); 5951cb0ef41Sopenharmony_ci void StoreTaggedField(Operand dst_field_operand, Register value); 5961cb0ef41Sopenharmony_ci void StoreTaggedSignedField(Operand dst_field_operand, Smi value); 5971cb0ef41Sopenharmony_ci void AtomicStoreTaggedField(Operand dst_field_operand, Register value); 5981cb0ef41Sopenharmony_ci 5991cb0ef41Sopenharmony_ci // The following macros work even when pointer compression is not enabled. 6001cb0ef41Sopenharmony_ci void DecompressTaggedSigned(Register destination, Operand field_operand); 6011cb0ef41Sopenharmony_ci void DecompressTaggedPointer(Register destination, Operand field_operand); 6021cb0ef41Sopenharmony_ci void DecompressTaggedPointer(Register destination, Register source); 6031cb0ef41Sopenharmony_ci void DecompressAnyTagged(Register destination, Operand field_operand); 6041cb0ef41Sopenharmony_ci 6051cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 6061cb0ef41Sopenharmony_ci // V8 Sandbox support 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_ci // Transform a SandboxedPointer from/to its encoded form, which is used when 6091cb0ef41Sopenharmony_ci // the pointer is stored on the heap and ensures that the pointer will always 6101cb0ef41Sopenharmony_ci // point into the sandbox. 6111cb0ef41Sopenharmony_ci void EncodeSandboxedPointer(Register value); 6121cb0ef41Sopenharmony_ci void DecodeSandboxedPointer(Register value); 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_ci // Load and decode a SandboxedPointer from the heap. 6151cb0ef41Sopenharmony_ci void LoadSandboxedPointerField(Register destination, Operand field_operand); 6161cb0ef41Sopenharmony_ci // Encode and store a SandboxedPointer to the heap. 6171cb0ef41Sopenharmony_ci void StoreSandboxedPointerField(Operand dst_field_operand, Register value); 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_ci enum class IsolateRootLocation { kInScratchRegister, kInRootRegister }; 6201cb0ef41Sopenharmony_ci // Loads a field containing off-heap pointer and does necessary decoding 6211cb0ef41Sopenharmony_ci // if sandboxed external pointers are enabled. 6221cb0ef41Sopenharmony_ci void LoadExternalPointerField(Register destination, Operand field_operand, 6231cb0ef41Sopenharmony_ci ExternalPointerTag tag, Register scratch, 6241cb0ef41Sopenharmony_ci IsolateRootLocation isolateRootLocation = 6251cb0ef41Sopenharmony_ci IsolateRootLocation::kInRootRegister); 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci protected: 6281cb0ef41Sopenharmony_ci static const int kSmiShift = kSmiTagSize + kSmiShiftSize; 6291cb0ef41Sopenharmony_ci 6301cb0ef41Sopenharmony_ci // Returns a register holding the smi value. The register MUST NOT be 6311cb0ef41Sopenharmony_ci // modified. It may be the "smi 1 constant" register. 6321cb0ef41Sopenharmony_ci Register GetSmiConstant(Smi value); 6331cb0ef41Sopenharmony_ci 6341cb0ef41Sopenharmony_ci // Drops arguments assuming that the return address was already popped. 6351cb0ef41Sopenharmony_ci void DropArguments(Register count, ArgumentsCountType type = kCountIsInteger, 6361cb0ef41Sopenharmony_ci ArgumentsCountMode mode = kCountExcludesReceiver); 6371cb0ef41Sopenharmony_ci}; 6381cb0ef41Sopenharmony_ci 6391cb0ef41Sopenharmony_ci// MacroAssembler implements a collection of frequently used macros. 6401cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE MacroAssembler : public TurboAssembler { 6411cb0ef41Sopenharmony_ci public: 6421cb0ef41Sopenharmony_ci using TurboAssembler::TurboAssembler; 6431cb0ef41Sopenharmony_ci 6441cb0ef41Sopenharmony_ci // Loads and stores the value of an external reference. 6451cb0ef41Sopenharmony_ci // Special case code for load and store to take advantage of 6461cb0ef41Sopenharmony_ci // load_rax/store_rax if possible/necessary. 6471cb0ef41Sopenharmony_ci // For other operations, just use: 6481cb0ef41Sopenharmony_ci // Operand operand = ExternalReferenceAsOperand(extref); 6491cb0ef41Sopenharmony_ci // operation(operand, ..); 6501cb0ef41Sopenharmony_ci void Load(Register destination, ExternalReference source); 6511cb0ef41Sopenharmony_ci void Store(ExternalReference destination, Register source); 6521cb0ef41Sopenharmony_ci 6531cb0ef41Sopenharmony_ci // Pushes the address of the external reference onto the stack. 6541cb0ef41Sopenharmony_ci void PushAddress(ExternalReference source); 6551cb0ef41Sopenharmony_ci 6561cb0ef41Sopenharmony_ci // Operations on roots in the root-array. 6571cb0ef41Sopenharmony_ci // Load a root value where the index (or part of it) is variable. 6581cb0ef41Sopenharmony_ci // The variable_offset register is added to the fixed_offset value 6591cb0ef41Sopenharmony_ci // to get the index into the root-array. 6601cb0ef41Sopenharmony_ci void PushRoot(RootIndex index); 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci // Compare the object in a register to a value and jump if they are equal. 6631cb0ef41Sopenharmony_ci void JumpIfRoot(Register with, RootIndex index, Label* if_equal, 6641cb0ef41Sopenharmony_ci Label::Distance if_equal_distance = Label::kFar) { 6651cb0ef41Sopenharmony_ci CompareRoot(with, index); 6661cb0ef41Sopenharmony_ci j(equal, if_equal, if_equal_distance); 6671cb0ef41Sopenharmony_ci } 6681cb0ef41Sopenharmony_ci void JumpIfRoot(Operand with, RootIndex index, Label* if_equal, 6691cb0ef41Sopenharmony_ci Label::Distance if_equal_distance = Label::kFar) { 6701cb0ef41Sopenharmony_ci CompareRoot(with, index); 6711cb0ef41Sopenharmony_ci j(equal, if_equal, if_equal_distance); 6721cb0ef41Sopenharmony_ci } 6731cb0ef41Sopenharmony_ci 6741cb0ef41Sopenharmony_ci // Compare the object in a register to a value and jump if they are not equal. 6751cb0ef41Sopenharmony_ci void JumpIfNotRoot(Register with, RootIndex index, Label* if_not_equal, 6761cb0ef41Sopenharmony_ci Label::Distance if_not_equal_distance = Label::kFar) { 6771cb0ef41Sopenharmony_ci CompareRoot(with, index); 6781cb0ef41Sopenharmony_ci j(not_equal, if_not_equal, if_not_equal_distance); 6791cb0ef41Sopenharmony_ci } 6801cb0ef41Sopenharmony_ci void JumpIfNotRoot(Operand with, RootIndex index, Label* if_not_equal, 6811cb0ef41Sopenharmony_ci Label::Distance if_not_equal_distance = Label::kFar) { 6821cb0ef41Sopenharmony_ci CompareRoot(with, index); 6831cb0ef41Sopenharmony_ci j(not_equal, if_not_equal, if_not_equal_distance); 6841cb0ef41Sopenharmony_ci } 6851cb0ef41Sopenharmony_ci 6861cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 6871cb0ef41Sopenharmony_ci // GC Support 6881cb0ef41Sopenharmony_ci 6891cb0ef41Sopenharmony_ci // Notify the garbage collector that we wrote a pointer into an object. 6901cb0ef41Sopenharmony_ci // |object| is the object being stored into, |value| is the object being 6911cb0ef41Sopenharmony_ci // stored. value and scratch registers are clobbered by the operation. 6921cb0ef41Sopenharmony_ci // The offset is the offset from the start of the object, not the offset from 6931cb0ef41Sopenharmony_ci // the tagged HeapObject pointer. For use with FieldOperand(reg, off). 6941cb0ef41Sopenharmony_ci void RecordWriteField( 6951cb0ef41Sopenharmony_ci Register object, int offset, Register value, Register slot_address, 6961cb0ef41Sopenharmony_ci SaveFPRegsMode save_fp, 6971cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action = RememberedSetAction::kEmit, 6981cb0ef41Sopenharmony_ci SmiCheck smi_check = SmiCheck::kInline); 6991cb0ef41Sopenharmony_ci 7001cb0ef41Sopenharmony_ci // For page containing |object| mark region covering |address| 7011cb0ef41Sopenharmony_ci // dirty. |object| is the object being stored into, |value| is the 7021cb0ef41Sopenharmony_ci // object being stored. The address and value registers are clobbered by the 7031cb0ef41Sopenharmony_ci // operation. RecordWrite filters out smis so it does not update 7041cb0ef41Sopenharmony_ci // the write barrier if the value is a smi. 7051cb0ef41Sopenharmony_ci void RecordWrite( 7061cb0ef41Sopenharmony_ci Register object, Register slot_address, Register value, 7071cb0ef41Sopenharmony_ci SaveFPRegsMode save_fp, 7081cb0ef41Sopenharmony_ci RememberedSetAction remembered_set_action = RememberedSetAction::kEmit, 7091cb0ef41Sopenharmony_ci SmiCheck smi_check = SmiCheck::kInline); 7101cb0ef41Sopenharmony_ci 7111cb0ef41Sopenharmony_ci // Enter specific kind of exit frame; either in normal or 7121cb0ef41Sopenharmony_ci // debug mode. Expects the number of arguments in register rax and 7131cb0ef41Sopenharmony_ci // sets up the number of arguments in register rdi and the pointer 7141cb0ef41Sopenharmony_ci // to the first argument in register rsi. 7151cb0ef41Sopenharmony_ci // 7161cb0ef41Sopenharmony_ci // Allocates arg_stack_space * kSystemPointerSize memory (not GCed) on the 7171cb0ef41Sopenharmony_ci // stack accessible via StackSpaceOperand. 7181cb0ef41Sopenharmony_ci void EnterExitFrame(int arg_stack_space = 0, bool save_doubles = false, 7191cb0ef41Sopenharmony_ci StackFrame::Type frame_type = StackFrame::EXIT); 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci // Enter specific kind of exit frame. Allocates 7221cb0ef41Sopenharmony_ci // (arg_stack_space * kSystemPointerSize) memory (not GCed) on the stack 7231cb0ef41Sopenharmony_ci // accessible via StackSpaceOperand. 7241cb0ef41Sopenharmony_ci void EnterApiExitFrame(int arg_stack_space); 7251cb0ef41Sopenharmony_ci 7261cb0ef41Sopenharmony_ci // Leave the current exit frame. Expects/provides the return value in 7271cb0ef41Sopenharmony_ci // register rax:rdx (untouched) and the pointer to the first 7281cb0ef41Sopenharmony_ci // argument in register rsi (if pop_arguments == true). 7291cb0ef41Sopenharmony_ci void LeaveExitFrame(bool save_doubles = false, bool pop_arguments = true); 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ci // Leave the current exit frame. Expects/provides the return value in 7321cb0ef41Sopenharmony_ci // register rax (untouched). 7331cb0ef41Sopenharmony_ci void LeaveApiExitFrame(); 7341cb0ef41Sopenharmony_ci 7351cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 7361cb0ef41Sopenharmony_ci // JavaScript invokes 7371cb0ef41Sopenharmony_ci 7381cb0ef41Sopenharmony_ci // Invoke the JavaScript function code by either calling or jumping. 7391cb0ef41Sopenharmony_ci void InvokeFunctionCode(Register function, Register new_target, 7401cb0ef41Sopenharmony_ci Register expected_parameter_count, 7411cb0ef41Sopenharmony_ci Register actual_parameter_count, InvokeType type); 7421cb0ef41Sopenharmony_ci 7431cb0ef41Sopenharmony_ci // On function call, call into the debugger. 7441cb0ef41Sopenharmony_ci void CallDebugOnFunctionCall(Register fun, Register new_target, 7451cb0ef41Sopenharmony_ci Register expected_parameter_count, 7461cb0ef41Sopenharmony_ci Register actual_parameter_count); 7471cb0ef41Sopenharmony_ci 7481cb0ef41Sopenharmony_ci // Invoke the JavaScript function in the given register. Changes the 7491cb0ef41Sopenharmony_ci // current context to the context in the function before invoking. 7501cb0ef41Sopenharmony_ci void InvokeFunction(Register function, Register new_target, 7511cb0ef41Sopenharmony_ci Register actual_parameter_count, InvokeType type); 7521cb0ef41Sopenharmony_ci 7531cb0ef41Sopenharmony_ci void InvokeFunction(Register function, Register new_target, 7541cb0ef41Sopenharmony_ci Register expected_parameter_count, 7551cb0ef41Sopenharmony_ci Register actual_parameter_count, InvokeType type); 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 7581cb0ef41Sopenharmony_ci // Macro instructions. 7591cb0ef41Sopenharmony_ci 7601cb0ef41Sopenharmony_ci using TurboAssembler::Cmp; 7611cb0ef41Sopenharmony_ci void Cmp(Register dst, Handle<Object> source); 7621cb0ef41Sopenharmony_ci void Cmp(Operand dst, Handle<Object> source); 7631cb0ef41Sopenharmony_ci 7641cb0ef41Sopenharmony_ci // Checks if value is in range [lower_limit, higher_limit] using a single 7651cb0ef41Sopenharmony_ci // comparison. Flags CF=1 or ZF=1 indicate the value is in the range 7661cb0ef41Sopenharmony_ci // (condition below_equal). 7671cb0ef41Sopenharmony_ci void CompareRange(Register value, unsigned lower_limit, 7681cb0ef41Sopenharmony_ci unsigned higher_limit); 7691cb0ef41Sopenharmony_ci void JumpIfIsInRange(Register value, unsigned lower_limit, 7701cb0ef41Sopenharmony_ci unsigned higher_limit, Label* on_in_range, 7711cb0ef41Sopenharmony_ci Label::Distance near_jump = Label::kFar); 7721cb0ef41Sopenharmony_ci 7731cb0ef41Sopenharmony_ci // Emit code to discard a non-negative number of pointer-sized elements 7741cb0ef41Sopenharmony_ci // from the stack, clobbering only the rsp register. 7751cb0ef41Sopenharmony_ci void Drop(int stack_elements); 7761cb0ef41Sopenharmony_ci // Emit code to discard a positive number of pointer-sized elements 7771cb0ef41Sopenharmony_ci // from the stack under the return address which remains on the top, 7781cb0ef41Sopenharmony_ci // clobbering the rsp register. 7791cb0ef41Sopenharmony_ci void DropUnderReturnAddress(int stack_elements, 7801cb0ef41Sopenharmony_ci Register scratch = kScratchRegister); 7811cb0ef41Sopenharmony_ci void PushQuad(Operand src); 7821cb0ef41Sopenharmony_ci void PushImm32(int32_t imm32); 7831cb0ef41Sopenharmony_ci void Pop(Register dst); 7841cb0ef41Sopenharmony_ci void Pop(Operand dst); 7851cb0ef41Sopenharmony_ci void PopQuad(Operand dst); 7861cb0ef41Sopenharmony_ci 7871cb0ef41Sopenharmony_ci // Generates a trampoline to jump to the off-heap instruction stream. 7881cb0ef41Sopenharmony_ci void JumpToOffHeapInstructionStream(Address entry); 7891cb0ef41Sopenharmony_ci 7901cb0ef41Sopenharmony_ci // Compare object type for heap object. 7911cb0ef41Sopenharmony_ci // Always use unsigned comparisons: above and below, not less and greater. 7921cb0ef41Sopenharmony_ci // Incoming register is heap_object and outgoing register is map. 7931cb0ef41Sopenharmony_ci // They may be the same register, and may be kScratchRegister. 7941cb0ef41Sopenharmony_ci void CmpObjectType(Register heap_object, InstanceType type, Register map); 7951cb0ef41Sopenharmony_ci 7961cb0ef41Sopenharmony_ci // Compare instance type for map. 7971cb0ef41Sopenharmony_ci // Always use unsigned comparisons: above and below, not less and greater. 7981cb0ef41Sopenharmony_ci void CmpInstanceType(Register map, InstanceType type); 7991cb0ef41Sopenharmony_ci 8001cb0ef41Sopenharmony_ci // Compare instance type ranges for a map (low and high inclusive) 8011cb0ef41Sopenharmony_ci // Always use unsigned comparisons: below_equal for a positive result. 8021cb0ef41Sopenharmony_ci void CmpInstanceTypeRange(Register map, Register instance_type_out, 8031cb0ef41Sopenharmony_ci InstanceType low, InstanceType high); 8041cb0ef41Sopenharmony_ci 8051cb0ef41Sopenharmony_ci template <typename Field> 8061cb0ef41Sopenharmony_ci void DecodeField(Register reg) { 8071cb0ef41Sopenharmony_ci static const int shift = Field::kShift; 8081cb0ef41Sopenharmony_ci static const int mask = Field::kMask >> Field::kShift; 8091cb0ef41Sopenharmony_ci if (shift != 0) { 8101cb0ef41Sopenharmony_ci shrq(reg, Immediate(shift)); 8111cb0ef41Sopenharmony_ci } 8121cb0ef41Sopenharmony_ci andq(reg, Immediate(mask)); 8131cb0ef41Sopenharmony_ci } 8141cb0ef41Sopenharmony_ci 8151cb0ef41Sopenharmony_ci // Abort execution if argument is not a CodeT, enabled via --debug-code. 8161cb0ef41Sopenharmony_ci void AssertCodeT(Register object); 8171cb0ef41Sopenharmony_ci 8181cb0ef41Sopenharmony_ci // Abort execution if argument is not a Constructor, enabled via --debug-code. 8191cb0ef41Sopenharmony_ci void AssertConstructor(Register object); 8201cb0ef41Sopenharmony_ci 8211cb0ef41Sopenharmony_ci // Abort execution if argument is not a JSFunction, enabled via --debug-code. 8221cb0ef41Sopenharmony_ci void AssertFunction(Register object); 8231cb0ef41Sopenharmony_ci 8241cb0ef41Sopenharmony_ci // Abort execution if argument is not a callable JSFunction, enabled via 8251cb0ef41Sopenharmony_ci // --debug-code. 8261cb0ef41Sopenharmony_ci void AssertCallableFunction(Register object); 8271cb0ef41Sopenharmony_ci 8281cb0ef41Sopenharmony_ci // Abort execution if argument is not a JSBoundFunction, 8291cb0ef41Sopenharmony_ci // enabled via --debug-code. 8301cb0ef41Sopenharmony_ci void AssertBoundFunction(Register object); 8311cb0ef41Sopenharmony_ci 8321cb0ef41Sopenharmony_ci // Abort execution if argument is not a JSGeneratorObject (or subclass), 8331cb0ef41Sopenharmony_ci // enabled via --debug-code. 8341cb0ef41Sopenharmony_ci void AssertGeneratorObject(Register object); 8351cb0ef41Sopenharmony_ci 8361cb0ef41Sopenharmony_ci // Abort execution if argument is not undefined or an AllocationSite, enabled 8371cb0ef41Sopenharmony_ci // via --debug-code. 8381cb0ef41Sopenharmony_ci void AssertUndefinedOrAllocationSite(Register object); 8391cb0ef41Sopenharmony_ci 8401cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 8411cb0ef41Sopenharmony_ci // Exception handling 8421cb0ef41Sopenharmony_ci 8431cb0ef41Sopenharmony_ci // Push a new stack handler and link it into stack handler chain. 8441cb0ef41Sopenharmony_ci void PushStackHandler(); 8451cb0ef41Sopenharmony_ci 8461cb0ef41Sopenharmony_ci // Unlink the stack handler on top of the stack from the stack handler chain. 8471cb0ef41Sopenharmony_ci void PopStackHandler(); 8481cb0ef41Sopenharmony_ci 8491cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 8501cb0ef41Sopenharmony_ci // Support functions. 8511cb0ef41Sopenharmony_ci 8521cb0ef41Sopenharmony_ci // Load the global proxy from the current context. 8531cb0ef41Sopenharmony_ci void LoadGlobalProxy(Register dst) { 8541cb0ef41Sopenharmony_ci LoadNativeContextSlot(dst, Context::GLOBAL_PROXY_INDEX); 8551cb0ef41Sopenharmony_ci } 8561cb0ef41Sopenharmony_ci 8571cb0ef41Sopenharmony_ci // Load the native context slot with the current index. 8581cb0ef41Sopenharmony_ci void LoadNativeContextSlot(Register dst, int index); 8591cb0ef41Sopenharmony_ci 8601cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 8611cb0ef41Sopenharmony_ci // Runtime calls 8621cb0ef41Sopenharmony_ci 8631cb0ef41Sopenharmony_ci // Call a runtime routine. 8641cb0ef41Sopenharmony_ci void CallRuntime(const Runtime::Function* f, int num_arguments, 8651cb0ef41Sopenharmony_ci SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore); 8661cb0ef41Sopenharmony_ci 8671cb0ef41Sopenharmony_ci // Convenience function: Same as above, but takes the fid instead. 8681cb0ef41Sopenharmony_ci void CallRuntime(Runtime::FunctionId fid, 8691cb0ef41Sopenharmony_ci SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) { 8701cb0ef41Sopenharmony_ci const Runtime::Function* function = Runtime::FunctionForId(fid); 8711cb0ef41Sopenharmony_ci CallRuntime(function, function->nargs, save_doubles); 8721cb0ef41Sopenharmony_ci } 8731cb0ef41Sopenharmony_ci 8741cb0ef41Sopenharmony_ci // Convenience function: Same as above, but takes the fid instead. 8751cb0ef41Sopenharmony_ci void CallRuntime(Runtime::FunctionId fid, int num_arguments, 8761cb0ef41Sopenharmony_ci SaveFPRegsMode save_doubles = SaveFPRegsMode::kIgnore) { 8771cb0ef41Sopenharmony_ci CallRuntime(Runtime::FunctionForId(fid), num_arguments, save_doubles); 8781cb0ef41Sopenharmony_ci } 8791cb0ef41Sopenharmony_ci 8801cb0ef41Sopenharmony_ci // Convenience function: tail call a runtime routine (jump) 8811cb0ef41Sopenharmony_ci void TailCallRuntime(Runtime::FunctionId fid); 8821cb0ef41Sopenharmony_ci 8831cb0ef41Sopenharmony_ci // Jump to a runtime routines 8841cb0ef41Sopenharmony_ci void JumpToExternalReference(const ExternalReference& ext, 8851cb0ef41Sopenharmony_ci bool builtin_exit_frame = false); 8861cb0ef41Sopenharmony_ci 8871cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 8881cb0ef41Sopenharmony_ci // StatsCounter support 8891cb0ef41Sopenharmony_ci void IncrementCounter(StatsCounter* counter, int value) { 8901cb0ef41Sopenharmony_ci if (!FLAG_native_code_counters) return; 8911cb0ef41Sopenharmony_ci EmitIncrementCounter(counter, value); 8921cb0ef41Sopenharmony_ci } 8931cb0ef41Sopenharmony_ci void EmitIncrementCounter(StatsCounter* counter, int value); 8941cb0ef41Sopenharmony_ci void DecrementCounter(StatsCounter* counter, int value) { 8951cb0ef41Sopenharmony_ci if (!FLAG_native_code_counters) return; 8961cb0ef41Sopenharmony_ci EmitDecrementCounter(counter, value); 8971cb0ef41Sopenharmony_ci } 8981cb0ef41Sopenharmony_ci void EmitDecrementCounter(StatsCounter* counter, int value); 8991cb0ef41Sopenharmony_ci 9001cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 9011cb0ef41Sopenharmony_ci // Stack limit utilities 9021cb0ef41Sopenharmony_ci Operand StackLimitAsOperand(StackLimitKind kind); 9031cb0ef41Sopenharmony_ci void StackOverflowCheck( 9041cb0ef41Sopenharmony_ci Register num_args, Label* stack_overflow, 9051cb0ef41Sopenharmony_ci Label::Distance stack_overflow_distance = Label::kFar); 9061cb0ef41Sopenharmony_ci 9071cb0ef41Sopenharmony_ci // --------------------------------------------------------------------------- 9081cb0ef41Sopenharmony_ci // In-place weak references. 9091cb0ef41Sopenharmony_ci void LoadWeakValue(Register in_out, Label* target_if_cleared); 9101cb0ef41Sopenharmony_ci 9111cb0ef41Sopenharmony_ci private: 9121cb0ef41Sopenharmony_ci // Helper functions for generating invokes. 9131cb0ef41Sopenharmony_ci void InvokePrologue(Register expected_parameter_count, 9141cb0ef41Sopenharmony_ci Register actual_parameter_count, Label* done, 9151cb0ef41Sopenharmony_ci InvokeType type); 9161cb0ef41Sopenharmony_ci 9171cb0ef41Sopenharmony_ci void EnterExitFramePrologue(Register saved_rax_reg, 9181cb0ef41Sopenharmony_ci StackFrame::Type frame_type); 9191cb0ef41Sopenharmony_ci 9201cb0ef41Sopenharmony_ci // Allocates arg_stack_space * kSystemPointerSize memory (not GCed) on the 9211cb0ef41Sopenharmony_ci // stack accessible via StackSpaceOperand. 9221cb0ef41Sopenharmony_ci void EnterExitFrameEpilogue(int arg_stack_space, bool save_doubles); 9231cb0ef41Sopenharmony_ci 9241cb0ef41Sopenharmony_ci void LeaveExitFrameEpilogue(); 9251cb0ef41Sopenharmony_ci 9261cb0ef41Sopenharmony_ci DISALLOW_IMPLICIT_CONSTRUCTORS(MacroAssembler); 9271cb0ef41Sopenharmony_ci}; 9281cb0ef41Sopenharmony_ci 9291cb0ef41Sopenharmony_ci// ----------------------------------------------------------------------------- 9301cb0ef41Sopenharmony_ci// Static helper functions. 9311cb0ef41Sopenharmony_ci 9321cb0ef41Sopenharmony_ci// Generate an Operand for loading a field from an object. 9331cb0ef41Sopenharmony_ciinline Operand FieldOperand(Register object, int offset) { 9341cb0ef41Sopenharmony_ci return Operand(object, offset - kHeapObjectTag); 9351cb0ef41Sopenharmony_ci} 9361cb0ef41Sopenharmony_ci 9371cb0ef41Sopenharmony_ci// Generate an Operand for loading an indexed field from an object. 9381cb0ef41Sopenharmony_ciinline Operand FieldOperand(Register object, Register index, ScaleFactor scale, 9391cb0ef41Sopenharmony_ci int offset) { 9401cb0ef41Sopenharmony_ci return Operand(object, index, scale, offset - kHeapObjectTag); 9411cb0ef41Sopenharmony_ci} 9421cb0ef41Sopenharmony_ci 9431cb0ef41Sopenharmony_ci// Provides access to exit frame stack space (not GCed). 9441cb0ef41Sopenharmony_ciinline Operand StackSpaceOperand(int index) { 9451cb0ef41Sopenharmony_ci#ifdef V8_TARGET_OS_WIN 9461cb0ef41Sopenharmony_ci const int kShaddowSpace = 4; 9471cb0ef41Sopenharmony_ci return Operand(rsp, (index + kShaddowSpace) * kSystemPointerSize); 9481cb0ef41Sopenharmony_ci#else 9491cb0ef41Sopenharmony_ci return Operand(rsp, index * kSystemPointerSize); 9501cb0ef41Sopenharmony_ci#endif 9511cb0ef41Sopenharmony_ci} 9521cb0ef41Sopenharmony_ci 9531cb0ef41Sopenharmony_ciinline Operand StackOperandForReturnAddress(int32_t disp) { 9541cb0ef41Sopenharmony_ci return Operand(rsp, disp); 9551cb0ef41Sopenharmony_ci} 9561cb0ef41Sopenharmony_ci 9571cb0ef41Sopenharmony_ci#define ACCESS_MASM(masm) masm-> 9581cb0ef41Sopenharmony_ci 9591cb0ef41Sopenharmony_ci} // namespace internal 9601cb0ef41Sopenharmony_ci} // namespace v8 9611cb0ef41Sopenharmony_ci 9621cb0ef41Sopenharmony_ci#endif // V8_CODEGEN_X64_MACRO_ASSEMBLER_X64_H_ 963