11cb0ef41Sopenharmony_ci// Copyright 2014 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_COMPILER_LINKAGE_H_ 61cb0ef41Sopenharmony_ci#define V8_COMPILER_LINKAGE_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/base/compiler-specific.h" 91cb0ef41Sopenharmony_ci#include "src/base/flags.h" 101cb0ef41Sopenharmony_ci#include "src/codegen/interface-descriptors.h" 111cb0ef41Sopenharmony_ci#include "src/codegen/machine-type.h" 121cb0ef41Sopenharmony_ci#include "src/codegen/register.h" 131cb0ef41Sopenharmony_ci#include "src/codegen/reglist.h" 141cb0ef41Sopenharmony_ci#include "src/codegen/signature.h" 151cb0ef41Sopenharmony_ci#include "src/common/globals.h" 161cb0ef41Sopenharmony_ci#include "src/compiler/frame.h" 171cb0ef41Sopenharmony_ci#include "src/compiler/operator.h" 181cb0ef41Sopenharmony_ci#include "src/execution/encoded-c-signature.h" 191cb0ef41Sopenharmony_ci#include "src/runtime/runtime.h" 201cb0ef41Sopenharmony_ci#include "src/zone/zone.h" 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_ci#if !defined(__clang__) && defined(_M_ARM64) 231cb0ef41Sopenharmony_ci// _M_ARM64 is an MSVC-specific macro that clang-cl emulates. 241cb0ef41Sopenharmony_ci#define NO_INLINE_FOR_ARM64_MSVC __declspec(noinline) 251cb0ef41Sopenharmony_ci#else 261cb0ef41Sopenharmony_ci#define NO_INLINE_FOR_ARM64_MSVC 271cb0ef41Sopenharmony_ci#endif 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_cinamespace v8 { 301cb0ef41Sopenharmony_ciclass CFunctionInfo; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cinamespace internal { 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ciclass CallInterfaceDescriptor; 351cb0ef41Sopenharmony_ciclass OptimizedCompilationInfo; 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_cinamespace compiler { 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ciconstexpr RegList kNoCalleeSaved; 401cb0ef41Sopenharmony_ciconstexpr DoubleRegList kNoCalleeSavedFp; 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_ciclass OsrHelper; 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_ci// Describes the location for a parameter or a return value to a call. 451cb0ef41Sopenharmony_ciclass LinkageLocation { 461cb0ef41Sopenharmony_ci public: 471cb0ef41Sopenharmony_ci bool operator==(const LinkageLocation& other) const { 481cb0ef41Sopenharmony_ci return bit_field_ == other.bit_field_ && 491cb0ef41Sopenharmony_ci machine_type_ == other.machine_type_; 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci bool operator!=(const LinkageLocation& other) const { 531cb0ef41Sopenharmony_ci return !(*this == other); 541cb0ef41Sopenharmony_ci } 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ci static bool IsSameLocation(const LinkageLocation& a, 571cb0ef41Sopenharmony_ci const LinkageLocation& b) { 581cb0ef41Sopenharmony_ci // Different MachineTypes may end up at the same physical location. With the 591cb0ef41Sopenharmony_ci // sub-type check we make sure that types like {AnyTagged} and 601cb0ef41Sopenharmony_ci // {TaggedPointer} which would end up with the same physical location are 611cb0ef41Sopenharmony_ci // considered equal here. 621cb0ef41Sopenharmony_ci return (a.bit_field_ == b.bit_field_) && 631cb0ef41Sopenharmony_ci (IsSubtype(a.machine_type_.representation(), 641cb0ef41Sopenharmony_ci b.machine_type_.representation()) || 651cb0ef41Sopenharmony_ci IsSubtype(b.machine_type_.representation(), 661cb0ef41Sopenharmony_ci a.machine_type_.representation())); 671cb0ef41Sopenharmony_ci } 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci static LinkageLocation ForAnyRegister( 701cb0ef41Sopenharmony_ci MachineType type = MachineType::None()) { 711cb0ef41Sopenharmony_ci return LinkageLocation(REGISTER, ANY_REGISTER, type); 721cb0ef41Sopenharmony_ci } 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_ci static LinkageLocation ForRegister(int32_t reg, 751cb0ef41Sopenharmony_ci MachineType type = MachineType::None()) { 761cb0ef41Sopenharmony_ci DCHECK_LE(0, reg); 771cb0ef41Sopenharmony_ci return LinkageLocation(REGISTER, reg, type); 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci 801cb0ef41Sopenharmony_ci static LinkageLocation ForCallerFrameSlot(int32_t slot, MachineType type) { 811cb0ef41Sopenharmony_ci DCHECK_GT(0, slot); 821cb0ef41Sopenharmony_ci return LinkageLocation(STACK_SLOT, slot, type); 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci static LinkageLocation ForCalleeFrameSlot(int32_t slot, MachineType type) { 861cb0ef41Sopenharmony_ci // TODO(titzer): bailout instead of crashing here. 871cb0ef41Sopenharmony_ci DCHECK(slot >= 0 && slot < LinkageLocation::MAX_STACK_SLOT); 881cb0ef41Sopenharmony_ci return LinkageLocation(STACK_SLOT, slot, type); 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci 911cb0ef41Sopenharmony_ci static LinkageLocation ForSavedCallerReturnAddress() { 921cb0ef41Sopenharmony_ci return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - 931cb0ef41Sopenharmony_ci StandardFrameConstants::kCallerPCOffset) / 941cb0ef41Sopenharmony_ci kSystemPointerSize, 951cb0ef41Sopenharmony_ci MachineType::Pointer()); 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci static LinkageLocation ForSavedCallerFramePtr() { 991cb0ef41Sopenharmony_ci return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - 1001cb0ef41Sopenharmony_ci StandardFrameConstants::kCallerFPOffset) / 1011cb0ef41Sopenharmony_ci kSystemPointerSize, 1021cb0ef41Sopenharmony_ci MachineType::Pointer()); 1031cb0ef41Sopenharmony_ci } 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci static LinkageLocation ForSavedCallerConstantPool() { 1061cb0ef41Sopenharmony_ci DCHECK(V8_EMBEDDED_CONSTANT_POOL); 1071cb0ef41Sopenharmony_ci return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - 1081cb0ef41Sopenharmony_ci StandardFrameConstants::kConstantPoolOffset) / 1091cb0ef41Sopenharmony_ci kSystemPointerSize, 1101cb0ef41Sopenharmony_ci MachineType::AnyTagged()); 1111cb0ef41Sopenharmony_ci } 1121cb0ef41Sopenharmony_ci 1131cb0ef41Sopenharmony_ci static LinkageLocation ForSavedCallerFunction() { 1141cb0ef41Sopenharmony_ci return ForCalleeFrameSlot((StandardFrameConstants::kCallerPCOffset - 1151cb0ef41Sopenharmony_ci StandardFrameConstants::kFunctionOffset) / 1161cb0ef41Sopenharmony_ci kSystemPointerSize, 1171cb0ef41Sopenharmony_ci MachineType::AnyTagged()); 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci static LinkageLocation ConvertToTailCallerLocation( 1211cb0ef41Sopenharmony_ci LinkageLocation caller_location, int stack_param_delta) { 1221cb0ef41Sopenharmony_ci if (!caller_location.IsRegister()) { 1231cb0ef41Sopenharmony_ci return LinkageLocation(STACK_SLOT, 1241cb0ef41Sopenharmony_ci caller_location.GetLocation() + stack_param_delta, 1251cb0ef41Sopenharmony_ci caller_location.GetType()); 1261cb0ef41Sopenharmony_ci } 1271cb0ef41Sopenharmony_ci return caller_location; 1281cb0ef41Sopenharmony_ci } 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_ci MachineType GetType() const { return machine_type_; } 1311cb0ef41Sopenharmony_ci 1321cb0ef41Sopenharmony_ci int GetSizeInPointers() const { 1331cb0ef41Sopenharmony_ci return ElementSizeInPointers(GetType().representation()); 1341cb0ef41Sopenharmony_ci } 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci int32_t GetLocation() const { 1371cb0ef41Sopenharmony_ci // We can't use LocationField::decode here because it doesn't work for 1381cb0ef41Sopenharmony_ci // negative values! 1391cb0ef41Sopenharmony_ci return static_cast<int32_t>(bit_field_ & LocationField::kMask) >> 1401cb0ef41Sopenharmony_ci LocationField::kShift; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci NO_INLINE_FOR_ARM64_MSVC bool IsRegister() const { 1441cb0ef41Sopenharmony_ci return TypeField::decode(bit_field_) == REGISTER; 1451cb0ef41Sopenharmony_ci } 1461cb0ef41Sopenharmony_ci bool IsAnyRegister() const { 1471cb0ef41Sopenharmony_ci return IsRegister() && GetLocation() == ANY_REGISTER; 1481cb0ef41Sopenharmony_ci } 1491cb0ef41Sopenharmony_ci bool IsCallerFrameSlot() const { return !IsRegister() && GetLocation() < 0; } 1501cb0ef41Sopenharmony_ci bool IsCalleeFrameSlot() const { return !IsRegister() && GetLocation() >= 0; } 1511cb0ef41Sopenharmony_ci 1521cb0ef41Sopenharmony_ci int32_t AsRegister() const { 1531cb0ef41Sopenharmony_ci DCHECK(IsRegister()); 1541cb0ef41Sopenharmony_ci return GetLocation(); 1551cb0ef41Sopenharmony_ci } 1561cb0ef41Sopenharmony_ci int32_t AsCallerFrameSlot() const { 1571cb0ef41Sopenharmony_ci DCHECK(IsCallerFrameSlot()); 1581cb0ef41Sopenharmony_ci return GetLocation(); 1591cb0ef41Sopenharmony_ci } 1601cb0ef41Sopenharmony_ci int32_t AsCalleeFrameSlot() const { 1611cb0ef41Sopenharmony_ci DCHECK(IsCalleeFrameSlot()); 1621cb0ef41Sopenharmony_ci return GetLocation(); 1631cb0ef41Sopenharmony_ci } 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ci private: 1661cb0ef41Sopenharmony_ci enum LocationType { REGISTER, STACK_SLOT }; 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci using TypeField = base::BitField<LocationType, 0, 1>; 1691cb0ef41Sopenharmony_ci using LocationField = TypeField::Next<int32_t, 31>; 1701cb0ef41Sopenharmony_ci 1711cb0ef41Sopenharmony_ci static constexpr int32_t ANY_REGISTER = -1; 1721cb0ef41Sopenharmony_ci static constexpr int32_t MAX_STACK_SLOT = 32767; 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci LinkageLocation(LocationType type, int32_t location, 1751cb0ef41Sopenharmony_ci MachineType machine_type) { 1761cb0ef41Sopenharmony_ci bit_field_ = TypeField::encode(type) | 1771cb0ef41Sopenharmony_ci // {location} can be -1 (ANY_REGISTER). 1781cb0ef41Sopenharmony_ci ((static_cast<uint32_t>(location) << LocationField::kShift) & 1791cb0ef41Sopenharmony_ci LocationField::kMask); 1801cb0ef41Sopenharmony_ci machine_type_ = machine_type; 1811cb0ef41Sopenharmony_ci } 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci int32_t bit_field_; 1841cb0ef41Sopenharmony_ci MachineType machine_type_; 1851cb0ef41Sopenharmony_ci}; 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ciusing LocationSignature = Signature<LinkageLocation>; 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_ci// Describes a call to various parts of the compiler. Every call has the notion 1901cb0ef41Sopenharmony_ci// of a "target", which is the first input to the call. 1911cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CallDescriptor final 1921cb0ef41Sopenharmony_ci : public NON_EXPORTED_BASE(ZoneObject) { 1931cb0ef41Sopenharmony_ci public: 1941cb0ef41Sopenharmony_ci // Describes the kind of this call, which determines the target. 1951cb0ef41Sopenharmony_ci enum Kind { 1961cb0ef41Sopenharmony_ci kCallCodeObject, // target is a Code object 1971cb0ef41Sopenharmony_ci kCallJSFunction, // target is a JSFunction object 1981cb0ef41Sopenharmony_ci kCallAddress, // target is a machine pointer 1991cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY // ↓ WebAssembly only 2001cb0ef41Sopenharmony_ci kCallWasmCapiFunction, // target is a Wasm C API function 2011cb0ef41Sopenharmony_ci kCallWasmFunction, // target is a wasm function 2021cb0ef41Sopenharmony_ci kCallWasmImportWrapper, // target is a wasm import wrapper 2031cb0ef41Sopenharmony_ci#endif // ↑ WebAssembly only 2041cb0ef41Sopenharmony_ci kCallBuiltinPointer, // target is a builtin pointer 2051cb0ef41Sopenharmony_ci }; 2061cb0ef41Sopenharmony_ci 2071cb0ef41Sopenharmony_ci // NOTE: The lowest 10 bits of the Flags field are encoded in InstructionCode 2081cb0ef41Sopenharmony_ci // (for use in the code generator). All higher bits are lost. 2091cb0ef41Sopenharmony_ci static constexpr int kFlagsBitsEncodedInInstructionCode = 10; 2101cb0ef41Sopenharmony_ci enum Flag { 2111cb0ef41Sopenharmony_ci kNoFlags = 0u, 2121cb0ef41Sopenharmony_ci kNeedsFrameState = 1u << 0, 2131cb0ef41Sopenharmony_ci kHasExceptionHandler = 1u << 1, 2141cb0ef41Sopenharmony_ci kCanUseRoots = 1u << 2, 2151cb0ef41Sopenharmony_ci // Causes the code generator to initialize the root register. 2161cb0ef41Sopenharmony_ci kInitializeRootRegister = 1u << 3, 2171cb0ef41Sopenharmony_ci // Does not ever try to allocate space on our heap. 2181cb0ef41Sopenharmony_ci kNoAllocate = 1u << 4, 2191cb0ef41Sopenharmony_ci // Use the kJavaScriptCallCodeStartRegister (fixed) register for the 2201cb0ef41Sopenharmony_ci // indirect target address when calling. 2211cb0ef41Sopenharmony_ci kFixedTargetRegister = 1u << 5, 2221cb0ef41Sopenharmony_ci kCallerSavedRegisters = 1u << 6, 2231cb0ef41Sopenharmony_ci // The kCallerSavedFPRegisters only matters (and set) when the more general 2241cb0ef41Sopenharmony_ci // flag for kCallerSavedRegisters above is also set. 2251cb0ef41Sopenharmony_ci kCallerSavedFPRegisters = 1u << 7, 2261cb0ef41Sopenharmony_ci // Tail calls for tier up are special (in fact they are different enough 2271cb0ef41Sopenharmony_ci // from normal tail calls to warrant a dedicated opcode; but they also have 2281cb0ef41Sopenharmony_ci // enough similar aspects that reusing the TailCall opcode is pragmatic). 2291cb0ef41Sopenharmony_ci // Specifically: 2301cb0ef41Sopenharmony_ci // 2311cb0ef41Sopenharmony_ci // 1. Caller and callee are both JS-linkage Code objects. 2321cb0ef41Sopenharmony_ci // 2. JS runtime arguments are passed unchanged from caller to callee. 2331cb0ef41Sopenharmony_ci // 3. JS runtime arguments are not attached as inputs to the TailCall node. 2341cb0ef41Sopenharmony_ci // 4. Prior to the tail call, frame and register state is torn down to just 2351cb0ef41Sopenharmony_ci // before the caller frame was constructed. 2361cb0ef41Sopenharmony_ci // 5. Unlike normal tail calls, arguments adaptor frames (if present) are 2371cb0ef41Sopenharmony_ci // *not* torn down. 2381cb0ef41Sopenharmony_ci // 2391cb0ef41Sopenharmony_ci // In other words, behavior is identical to a jmp instruction prior caller 2401cb0ef41Sopenharmony_ci // frame construction. 2411cb0ef41Sopenharmony_ci kIsTailCallForTierUp = 1u << 8, 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci // AIX has a function descriptor by default but it can be disabled for a 2441cb0ef41Sopenharmony_ci // certain CFunction call (only used for Kind::kCallAddress). 2451cb0ef41Sopenharmony_ci kNoFunctionDescriptor = 1u << 9, 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci // Flags past here are *not* encoded in InstructionCode and are thus not 2481cb0ef41Sopenharmony_ci // accessible from the code generator. See also 2491cb0ef41Sopenharmony_ci // kFlagsBitsEncodedInInstructionCode. 2501cb0ef41Sopenharmony_ci }; 2511cb0ef41Sopenharmony_ci using Flags = base::Flags<Flag>; 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci CallDescriptor(Kind kind, MachineType target_type, LinkageLocation target_loc, 2541cb0ef41Sopenharmony_ci LocationSignature* location_sig, size_t param_slot_count, 2551cb0ef41Sopenharmony_ci Operator::Properties properties, 2561cb0ef41Sopenharmony_ci RegList callee_saved_registers, 2571cb0ef41Sopenharmony_ci DoubleRegList callee_saved_fp_registers, Flags flags, 2581cb0ef41Sopenharmony_ci const char* debug_name = "", 2591cb0ef41Sopenharmony_ci StackArgumentOrder stack_order = StackArgumentOrder::kDefault, 2601cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2611cb0ef41Sopenharmony_ci const wasm::FunctionSig* wasm_sig = nullptr, 2621cb0ef41Sopenharmony_ci#endif 2631cb0ef41Sopenharmony_ci const RegList allocatable_registers = {}, 2641cb0ef41Sopenharmony_ci size_t return_slot_count = 0) 2651cb0ef41Sopenharmony_ci : kind_(kind), 2661cb0ef41Sopenharmony_ci target_type_(target_type), 2671cb0ef41Sopenharmony_ci target_loc_(target_loc), 2681cb0ef41Sopenharmony_ci location_sig_(location_sig), 2691cb0ef41Sopenharmony_ci param_slot_count_(param_slot_count), 2701cb0ef41Sopenharmony_ci return_slot_count_(return_slot_count), 2711cb0ef41Sopenharmony_ci properties_(properties), 2721cb0ef41Sopenharmony_ci callee_saved_registers_(callee_saved_registers), 2731cb0ef41Sopenharmony_ci callee_saved_fp_registers_(callee_saved_fp_registers), 2741cb0ef41Sopenharmony_ci allocatable_registers_(allocatable_registers), 2751cb0ef41Sopenharmony_ci flags_(flags), 2761cb0ef41Sopenharmony_ci stack_order_(stack_order), 2771cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2781cb0ef41Sopenharmony_ci wasm_sig_(wasm_sig), 2791cb0ef41Sopenharmony_ci#endif 2801cb0ef41Sopenharmony_ci debug_name_(debug_name) { 2811cb0ef41Sopenharmony_ci } 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci CallDescriptor(const CallDescriptor&) = delete; 2841cb0ef41Sopenharmony_ci CallDescriptor& operator=(const CallDescriptor&) = delete; 2851cb0ef41Sopenharmony_ci 2861cb0ef41Sopenharmony_ci // Returns the kind of this call. 2871cb0ef41Sopenharmony_ci Kind kind() const { return kind_; } 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_ci // Returns {true} if this descriptor is a call to a C function. 2901cb0ef41Sopenharmony_ci bool IsCFunctionCall() const { return kind_ == kCallAddress; } 2911cb0ef41Sopenharmony_ci 2921cb0ef41Sopenharmony_ci // Returns {true} if this descriptor is a call to a JSFunction. 2931cb0ef41Sopenharmony_ci bool IsJSFunctionCall() const { return kind_ == kCallJSFunction; } 2941cb0ef41Sopenharmony_ci 2951cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 2961cb0ef41Sopenharmony_ci // Returns {true} if this descriptor is a call to a WebAssembly function. 2971cb0ef41Sopenharmony_ci bool IsWasmFunctionCall() const { return kind_ == kCallWasmFunction; } 2981cb0ef41Sopenharmony_ci 2991cb0ef41Sopenharmony_ci // Returns {true} if this descriptor is a call to a WebAssembly function. 3001cb0ef41Sopenharmony_ci bool IsWasmImportWrapper() const { return kind_ == kCallWasmImportWrapper; } 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci // Returns {true} if this descriptor is a call to a Wasm C API function. 3031cb0ef41Sopenharmony_ci bool IsWasmCapiFunction() const { return kind_ == kCallWasmCapiFunction; } 3041cb0ef41Sopenharmony_ci 3051cb0ef41Sopenharmony_ci // Returns the wasm signature for this call based on the real parameter types. 3061cb0ef41Sopenharmony_ci const wasm::FunctionSig* wasm_sig() const { return wasm_sig_; } 3071cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 3081cb0ef41Sopenharmony_ci 3091cb0ef41Sopenharmony_ci bool RequiresFrameAsIncoming() const { 3101cb0ef41Sopenharmony_ci if (IsCFunctionCall() || IsJSFunctionCall()) return true; 3111cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 3121cb0ef41Sopenharmony_ci if (IsWasmFunctionCall()) return true; 3131cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WEBASSEMBLY 3141cb0ef41Sopenharmony_ci if (CalleeSavedRegisters() != kNoCalleeSaved) return true; 3151cb0ef41Sopenharmony_ci return false; 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci // The number of return values from this call. 3191cb0ef41Sopenharmony_ci size_t ReturnCount() const { return location_sig_->return_count(); } 3201cb0ef41Sopenharmony_ci 3211cb0ef41Sopenharmony_ci // The number of C parameters to this call. The following invariant 3221cb0ef41Sopenharmony_ci // should hold true: 3231cb0ef41Sopenharmony_ci // ParameterCount() == GPParameterCount() + FPParameterCount() 3241cb0ef41Sopenharmony_ci size_t ParameterCount() const { return location_sig_->parameter_count(); } 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci // The number of general purpose C parameters to this call. 3271cb0ef41Sopenharmony_ci size_t GPParameterCount() const { 3281cb0ef41Sopenharmony_ci if (!gp_param_count_) { 3291cb0ef41Sopenharmony_ci ComputeParamCounts(); 3301cb0ef41Sopenharmony_ci } 3311cb0ef41Sopenharmony_ci return gp_param_count_.value(); 3321cb0ef41Sopenharmony_ci } 3331cb0ef41Sopenharmony_ci 3341cb0ef41Sopenharmony_ci // The number of floating point C parameters to this call. 3351cb0ef41Sopenharmony_ci size_t FPParameterCount() const { 3361cb0ef41Sopenharmony_ci if (!fp_param_count_) { 3371cb0ef41Sopenharmony_ci ComputeParamCounts(); 3381cb0ef41Sopenharmony_ci } 3391cb0ef41Sopenharmony_ci return fp_param_count_.value(); 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci 3421cb0ef41Sopenharmony_ci // The number of stack parameter slots to the call. 3431cb0ef41Sopenharmony_ci size_t ParameterSlotCount() const { return param_slot_count_; } 3441cb0ef41Sopenharmony_ci 3451cb0ef41Sopenharmony_ci // The number of stack return value slots from the call. 3461cb0ef41Sopenharmony_ci size_t ReturnSlotCount() const { return return_slot_count_; } 3471cb0ef41Sopenharmony_ci 3481cb0ef41Sopenharmony_ci // The number of parameters to the JS function call. 3491cb0ef41Sopenharmony_ci size_t JSParameterCount() const { 3501cb0ef41Sopenharmony_ci DCHECK(IsJSFunctionCall()); 3511cb0ef41Sopenharmony_ci return param_slot_count_; 3521cb0ef41Sopenharmony_ci } 3531cb0ef41Sopenharmony_ci 3541cb0ef41Sopenharmony_ci int GetStackIndexFromSlot(int slot_index) const { 3551cb0ef41Sopenharmony_ci switch (GetStackArgumentOrder()) { 3561cb0ef41Sopenharmony_ci case StackArgumentOrder::kDefault: 3571cb0ef41Sopenharmony_ci return -slot_index - 1; 3581cb0ef41Sopenharmony_ci case StackArgumentOrder::kJS: 3591cb0ef41Sopenharmony_ci return slot_index + static_cast<int>(ParameterSlotCount()); 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci // The total number of inputs to this call, which includes the target, 3641cb0ef41Sopenharmony_ci // receiver, context, etc. 3651cb0ef41Sopenharmony_ci // TODO(titzer): this should input the framestate input too. 3661cb0ef41Sopenharmony_ci size_t InputCount() const { return 1 + location_sig_->parameter_count(); } 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci size_t FrameStateCount() const { return NeedsFrameState() ? 1 : 0; } 3691cb0ef41Sopenharmony_ci 3701cb0ef41Sopenharmony_ci Flags flags() const { return flags_; } 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci bool NeedsFrameState() const { return flags() & kNeedsFrameState; } 3731cb0ef41Sopenharmony_ci bool InitializeRootRegister() const { 3741cb0ef41Sopenharmony_ci return flags() & kInitializeRootRegister; 3751cb0ef41Sopenharmony_ci } 3761cb0ef41Sopenharmony_ci bool NeedsCallerSavedRegisters() const { 3771cb0ef41Sopenharmony_ci return flags() & kCallerSavedRegisters; 3781cb0ef41Sopenharmony_ci } 3791cb0ef41Sopenharmony_ci bool NeedsCallerSavedFPRegisters() const { 3801cb0ef41Sopenharmony_ci return flags() & kCallerSavedFPRegisters; 3811cb0ef41Sopenharmony_ci } 3821cb0ef41Sopenharmony_ci bool IsTailCallForTierUp() const { return flags() & kIsTailCallForTierUp; } 3831cb0ef41Sopenharmony_ci bool NoFunctionDescriptor() const { return flags() & kNoFunctionDescriptor; } 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci LinkageLocation GetReturnLocation(size_t index) const { 3861cb0ef41Sopenharmony_ci return location_sig_->GetReturn(index); 3871cb0ef41Sopenharmony_ci } 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci LinkageLocation GetInputLocation(size_t index) const { 3901cb0ef41Sopenharmony_ci if (index == 0) return target_loc_; 3911cb0ef41Sopenharmony_ci return location_sig_->GetParam(index - 1); 3921cb0ef41Sopenharmony_ci } 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci MachineSignature* GetMachineSignature(Zone* zone) const; 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci MachineType GetReturnType(size_t index) const { 3971cb0ef41Sopenharmony_ci return location_sig_->GetReturn(index).GetType(); 3981cb0ef41Sopenharmony_ci } 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci MachineType GetInputType(size_t index) const { 4011cb0ef41Sopenharmony_ci if (index == 0) return target_type_; 4021cb0ef41Sopenharmony_ci return location_sig_->GetParam(index - 1).GetType(); 4031cb0ef41Sopenharmony_ci } 4041cb0ef41Sopenharmony_ci 4051cb0ef41Sopenharmony_ci MachineType GetParameterType(size_t index) const { 4061cb0ef41Sopenharmony_ci return location_sig_->GetParam(index).GetType(); 4071cb0ef41Sopenharmony_ci } 4081cb0ef41Sopenharmony_ci 4091cb0ef41Sopenharmony_ci StackArgumentOrder GetStackArgumentOrder() const { return stack_order_; } 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci // Operator properties describe how this call can be optimized, if at all. 4121cb0ef41Sopenharmony_ci Operator::Properties properties() const { return properties_; } 4131cb0ef41Sopenharmony_ci 4141cb0ef41Sopenharmony_ci // Get the callee-saved registers, if any, across this call. 4151cb0ef41Sopenharmony_ci RegList CalleeSavedRegisters() const { return callee_saved_registers_; } 4161cb0ef41Sopenharmony_ci 4171cb0ef41Sopenharmony_ci // Get the callee-saved FP registers, if any, across this call. 4181cb0ef41Sopenharmony_ci DoubleRegList CalleeSavedFPRegisters() const { 4191cb0ef41Sopenharmony_ci return callee_saved_fp_registers_; 4201cb0ef41Sopenharmony_ci } 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci const char* debug_name() const { return debug_name_; } 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci // Difference between the number of parameter slots of *this* and 4251cb0ef41Sopenharmony_ci // *tail_caller* (callee minus caller). 4261cb0ef41Sopenharmony_ci int GetStackParameterDelta(const CallDescriptor* tail_caller) const; 4271cb0ef41Sopenharmony_ci 4281cb0ef41Sopenharmony_ci // Returns the offset to the area below the parameter slots on the stack, 4291cb0ef41Sopenharmony_ci // relative to callee slot 0, the return address. If there are no parameter 4301cb0ef41Sopenharmony_ci // slots, returns +1. 4311cb0ef41Sopenharmony_ci int GetOffsetToFirstUnusedStackSlot() const; 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci // Returns the offset to the area above the return slots on the stack, 4341cb0ef41Sopenharmony_ci // relative to callee slot 0, the return address. If there are no return 4351cb0ef41Sopenharmony_ci // slots, returns the offset to the lowest slot of the parameter area. 4361cb0ef41Sopenharmony_ci // If there are no parameter slots, returns 0. 4371cb0ef41Sopenharmony_ci int GetOffsetToReturns() const; 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci // Returns two 16-bit numbers packed together: (first slot << 16) | num_slots. 4401cb0ef41Sopenharmony_ci uint32_t GetTaggedParameterSlots() const; 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci bool CanTailCall(const CallDescriptor* callee) const; 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci int CalculateFixedFrameSize(CodeKind code_kind) const; 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_ci RegList AllocatableRegisters() const { return allocatable_registers_; } 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci bool HasRestrictedAllocatableRegisters() const { 4491cb0ef41Sopenharmony_ci return !allocatable_registers_.is_empty(); 4501cb0ef41Sopenharmony_ci } 4511cb0ef41Sopenharmony_ci 4521cb0ef41Sopenharmony_ci EncodedCSignature ToEncodedCSignature() const; 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci private: 4551cb0ef41Sopenharmony_ci void ComputeParamCounts() const; 4561cb0ef41Sopenharmony_ci 4571cb0ef41Sopenharmony_ci friend class Linkage; 4581cb0ef41Sopenharmony_ci 4591cb0ef41Sopenharmony_ci const Kind kind_; 4601cb0ef41Sopenharmony_ci const MachineType target_type_; 4611cb0ef41Sopenharmony_ci const LinkageLocation target_loc_; 4621cb0ef41Sopenharmony_ci const LocationSignature* const location_sig_; 4631cb0ef41Sopenharmony_ci const size_t param_slot_count_; 4641cb0ef41Sopenharmony_ci const size_t return_slot_count_; 4651cb0ef41Sopenharmony_ci const Operator::Properties properties_; 4661cb0ef41Sopenharmony_ci const RegList callee_saved_registers_; 4671cb0ef41Sopenharmony_ci const DoubleRegList callee_saved_fp_registers_; 4681cb0ef41Sopenharmony_ci // Non-zero value means restricting the set of allocatable registers for 4691cb0ef41Sopenharmony_ci // register allocator to use. 4701cb0ef41Sopenharmony_ci const RegList allocatable_registers_; 4711cb0ef41Sopenharmony_ci const Flags flags_; 4721cb0ef41Sopenharmony_ci const StackArgumentOrder stack_order_; 4731cb0ef41Sopenharmony_ci#if V8_ENABLE_WEBASSEMBLY 4741cb0ef41Sopenharmony_ci const wasm::FunctionSig* wasm_sig_; 4751cb0ef41Sopenharmony_ci#endif 4761cb0ef41Sopenharmony_ci const char* const debug_name_; 4771cb0ef41Sopenharmony_ci 4781cb0ef41Sopenharmony_ci mutable base::Optional<size_t> gp_param_count_; 4791cb0ef41Sopenharmony_ci mutable base::Optional<size_t> fp_param_count_; 4801cb0ef41Sopenharmony_ci}; 4811cb0ef41Sopenharmony_ci 4821cb0ef41Sopenharmony_ciDEFINE_OPERATORS_FOR_FLAGS(CallDescriptor::Flags) 4831cb0ef41Sopenharmony_ci 4841cb0ef41Sopenharmony_cistd::ostream& operator<<(std::ostream& os, const CallDescriptor& d); 4851cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 4861cb0ef41Sopenharmony_ci const CallDescriptor::Kind& k); 4871cb0ef41Sopenharmony_ci 4881cb0ef41Sopenharmony_ci// Defines the linkage for a compilation, including the calling conventions 4891cb0ef41Sopenharmony_ci// for incoming parameters and return value(s) as well as the outgoing calling 4901cb0ef41Sopenharmony_ci// convention for any kind of call. Linkage is generally architecture-specific. 4911cb0ef41Sopenharmony_ci// 4921cb0ef41Sopenharmony_ci// Can be used to translate {arg_index} (i.e. index of the call node input) as 4931cb0ef41Sopenharmony_ci// well as {param_index} (i.e. as stored in parameter nodes) into an operator 4941cb0ef41Sopenharmony_ci// representing the architecture-specific location. The following call node 4951cb0ef41Sopenharmony_ci// layouts are supported (where {n} is the number of value inputs): 4961cb0ef41Sopenharmony_ci// 4971cb0ef41Sopenharmony_ci// #0 #1 #2 [...] #n 4981cb0ef41Sopenharmony_ci// Call[CodeStub] code, arg 1, arg 2, [...], context 4991cb0ef41Sopenharmony_ci// Call[JSFunction] function, rcvr, arg 1, [...], new, #arg, context 5001cb0ef41Sopenharmony_ci// Call[Runtime] CEntry, arg 1, arg 2, [...], fun, #arg, context 5011cb0ef41Sopenharmony_ci// Call[BytecodeDispatch] address, arg 1, arg 2, [...] 5021cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE Linkage : public NON_EXPORTED_BASE(ZoneObject) { 5031cb0ef41Sopenharmony_ci public: 5041cb0ef41Sopenharmony_ci explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {} 5051cb0ef41Sopenharmony_ci Linkage(const Linkage&) = delete; 5061cb0ef41Sopenharmony_ci Linkage& operator=(const Linkage&) = delete; 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ci static CallDescriptor* ComputeIncoming(Zone* zone, 5091cb0ef41Sopenharmony_ci OptimizedCompilationInfo* info); 5101cb0ef41Sopenharmony_ci 5111cb0ef41Sopenharmony_ci // The call descriptor for this compilation unit describes the locations 5121cb0ef41Sopenharmony_ci // of incoming parameters and the outgoing return value(s). 5131cb0ef41Sopenharmony_ci CallDescriptor* GetIncomingDescriptor() const { return incoming_; } 5141cb0ef41Sopenharmony_ci static CallDescriptor* GetJSCallDescriptor(Zone* zone, bool is_osr, 5151cb0ef41Sopenharmony_ci int parameter_count, 5161cb0ef41Sopenharmony_ci CallDescriptor::Flags flags); 5171cb0ef41Sopenharmony_ci 5181cb0ef41Sopenharmony_ci static CallDescriptor* GetRuntimeCallDescriptor( 5191cb0ef41Sopenharmony_ci Zone* zone, Runtime::FunctionId function, int js_parameter_count, 5201cb0ef41Sopenharmony_ci Operator::Properties properties, CallDescriptor::Flags flags); 5211cb0ef41Sopenharmony_ci 5221cb0ef41Sopenharmony_ci static CallDescriptor* GetCEntryStubCallDescriptor( 5231cb0ef41Sopenharmony_ci Zone* zone, int return_count, int js_parameter_count, 5241cb0ef41Sopenharmony_ci const char* debug_name, Operator::Properties properties, 5251cb0ef41Sopenharmony_ci CallDescriptor::Flags flags, 5261cb0ef41Sopenharmony_ci StackArgumentOrder stack_order = StackArgumentOrder::kDefault); 5271cb0ef41Sopenharmony_ci 5281cb0ef41Sopenharmony_ci static CallDescriptor* GetStubCallDescriptor( 5291cb0ef41Sopenharmony_ci Zone* zone, const CallInterfaceDescriptor& descriptor, 5301cb0ef41Sopenharmony_ci int stack_parameter_count, CallDescriptor::Flags flags, 5311cb0ef41Sopenharmony_ci Operator::Properties properties = Operator::kNoProperties, 5321cb0ef41Sopenharmony_ci StubCallMode stub_mode = StubCallMode::kCallCodeObject); 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ci static CallDescriptor* GetBytecodeDispatchCallDescriptor( 5351cb0ef41Sopenharmony_ci Zone* zone, const CallInterfaceDescriptor& descriptor, 5361cb0ef41Sopenharmony_ci int stack_parameter_count); 5371cb0ef41Sopenharmony_ci 5381cb0ef41Sopenharmony_ci // Creates a call descriptor for simplified C calls that is appropriate 5391cb0ef41Sopenharmony_ci // for the host platform. This simplified calling convention only supports 5401cb0ef41Sopenharmony_ci // integers and pointers of one word size each, i.e. no floating point, 5411cb0ef41Sopenharmony_ci // structs, pointers to members, etc. 5421cb0ef41Sopenharmony_ci static CallDescriptor* GetSimplifiedCDescriptor( 5431cb0ef41Sopenharmony_ci Zone* zone, const MachineSignature* sig, 5441cb0ef41Sopenharmony_ci CallDescriptor::Flags flags = CallDescriptor::kNoFlags); 5451cb0ef41Sopenharmony_ci 5461cb0ef41Sopenharmony_ci // Get the location of an (incoming) parameter to this function. 5471cb0ef41Sopenharmony_ci LinkageLocation GetParameterLocation(int index) const { 5481cb0ef41Sopenharmony_ci return incoming_->GetInputLocation(index + 1); // + 1 to skip target. 5491cb0ef41Sopenharmony_ci } 5501cb0ef41Sopenharmony_ci 5511cb0ef41Sopenharmony_ci // Get the machine type of an (incoming) parameter to this function. 5521cb0ef41Sopenharmony_ci MachineType GetParameterType(int index) const { 5531cb0ef41Sopenharmony_ci return incoming_->GetInputType(index + 1); // + 1 to skip target. 5541cb0ef41Sopenharmony_ci } 5551cb0ef41Sopenharmony_ci 5561cb0ef41Sopenharmony_ci // Get the location where this function should place its return value. 5571cb0ef41Sopenharmony_ci LinkageLocation GetReturnLocation(size_t index = 0) const { 5581cb0ef41Sopenharmony_ci return incoming_->GetReturnLocation(index); 5591cb0ef41Sopenharmony_ci } 5601cb0ef41Sopenharmony_ci 5611cb0ef41Sopenharmony_ci // Get the machine type of this function's return value. 5621cb0ef41Sopenharmony_ci MachineType GetReturnType(size_t index = 0) const { 5631cb0ef41Sopenharmony_ci return incoming_->GetReturnType(index); 5641cb0ef41Sopenharmony_ci } 5651cb0ef41Sopenharmony_ci 5661cb0ef41Sopenharmony_ci bool ParameterHasSecondaryLocation(int index) const; 5671cb0ef41Sopenharmony_ci LinkageLocation GetParameterSecondaryLocation(int index) const; 5681cb0ef41Sopenharmony_ci 5691cb0ef41Sopenharmony_ci static bool NeedsFrameStateInput(Runtime::FunctionId function); 5701cb0ef41Sopenharmony_ci 5711cb0ef41Sopenharmony_ci // Get the location where an incoming OSR value is stored. 5721cb0ef41Sopenharmony_ci LinkageLocation GetOsrValueLocation(int index) const; 5731cb0ef41Sopenharmony_ci 5741cb0ef41Sopenharmony_ci // A special {Parameter} index for Stub Calls that represents context. 5751cb0ef41Sopenharmony_ci static int GetStubCallContextParamIndex(int parameter_count) { 5761cb0ef41Sopenharmony_ci return parameter_count + 0; // Parameter (arity + 0) is special. 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci // A special {Parameter} index for JSCalls that represents the new target. 5801cb0ef41Sopenharmony_ci static constexpr int GetJSCallNewTargetParamIndex(int parameter_count) { 5811cb0ef41Sopenharmony_ci return parameter_count + 0; // Parameter (arity + 0) is special. 5821cb0ef41Sopenharmony_ci } 5831cb0ef41Sopenharmony_ci 5841cb0ef41Sopenharmony_ci // A special {Parameter} index for JSCalls that represents the argument count. 5851cb0ef41Sopenharmony_ci static constexpr int GetJSCallArgCountParamIndex(int parameter_count) { 5861cb0ef41Sopenharmony_ci return parameter_count + 1; // Parameter (arity + 1) is special. 5871cb0ef41Sopenharmony_ci } 5881cb0ef41Sopenharmony_ci 5891cb0ef41Sopenharmony_ci // A special {Parameter} index for JSCalls that represents the context. 5901cb0ef41Sopenharmony_ci static constexpr int GetJSCallContextParamIndex(int parameter_count) { 5911cb0ef41Sopenharmony_ci return parameter_count + 2; // Parameter (arity + 2) is special. 5921cb0ef41Sopenharmony_ci } 5931cb0ef41Sopenharmony_ci 5941cb0ef41Sopenharmony_ci // A special {Parameter} index for JSCalls that represents the closure. 5951cb0ef41Sopenharmony_ci static constexpr int kJSCallClosureParamIndex = -1; 5961cb0ef41Sopenharmony_ci 5971cb0ef41Sopenharmony_ci // A special {OsrValue} index to indicate the context spill slot. 5981cb0ef41Sopenharmony_ci static const int kOsrContextSpillSlotIndex = -1; 5991cb0ef41Sopenharmony_ci 6001cb0ef41Sopenharmony_ci // A special {OsrValue} index to indicate the accumulator register. 6011cb0ef41Sopenharmony_ci static const int kOsrAccumulatorRegisterIndex = -1; 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_ci private: 6041cb0ef41Sopenharmony_ci CallDescriptor* const incoming_; 6051cb0ef41Sopenharmony_ci}; 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci} // namespace compiler 6081cb0ef41Sopenharmony_ci} // namespace internal 6091cb0ef41Sopenharmony_ci} // namespace v8 6101cb0ef41Sopenharmony_ci#undef NO_INLINE_FOR_ARM64_MSVC 6111cb0ef41Sopenharmony_ci 6121cb0ef41Sopenharmony_ci#endif // V8_COMPILER_LINKAGE_H_ 613