mirror of
https://github.com/nodejs/node.git
synced 2025-04-28 21:46:48 +00:00

PR-URL: https://github.com/nodejs/node/pull/45579 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
598 lines
20 KiB
C++
598 lines
20 KiB
C++
// 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 <utility>
|
|
|
|
#include "src/base/logging.h"
|
|
#include "src/codegen/interface-descriptors.h"
|
|
#include "src/codegen/register.h"
|
|
|
|
#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_PPC || V8_TARGET_ARCH_PPC64
|
|
#include "src/codegen/ppc/interface-descriptors-ppc-inl.h"
|
|
#elif V8_TARGET_ARCH_S390
|
|
#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 StaticJSCallInterfaceDescriptor<DerivedDescriptor>::registers() {
|
|
return CallInterfaceDescriptor::DefaultJSRegisterArray();
|
|
}
|
|
|
|
template <typename DerivedDescriptor>
|
|
void StaticCallInterfaceDescriptor<DerivedDescriptor>::Initialize(
|
|
CallInterfaceDescriptorData* data) {
|
|
// Static local copy of the Registers array, for platform-specific
|
|
// initialization
|
|
static auto registers = DerivedDescriptor::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);
|
|
}
|
|
|
|
data->InitializeRegisters(
|
|
DerivedDescriptor::flags(), DerivedDescriptor::kReturnCount,
|
|
DerivedDescriptor::GetParameterCount(),
|
|
DerivedDescriptor::kStackArgumentOrder,
|
|
DerivedDescriptor::GetRegisterParameterCount(), 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 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 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) {
|
|
return DerivedDescriptor::registers()[i];
|
|
}
|
|
|
|
// static
|
|
template <typename DerivedDescriptor>
|
|
constexpr int
|
|
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetStackParameterIndex(
|
|
int i) {
|
|
return i - DerivedDescriptor::GetRegisterParameterCount();
|
|
}
|
|
|
|
// static
|
|
template <typename DerivedDescriptor>
|
|
constexpr DoubleRegister
|
|
StaticCallInterfaceDescriptor<DerivedDescriptor>::GetDoubleRegisterParameter(
|
|
int i) {
|
|
return DoubleRegister::from_code(DerivedDescriptor::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
|
|
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 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 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 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_PPC || V8_TARGET_ARCH_PPC64 || V8_TARGET_ARCH_S390 || \
|
|
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_PPC || V8_TARGET_ARCH_PPC64 || \
|
|
V8_TARGET_ARCH_S390 || 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() {
|
|
return DefaultRegisterArray();
|
|
}
|
|
|
|
// 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 auto VoidDescriptor::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 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 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
|
|
// static
|
|
constexpr Register RunMicrotasksDescriptor::MicrotaskQueueRegister() {
|
|
return GetRegisterParameter(0);
|
|
}
|
|
|
|
#define DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER(Name, DescriptorName) \
|
|
template <> \
|
|
struct CallInterfaceDescriptorFor<Builtin::k##Name> { \
|
|
using type = DescriptorName##Descriptor; \
|
|
};
|
|
BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN,
|
|
/*TFC*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, IGNORE_BUILTIN,
|
|
/*TFH*/ DEFINE_STATIC_BUILTIN_DESCRIPTOR_GETTER, 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_
|