diff options
Diffstat (limited to 'deps/v8/src/codegen/interface-descriptors-inl.h')
-rw-r--r-- | deps/v8/src/codegen/interface-descriptors-inl.h | 484 |
1 files changed, 484 insertions, 0 deletions
diff --git a/deps/v8/src/codegen/interface-descriptors-inl.h b/deps/v8/src/codegen/interface-descriptors-inl.h new file mode 100644 index 0000000000..273e9d3e8e --- /dev/null +++ b/deps/v8/src/codegen/interface-descriptors-inl.h @@ -0,0 +1,484 @@ +// 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-arch.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_MIPS +#include "src/codegen/mips/interface-descriptors-mips-inl.h" +#elif V8_TARGET_ARCH_RISCV64 +#include "src/codegen/riscv64/interface-descriptors-riscv64-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()); + } + + 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)); +} + +// 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 +constexpr Register FastNewObjectDescriptor::TargetRegister() { + return kJSFunctionRegister; +} + +// static +constexpr Register FastNewObjectDescriptor::NewTargetRegister() { + return kJavaScriptCallNewTargetRegister; +} + +// 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_IA32 || \ + V8_TARGET_ARCH_ARM || V8_TARGET_ARCH_PPC || V8_TARGET_ARCH_PPC64 || \ + V8_TARGET_ARCH_S390 || V8_TARGET_ARCH_RISCV64 + return RegisterArray( + kContextRegister, kJSFunctionRegister, kJavaScriptCallArgCountRegister, + kJavaScriptCallExtraArg1Register, kJavaScriptCallNewTargetRegister, + kInterpreterBytecodeArrayRegister); +#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 + return RegisterArray(ParamsSizeRegister(), WeightRegister()); +#else + return DefaultRegisterArray(); +#endif +} + +// 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 TailCallOptimizedCodeSlotDescriptor::registers() { + return RegisterArray(kJavaScriptCallCodeStartRegister); +} + +// 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 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<Builtins::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<Builtins::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_ |