1 // Copyright 2014 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef V8_CALL_INTERFACE_DESCRIPTOR_H_
6 #define V8_CALL_INTERFACE_DESCRIPTOR_H_
8 #include "src/assembler.h"
9 #include "src/macro-assembler.h"
14 class PlatformInterfaceDescriptor;
16 #define INTERFACE_DESCRIPTOR_LIST(V) \
20 V(VectorStoreTransition) \
21 V(VectorStoreICTrampoline) \
32 V(FastCloneShallowArray) \
33 V(FastCloneShallowObject) \
34 V(CreateAllocationSite) \
37 V(CallFunctionWithFeedback) \
38 V(CallFunctionWithFeedbackAndVector) \
42 V(RegExpConstructResult) \
43 V(TransitionElementsKind) \
44 V(AllocateHeapNumber) \
45 V(ArrayConstructorConstantArgCount) \
47 V(InternalArrayConstructorConstantArgCount) \
48 V(InternalArrayConstructor) \
53 V(BinaryOpWithAllocationSite) \
63 V(ArgumentsAccessRead) \
64 V(ArgumentsAccessNew) \
65 V(StoreArrayLiteralElement) \
66 V(LoadGlobalViaContext) \
67 V(StoreGlobalViaContext) \
71 V(GrowArrayElements) \
72 V(MathRoundVariantCallFromUnoptimizedCode) \
73 V(MathRoundVariantCallFromOptimizedCode)
76 class CallInterfaceDescriptorData {
78 CallInterfaceDescriptorData()
79 : register_param_count_(-1), function_type_(nullptr) {}
81 // A copy of the passed in registers and param_representations is made
82 // and owned by the CallInterfaceDescriptorData.
84 void InitializePlatformIndependent(Type::FunctionType* function_type) {
85 function_type_ = function_type;
88 // TODO(mvstanton): Instead of taking parallel arrays register and
89 // param_representations, how about a struct that puts the representation
90 // and register side by side (eg, RegRep(r1, Representation::Tagged()).
91 // The same should go for the CodeStubDescriptor class.
92 void InitializePlatformSpecific(
93 int register_parameter_count, Register* registers,
94 PlatformInterfaceDescriptor* platform_descriptor = NULL);
96 bool IsInitialized() const { return register_param_count_ >= 0; }
98 int param_count() const { return function_type_->Arity(); }
99 int register_param_count() const { return register_param_count_; }
100 Register register_param(int index) const { return register_params_[index]; }
101 Register* register_params() const { return register_params_.get(); }
102 Type* param_type(int index) const { return function_type_->Parameter(index); }
103 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
104 return platform_specific_descriptor_;
107 Type::FunctionType* function_type() const { return function_type_; }
110 int register_param_count_;
112 // The Register params are allocated dynamically by the
113 // InterfaceDescriptor, and freed on destruction. This is because static
114 // arrays of Registers cause creation of runtime static initializers
115 // which we don't want.
116 base::SmartArrayPointer<Register> register_params_;
118 // Specifies types for parameters and return
119 Type::FunctionType* function_type_;
121 PlatformInterfaceDescriptor* platform_specific_descriptor_;
123 DISALLOW_COPY_AND_ASSIGN(CallInterfaceDescriptorData);
127 class CallDescriptors {
130 #define DEF_ENUM(name) name,
131 INTERFACE_DESCRIPTOR_LIST(DEF_ENUM)
133 NUMBER_OF_DESCRIPTORS
138 class CallInterfaceDescriptor {
140 CallInterfaceDescriptor() : data_(NULL) {}
141 virtual ~CallInterfaceDescriptor() {}
143 CallInterfaceDescriptor(Isolate* isolate, CallDescriptors::Key key)
144 : data_(isolate->call_descriptor_data(key)) {}
146 int GetParameterCount() const { return data()->param_count(); }
148 int GetRegisterParameterCount() const {
149 return data()->register_param_count();
152 int GetStackParameterCount() const {
153 return data()->function_type()->Arity() - data()->register_param_count();
156 Register GetRegisterParameter(int index) const {
157 return data()->register_param(index);
160 Type* GetParameterType(int index) const {
161 DCHECK(index < data()->param_count());
162 return data()->param_type(index);
165 // Some platforms have extra information to associate with the descriptor.
166 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
167 return data()->platform_specific_descriptor();
170 Type::FunctionType* GetFunctionType() const {
171 return data()->function_type();
174 static const Register ContextRegister();
176 const char* DebugName(Isolate* isolate) const;
178 static Type::FunctionType* BuildDefaultFunctionType(Isolate* isolate,
179 int paramater_count);
182 const CallInterfaceDescriptorData* data() const { return data_; }
184 virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType(
185 Isolate* isolate, int register_param_count) {
186 return BuildDefaultFunctionType(isolate, register_param_count);
189 virtual void InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
193 void Initialize(Isolate* isolate, CallDescriptors::Key key) {
194 if (!data()->IsInitialized()) {
195 CallInterfaceDescriptorData* d = isolate->call_descriptor_data(key);
196 InitializePlatformSpecific(d);
197 Type::FunctionType* function_type =
198 BuildCallInterfaceDescriptorFunctionType(isolate,
199 d->register_param_count());
200 d->InitializePlatformIndependent(function_type);
205 const CallInterfaceDescriptorData* data_;
209 #define DECLARE_DESCRIPTOR(name, base) \
210 explicit name(Isolate* isolate) : base(isolate, key()) { \
211 Initialize(isolate, key()); \
215 void InitializePlatformSpecific(CallInterfaceDescriptorData* data) override; \
216 name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {} \
219 static inline CallDescriptors::Key key();
222 #define DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(name, base) \
223 DECLARE_DESCRIPTOR(name, base) \
225 virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType( \
226 Isolate* isolate, int register_param_count) override; \
229 // LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
230 class LoadDescriptor : public CallInterfaceDescriptor {
232 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadDescriptor,
233 CallInterfaceDescriptor)
235 enum ParameterIndices { kReceiverIndex, kNameIndex, kSlotIndex };
236 static const Register ReceiverRegister();
237 static const Register NameRegister();
238 static const Register SlotRegister();
242 class StoreDescriptor : public CallInterfaceDescriptor {
244 DECLARE_DESCRIPTOR(StoreDescriptor, CallInterfaceDescriptor)
246 enum ParameterIndices {
252 static const Register ReceiverRegister();
253 static const Register NameRegister();
254 static const Register ValueRegister();
258 class StoreTransitionDescriptor : public StoreDescriptor {
260 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreTransitionDescriptor,
263 // Extends StoreDescriptor with Map parameter.
264 enum ParameterIndices {
272 static const Register MapRegister();
276 class VectorStoreTransitionDescriptor : public StoreDescriptor {
278 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(VectorStoreTransitionDescriptor,
281 // Extends StoreDescriptor with Map parameter.
282 enum ParameterIndices {
292 // These registers are no_reg for ia32, using the stack instead.
293 static const Register SlotRegister();
294 static const Register VectorRegister();
295 static const Register MapRegister();
299 class InstanceOfDescriptor final : public CallInterfaceDescriptor {
301 DECLARE_DESCRIPTOR(InstanceOfDescriptor, CallInterfaceDescriptor)
303 enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount };
304 static const Register LeftRegister();
305 static const Register RightRegister();
309 class VectorStoreICTrampolineDescriptor : public StoreDescriptor {
311 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
312 VectorStoreICTrampolineDescriptor, StoreDescriptor)
314 enum ParameterIndices { kReceiverIndex, kNameIndex, kValueIndex, kSlotIndex };
316 static const Register SlotRegister();
320 class VectorStoreICDescriptor : public VectorStoreICTrampolineDescriptor {
322 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
323 VectorStoreICDescriptor, VectorStoreICTrampolineDescriptor)
325 enum ParameterIndices {
333 static const Register VectorRegister();
337 class LoadWithVectorDescriptor : public LoadDescriptor {
339 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadWithVectorDescriptor,
342 enum ParameterIndices {
349 static const Register VectorRegister();
353 class FastNewClosureDescriptor : public CallInterfaceDescriptor {
355 DECLARE_DESCRIPTOR(FastNewClosureDescriptor, CallInterfaceDescriptor)
359 class FastNewContextDescriptor : public CallInterfaceDescriptor {
361 DECLARE_DESCRIPTOR(FastNewContextDescriptor, CallInterfaceDescriptor)
365 class ToNumberDescriptor : public CallInterfaceDescriptor {
367 DECLARE_DESCRIPTOR(ToNumberDescriptor, CallInterfaceDescriptor)
371 class ToStringDescriptor : public CallInterfaceDescriptor {
373 enum ParameterIndices { kReceiverIndex };
375 DECLARE_DESCRIPTOR(ToStringDescriptor, CallInterfaceDescriptor)
377 static const Register ReceiverRegister();
381 class ToObjectDescriptor : public CallInterfaceDescriptor {
383 enum ParameterIndices { kReceiverIndex };
385 DECLARE_DESCRIPTOR(ToObjectDescriptor, CallInterfaceDescriptor)
387 static const Register ReceiverRegister();
391 class NumberToStringDescriptor : public CallInterfaceDescriptor {
393 DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
397 class TypeofDescriptor : public CallInterfaceDescriptor {
399 DECLARE_DESCRIPTOR(TypeofDescriptor, CallInterfaceDescriptor)
403 class FastCloneShallowArrayDescriptor : public CallInterfaceDescriptor {
405 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastCloneShallowArrayDescriptor,
406 CallInterfaceDescriptor)
410 class FastCloneShallowObjectDescriptor : public CallInterfaceDescriptor {
412 DECLARE_DESCRIPTOR(FastCloneShallowObjectDescriptor, CallInterfaceDescriptor)
416 class CreateAllocationSiteDescriptor : public CallInterfaceDescriptor {
418 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateAllocationSiteDescriptor,
419 CallInterfaceDescriptor)
423 class CreateWeakCellDescriptor : public CallInterfaceDescriptor {
425 enum ParameterIndices {
432 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateWeakCellDescriptor,
433 CallInterfaceDescriptor)
437 class CallTrampolineDescriptor : public CallInterfaceDescriptor {
439 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CallTrampolineDescriptor,
440 CallInterfaceDescriptor)
444 class CallFunctionDescriptor : public CallInterfaceDescriptor {
446 DECLARE_DESCRIPTOR(CallFunctionDescriptor, CallInterfaceDescriptor)
450 class CallFunctionWithFeedbackDescriptor : public CallInterfaceDescriptor {
452 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
453 CallFunctionWithFeedbackDescriptor, CallInterfaceDescriptor)
457 class CallFunctionWithFeedbackAndVectorDescriptor
458 : public CallInterfaceDescriptor {
460 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
461 CallFunctionWithFeedbackAndVectorDescriptor, CallInterfaceDescriptor)
465 class CallConstructDescriptor : public CallInterfaceDescriptor {
467 DECLARE_DESCRIPTOR(CallConstructDescriptor, CallInterfaceDescriptor)
471 class RegExpConstructResultDescriptor : public CallInterfaceDescriptor {
473 DECLARE_DESCRIPTOR(RegExpConstructResultDescriptor, CallInterfaceDescriptor)
477 class LoadGlobalViaContextDescriptor : public CallInterfaceDescriptor {
479 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalViaContextDescriptor,
480 CallInterfaceDescriptor)
482 static const Register SlotRegister();
486 class StoreGlobalViaContextDescriptor : public CallInterfaceDescriptor {
488 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreGlobalViaContextDescriptor,
489 CallInterfaceDescriptor)
491 static const Register SlotRegister();
492 static const Register ValueRegister();
496 class TransitionElementsKindDescriptor : public CallInterfaceDescriptor {
498 DECLARE_DESCRIPTOR(TransitionElementsKindDescriptor, CallInterfaceDescriptor)
502 class AllocateHeapNumberDescriptor : public CallInterfaceDescriptor {
504 DECLARE_DESCRIPTOR(AllocateHeapNumberDescriptor, CallInterfaceDescriptor)
508 class ArrayConstructorConstantArgCountDescriptor
509 : public CallInterfaceDescriptor {
511 DECLARE_DESCRIPTOR(ArrayConstructorConstantArgCountDescriptor,
512 CallInterfaceDescriptor)
516 class ArrayConstructorDescriptor : public CallInterfaceDescriptor {
518 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArrayConstructorDescriptor,
519 CallInterfaceDescriptor)
523 class InternalArrayConstructorConstantArgCountDescriptor
524 : public CallInterfaceDescriptor {
526 DECLARE_DESCRIPTOR(InternalArrayConstructorConstantArgCountDescriptor,
527 CallInterfaceDescriptor)
531 class InternalArrayConstructorDescriptor : public CallInterfaceDescriptor {
533 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
534 InternalArrayConstructorDescriptor, CallInterfaceDescriptor)
538 class CompareDescriptor : public CallInterfaceDescriptor {
540 DECLARE_DESCRIPTOR(CompareDescriptor, CallInterfaceDescriptor)
544 class CompareNilDescriptor : public CallInterfaceDescriptor {
546 DECLARE_DESCRIPTOR(CompareNilDescriptor, CallInterfaceDescriptor)
550 class ToBooleanDescriptor : public CallInterfaceDescriptor {
552 DECLARE_DESCRIPTOR(ToBooleanDescriptor, CallInterfaceDescriptor)
556 class BinaryOpDescriptor : public CallInterfaceDescriptor {
558 DECLARE_DESCRIPTOR(BinaryOpDescriptor, CallInterfaceDescriptor)
562 class BinaryOpWithAllocationSiteDescriptor : public CallInterfaceDescriptor {
564 DECLARE_DESCRIPTOR(BinaryOpWithAllocationSiteDescriptor,
565 CallInterfaceDescriptor)
569 class StringAddDescriptor : public CallInterfaceDescriptor {
571 DECLARE_DESCRIPTOR(StringAddDescriptor, CallInterfaceDescriptor)
575 class StringCompareDescriptor : public CallInterfaceDescriptor {
577 DECLARE_DESCRIPTOR(StringCompareDescriptor, CallInterfaceDescriptor)
579 enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount };
580 static const Register LeftRegister();
581 static const Register RightRegister();
585 class KeyedDescriptor : public CallInterfaceDescriptor {
587 DECLARE_DESCRIPTOR(KeyedDescriptor, CallInterfaceDescriptor)
591 class NamedDescriptor : public CallInterfaceDescriptor {
593 DECLARE_DESCRIPTOR(NamedDescriptor, CallInterfaceDescriptor)
597 class CallHandlerDescriptor : public CallInterfaceDescriptor {
599 DECLARE_DESCRIPTOR(CallHandlerDescriptor, CallInterfaceDescriptor)
603 class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor {
605 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentAdaptorDescriptor,
606 CallInterfaceDescriptor)
610 class ApiFunctionDescriptor : public CallInterfaceDescriptor {
612 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiFunctionDescriptor,
613 CallInterfaceDescriptor)
617 class ApiAccessorDescriptor : public CallInterfaceDescriptor {
619 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiAccessorDescriptor,
620 CallInterfaceDescriptor)
624 class ApiGetterDescriptor : public CallInterfaceDescriptor {
626 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiGetterDescriptor,
627 CallInterfaceDescriptor)
629 static const Register function_address();
633 class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor {
635 DECLARE_DESCRIPTOR(ArgumentsAccessReadDescriptor, CallInterfaceDescriptor)
637 static const Register index();
638 static const Register parameter_count();
642 class ArgumentsAccessNewDescriptor : public CallInterfaceDescriptor {
644 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentsAccessNewDescriptor,
645 CallInterfaceDescriptor)
647 static const Register function();
648 static const Register parameter_count();
649 static const Register parameter_pointer();
653 class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor {
655 DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor,
656 CallInterfaceDescriptor)
660 class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
662 DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
664 static const Register exponent();
668 class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
670 DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
672 static const Register exponent();
676 class MathRoundVariantCallFromOptimizedCodeDescriptor
677 : public CallInterfaceDescriptor {
679 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
680 MathRoundVariantCallFromOptimizedCodeDescriptor, CallInterfaceDescriptor)
684 class MathRoundVariantCallFromUnoptimizedCodeDescriptor
685 : public CallInterfaceDescriptor {
687 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
688 MathRoundVariantCallFromUnoptimizedCodeDescriptor,
689 CallInterfaceDescriptor)
693 class ContextOnlyDescriptor : public CallInterfaceDescriptor {
695 DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
699 class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
701 DECLARE_DESCRIPTOR(GrowArrayElementsDescriptor, CallInterfaceDescriptor)
703 enum RegisterInfo { kObjectIndex, kKeyIndex };
704 static const Register ObjectRegister();
705 static const Register KeyRegister();
709 class PushArgsAndCallDescriptor : public CallInterfaceDescriptor {
711 DECLARE_DESCRIPTOR(PushArgsAndCallDescriptor, CallInterfaceDescriptor)
714 #undef DECLARE_DESCRIPTOR
717 // We define the association between CallDescriptors::Key and the specialized
718 // descriptor here to reduce boilerplate and mistakes.
719 #define DEF_KEY(name) \
720 CallDescriptors::Key name##Descriptor::key() { return CallDescriptors::name; }
721 INTERFACE_DESCRIPTOR_LIST(DEF_KEY)
724 } // namespace v8::internal
727 #if V8_TARGET_ARCH_ARM64
728 #include "src/arm64/interface-descriptors-arm64.h"
729 #elif V8_TARGET_ARCH_ARM
730 #include "src/arm/interface-descriptors-arm.h"
733 #endif // V8_CALL_INTERFACE_DESCRIPTOR_H_