// Copyright 2014 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_H_ #define V8_CODEGEN_INTERFACE_DESCRIPTORS_H_ #include #include "src/base/logging.h" #include "src/codegen/machine-type.h" #include "src/codegen/register.h" #include "src/codegen/tnode.h" #include "src/common/globals.h" #include "src/execution/isolate.h" namespace v8 { namespace internal { #define TORQUE_BUILTIN_LIST_TFC(V) \ BUILTIN_LIST_FROM_TORQUE(IGNORE_BUILTIN, IGNORE_BUILTIN, V, IGNORE_BUILTIN, \ IGNORE_BUILTIN, IGNORE_BUILTIN) #define INTERFACE_DESCRIPTOR_LIST(V) \ V(Abort) \ V(Allocate) \ V(ApiCallback) \ V(ApiGetter) \ V(ArrayConstructor) \ V(ArrayNArgumentsConstructor) \ V(ArrayNoArgumentConstructor) \ V(ArraySingleArgumentConstructor) \ V(AsyncFunctionStackParameter) \ V(BaselineLeaveFrame) \ V(BaselineOutOfLinePrologue) \ V(BigIntToI32Pair) \ V(BigIntToI64) \ V(BinaryOp) \ V(BinaryOp_Baseline) \ V(BinaryOp_WithFeedback) \ V(BinarySmiOp_Baseline) \ V(CallForwardVarargs) \ V(CallFunctionTemplate) \ V(CallTrampoline) \ V(CallTrampoline_Baseline) \ V(CallTrampoline_Baseline_Compact) \ V(CallTrampoline_WithFeedback) \ V(CallVarargs) \ V(CallWithArrayLike) \ V(CallWithArrayLike_WithFeedback) \ V(CallWithSpread) \ V(CallWithSpread_Baseline) \ V(CallWithSpread_WithFeedback) \ V(CEntry1ArgvOnStack) \ V(CloneObjectBaseline) \ V(CloneObjectWithVector) \ V(Compare) \ V(Compare_Baseline) \ V(Compare_WithFeedback) \ V(Construct_Baseline) \ V(ConstructForwardVarargs) \ V(ConstructStub) \ V(ConstructVarargs) \ V(ConstructWithArrayLike) \ V(ConstructWithArrayLike_WithFeedback) \ V(Construct_WithFeedback) \ V(ConstructWithSpread) \ V(ConstructWithSpread_Baseline) \ V(ConstructWithSpread_WithFeedback) \ V(ContextOnly) \ V(CopyDataPropertiesWithExcludedProperties) \ V(CopyDataPropertiesWithExcludedPropertiesOnStack) \ V(CppBuiltinAdaptor) \ V(FastNewObject) \ V(FindNonDefaultConstructorOrConstruct) \ V(ForInPrepare) \ V(GetIteratorStackParameter) \ V(GetProperty) \ V(GrowArrayElements) \ V(I32PairToBigInt) \ V(I64ToBigInt) \ V(InterpreterCEntry1) \ V(InterpreterCEntry2) \ V(InterpreterDispatch) \ V(InterpreterPushArgsThenCall) \ V(InterpreterPushArgsThenConstruct) \ V(JSTrampoline) \ V(KeyedHasICBaseline) \ V(KeyedHasICWithVector) \ V(KeyedLoad) \ V(KeyedLoadBaseline) \ V(KeyedLoadWithVector) \ V(Load) \ V(LoadBaseline) \ V(LoadGlobal) \ V(LoadGlobalBaseline) \ V(LoadGlobalNoFeedback) \ V(LoadGlobalWithVector) \ V(LoadNoFeedback) \ V(LoadWithReceiverAndVector) \ V(LoadWithReceiverBaseline) \ V(LoadWithVector) \ V(LookupTrampoline) \ V(LookupBaseline) \ V(NewHeapNumber) \ V(NoContext) \ V(OnStackReplacement) \ V(RestartFrameTrampoline) \ V(ResumeGenerator) \ V(ResumeGeneratorBaseline) \ V(RunMicrotasks) \ V(RunMicrotasksEntry) \ V(SingleParameterOnStack) \ V(Store) \ V(StoreBaseline) \ V(StoreGlobal) \ V(StoreGlobalBaseline) \ V(StoreGlobalWithVector) \ V(StoreTransition) \ V(StoreWithVector) \ V(StringAtAsString) \ V(StringSubstring) \ V(SuspendGeneratorBaseline) \ V(TypeConversion) \ V(TypeConversion_Baseline) \ V(TypeConversionNoContext) \ V(Typeof) \ V(UnaryOp_Baseline) \ V(UnaryOp_WithFeedback) \ V(Void) \ V(WasmFloat32ToNumber) \ V(WasmFloat64ToNumber) \ V(WasmI32AtomicWait32) \ V(WasmI64AtomicWait32) \ V(WasmSuspend) \ V(WriteBarrier) \ IF_TSAN(V, TSANLoad) \ IF_TSAN(V, TSANStore) \ BUILTIN_LIST_TFS(V) \ TORQUE_BUILTIN_LIST_TFC(V) enum class StackArgumentOrder { kDefault, // Arguments in the stack are pushed in the default/stub order (the // first argument is pushed first). kJS, // Arguments in the stack are pushed in the same order as the one used // by JS-to-JS function calls. This should be used if calling a // JSFunction or if the builtin is expected to be called directly from a // JSFunction. This order is reversed compared to kDefault. }; class V8_EXPORT_PRIVATE CallInterfaceDescriptorData { public: enum Flag { kNoFlags = 0u, kNoContext = 1u << 0, // This indicates that the code uses a special frame that does not scan the // stack arguments, e.g. EntryFrame. And this allows the code to use // untagged stack arguments. kNoStackScan = 1u << 1, // In addition to the specified parameters, additional arguments can be // passed on the stack. // This does not indicate if arguments adaption is used or not. kAllowVarArgs = 1u << 2, // Callee save allocatable_registers. kCalleeSaveRegisters = 1u << 3, }; using Flags = base::Flags; static constexpr int kUninitializedCount = -1; CallInterfaceDescriptorData() = default; CallInterfaceDescriptorData(const CallInterfaceDescriptorData&) = delete; CallInterfaceDescriptorData& operator=(const CallInterfaceDescriptorData&) = delete; // The passed registers are owned by the caller, and their lifetime is // expected to exceed that of this data. In practice, they are expected to // be in a static local. void InitializeRegisters(Flags flags, int return_count, int parameter_count, StackArgumentOrder stack_order, int register_parameter_count, const Register* registers); // if machine_types is null, then an array of size // (return_count + parameter_count) will be created with // MachineType::AnyTagged() for each member. // // if machine_types is not null, then it should be of the size // (return_count + parameter_count). Those members of the parameter array will // be initialized from {machine_types}, and the rest initialized to // MachineType::AnyTagged(). void InitializeTypes(const MachineType* machine_types, int machine_types_length); void Reset(); bool IsInitialized() const { return IsInitializedRegisters() && IsInitializedTypes(); } Flags flags() const { return flags_; } int return_count() const { return return_count_; } int param_count() const { return param_count_; } int register_param_count() const { return register_param_count_; } Register register_param(int index) const { return register_params_[index]; } MachineType return_type(int index) const { DCHECK_LT(index, return_count_); return machine_types_[index]; } MachineType param_type(int index) const { DCHECK_LT(index, param_count_); return machine_types_[return_count_ + index]; } StackArgumentOrder stack_order() const { return stack_order_; } void RestrictAllocatableRegisters(const Register* registers, size_t num) { DCHECK(allocatable_registers_.is_empty()); for (size_t i = 0; i < num; ++i) { allocatable_registers_.set(registers[i]); } DCHECK(!allocatable_registers_.is_empty()); } RegList allocatable_registers() const { return allocatable_registers_; } private: bool IsInitializedRegisters() const { const bool initialized = return_count_ != kUninitializedCount && param_count_ != kUninitializedCount && (register_param_count_ == 0 || register_params_ != nullptr); // Register initialization happens before type initialization. return initialized; } bool IsInitializedTypes() const { const bool initialized = machine_types_ != nullptr; // Register initialization happens before type initialization. return initialized; } #ifdef DEBUG bool AllStackParametersAreTagged() const; #endif // DEBUG int register_param_count_ = kUninitializedCount; int return_count_ = kUninitializedCount; int param_count_ = kUninitializedCount; Flags flags_ = kNoFlags; StackArgumentOrder stack_order_ = StackArgumentOrder::kDefault; // Specifying the set of registers that could be used by the register // allocator. Currently, it's only used by RecordWrite code stub. RegList allocatable_registers_; // |registers_params_| defines registers that are used for parameter passing. // |machine_types_| defines machine types for resulting values and incomping // parameters. // The register params array is owned by the caller, and it's expected that it // is a static local stored in the caller function. The machine types are // allocated dynamically by the InterfaceDescriptor and freed on destruction. const Register* register_params_ = nullptr; MachineType* machine_types_ = nullptr; }; class V8_EXPORT_PRIVATE CallDescriptors : public AllStatic { public: enum Key { #define DEF_ENUM(name, ...) name, INTERFACE_DESCRIPTOR_LIST(DEF_ENUM) #undef DEF_ENUM NUMBER_OF_DESCRIPTORS }; static void InitializeOncePerProcess(); static void TearDown(); static CallInterfaceDescriptorData* call_descriptor_data( CallDescriptors::Key key) { return &call_descriptor_data_[key]; } static Key GetKey(const CallInterfaceDescriptorData* data) { ptrdiff_t index = data - call_descriptor_data_; DCHECK_LE(0, index); DCHECK_LT(index, CallDescriptors::NUMBER_OF_DESCRIPTORS); return static_cast(index); } private: static CallInterfaceDescriptorData call_descriptor_data_[NUMBER_OF_DESCRIPTORS]; }; #if defined(V8_TARGET_ARCH_IA32) // To support all possible cases, we must limit the number of register args for // TFS builtins on ia32 to 3. Out of the 6 allocatable registers, esi is taken // as the context register and ebx is the root register. One register must // remain available to store the jump/call target. Thus 3 registers remain for // arguments. The reason this applies to TFS builtins specifically is because // this becomes relevant for builtins used as targets of Torque function // pointers (which must have a register available to store the target). // TODO(jgruber): Ideally we should just decrement kMaxBuiltinRegisterParams but // that comes with its own set of complications. It's possible, but requires // refactoring the calling convention of other existing stubs. constexpr int kMaxBuiltinRegisterParams = 4; constexpr int kMaxTFSBuiltinRegisterParams = 3; #else constexpr int kMaxBuiltinRegisterParams = 5; constexpr int kMaxTFSBuiltinRegisterParams = kMaxBuiltinRegisterParams; #endif static_assert(kMaxTFSBuiltinRegisterParams <= kMaxBuiltinRegisterParams); constexpr int kJSBuiltinRegisterParams = 4; // Polymorphic base class for call interface descriptors, which defines getters // for the various descriptor properties via a runtime-loaded // CallInterfaceDescriptorData field. class V8_EXPORT_PRIVATE CallInterfaceDescriptor { public: using Flags = CallInterfaceDescriptorData::Flags; CallInterfaceDescriptor() : data_(nullptr) {} ~CallInterfaceDescriptor() = default; explicit CallInterfaceDescriptor(CallDescriptors::Key key) : data_(CallDescriptors::call_descriptor_data(key)) {} Flags flags() const { return data()->flags(); } bool HasContextParameter() const { return (flags() & CallInterfaceDescriptorData::kNoContext) == 0; } bool AllowVarArgs() const { return flags() & CallInterfaceDescriptorData::kAllowVarArgs; } bool CalleeSaveRegisters() const { return flags() & CallInterfaceDescriptorData::kCalleeSaveRegisters; } int GetReturnCount() const { return data()->return_count(); } MachineType GetReturnType(int index) const { DCHECK_LT(index, data()->return_count()); return data()->return_type(index); } int GetParameterCount() const { return data()->param_count(); } int GetRegisterParameterCount() const { return data()->register_param_count(); } int GetStackParameterCount() const { return data()->param_count() - data()->register_param_count(); } Register GetRegisterParameter(int index) const { DCHECK_LT(index, data()->register_param_count()); return data()->register_param(index); } MachineType GetParameterType(int index) const { DCHECK_LT(index, data()->param_count()); return data()->param_type(index); } RegList allocatable_registers() const { return data()->allocatable_registers(); } StackArgumentOrder GetStackArgumentOrder() const { return data()->stack_order(); } static constexpr inline Register ContextRegister() { return kContextRegister; } const char* DebugName() const; bool operator==(const CallInterfaceDescriptor& other) const { return data() == other.data(); } protected: const CallInterfaceDescriptorData* data() const { return data_; } // Helper for defining the default register set. // // Use auto for the return type to allow different architectures to have // differently sized default register arrays. static constexpr inline auto DefaultRegisterArray(); static constexpr inline std::array DefaultJSRegisterArray(); // Checks if float parameters are not assigned invalid registers. bool CheckFloatingPointParameters(CallInterfaceDescriptorData* data) { for (int i = 0; i < data->register_param_count(); i++) { if (IsFloatingPoint(data->param_type(i).representation())) { if (!IsValidFloatParameterRegister(data->register_param(i))) { return false; } } } return true; } bool IsValidFloatParameterRegister(Register reg); private: const CallInterfaceDescriptorData* data_; }; // CRTP base class for call interface descriptors, which defines static getters // for the various descriptor properties based on static values defined in the // subclass. template class StaticCallInterfaceDescriptor : public CallInterfaceDescriptor { public: // =========================================================================== // The following are the descriptor's CRTP configuration points, overwritable // by DerivedDescriptor. static constexpr int kReturnCount = CallInterfaceDescriptorData::kUninitializedCount; static constexpr int kParameterCount = CallInterfaceDescriptorData::kUninitializedCount; static constexpr bool kNoContext = false; static constexpr bool kAllowVarArgs = false; static constexpr bool kNoStackScan = false; static constexpr auto kStackArgumentOrder = StackArgumentOrder::kDefault; // The set of registers available to the parameters, as a // std::array. Can be larger or smaller than kParameterCount; if // larger then any remaining registers are ignored; if smaller, any parameters // after registers().size() will be stack registers. // // Defaults to CallInterfaceDescriptor::DefaultRegisterArray(). static constexpr inline auto registers(); // An additional limit on the number of register parameters allowed. This is // here so that it can be overwritten to kMaxTFSBuiltinRegisterParams for TFS // builtins, see comment on kMaxTFSBuiltinRegisterParams above. static constexpr int kMaxRegisterParams = kMaxBuiltinRegisterParams; // If set to true, the descriptor will restrict the set of allocatable // registers to the set returned by registers(). Then, it is expected that // the first kParameterCount registers() are the parameters of the builtin. static constexpr bool kRestrictAllocatableRegisters = false; // If set to true, builtins will callee save the set returned by registers(). static constexpr bool kCalleeSaveRegisters = false; // End of customization points. // =========================================================================== static constexpr inline Flags flags() { return Flags((DerivedDescriptor::kNoContext ? CallInterfaceDescriptorData::kNoContext : 0) | (DerivedDescriptor::kAllowVarArgs ? CallInterfaceDescriptorData::kAllowVarArgs : 0) | (DerivedDescriptor::kNoStackScan ? CallInterfaceDescriptorData::kNoStackScan : 0) | (DerivedDescriptor::kCalleeSaveRegisters ? CallInterfaceDescriptorData::kCalleeSaveRegisters : 0)); } static constexpr inline bool AllowVarArgs() { return DerivedDescriptor::kAllowVarArgs; } static constexpr inline bool HasContextParameter() { return !DerivedDescriptor::kNoContext; } static constexpr inline int GetReturnCount(); static constexpr inline int GetParameterCount(); static constexpr inline int GetRegisterParameterCount(); static constexpr inline int GetStackParameterCount(); static constexpr inline Register* GetRegisterData(); static constexpr inline Register GetRegisterParameter(int i); // Interface descriptors don't really support double registers. // This reinterprets the i-th register as a double with the same code. static constexpr inline DoubleRegister GetDoubleRegisterParameter(int i); explicit StaticCallInterfaceDescriptor(CallDescriptors::Key key) : CallInterfaceDescriptor(key) {} #if DEBUG // Overwritten in DerivedDescriptor. static void Verify(CallInterfaceDescriptorData* data); // Verify that the CallInterfaceDescriptorData contains the default // argument registers for {argc} arguments. static inline void VerifyArgumentRegisterCount( CallInterfaceDescriptorData* data, int nof_expected_args); #endif private: // {CallDescriptors} is allowed to call the private {Initialize} method. friend class CallDescriptors; inline void Initialize(CallInterfaceDescriptorData* data); // Set up the types of the descriptor. This is a static function, so that it // is overwritable by subclasses. By default, all parameters have // MachineType::AnyTagged() type. static void InitializeTypes(CallInterfaceDescriptorData* data) { data->InitializeTypes(nullptr, 0); } }; template class StaticJSCallInterfaceDescriptor : public StaticCallInterfaceDescriptor { public: static constexpr auto kStackArgumentOrder = StackArgumentOrder::kJS; static constexpr inline auto registers(); using StaticCallInterfaceDescriptor< Descriptor>::StaticCallInterfaceDescriptor; }; template struct CallInterfaceDescriptorFor; // Stub class replacing std::array, as a workaround for MSVC's // https://github.com/microsoft/STL/issues/942 struct EmptyRegisterArray { Register* data() { return nullptr; } size_t size() const { return 0; } Register operator[](size_t i) const { UNREACHABLE(); } }; // Helper method for defining an array of unique registers for the various // Descriptor::registers() methods. template constexpr std::array RegisterArray( Register first_reg, Registers... regs) { DCHECK(!AreAliased(first_reg, regs...)); return {first_reg, regs...}; } constexpr EmptyRegisterArray RegisterArray() { return {}; } #define DECLARE_DESCRIPTOR_WITH_BASE(name, base) \ public: \ /* StaticCallInterfaceDescriptor can call Initialize methods */ \ friend class StaticCallInterfaceDescriptor; \ explicit name() : base(key()) {} \ static inline CallDescriptors::Key key(); #define DECLARE_DEFAULT_DESCRIPTOR(name) \ DECLARE_DESCRIPTOR_WITH_BASE(name, StaticCallInterfaceDescriptor) \ static constexpr int kMaxRegisterParams = kMaxTFSBuiltinRegisterParams; \ \ protected: \ explicit name(CallDescriptors::Key key) \ : StaticCallInterfaceDescriptor(key) {} \ \ public: #define DECLARE_JS_COMPATIBLE_DESCRIPTOR(name) \ DECLARE_DESCRIPTOR_WITH_BASE(name, StaticJSCallInterfaceDescriptor) \ protected: \ explicit name(CallDescriptors::Key key) \ : StaticJSCallInterfaceDescriptor(key) {} \ \ public: #define DEFINE_RESULT_AND_PARAMETERS(return_count, ...) \ static constexpr int kReturnCount = return_count; \ enum ParameterIndices { \ __dummy = -1, /* to be able to pass zero arguments */ \ ##__VA_ARGS__, \ \ kParameterCount, \ kContext = kParameterCount /* implicit parameter */ \ }; // This is valid only for builtins that use EntryFrame, which does not scan // stack arguments on GC. #define DEFINE_PARAMETERS_ENTRY(...) \ static constexpr bool kNoContext = true; \ static constexpr bool kNoStackScan = true; \ static constexpr StackArgumentOrder kStackArgumentOrder = \ StackArgumentOrder::kDefault; \ static constexpr int kReturnCount = 1; \ enum ParameterIndices { \ __dummy = -1, /* to be able to pass zero arguments */ \ ##__VA_ARGS__, \ \ kParameterCount \ }; #define DEFINE_PARAMETERS(...) DEFINE_RESULT_AND_PARAMETERS(1, ##__VA_ARGS__) #define DEFINE_PARAMETERS_NO_CONTEXT(...) \ DEFINE_PARAMETERS(__VA_ARGS__) \ static constexpr bool kNoContext = true; #define DEFINE_PARAMETERS_VARARGS(...) \ DEFINE_PARAMETERS(__VA_ARGS__) \ static constexpr bool kAllowVarArgs = true; \ static constexpr StackArgumentOrder kStackArgumentOrder = \ StackArgumentOrder::kJS; #define DEFINE_PARAMETERS_NO_CONTEXT_VARARGS(...) \ DEFINE_PARAMETERS_NO_CONTEXT(__VA_ARGS__) \ static constexpr bool kAllowVarArgs = true; \ static constexpr StackArgumentOrder kStackArgumentOrder = \ StackArgumentOrder::kJS; #define DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(return_count, ...) \ DEFINE_RESULT_AND_PARAMETERS(return_count, ##__VA_ARGS__) \ static constexpr bool kNoContext = true; #define DEFINE_RESULT_AND_PARAMETER_TYPES(...) \ static void InitializeTypes(CallInterfaceDescriptorData* data) { \ MachineType machine_types[] = {__VA_ARGS__}; \ static_assert( \ kReturnCount + kParameterCount == arraysize(machine_types), \ "Parameter names definition is not consistent with parameter types"); \ data->InitializeTypes(machine_types, arraysize(machine_types)); \ } #define DEFINE_PARAMETER_TYPES(...) \ DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged() /* result */, \ ##__VA_ARGS__) // When the extra arguments described here are located in the stack, they are // just above the return address in the frame (first arguments). #define DEFINE_JS_PARAMETERS(...) \ static constexpr bool kAllowVarArgs = true; \ static constexpr int kReturnCount = 1; \ static constexpr StackArgumentOrder kStackArgumentOrder = \ StackArgumentOrder::kJS; \ enum ParameterIndices { \ kTarget, \ kNewTarget, \ kActualArgumentsCount, \ ##__VA_ARGS__, \ kParameterCount, \ kContext = kParameterCount /* implicit parameter */ \ }; #define DEFINE_JS_PARAMETERS_NO_CONTEXT(...) \ static constexpr bool kAllowVarArgs = true; \ static constexpr bool kNoContext = true; \ static constexpr int kReturnCount = 1; \ static constexpr StackArgumentOrder kStackArgumentOrder = \ StackArgumentOrder::kJS; \ enum ParameterIndices { \ kTarget, \ kNewTarget, \ kActualArgumentsCount, \ ##__VA_ARGS__, \ kParameterCount, \ }; #define DEFINE_JS_PARAMETER_TYPES(...) \ DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), /* kTarget */ \ MachineType::AnyTagged(), /* kNewTarget */ \ MachineType::Int32(), /* kActualArgumentsCount */ \ ##__VA_ARGS__) #define DECLARE_DESCRIPTOR(name) \ DECLARE_DESCRIPTOR_WITH_BASE(name, StaticCallInterfaceDescriptor) \ protected: \ explicit name(CallDescriptors::Key key) \ : StaticCallInterfaceDescriptor(key) {} \ \ public: class V8_EXPORT_PRIVATE VoidDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS() DEFINE_PARAMETER_TYPES() DECLARE_DESCRIPTOR(VoidDescriptor) static constexpr auto registers(); }; // Dummy descriptor that marks builtins with C calling convention. // TODO(jgruber): Define real descriptors for C calling conventions. using CCallDescriptor = VoidDescriptor; // Marks deoptimization entry builtins. Precise calling conventions currently // differ based on the platform. // TODO(jgruber): Once this is unified, we could create a better description // here. using DeoptimizationEntryDescriptor = VoidDescriptor; // TODO(jgruber): Consider filling in the details here; however, this doesn't // make too much sense as long as the descriptor isn't used or verified. using JSEntryDescriptor = VoidDescriptor; // TODO(jgruber): Consider filling in the details here; however, this doesn't // make too much sense as long as the descriptor isn't used or verified. using CEntryDummyDescriptor = VoidDescriptor; // TODO(jgruber): Consider filling in the details here; however, this doesn't // make too much sense as long as the descriptor isn't used or verified. using ContinueToBuiltinDescriptor = VoidDescriptor; // TODO(wasm): Consider filling in details / defining real descriptors for all // builtins still using this placeholder descriptor. using WasmDummyDescriptor = VoidDescriptor; class AllocateDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kRequestedSize) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::TaggedPointer(), // result 1 MachineType::IntPtr()) // kRequestedSize DECLARE_DESCRIPTOR(AllocateDescriptor) static constexpr auto registers(); }; class NewHeapNumberDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kValue) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::TaggedPointer(), // Result MachineType::Float64()) // kValue DECLARE_DESCRIPTOR(NewHeapNumberDescriptor) #if V8_TARGET_ARCH_IA32 // We need a custom descriptor on ia32 to avoid using xmm0. static constexpr inline auto registers(); #endif }; // This descriptor defines the JavaScript calling convention that can be used // by stubs: target, new.target, argc and context are passed in registers while // receiver and the rest of the JS arguments are passed on the stack. class JSTrampolineDescriptor : public StaticJSCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS() DEFINE_JS_PARAMETER_TYPES() DECLARE_JS_COMPATIBLE_DESCRIPTOR(JSTrampolineDescriptor) }; class ContextOnlyDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS() DEFINE_PARAMETER_TYPES() DECLARE_DESCRIPTOR(ContextOnlyDescriptor) static constexpr auto registers(); }; class NoContextDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT() DEFINE_PARAMETER_TYPES() DECLARE_DESCRIPTOR(NoContextDescriptor) static constexpr auto registers(); }; // LoadDescriptor is used by all stubs that implement Load ICs. class LoadDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(LoadDescriptor) static constexpr inline Register ReceiverRegister(); static constexpr inline Register NameRegister(); static constexpr inline Register SlotRegister(); static constexpr auto registers(); }; // LoadBaselineDescriptor is a load descriptor that does not take a context as // input. class LoadBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kReceiver, kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(LoadBaselineDescriptor) static constexpr auto registers(); }; class LoadGlobalNoFeedbackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kName, kICKind) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kICKind DECLARE_DESCRIPTOR(LoadGlobalNoFeedbackDescriptor) static constexpr inline Register ICKindRegister(); static constexpr auto registers(); }; class LoadNoFeedbackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kICKind) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kICKind DECLARE_DESCRIPTOR(LoadNoFeedbackDescriptor) static constexpr inline Register ICKindRegister(); static constexpr auto registers(); }; class LoadGlobalDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(LoadGlobalDescriptor) static constexpr auto registers(); }; class LoadGlobalBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(LoadGlobalBaselineDescriptor) static constexpr auto registers(); }; class LookupTrampolineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kName, kDepth, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kDepth MachineType::AnyTagged()) // kSlot DECLARE_DESCRIPTOR(LookupTrampolineDescriptor) }; class LookupBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kName, kDepth, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kDepth MachineType::AnyTagged()) // kSlot DECLARE_DESCRIPTOR(LookupBaselineDescriptor) }; class StoreDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kValue, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kValue MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(StoreDescriptor) static constexpr inline Register ReceiverRegister(); static constexpr inline Register NameRegister(); static constexpr inline Register ValueRegister(); static constexpr inline Register SlotRegister(); static constexpr auto registers(); }; class StoreBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kReceiver, kName, kValue, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kValue MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(StoreBaselineDescriptor) static constexpr auto registers(); }; class StoreTransitionDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kMap, kValue, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kMap MachineType::AnyTagged(), // kValue MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(StoreTransitionDescriptor) static constexpr inline Register MapRegister(); static constexpr auto registers(); }; class StoreWithVectorDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kValue, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kValue MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(StoreWithVectorDescriptor) static constexpr inline Register VectorRegister(); static constexpr auto registers(); }; class StoreGlobalDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kName, kValue, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kValue MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(StoreGlobalDescriptor) static constexpr auto registers(); }; class StoreGlobalBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kName, kValue, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kValue MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(StoreGlobalBaselineDescriptor) static constexpr auto registers(); }; class StoreGlobalWithVectorDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kName, kValue, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kValue MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(StoreGlobalWithVectorDescriptor) static constexpr auto registers(); }; class LoadWithVectorDescriptor : public StaticCallInterfaceDescriptor { public: // TODO(v8:9497): Revert the Machine type for kSlot to the // TaggedSigned once Torque can emit better call descriptors DEFINE_PARAMETERS(kReceiver, kName, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(LoadWithVectorDescriptor) static constexpr inline Register VectorRegister(); static constexpr auto registers(); }; class KeyedLoadBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kReceiver, kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(KeyedLoadBaselineDescriptor) static constexpr inline Register ReceiverRegister(); static constexpr inline Register NameRegister(); static constexpr inline Register SlotRegister(); static constexpr auto registers(); }; class KeyedLoadDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(KeyedLoadDescriptor) static constexpr auto registers(); }; class KeyedLoadWithVectorDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(KeyedLoadWithVectorDescriptor) static constexpr inline Register VectorRegister(); static constexpr auto registers(); }; class KeyedHasICBaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kReceiver, kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(KeyedHasICBaselineDescriptor) static constexpr inline Register ReceiverRegister(); static constexpr inline Register NameRegister(); static constexpr inline Register SlotRegister(); static constexpr auto registers(); }; class KeyedHasICWithVectorDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kName, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kName MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(KeyedHasICWithVectorDescriptor) static constexpr inline Register VectorRegister(); static constexpr auto registers(); }; // Like LoadWithVectorDescriptor, except we pass the receiver (the object which // should be used as the receiver for accessor function calls) and the lookup // start object separately. class LoadWithReceiverAndVectorDescriptor : public StaticCallInterfaceDescriptor< LoadWithReceiverAndVectorDescriptor> { public: // TODO(v8:9497): Revert the Machine type for kSlot to the // TaggedSigned once Torque can emit better call descriptors DEFINE_PARAMETERS(kReceiver, kLookupStartObject, kName, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kLookupStartObject MachineType::AnyTagged(), // kName MachineType::AnyTagged(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(LoadWithReceiverAndVectorDescriptor) static constexpr inline Register LookupStartObjectRegister(); static constexpr auto registers(); }; class LoadWithReceiverBaselineDescriptor : public StaticCallInterfaceDescriptor { public: // TODO(v8:9497): Revert the Machine type for kSlot to the // TaggedSigned once Torque can emit better call descriptors DEFINE_PARAMETERS_NO_CONTEXT(kReceiver, kLookupStartObject, kName, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kLookupStartObject MachineType::AnyTagged(), // kName MachineType::AnyTagged()) // kSlot DECLARE_DESCRIPTOR(LoadWithReceiverBaselineDescriptor) static constexpr auto registers(); }; class LoadGlobalWithVectorDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kName, kSlot, kVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kName MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(LoadGlobalWithVectorDescriptor) static constexpr inline Register VectorRegister(); static constexpr auto registers(); }; class FastNewObjectDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kTarget, kNewTarget) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::AnyTagged()) // kNewTarget DECLARE_DESCRIPTOR(FastNewObjectDescriptor) static constexpr inline Register TargetRegister(); static constexpr inline Register NewTargetRegister(); static constexpr auto registers(); }; class WriteBarrierDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kObject, kSlotAddress) DEFINE_PARAMETER_TYPES(MachineType::TaggedPointer(), // kObject MachineType::Pointer()) // kSlotAddress DECLARE_DESCRIPTOR(WriteBarrierDescriptor) static constexpr auto registers(); static constexpr bool kRestrictAllocatableRegisters = true; static constexpr bool kCalleeSaveRegisters = true; static constexpr inline Register ObjectRegister(); static constexpr inline Register SlotAddressRegister(); // A temporary register used in helpers. static constexpr inline Register ValueRegister(); static constexpr inline RegList ComputeSavedRegisters( Register object, Register slot_address = no_reg); #if DEBUG static void Verify(CallInterfaceDescriptorData* data); #endif }; #ifdef V8_IS_TSAN class TSANStoreDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kAddress, kValue) DEFINE_PARAMETER_TYPES(MachineType::Pointer(), // kAddress MachineType::AnyTagged()) // kValue DECLARE_DESCRIPTOR(TSANStoreDescriptor) static constexpr auto registers(); static constexpr bool kRestrictAllocatableRegisters = true; }; class TSANLoadDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kAddress) DEFINE_PARAMETER_TYPES(MachineType::Pointer()) // kAddress DECLARE_DESCRIPTOR(TSANLoadDescriptor) static constexpr auto registers(); static constexpr bool kRestrictAllocatableRegisters = true; }; #endif // V8_IS_TSAN class TypeConversionDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kArgument) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_DESCRIPTOR(TypeConversionDescriptor) static constexpr inline Register ArgumentRegister(); static constexpr auto registers(); }; class TypeConversionNoContextDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kArgument) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_DESCRIPTOR(TypeConversionNoContextDescriptor) static constexpr auto registers(); }; class TypeConversion_BaselineDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kArgument, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), MachineType::UintPtr()) DECLARE_DESCRIPTOR(TypeConversion_BaselineDescriptor) }; class SingleParameterOnStackDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kArgument) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_DESCRIPTOR(SingleParameterOnStackDescriptor) static constexpr auto registers(); }; class AsyncFunctionStackParameterDescriptor final : public StaticCallInterfaceDescriptor< AsyncFunctionStackParameterDescriptor> { public: DEFINE_PARAMETERS(kPromise, kResult) DEFINE_PARAMETER_TYPES(MachineType::TaggedPointer(), MachineType::AnyTagged()) DECLARE_DESCRIPTOR(AsyncFunctionStackParameterDescriptor) static constexpr auto registers(); }; class GetIteratorStackParameterDescriptor final : public StaticCallInterfaceDescriptor< GetIteratorStackParameterDescriptor> { public: DEFINE_PARAMETERS(kReceiver, kCallSlot, kFeedback, kResult) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), MachineType::AnyTagged(), MachineType::AnyTagged(), MachineType::AnyTagged()) DECLARE_DESCRIPTOR(GetIteratorStackParameterDescriptor) static constexpr auto registers(); }; class GetPropertyDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kObject, kKey) DECLARE_DEFAULT_DESCRIPTOR(GetPropertyDescriptor) }; class TypeofDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kObject) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_DESCRIPTOR(TypeofDescriptor) static constexpr inline auto registers(); }; class CallTrampolineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_VARARGS(kFunction, kActualArgumentsCount) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction MachineType::Int32()) // kActualArgumentsCount DECLARE_DESCRIPTOR(CallTrampolineDescriptor) static constexpr inline auto registers(); }; class CopyDataPropertiesWithExcludedPropertiesDescriptor : public StaticCallInterfaceDescriptor< CopyDataPropertiesWithExcludedPropertiesDescriptor> { public: DEFINE_PARAMETERS_VARARGS(kSource, kExcludedPropertyCount) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kSource MachineType::AnyTagged()) // kExcludedPropertyCount DECLARE_DESCRIPTOR(CopyDataPropertiesWithExcludedPropertiesDescriptor) static constexpr inline auto registers(); }; class CopyDataPropertiesWithExcludedPropertiesOnStackDescriptor : public StaticCallInterfaceDescriptor< CopyDataPropertiesWithExcludedPropertiesOnStackDescriptor> { public: DEFINE_PARAMETERS(kSource, kExcludedPropertyCount, kExcludedPropertyBase) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kSource MachineType::IntPtr(), MachineType::IntPtr()) // kExcludedPropertyCount DECLARE_DESCRIPTOR(CopyDataPropertiesWithExcludedPropertiesOnStackDescriptor) static constexpr inline auto registers(); }; class CallVarargsDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_VARARGS(kTarget, kActualArgumentsCount, kArgumentsLength, kArgumentsList) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::Int32(), // kActualArgumentsCount MachineType::Int32(), // kArgumentsLength MachineType::AnyTagged()) // kArgumentsList DECLARE_DESCRIPTOR(CallVarargsDescriptor) static constexpr inline auto registers(); }; class CallForwardVarargsDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_VARARGS(kTarget, kActualArgumentsCount, kStartIndex) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::Int32(), // kActualArgumentsCount MachineType::Int32()) // kStartIndex DECLARE_DESCRIPTOR(CallForwardVarargsDescriptor) static constexpr inline auto registers(); }; class CallFunctionTemplateDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_VARARGS(kFunctionTemplateInfo, kArgumentsCount) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunctionTemplateInfo MachineType::IntPtr()) // kArgumentsCount DECLARE_DESCRIPTOR(CallFunctionTemplateDescriptor) static constexpr inline auto registers(); }; class CallWithSpreadDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_VARARGS(kTarget, kArgumentsCount, kSpread) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::Int32(), // kArgumentsCount MachineType::AnyTagged()) // kSpread DECLARE_DESCRIPTOR(CallWithSpreadDescriptor) static constexpr inline auto registers(); }; class CallWithSpread_BaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT_VARARGS(kTarget, kArgumentsCount, kSpread, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::Int32(), // kArgumentsCount MachineType::AnyTagged(), // kSpread MachineType::UintPtr()) // kSlot DECLARE_DESCRIPTOR(CallWithSpread_BaselineDescriptor) }; class CallWithSpread_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor< CallWithSpread_WithFeedbackDescriptor> { public: DEFINE_PARAMETERS_VARARGS(kTarget, kArgumentsCount, kSpread, kSlot, kFeedbackVector, kReceiver) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::Int32(), // kArgumentsCount MachineType::AnyTagged(), // kSpread MachineType::UintPtr(), // kSlot MachineType::AnyTagged(), // kFeedbackVector MachineType::AnyTagged()) // kReceiver DECLARE_DESCRIPTOR(CallWithSpread_WithFeedbackDescriptor) }; class CallWithArrayLikeDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kTarget, kArgumentsList) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::AnyTagged()) // kArgumentsList DECLARE_DESCRIPTOR(CallWithArrayLikeDescriptor) static constexpr inline auto registers(); }; class CallWithArrayLike_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor< CallWithArrayLike_WithFeedbackDescriptor> { public: DEFINE_PARAMETERS(kTarget, kArgumentsList, kSlot, kFeedbackVector, kReceiver) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::AnyTagged(), // kArgumentsList MachineType::UintPtr(), // kSlot MachineType::AnyTagged(), // kFeedbackVector MachineType::AnyTagged()) // kReceiver DECLARE_DESCRIPTOR(CallWithArrayLike_WithFeedbackDescriptor) }; class ConstructVarargsDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS(kArgumentsLength, kArgumentsList) DEFINE_JS_PARAMETER_TYPES(MachineType::Int32(), // kArgumentsLength MachineType::AnyTagged()) // kArgumentsList DECLARE_DESCRIPTOR(ConstructVarargsDescriptor) static constexpr inline auto registers(); }; class ConstructForwardVarargsDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS(kStartIndex) DEFINE_JS_PARAMETER_TYPES(MachineType::Int32()) DECLARE_DESCRIPTOR(ConstructForwardVarargsDescriptor) static constexpr inline auto registers(); }; class ConstructWithSpreadDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS(kSpread) DEFINE_JS_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_DESCRIPTOR(ConstructWithSpreadDescriptor) static constexpr inline auto registers(); }; class ConstructWithSpread_BaselineDescriptor : public StaticCallInterfaceDescriptor< ConstructWithSpread_BaselineDescriptor> { public: // Note: kSlot comes before kSpread since as an untagged value it must be // passed in a register. DEFINE_JS_PARAMETERS_NO_CONTEXT(kSlot, kSpread) DEFINE_JS_PARAMETER_TYPES(MachineType::UintPtr(), // kSlot MachineType::AnyTagged()) // kSpread DECLARE_DESCRIPTOR(ConstructWithSpread_BaselineDescriptor) }; class ConstructWithSpread_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor< ConstructWithSpread_WithFeedbackDescriptor> { public: // Note: kSlot comes before kSpread since as an untagged value it must be // passed in a register. DEFINE_JS_PARAMETERS(kSlot, kSpread, kFeedbackVector) DEFINE_JS_PARAMETER_TYPES(MachineType::UintPtr(), // kSlot MachineType::AnyTagged(), // kSpread MachineType::AnyTagged()) // kFeedbackVector DECLARE_DESCRIPTOR(ConstructWithSpread_WithFeedbackDescriptor) }; class ConstructWithArrayLikeDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kTarget, kNewTarget, kArgumentsList) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::AnyTagged(), // kNewTarget MachineType::AnyTagged()) // kArgumentsList DECLARE_DESCRIPTOR(ConstructWithArrayLikeDescriptor) static constexpr inline auto registers(); }; class ConstructWithArrayLike_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor< ConstructWithArrayLike_WithFeedbackDescriptor> { public: DEFINE_PARAMETERS(kTarget, kNewTarget, kArgumentsList, kSlot, kFeedbackVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kTarget MachineType::AnyTagged(), // kNewTarget MachineType::AnyTagged(), // kArgumentsList MachineType::UintPtr(), // kSlot MachineType::AnyTagged()) // kFeedbackVector DECLARE_DESCRIPTOR(ConstructWithArrayLike_WithFeedbackDescriptor) }; // TODO(ishell): consider merging this with ArrayConstructorDescriptor class ConstructStubDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS() DEFINE_JS_PARAMETER_TYPES() // TODO(ishell): Use DECLARE_JS_COMPATIBLE_DESCRIPTOR if registers match DECLARE_DESCRIPTOR(ConstructStubDescriptor) static constexpr inline auto registers(); }; class AbortDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kMessageOrMessageId) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_DESCRIPTOR(AbortDescriptor) static constexpr inline auto registers(); }; class ArrayConstructorDescriptor : public StaticJSCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS(kAllocationSite) DEFINE_JS_PARAMETER_TYPES(MachineType::AnyTagged()) DECLARE_JS_COMPATIBLE_DESCRIPTOR(ArrayConstructorDescriptor) }; class ArrayNArgumentsConstructorDescriptor : public StaticCallInterfaceDescriptor< ArrayNArgumentsConstructorDescriptor> { public: // This descriptor declares only register arguments while respective number // of JS arguments stay on the expression stack. // The ArrayNArgumentsConstructor builtin does not access stack arguments // directly it just forwards them to the runtime function. DEFINE_PARAMETERS(kFunction, kAllocationSite, kActualArgumentsCount) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction, MachineType::AnyTagged(), // kAllocationSite MachineType::Int32()) // kActualArgumentsCount DECLARE_DESCRIPTOR(ArrayNArgumentsConstructorDescriptor) static constexpr auto registers(); }; class ArrayNoArgumentConstructorDescriptor : public StaticCallInterfaceDescriptor< ArrayNoArgumentConstructorDescriptor> { public: // This descriptor declares same register arguments as the parent // ArrayNArgumentsConstructorDescriptor and it declares indices for // JS arguments passed on the expression stack. DEFINE_PARAMETERS(kFunction, kAllocationSite, kActualArgumentsCount, kFunctionParameter) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction MachineType::AnyTagged(), // kAllocationSite MachineType::Int32(), // kActualArgumentsCount MachineType::AnyTagged()) // kFunctionParameter DECLARE_DESCRIPTOR(ArrayNoArgumentConstructorDescriptor) static constexpr auto registers(); }; class ArraySingleArgumentConstructorDescriptor : public StaticCallInterfaceDescriptor< ArraySingleArgumentConstructorDescriptor> { public: // This descriptor declares same register arguments as the parent // ArrayNArgumentsConstructorDescriptor and it declares indices for // JS arguments passed on the expression stack. DEFINE_PARAMETERS(kFunction, kAllocationSite, kActualArgumentsCount, kArraySizeSmiParameter, kReceiverParameter) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction MachineType::AnyTagged(), // kAllocationSite MachineType::Int32(), // kActualArgumentsCount // JS arguments on the stack MachineType::AnyTagged(), // kArraySizeSmiParameter MachineType::AnyTagged()) // kReceiverParameter DECLARE_DESCRIPTOR(ArraySingleArgumentConstructorDescriptor) static constexpr auto registers(); }; class CompareDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kLeft, kRight) DECLARE_DESCRIPTOR(CompareDescriptor) static constexpr inline auto registers(); }; class BinaryOpDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kLeft, kRight) DECLARE_DESCRIPTOR(BinaryOpDescriptor) static constexpr inline auto registers(); }; class BinaryOp_BaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kLeft, kRight, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kLeft MachineType::AnyTagged(), // kRight MachineType::UintPtr()) // kSlot DECLARE_DESCRIPTOR(BinaryOp_BaselineDescriptor) static constexpr inline auto registers(); }; class BinarySmiOp_BaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kLeft, kRight, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kLeft MachineType::TaggedSigned(), // kRight MachineType::UintPtr()) // kSlot DECLARE_DESCRIPTOR(BinarySmiOp_BaselineDescriptor) static constexpr inline auto registers(); }; class StringAtAsStringDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kPosition) // TODO(turbofan): Return untagged value here. DEFINE_RESULT_AND_PARAMETER_TYPES( MachineType::TaggedPointer(), // result string MachineType::AnyTagged(), // kReceiver MachineType::IntPtr()) // kPosition DECLARE_DESCRIPTOR(StringAtAsStringDescriptor) }; class StringSubstringDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kString, kFrom, kTo) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kString MachineType::IntPtr(), // kFrom MachineType::IntPtr()) // kTo // TODO(turbofan): Allow builtins to return untagged values. DECLARE_DESCRIPTOR(StringSubstringDescriptor) }; class CppBuiltinAdaptorDescriptor : public StaticJSCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS(kCFunction) DEFINE_JS_PARAMETER_TYPES(MachineType::Pointer()) DECLARE_JS_COMPATIBLE_DESCRIPTOR(CppBuiltinAdaptorDescriptor) }; class CEntry1ArgvOnStackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kArity, // register argument kCFunction, // register argument kPadding, // stack argument 1 (just padding) kArgcSmi, // stack argument 2 kTargetCopy, // stack argument 3 kNewTargetCopy) // stack argument 4 DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kArity MachineType::Pointer(), // kCFunction MachineType::AnyTagged(), // kPadding MachineType::AnyTagged(), // kArgcSmi MachineType::AnyTagged(), // kTargetCopy MachineType::AnyTagged()) // kNewTargetCopy DECLARE_DESCRIPTOR(CEntry1ArgvOnStackDescriptor) static constexpr auto registers(); }; class ApiCallbackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_VARARGS(kApiFunctionAddress, kActualArgumentsCount, kCallData, kHolder) // receiver is implicit stack argument 1 // argv are implicit stack arguments [2, 2 + kArgc[ DEFINE_PARAMETER_TYPES(MachineType::Pointer(), // kApiFunctionAddress MachineType::IntPtr(), // kActualArgumentsCount MachineType::AnyTagged(), // kCallData MachineType::AnyTagged()) // kHolder DECLARE_DESCRIPTOR(ApiCallbackDescriptor) static constexpr inline auto registers(); }; class ApiGetterDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kReceiver, kHolder, kCallback) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kReceiver MachineType::AnyTagged(), // kHolder MachineType::AnyTagged()) // kCallback DECLARE_DESCRIPTOR(ApiGetterDescriptor) static constexpr inline Register ReceiverRegister(); static constexpr inline Register HolderRegister(); static constexpr inline Register CallbackRegister(); static constexpr auto registers(); }; // TODO(turbofan): We should probably rename this to GrowFastElementsDescriptor. class GrowArrayElementsDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kObject, kKey) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kObject MachineType::AnyTagged()) // kKey DECLARE_DESCRIPTOR(GrowArrayElementsDescriptor) static constexpr inline Register ObjectRegister(); static constexpr inline Register KeyRegister(); static constexpr auto registers(); }; class BaselineOutOfLinePrologueDescriptor : public StaticCallInterfaceDescriptor< BaselineOutOfLinePrologueDescriptor> { public: DEFINE_PARAMETERS_NO_CONTEXT(kCalleeContext, kClosure, kJavaScriptCallArgCount, kStackFrameSize, kJavaScriptCallNewTarget, kInterpreterBytecodeArray) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kCalleeContext MachineType::AnyTagged(), // kClosure MachineType::Int32(), // kJavaScriptCallArgCount MachineType::Int32(), // kStackFrameSize MachineType::AnyTagged(), // kJavaScriptCallNewTarget MachineType::AnyTagged()) // kInterpreterBytecodeArray DECLARE_DESCRIPTOR(BaselineOutOfLinePrologueDescriptor) static constexpr inline auto registers(); // We pass the context manually, so we have one extra register. static constexpr int kMaxRegisterParams = StaticCallInterfaceDescriptor::kMaxRegisterParams + 1; }; class BaselineLeaveFrameDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kParamsSize, kWeight) DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kParamsSize MachineType::Int32()) // kWeight DECLARE_DESCRIPTOR(BaselineLeaveFrameDescriptor) static constexpr inline Register ParamsSizeRegister(); static constexpr inline Register WeightRegister(); static constexpr inline auto registers(); }; class OnStackReplacementDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kMaybeTargetCode) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged()) // kMaybeTargetCode DECLARE_DESCRIPTOR(OnStackReplacementDescriptor) static constexpr inline Register MaybeTargetCodeRegister(); static constexpr inline auto registers(); }; class V8_EXPORT_PRIVATE InterpreterDispatchDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kAccumulator, kBytecodeOffset, kBytecodeArray, kDispatchTable) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kAccumulator MachineType::IntPtr(), // kBytecodeOffset MachineType::AnyTagged(), // kBytecodeArray MachineType::IntPtr()) // kDispatchTable DECLARE_DESCRIPTOR(InterpreterDispatchDescriptor) static constexpr inline auto registers(); }; class InterpreterPushArgsThenCallDescriptor : public StaticCallInterfaceDescriptor< InterpreterPushArgsThenCallDescriptor> { public: DEFINE_PARAMETERS(kNumberOfArguments, kFirstArgument, kFunction) DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kNumberOfArguments MachineType::Pointer(), // kFirstArgument MachineType::AnyTagged()) // kFunction DECLARE_DESCRIPTOR(InterpreterPushArgsThenCallDescriptor) static constexpr inline auto registers(); }; class InterpreterPushArgsThenConstructDescriptor : public StaticCallInterfaceDescriptor< InterpreterPushArgsThenConstructDescriptor> { public: DEFINE_PARAMETERS(kNumberOfArguments, kFirstArgument, kConstructor, kNewTarget, kFeedbackElement) DEFINE_PARAMETER_TYPES(MachineType::Int32(), // kNumberOfArguments MachineType::Pointer(), // kFirstArgument MachineType::AnyTagged(), // kConstructor MachineType::AnyTagged(), // kNewTarget MachineType::AnyTagged()) // kFeedbackElement DECLARE_DESCRIPTOR(InterpreterPushArgsThenConstructDescriptor) static constexpr inline auto registers(); }; class InterpreterCEntry1Descriptor : public StaticCallInterfaceDescriptor { public: DEFINE_RESULT_AND_PARAMETERS(1, kNumberOfArguments, kFirstArgument, kFunctionEntry) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result 1 MachineType::Int32(), // kNumberOfArguments MachineType::Pointer(), // kFirstArgument MachineType::Pointer()) // kFunctionEntry DECLARE_DESCRIPTOR(InterpreterCEntry1Descriptor) static constexpr auto registers(); }; class InterpreterCEntry2Descriptor : public StaticCallInterfaceDescriptor { public: DEFINE_RESULT_AND_PARAMETERS(2, kNumberOfArguments, kFirstArgument, kFunctionEntry) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result 1 MachineType::AnyTagged(), // result 2 MachineType::Int32(), // kNumberOfArguments MachineType::Pointer(), // kFirstArgument MachineType::Pointer()) // kFunctionEntry DECLARE_DESCRIPTOR(InterpreterCEntry2Descriptor) static constexpr auto registers(); }; class FindNonDefaultConstructorOrConstructDescriptor : public StaticCallInterfaceDescriptor< FindNonDefaultConstructorOrConstructDescriptor> { public: DEFINE_RESULT_AND_PARAMETERS(2, kThisFunction, kNewTarget) DEFINE_RESULT_AND_PARAMETER_TYPES( MachineType::AnyTagged(), // result 1 (true / false) MachineType::AnyTagged(), // result 2 (constructor_or_instance) MachineType::AnyTagged(), // kThisFunction MachineType::AnyTagged()) // kNewTarget DECLARE_DESCRIPTOR(FindNonDefaultConstructorOrConstructDescriptor) }; class ForInPrepareDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_RESULT_AND_PARAMETERS(2, kEnumerator, kVectorIndex, kFeedbackVector) DEFINE_RESULT_AND_PARAMETER_TYPES( MachineType::AnyTagged(), // result 1 (cache array) MachineType::AnyTagged(), // result 2 (cache length) MachineType::AnyTagged(), // kEnumerator MachineType::TaggedSigned(), // kVectorIndex MachineType::AnyTagged()) // kFeedbackVector DECLARE_DESCRIPTOR(ForInPrepareDescriptor) }; class ResumeGeneratorDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kValue, kGenerator) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kValue MachineType::AnyTagged()) // kGenerator DECLARE_DESCRIPTOR(ResumeGeneratorDescriptor) static constexpr inline auto registers(); }; class ResumeGeneratorBaselineDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kGeneratorObject, kRegisterCount) DEFINE_RESULT_AND_PARAMETER_TYPES( MachineType::TaggedSigned(), // return type MachineType::AnyTagged(), // kGeneratorObject MachineType::IntPtr(), // kRegisterCount ) DECLARE_DESCRIPTOR(ResumeGeneratorBaselineDescriptor) }; class SuspendGeneratorBaselineDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kGeneratorObject, kSuspendId, kBytecodeOffset, kRegisterCount) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kGeneratorObject MachineType::IntPtr(), // kSuspendId MachineType::IntPtr(), // kBytecodeOffset MachineType::IntPtr(), // kRegisterCount ) DECLARE_DESCRIPTOR(SuspendGeneratorBaselineDescriptor) }; class RestartFrameTrampolineDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS() DECLARE_DESCRIPTOR(RestartFrameTrampolineDescriptor) }; class RunMicrotasksEntryDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_ENTRY(kRootRegisterValue, kMicrotaskQueue) DEFINE_PARAMETER_TYPES(MachineType::Pointer(), // kRootRegisterValue MachineType::Pointer()) // kMicrotaskQueue DECLARE_DESCRIPTOR(RunMicrotasksEntryDescriptor) static constexpr inline auto registers(); }; class RunMicrotasksDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kMicrotaskQueue) DEFINE_PARAMETER_TYPES(MachineType::Pointer()) DECLARE_DESCRIPTOR(RunMicrotasksDescriptor) static constexpr inline Register MicrotaskQueueRegister(); }; class WasmFloat32ToNumberDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kValue) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result MachineType::Float32()) // value DECLARE_DESCRIPTOR(WasmFloat32ToNumberDescriptor) #if V8_TARGET_ARCH_IA32 // We need a custom descriptor on ia32 to avoid using xmm0. static constexpr inline auto registers(); #endif }; class WasmFloat64ToNumberDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kValue) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result MachineType::Float64()) // value DECLARE_DESCRIPTOR(WasmFloat64ToNumberDescriptor) #if V8_TARGET_ARCH_IA32 // We need a custom descriptor on ia32 to avoid using xmm0. static constexpr inline auto registers(); #endif }; class WasmSuspendDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT(1, kArg0, kArg1) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::AnyTagged(), // result MachineType::AnyTagged(), // value MachineType::AnyTagged()) // value DECLARE_DESCRIPTOR(WasmSuspendDescriptor) }; class V8_EXPORT_PRIVATE I64ToBigIntDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kArgument) DEFINE_PARAMETER_TYPES(MachineType::Int64()) // kArgument DECLARE_DESCRIPTOR(I64ToBigIntDescriptor) }; // 32 bits version of the I64ToBigIntDescriptor call interface descriptor class V8_EXPORT_PRIVATE I32PairToBigIntDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kLow, kHigh) DEFINE_PARAMETER_TYPES(MachineType::Uint32(), // kLow MachineType::Uint32()) // kHigh DECLARE_DESCRIPTOR(I32PairToBigIntDescriptor) }; class V8_EXPORT_PRIVATE BigIntToI64Descriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kArgument) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::Int64(), // result 1 MachineType::AnyTagged()) // kArgument DECLARE_DESCRIPTOR(BigIntToI64Descriptor) }; class V8_EXPORT_PRIVATE BigIntToI32PairDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_RESULT_AND_PARAMETERS(2, kArgument) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::Uint32(), // result 1 MachineType::Uint32(), // result 2 MachineType::AnyTagged()) // kArgument DECLARE_DESCRIPTOR(BigIntToI32PairDescriptor) }; class WasmI32AtomicWait32Descriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kAddress, kExpectedValue, kTimeoutLow, kTimeoutHigh) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::Uint32(), // result 1 MachineType::Uint32(), // kAddress MachineType::Int32(), // kExpectedValue MachineType::Uint32(), // kTimeoutLow MachineType::Uint32()) // kTimeoutHigh DECLARE_DESCRIPTOR(WasmI32AtomicWait32Descriptor) }; class WasmI64AtomicWait32Descriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kAddress, kExpectedValueLow, kExpectedValueHigh, kTimeoutLow, kTimeoutHigh) static constexpr bool kNoStackScan = true; DEFINE_RESULT_AND_PARAMETER_TYPES( MachineType::Uint32(), // result 1 MachineType::Uint32(), // kAddress MachineType::Uint32(), // kExpectedValueLow MachineType::Uint32(), // kExpectedValueHigh MachineType::Uint32(), // kTimeoutLow MachineType::Uint32()) // kTimeoutHigh DECLARE_DESCRIPTOR(WasmI64AtomicWait32Descriptor) }; class CloneObjectWithVectorDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kSource, kFlags, kSlot, kVector) DEFINE_RESULT_AND_PARAMETER_TYPES(MachineType::TaggedPointer(), // result 1 MachineType::AnyTagged(), // kSource MachineType::TaggedSigned(), // kFlags MachineType::TaggedSigned(), // kSlot MachineType::AnyTagged()) // kVector DECLARE_DESCRIPTOR(CloneObjectWithVectorDescriptor) }; class CloneObjectBaselineDescriptor final : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kSource, kFlags, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kSource MachineType::TaggedSigned(), // kFlags MachineType::TaggedSigned()) // kSlot DECLARE_DESCRIPTOR(CloneObjectBaselineDescriptor) }; class BinaryOp_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kLeft, kRight, kSlot, kFeedbackVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kLeft MachineType::AnyTagged(), // kRight MachineType::UintPtr(), // kSlot MachineType::AnyTagged()) // kFeedbackVector DECLARE_DESCRIPTOR(BinaryOp_WithFeedbackDescriptor) }; class CallTrampoline_Baseline_CompactDescriptor : public StaticCallInterfaceDescriptor< CallTrampoline_Baseline_CompactDescriptor> { public: using ArgumentCountField = base::BitField; using SlotField = base::BitField; static bool EncodeBitField(uint32_t argc, uintptr_t slot, uint32_t* out) { if (ArgumentCountField::is_valid(argc) && SlotField::is_valid(slot)) { *out = ArgumentCountField::encode(argc) | SlotField::encode(slot); return true; } return false; } DEFINE_PARAMETERS_NO_CONTEXT_VARARGS(kFunction, kBitField) DEFINE_PARAMETER_TYPES( MachineType::AnyTagged(), // kFunction MachineType::Uint32()) // kBitField = ArgumentCountField | SlotField DECLARE_DESCRIPTOR(CallTrampoline_Baseline_CompactDescriptor) }; class CallTrampoline_BaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT_VARARGS(kFunction, kActualArgumentsCount, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction MachineType::Int32(), // kActualArgumentsCount MachineType::UintPtr()) // kSlot DECLARE_DESCRIPTOR(CallTrampoline_BaselineDescriptor) }; class CallTrampoline_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor< CallTrampoline_WithFeedbackDescriptor> { public: DEFINE_PARAMETERS_VARARGS(kFunction, kActualArgumentsCount, kSlot, kFeedbackVector, kReceiver) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kFunction MachineType::Int32(), // kActualArgumentsCount MachineType::UintPtr(), // kSlot MachineType::AnyTagged(), // kFeedbackVector MachineType::AnyTagged()) // kReceiver DECLARE_DESCRIPTOR(CallTrampoline_WithFeedbackDescriptor) }; class Compare_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kLeft, kRight, kSlot, kFeedbackVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kLeft MachineType::AnyTagged(), // kRight MachineType::UintPtr(), // kSlot MachineType::AnyTagged()) // kFeedbackVector DECLARE_DESCRIPTOR(Compare_WithFeedbackDescriptor) }; class Compare_BaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kLeft, kRight, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kLeft MachineType::AnyTagged(), // kRight MachineType::UintPtr()) // kSlot DECLARE_DESCRIPTOR(Compare_BaselineDescriptor) static constexpr inline auto registers(); }; class Construct_BaselineDescriptor : public StaticJSCallInterfaceDescriptor { public: DEFINE_JS_PARAMETERS_NO_CONTEXT(kSlot) DEFINE_JS_PARAMETER_TYPES(MachineType::UintPtr()) // kSlot DECLARE_JS_COMPATIBLE_DESCRIPTOR(Construct_BaselineDescriptor) }; class Construct_WithFeedbackDescriptor : public StaticJSCallInterfaceDescriptor { public: // kSlot is passed in a register, kFeedbackVector on the stack. DEFINE_JS_PARAMETERS(kSlot, kFeedbackVector) DEFINE_JS_PARAMETER_TYPES(MachineType::UintPtr(), // kSlot MachineType::AnyTagged()) // kFeedbackVector DECLARE_JS_COMPATIBLE_DESCRIPTOR(Construct_WithFeedbackDescriptor) }; class UnaryOp_WithFeedbackDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS(kValue, kSlot, kFeedbackVector) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kValue MachineType::UintPtr(), // kSlot MachineType::AnyTagged()) // kFeedbackVector DECLARE_DESCRIPTOR(UnaryOp_WithFeedbackDescriptor) }; class UnaryOp_BaselineDescriptor : public StaticCallInterfaceDescriptor { public: DEFINE_PARAMETERS_NO_CONTEXT(kValue, kSlot) DEFINE_PARAMETER_TYPES(MachineType::AnyTagged(), // kValue MachineType::UintPtr()) // kSlot DECLARE_DESCRIPTOR(UnaryOp_BaselineDescriptor) }; #define DEFINE_TFS_BUILTIN_DESCRIPTOR(Name, ...) \ class Name##Descriptor \ : public StaticCallInterfaceDescriptor { \ public: \ DEFINE_PARAMETERS(__VA_ARGS__) \ DECLARE_DEFAULT_DESCRIPTOR(Name##Descriptor) \ }; BUILTIN_LIST_TFS(DEFINE_TFS_BUILTIN_DESCRIPTOR) #undef DEFINE_TFS_BUILTIN_DESCRIPTOR // This file contains interface descriptor class definitions for builtins // defined in Torque. It is included here because the class definitions need to // precede the definition of name##Descriptor::key() below. #include "torque-generated/interface-descriptors.inc" #undef DECLARE_DEFAULT_DESCRIPTOR #undef DECLARE_DESCRIPTOR_WITH_BASE #undef DECLARE_DESCRIPTOR #undef DECLARE_JS_COMPATIBLE_DESCRIPTOR #undef DEFINE_RESULT_AND_PARAMETERS #undef DEFINE_PARAMETERS_ENTRY #undef DEFINE_PARAMETERS #undef DEFINE_PARAMETERS_VARARGS #undef DEFINE_PARAMETERS_NO_CONTEXT #undef DEFINE_RESULT_AND_PARAMETERS_NO_CONTEXT #undef DEFINE_RESULT_AND_PARAMETER_TYPES #undef DEFINE_PARAMETER_TYPES #undef DEFINE_JS_PARAMETERS #undef DEFINE_JS_PARAMETER_TYPES // We define the association between CallDescriptors::Key and the specialized // descriptor here to reduce boilerplate and mistakes. #define DEF_KEY(name, ...) \ CallDescriptors::Key name##Descriptor::key() { return CallDescriptors::name; } INTERFACE_DESCRIPTOR_LIST(DEF_KEY) #undef DEF_KEY } // namespace internal } // namespace v8 #endif // V8_CODEGEN_INTERFACE_DESCRIPTORS_H_