blob: 2288da3f8445b1851669bcc7fe4b281cc754f358 [file] [log] [blame]
// Copyright 2021 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
#define V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_
#include "src/codegen/interface-descriptors.h"
// Include the non-inl header before the rest of the headers.
#include <utility>
#include "src/base/logging.h"
#include "src/codegen/register.h"
#if V8_ENABLE_WEBASSEMBLY
#include "src/wasm/wasm-linkage.h"
#endif
#if V8_TARGET_ARCH_X64
#include "src/codegen/x64/interface-descriptors-x64-inl.h"
#elif V8_TARGET_ARCH_ARM64
#include "src/codegen/arm64/interface-descriptors-arm64-inl.h"
#elif V8_TARGET_ARCH_IA32
#include "src/codegen/ia32/interface-descriptors-ia32-inl.h"
#elif V8_TARGET_ARCH_ARM
#include "src/codegen/arm/interface-descriptors-arm-inl.h"
#elif V8_TARGET_ARCH_PPC64
#include "src/codegen/ppc/interface-descriptors-ppc-inl.h"
#elif V8_TARGET_ARCH_S390X
#include "src/codegen/s390/interface-descriptors-s390-inl.h"
#elif V8_TARGET_ARCH_MIPS64
#include "src/codegen/mips64/interface-descriptors-mips64-inl.h"
#elif V8_TARGET_ARCH_LOONG64
#include "src/codegen/loong64/interface-descriptors-loong64-inl.h"
#elif V8_TARGET_ARCH_RISCV32 || V8_TARGET_ARCH_RISCV64
#include "src/codegen/riscv/interface-descriptors-riscv-inl.h"
#else
#error Unsupported target architecture.
#endif
namespace v8 {
namespace internal {
// static
constexpr std::array<Register, kJSBuiltinRegisterParams>
CallInterfaceDescriptor::DefaultJSRegisterArray() {
return RegisterArray(
kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
kJavaScriptCallArgCountRegister, kJavaScriptCallExtraArg1Register);
}
// static
template <typename DerivedDescriptor>
constexpr auto StaticCallInterfaceDescriptor<DerivedDescriptor>::registers() {
return CallInterfaceDescriptor::DefaultRegisterArray();
}
// static
template <typename DerivedDescriptor>
constexpr auto
StaticCallInterfaceDescriptor<DerivedDescriptor>::double_registers() {
return CallInterfaceDescriptor::DefaultDoubleRegisterArray();
}
// static
template <typename DerivedDescriptor>
constexpr auto
StaticCallInterfaceDescriptor<DerivedDescriptor>::return_registers() {
return CallInterfaceDescriptor::DefaultReturnRegisterArray();
}
// static
template <typename DerivedDescriptor>
constexpr auto
StaticCallInterfaceDescriptor<DerivedDescriptor>::return_double_registers() {
return CallInterfaceDescriptor::DefaultReturnDoubleRegisterArray();
}
// static
template <typename DerivedDescriptor>
constexpr auto StaticJSCallInterfaceDescriptor<DerivedDescriptor>::registers() {
return CallInterfaceDescriptor::DefaultJSRegisterArray();
}
// static
constexpr auto JSTrampolineDescriptor::registers() {
return RegisterArray(
kJavaScriptCallTargetRegister, kJavaScriptCallNewTargetRegister,
kJavaScriptCallArgCountRegister, kJavaScriptCallDispatchHandleRegister);
}
// static
constexpr auto CompareNoContextDescriptor::registers() {
return CompareDescriptor::registers();
}
template <typename DerivedDescriptor>
void StaticCallInterfaceDescriptor<DerivedDescriptor>::Initialize(
CallInterfaceDescriptorData* data) {
// Static local copy of the Registers array, for platform-specific
// initialization
static constexpr auto registers = DerivedDescriptor::registers();
static constexpr auto double_registers =
DerivedDescriptor::double_registers();
static constexpr auto return_registers =
DerivedDescriptor::return_registers();
static constexpr auto return_double_registers =
DerivedDescriptor::return_double_registers();
// The passed pointer should be a modifiable pointer to our own data.
DCHECK_EQ(data, this->data());
DCHECK(!data->IsInitialized());
if (DerivedDescriptor::kRestrictAllocatableRegisters) {
data->RestrictAllocatableRegisters(registers.data(), registers.size());
} else {
DCHECK(!DerivedDescriptor::kCalleeSaveRegisters);
}
// Make sure the defined arrays are big enough. The arrays can be filled up
// with `no_reg` and `no_dreg` to pass this DCHECK.
DCHECK_GE(registers.size(), GetRegisterParameterCount());
DCHECK_GE(double_registers.size(), GetRegisterParameterCount());
DCHECK_GE(return_registers.size(), DerivedDescriptor::kReturnCount);
DCHECK_GE(return_double_registers.size(), DerivedDescriptor::kReturnCount);
data->InitializeRegisters(
DerivedDescriptor::flags(), DerivedDescriptor::kEntrypointTag,
DerivedDescriptor::kSandboxingMode, DerivedDescriptor::kReturnCount,
DerivedDescriptor::GetParameterCount(),
DerivedDescriptor::kStackArgumentOrder,
DerivedDescriptor::GetRegisterParameterCount(), registers.data(),
double_registers.data(), return_registers.data(),
return_double_registers.data());
// InitializeTypes is customizable by the DerivedDescriptor subclass.
DerivedDescriptor::InitializeTypes(data);
DCHECK(data->IsInitialized());
DCHECK(this->CheckFloatingPointParameters(data));
#if DEBUG
DerivedDescriptor::Verify(data);
#endif
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetReturnCount() {
static_assert(
DerivedDescriptor::kReturnCount >= 0,
"DerivedDescriptor subclass should override return count with a value "
"that is greater than or equal to 0");
return DerivedDescriptor::kReturnCount;
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetParameterCount() {
static_assert(
DerivedDescriptor::kParameterCount >= 0,
"DerivedDescriptor subclass should override parameter count with a "
"value that is greater than or equal to 0");
return DerivedDescriptor::kParameterCount;
}
namespace detail {
// Helper trait for statically checking if a type is a std::array<Register,N>.
template <typename T>
struct IsRegisterArray : public std::false_type {};
template <size_t N>
struct IsRegisterArray<std::array<Register, N>> : public std::true_type {};
template <>
struct IsRegisterArray<EmptyRegisterArray> : public std::true_type {};
// Helper for finding the index of the first invalid register in a register
// array.
template <size_t N, size_t Index>
struct FirstInvalidRegisterHelper {
static constexpr int Call(std::array<Register, N> regs) {
if (!std::get<Index>(regs).is_valid()) {
// All registers after the first invalid one have to also be invalid (this
// DCHECK will be checked recursively).
DCHECK_EQ((FirstInvalidRegisterHelper<N, Index + 1>::Call(regs)),
Index + 1);
return Index;
}
return FirstInvalidRegisterHelper<N, Index + 1>::Call(regs);
}
};
template <size_t N>
struct FirstInvalidRegisterHelper<N, N> {
static constexpr int Call(std::array<Register, N> regs) { return N; }
};
template <size_t N, size_t Index = 0>
constexpr size_t FirstInvalidRegister(std::array<Register, N> regs) {
return FirstInvalidRegisterHelper<N, 0>::Call(regs);
}
constexpr size_t FirstInvalidRegister(EmptyRegisterArray regs) { return 0; }
} // namespace detail
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetRegisterParameterCount() {
static_assert(
detail::IsRegisterArray<decltype(DerivedDescriptor::registers())>::value,
"DerivedDescriptor subclass should define a registers() function "
"returning a std::array<Register>");
// The register parameter count is the minimum of:
// 1. The number of named parameters in the descriptor, and
// 2. The number of valid registers the descriptor provides with its
// registers() function, e.g. for {rax, rbx, no_reg} this number is 2.
// 3. The maximum number of register parameters allowed (
// kMaxBuiltinRegisterParams for most builtins,
// kMaxTFSBuiltinRegisterParams for TFS builtins, customizable by the
// subclass otherwise).
return std::min<int>({DerivedDescriptor::GetParameterCount(),
static_cast<int>(detail::FirstInvalidRegister(
DerivedDescriptor::registers())),
DerivedDescriptor::kMaxRegisterParams});
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetStackParameterCount() {
return DerivedDescriptor::GetParameterCount() -
DerivedDescriptor::GetRegisterParameterCount();
}
// static
template <typename DerivedDescriptor>
constexpr Register
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetRegisterParameter(int i) {
DCHECK(!IsFloatingPoint(GetParameterType(i).representation()));
return DerivedDescriptor::registers()[i];
}
// static
template <typename DerivedDescriptor>
constexpr int
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetStackParameterIndex(
int i) {
return i - DerivedDescriptor::GetRegisterParameterCount();
}
// static
template <typename DerivedDescriptor>
constexpr MachineType
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetParameterType(int i) {
if constexpr (!DerivedDescriptor::kCustomMachineTypes) {
// If there are no custom machine types, all results and parameters are
// tagged.
return MachineType::AnyTagged();
} else {
// All varags are tagged.
if (DerivedDescriptor::AllowVarArgs() &&
i >= DerivedDescriptor::GetParameterCount()) {
return MachineType::AnyTagged();
}
DCHECK_LT(i, DerivedDescriptor::GetParameterCount());
return DerivedDescriptor::kMachineTypes
[DerivedDescriptor::GetReturnCount() + i];
}
}
// static
template <typename DerivedDescriptor>
constexpr DoubleRegister
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetDoubleRegisterParameter(
int i) {
DCHECK(IsFloatingPoint(GetParameterType(i).representation()));
return DoubleRegister::from_code(
DerivedDescriptor::double_registers()[i].code());
}
// static
constexpr Register FastNewObjectDescriptor::TargetRegister() {
return kJSFunctionRegister;
}
// static
constexpr Register FastNewObjectDescriptor::NewTargetRegister() {
return kJavaScriptCallNewTargetRegister;
}
// static
constexpr Register WriteBarrierDescriptor::ObjectRegister() {
return std::get<kObject>(registers());
}
// static
constexpr Register WriteBarrierDescriptor::SlotAddressRegister() {
return std::get<kSlotAddress>(registers());
}
// static
constexpr Register WriteBarrierDescriptor::ValueRegister() {
return std::get<kSlotAddress + 1>(registers());
}
// static
constexpr RegList WriteBarrierDescriptor::ComputeSavedRegisters(
Register object, Register slot_address) {
DCHECK(!AreAliased(object, slot_address));
RegList saved_registers;
#if V8_TARGET_ARCH_X64
// Only push clobbered registers.
if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
if (slot_address != no_reg && slot_address != SlotAddressRegister()) {
saved_registers.set(SlotAddressRegister());
}
#elif V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_LOONG64 || \
V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_RISCV32
if (object != ObjectRegister()) saved_registers.set(ObjectRegister());
// The slot address is always clobbered.
saved_registers.set(SlotAddressRegister());
#else
// TODO(cbruni): Enable callee-saved registers for other platforms.
// This is a temporary workaround to prepare code for callee-saved registers.
constexpr auto allocated_registers = registers();
for (size_t i = 0; i < allocated_registers.size(); ++i) {
saved_registers.set(allocated_registers[i]);
}
#endif
return saved_registers;
}
// static
constexpr auto IndirectPointerWriteBarrierDescriptor::registers() {
return WriteBarrierDescriptor::registers();
}
// static
constexpr Register IndirectPointerWriteBarrierDescriptor::ObjectRegister() {
return std::get<kObject>(registers());
}
// static
constexpr Register
IndirectPointerWriteBarrierDescriptor::SlotAddressRegister() {
return std::get<kSlotAddress>(registers());
}
// static
constexpr Register
IndirectPointerWriteBarrierDescriptor::IndirectPointerTagRegister() {
return std::get<kIndirectPointerTag>(registers());
}
// static
constexpr RegList IndirectPointerWriteBarrierDescriptor::ComputeSavedRegisters(
Register object, Register slot_address) {
DCHECK(!AreAliased(object, slot_address));
// This write barrier behaves identical to the generic one, except that it
// passes one additional parameter.
RegList saved_registers =
WriteBarrierDescriptor::ComputeSavedRegisters(object, slot_address);
saved_registers.set(IndirectPointerTagRegister());
return saved_registers;
}
// static
constexpr Register ApiGetterDescriptor::ReceiverRegister() {
return LoadDescriptor::ReceiverRegister();
}
// static
constexpr Register LoadGlobalNoFeedbackDescriptor::ICKindRegister() {
return LoadDescriptor::SlotRegister();
}
// static
constexpr Register LoadNoFeedbackDescriptor::ICKindRegister() {
return LoadGlobalNoFeedbackDescriptor::ICKindRegister();
}
#if V8_TARGET_ARCH_IA32
// On ia32, LoadWithVectorDescriptor passes vector on the stack and thus we
// need to choose a new register here.
// static
constexpr Register LoadGlobalWithVectorDescriptor::VectorRegister() {
static_assert(!LoadWithVectorDescriptor::VectorRegister().is_valid());
return LoadDescriptor::ReceiverRegister();
}
#else
// static
constexpr Register LoadGlobalWithVectorDescriptor::VectorRegister() {
return LoadWithVectorDescriptor::VectorRegister();
}
#endif
// static
constexpr auto LoadDescriptor::registers() {
return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
}
// static
constexpr auto LoadBaselineDescriptor::registers() {
return LoadDescriptor::registers();
}
// static
constexpr auto LoadGlobalDescriptor::registers() {
return RegisterArray(LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister());
}
// static
constexpr auto LoadGlobalBaselineDescriptor::registers() {
return LoadGlobalDescriptor::registers();
}
// static
constexpr auto StoreDescriptor::registers() {
return RegisterArray(ReceiverRegister(), NameRegister(), ValueRegister(),
SlotRegister());
}
// static
constexpr auto StoreNoFeedbackDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister());
}
// static
constexpr auto StoreBaselineDescriptor::registers() {
return StoreDescriptor::registers();
}
// static
constexpr auto StoreGlobalDescriptor::registers() {
return RegisterArray(StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister());
}
// static
constexpr auto StoreGlobalBaselineDescriptor::registers() {
return StoreGlobalDescriptor::registers();
}
// static
constexpr auto DefineKeyedOwnDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
DefineKeyedOwnDescriptor::FlagsRegister(),
StoreDescriptor::SlotRegister());
}
// static
constexpr auto DefineKeyedOwnBaselineDescriptor::registers() {
return DefineKeyedOwnDescriptor::registers();
}
// static
constexpr auto LoadWithReceiverBaselineDescriptor::registers() {
return RegisterArray(
LoadDescriptor::ReceiverRegister(),
LoadWithReceiverAndVectorDescriptor::LookupStartObjectRegister(),
LoadDescriptor::NameRegister(), LoadDescriptor::SlotRegister());
}
// static
constexpr auto BaselineOutOfLinePrologueDescriptor::registers() {
// TODO(v8:11421): Implement on other platforms.
#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || V8_TARGET_ARCH_ARM || \
V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X || V8_TARGET_ARCH_RISCV64 || \
V8_TARGET_ARCH_MIPS64 || V8_TARGET_ARCH_LOONG64 || V8_TARGET_ARCH_RISCV32
return RegisterArray(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
kJavaScriptCallExtraArg1Register, kJavaScriptCallNewTargetRegister,
kInterpreterBytecodeArrayRegister);
#elif V8_TARGET_ARCH_IA32
static_assert(kJSFunctionRegister == kInterpreterBytecodeArrayRegister);
return RegisterArray(
kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister,
kJavaScriptCallExtraArg1Register, kJavaScriptCallNewTargetRegister);
#else
return DefaultRegisterArray();
#endif
}
// static
constexpr auto BaselineLeaveFrameDescriptor::registers() {
// TODO(v8:11421): Implement on other platforms.
#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_ARM64 || \
V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390X || \
V8_TARGET_ARCH_RISCV64 || V8_TARGET_ARCH_MIPS64 || \
V8_TARGET_ARCH_LOONG64 || V8_TARGET_ARCH_RISCV32
return RegisterArray(ParamsSizeRegister(), WeightRegister());
#else
return DefaultRegisterArray();
#endif
}
// static
constexpr auto OnStackReplacementDescriptor::registers() {
#if V8_TARGET_ARCH_MIPS64
return RegisterArray(kReturnRegister0, kJavaScriptCallArgCountRegister,
kJavaScriptCallTargetRegister,
kJavaScriptCallCodeStartRegister,
kJavaScriptCallNewTargetRegister);
#else
return DefaultRegisterArray();
#endif
}
// static
constexpr auto
MaglevOptimizeCodeOrTailCallOptimizedCodeSlotDescriptor::registers() {
#ifdef V8_ENABLE_MAGLEV
return RegisterArray(FlagsRegister(), FeedbackVectorRegister(),
TemporaryRegister());
#else
return DefaultRegisterArray();
#endif
}
// static
constexpr Register OnStackReplacementDescriptor::MaybeTargetCodeRegister() {
// Picking the first register on purpose because it's convenient that this
// register is the same as the platform's return-value register.
return registers()[0];
}
// static
constexpr Register
OnStackReplacementDescriptor::ExpectedParameterCountRegister() {
return registers()[1];
}
// static
constexpr auto VoidDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto JSEntryDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto AllocateDescriptor::registers() {
return RegisterArray(kAllocateSizeRegister);
}
// static
constexpr auto CEntry1ArgvOnStackDescriptor::registers() {
return RegisterArray(kRuntimeCallArgCountRegister,
kRuntimeCallFunctionRegister);
}
// static
constexpr auto InterpreterCEntry1Descriptor::registers() {
return RegisterArray(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
kRuntimeCallFunctionRegister);
}
// static
constexpr auto InterpreterCEntry2Descriptor::registers() {
return RegisterArray(kRuntimeCallArgCountRegister, kRuntimeCallArgvRegister,
kRuntimeCallFunctionRegister);
}
// static
constexpr auto FastNewObjectDescriptor::registers() {
return RegisterArray(TargetRegister(), NewTargetRegister());
}
// static
constexpr auto LoadNoFeedbackDescriptor::registers() {
return RegisterArray(LoadDescriptor::ReceiverRegister(),
LoadDescriptor::NameRegister(), ICKindRegister());
}
// static
constexpr auto LoadGlobalNoFeedbackDescriptor::registers() {
return RegisterArray(LoadDescriptor::NameRegister(), ICKindRegister());
}
// static
constexpr auto LoadGlobalWithVectorDescriptor::registers() {
return RegisterArray(LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister(), VectorRegister());
}
// static
constexpr auto LoadWithReceiverAndVectorDescriptor::registers() {
return RegisterArray(
LoadDescriptor::ReceiverRegister(), LookupStartObjectRegister(),
LoadDescriptor::NameRegister(), LoadDescriptor::SlotRegister(),
LoadWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto StoreGlobalWithVectorDescriptor::registers() {
return RegisterArray(StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister(),
StoreWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto StoreTransitionDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(), MapRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister(),
StoreWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto TypeConversionDescriptor::registers() {
return RegisterArray(ArgumentRegister());
}
// static
constexpr auto TypeConversionNoContextDescriptor::registers() {
return RegisterArray(TypeConversionDescriptor::ArgumentRegister());
}
// static
constexpr auto SingleParameterOnStackDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto AsyncFunctionStackParameterDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto GetIteratorStackParameterDescriptor::registers() {
return RegisterArray();
}
// static
constexpr auto LoadWithVectorDescriptor::registers() {
return RegisterArray(LoadDescriptor::ReceiverRegister(),
LoadDescriptor::NameRegister(),
LoadDescriptor::SlotRegister(), VectorRegister());
}
// static
constexpr auto KeyedLoadBaselineDescriptor::registers() {
return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
}
// static
constexpr auto EnumeratedKeyedLoadBaselineDescriptor::registers() {
return RegisterArray(KeyedLoadBaselineDescriptor::ReceiverRegister(),
KeyedLoadBaselineDescriptor::NameRegister(),
EnumIndexRegister(), CacheTypeRegister(),
SlotRegister());
}
// static
constexpr auto EnumeratedKeyedLoadDescriptor::registers() {
return RegisterArray(
KeyedLoadBaselineDescriptor::ReceiverRegister(),
KeyedLoadBaselineDescriptor::NameRegister(),
EnumeratedKeyedLoadBaselineDescriptor::EnumIndexRegister(),
EnumeratedKeyedLoadBaselineDescriptor::CacheTypeRegister(),
EnumeratedKeyedLoadBaselineDescriptor::SlotRegister(),
KeyedLoadWithVectorDescriptor::VectorRegister());
}
// static
constexpr auto KeyedLoadDescriptor::registers() {
return KeyedLoadBaselineDescriptor::registers();
}
// static
constexpr auto KeyedLoadWithVectorDescriptor::registers() {
return RegisterArray(KeyedLoadBaselineDescriptor::ReceiverRegister(),
KeyedLoadBaselineDescriptor::NameRegister(),
KeyedLoadBaselineDescriptor::SlotRegister(),
VectorRegister());
}
// static
constexpr auto KeyedHasICBaselineDescriptor::registers() {
return RegisterArray(ReceiverRegister(), NameRegister(), SlotRegister());
}
// static
constexpr auto KeyedHasICWithVectorDescriptor::registers() {
return RegisterArray(KeyedHasICBaselineDescriptor::ReceiverRegister(),
KeyedHasICBaselineDescriptor::NameRegister(),
KeyedHasICBaselineDescriptor::SlotRegister(),
VectorRegister());
}
// static
constexpr auto StoreWithVectorDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
StoreDescriptor::SlotRegister(), VectorRegister());
}
// static
constexpr auto DefineKeyedOwnWithVectorDescriptor::registers() {
return RegisterArray(StoreDescriptor::ReceiverRegister(),
StoreDescriptor::NameRegister(),
StoreDescriptor::ValueRegister(),
DefineKeyedOwnDescriptor::FlagsRegister(),
StoreDescriptor::SlotRegister());
}
// static
constexpr auto CallApiCallbackOptimizedDescriptor::registers() {
return RegisterArray(ApiFunctionAddressRegister(),
ActualArgumentsCountRegister(),
FunctionTemplateInfoRegister());
}
// static
constexpr auto CallApiCallbackGenericDescriptor::registers() {
return RegisterArray(ActualArgumentsCountRegister(),
TopmostScriptHavingContextRegister(),
FunctionTemplateInfoRegister());
}
// static
constexpr auto ApiGetterDescriptor::registers() {
return RegisterArray(ReceiverRegister(), HolderRegister(),
CallbackRegister());
}
// static
constexpr auto ContextOnlyDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto NoContextDescriptor::registers() { return RegisterArray(); }
// static
constexpr auto GrowArrayElementsDescriptor::registers() {
return RegisterArray(ObjectRegister(), KeyRegister());
}
// static
constexpr auto ArrayNArgumentsConstructorDescriptor::registers() {
// Keep the arguments on the same registers as they were in
// ArrayConstructorDescriptor to avoid unnecessary register moves.
// kFunction, kAllocationSite, kActualArgumentsCount
return RegisterArray(kJavaScriptCallTargetRegister,
kJavaScriptCallExtraArg1Register,
kJavaScriptCallArgCountRegister);
}
// static
constexpr auto ArrayNoArgumentConstructorDescriptor::registers() {
// This descriptor must use the same set of registers as the
// ArrayNArgumentsConstructorDescriptor.
return ArrayNArgumentsConstructorDescriptor::registers();
}
// static
constexpr auto ArraySingleArgumentConstructorDescriptor::registers() {
// This descriptor must use the same set of registers as the
// ArrayNArgumentsConstructorDescriptor.
return ArrayNArgumentsConstructorDescriptor::registers();
}
// static
constexpr Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
return GetRegisterParameter(0);
}
// static
constexpr inline Register
WasmJSToWasmWrapperDescriptor::WrapperBufferRegister() {
return std::get<kWrapperBuffer>(registers());
}
// static
constexpr inline Register
WasmHandleStackOverflowDescriptor::FrameBaseRegister() {
return std::get<kFrameBase>(registers());
}
constexpr inline Register WasmHandleStackOverflowDescriptor::GapRegister() {
return std::get<kGap>(registers());
}
constexpr auto WasmToJSWrapperDescriptor::registers() {
#if V8_ENABLE_WEBASSEMBLY
return RegisterArray(wasm::kGpParamRegisters[0]);
#else
return EmptyRegisterArray();
#endif
}
constexpr auto WasmToJSWrapperDescriptor::return_registers() {
#if V8_ENABLE_WEBASSEMBLY
return RegisterArray(wasm::kGpReturnRegisters[0], wasm::kGpReturnRegisters[1],
no_reg, no_reg);
#else
// An arbitrary register array so that the code compiles.
return CallInterfaceDescriptor::DefaultRegisterArray();
#endif
}
constexpr auto WasmToJSWrapperDescriptor::return_double_registers() {
#if V8_ENABLE_WEBASSEMBLY
return DoubleRegisterArray(no_dreg, no_dreg, wasm::kFpReturnRegisters[0],
wasm::kFpReturnRegisters[1]);
#else
// An arbitrary register array so that the code compiles.
return CallInterfaceDescriptor::DefaultDoubleRegisterArray();
#endif
}
#if V8_ENABLE_WEBASSEMBLY
constexpr auto WasmFXResumeDescriptor::registers() {
return RegisterArray(wasm::kGpParamRegisters[0]);
}
#endif
#define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, DescriptorName) \
template <> \
struct CallInterfaceDescriptorFor<Builtin::k##Name> { \
using type = DescriptorName##Descriptor; \
};
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN,
/*TFC_TSA*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER,
/*TFC*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
/*TFH*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
IGNORE_BUILTIN,
/*ASM*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER)
#undef DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER
#define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, ...) \
template <> \
struct CallInterfaceDescriptorFor<Builtin::k##Name> { \
using type = Name##Descriptor; \
};
BUILTIN_LIST_TFS(DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER)
#undef DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER
} // namespace internal
} // namespace v8
#endif // V8_CODEGEN_INTERFACE_DESCRIPTORS_INL_H_