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(VectorStoreICTrampoline) \
29 V(FastCloneShallowArray) \
30 V(FastCloneShallowObject) \
31 V(CreateAllocationSite) \
34 V(CallFunctionWithFeedback) \
35 V(CallFunctionWithFeedbackAndVector) \
37 V(RegExpConstructResult) \
38 V(TransitionElementsKind) \
39 V(AllocateHeapNumber) \
40 V(ArrayConstructorConstantArgCount) \
42 V(InternalArrayConstructorConstantArgCount) \
43 V(InternalArrayConstructor) \
48 V(BinaryOpWithAllocationSite) \
57 V(ArgumentsAccessRead) \
58 V(StoreArrayLiteralElement) \
59 V(LoadGlobalViaContext) \
60 V(StoreGlobalViaContext) \
64 V(GrowArrayElements) \
65 V(MathRoundVariantCallFromUnoptimizedCode) \
66 V(MathRoundVariantCallFromOptimizedCode)
69 class CallInterfaceDescriptorData {
71 CallInterfaceDescriptorData()
72 : register_param_count_(-1), function_type_(nullptr) {}
74 // A copy of the passed in registers and param_representations is made
75 // and owned by the CallInterfaceDescriptorData.
77 void InitializePlatformIndependent(Type::FunctionType* function_type) {
78 function_type_ = function_type;
81 // TODO(mvstanton): Instead of taking parallel arrays register and
82 // param_representations, how about a struct that puts the representation
83 // and register side by side (eg, RegRep(r1, Representation::Tagged()).
84 // The same should go for the CodeStubDescriptor class.
85 void InitializePlatformSpecific(
86 int register_parameter_count, Register* registers,
87 PlatformInterfaceDescriptor* platform_descriptor = NULL);
89 bool IsInitialized() const { return register_param_count_ >= 0; }
91 int param_count() const { return function_type_->Arity(); }
92 int register_param_count() const { return register_param_count_; }
93 Register register_param(int index) const { return register_params_[index]; }
94 Register* register_params() const { return register_params_.get(); }
95 Type* param_type(int index) const { return function_type_->Parameter(index); }
96 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
97 return platform_specific_descriptor_;
100 Type::FunctionType* function_type() const { return function_type_; }
103 int register_param_count_;
105 // The Register params are allocated dynamically by the
106 // InterfaceDescriptor, and freed on destruction. This is because static
107 // arrays of Registers cause creation of runtime static initializers
108 // which we don't want.
109 base::SmartArrayPointer<Register> register_params_;
111 // Specifies types for parameters and return
112 Type::FunctionType* function_type_;
114 PlatformInterfaceDescriptor* platform_specific_descriptor_;
116 DISALLOW_COPY_AND_ASSIGN(CallInterfaceDescriptorData);
120 class CallDescriptors {
123 #define DEF_ENUM(name) name,
124 INTERFACE_DESCRIPTOR_LIST(DEF_ENUM)
126 NUMBER_OF_DESCRIPTORS
131 class CallInterfaceDescriptor {
133 CallInterfaceDescriptor() : data_(NULL) {}
134 virtual ~CallInterfaceDescriptor() {}
136 CallInterfaceDescriptor(Isolate* isolate, CallDescriptors::Key key)
137 : data_(isolate->call_descriptor_data(key)) {}
139 int GetParameterCount() const { return data()->param_count(); }
141 int GetRegisterParameterCount() const {
142 return data()->register_param_count();
145 int GetStackParameterCount() const {
146 return data()->function_type()->Arity() - data()->register_param_count();
149 Register GetRegisterParameter(int index) const {
150 return data()->register_param(index);
153 Type* GetParameterType(int index) const {
154 DCHECK(index < data()->param_count());
155 return data()->param_type(index);
158 // Some platforms have extra information to associate with the descriptor.
159 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
160 return data()->platform_specific_descriptor();
163 Type::FunctionType* GetFunctionType() const {
164 return data()->function_type();
167 static const Register ContextRegister();
169 const char* DebugName(Isolate* isolate) const;
171 static Type::FunctionType* BuildDefaultFunctionType(Isolate* isolate,
172 int paramater_count);
175 const CallInterfaceDescriptorData* data() const { return data_; }
177 virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType(
178 Isolate* isolate, int register_param_count) {
179 return BuildDefaultFunctionType(isolate, register_param_count);
182 virtual void InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
186 void Initialize(Isolate* isolate, CallDescriptors::Key key) {
187 if (!data()->IsInitialized()) {
188 CallInterfaceDescriptorData* d = isolate->call_descriptor_data(key);
189 InitializePlatformSpecific(d);
190 Type::FunctionType* function_type =
191 BuildCallInterfaceDescriptorFunctionType(isolate,
192 d->register_param_count());
193 d->InitializePlatformIndependent(function_type);
198 const CallInterfaceDescriptorData* data_;
202 #define DECLARE_DESCRIPTOR(name, base) \
203 explicit name(Isolate* isolate) : base(isolate, key()) { \
204 Initialize(isolate, key()); \
208 void InitializePlatformSpecific(CallInterfaceDescriptorData* data) override; \
209 name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {} \
212 static inline CallDescriptors::Key key();
215 #define DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(name, base) \
216 DECLARE_DESCRIPTOR(name, base) \
218 virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType( \
219 Isolate* isolate, int register_param_count) override; \
222 // LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
223 class LoadDescriptor : public CallInterfaceDescriptor {
225 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadDescriptor,
226 CallInterfaceDescriptor)
228 enum ParameterIndices { kReceiverIndex, kNameIndex, kSlotIndex };
229 static const Register ReceiverRegister();
230 static const Register NameRegister();
231 static const Register SlotRegister();
235 class StoreDescriptor : public CallInterfaceDescriptor {
237 DECLARE_DESCRIPTOR(StoreDescriptor, CallInterfaceDescriptor)
239 enum ParameterIndices {
245 static const Register ReceiverRegister();
246 static const Register NameRegister();
247 static const Register ValueRegister();
251 class StoreTransitionDescriptor : public StoreDescriptor {
253 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreTransitionDescriptor,
256 // Extends StoreDescriptor with Map parameter.
257 enum ParameterIndices {
265 // MapRegister() is no_reg on ia32, instead it's on the stack.
266 static const Register MapRegister();
270 class InstanceofDescriptor : public CallInterfaceDescriptor {
272 DECLARE_DESCRIPTOR(InstanceofDescriptor, CallInterfaceDescriptor)
274 enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount };
275 static const Register left();
276 static const Register right();
280 class VectorStoreICTrampolineDescriptor : public StoreDescriptor {
282 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
283 VectorStoreICTrampolineDescriptor, StoreDescriptor)
285 enum ParameterIndices { kReceiverIndex, kNameIndex, kValueIndex, kSlotIndex };
287 static const Register SlotRegister();
291 class VectorStoreICDescriptor : public VectorStoreICTrampolineDescriptor {
293 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
294 VectorStoreICDescriptor, VectorStoreICTrampolineDescriptor)
296 enum ParameterIndices {
304 static const Register VectorRegister();
308 class LoadWithVectorDescriptor : public LoadDescriptor {
310 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadWithVectorDescriptor,
313 enum ParameterIndices {
320 static const Register VectorRegister();
324 class FastNewClosureDescriptor : public CallInterfaceDescriptor {
326 DECLARE_DESCRIPTOR(FastNewClosureDescriptor, CallInterfaceDescriptor)
330 class FastNewContextDescriptor : public CallInterfaceDescriptor {
332 DECLARE_DESCRIPTOR(FastNewContextDescriptor, CallInterfaceDescriptor)
336 class ToNumberDescriptor : public CallInterfaceDescriptor {
338 DECLARE_DESCRIPTOR(ToNumberDescriptor, CallInterfaceDescriptor)
342 class NumberToStringDescriptor : public CallInterfaceDescriptor {
344 DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
348 class TypeofDescriptor : public CallInterfaceDescriptor {
350 DECLARE_DESCRIPTOR(TypeofDescriptor, CallInterfaceDescriptor)
354 class FastCloneShallowArrayDescriptor : public CallInterfaceDescriptor {
356 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastCloneShallowArrayDescriptor,
357 CallInterfaceDescriptor)
361 class FastCloneShallowObjectDescriptor : public CallInterfaceDescriptor {
363 DECLARE_DESCRIPTOR(FastCloneShallowObjectDescriptor, CallInterfaceDescriptor)
367 class CreateAllocationSiteDescriptor : public CallInterfaceDescriptor {
369 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateAllocationSiteDescriptor,
370 CallInterfaceDescriptor)
374 class CreateWeakCellDescriptor : public CallInterfaceDescriptor {
376 enum ParameterIndices {
383 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateWeakCellDescriptor,
384 CallInterfaceDescriptor)
388 class CallFunctionDescriptor : public CallInterfaceDescriptor {
390 DECLARE_DESCRIPTOR(CallFunctionDescriptor, CallInterfaceDescriptor)
394 class CallFunctionWithFeedbackDescriptor : public CallInterfaceDescriptor {
396 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
397 CallFunctionWithFeedbackDescriptor, CallInterfaceDescriptor)
401 class CallFunctionWithFeedbackAndVectorDescriptor
402 : public CallInterfaceDescriptor {
404 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
405 CallFunctionWithFeedbackAndVectorDescriptor, CallInterfaceDescriptor)
409 class CallConstructDescriptor : public CallInterfaceDescriptor {
411 DECLARE_DESCRIPTOR(CallConstructDescriptor, CallInterfaceDescriptor)
415 class RegExpConstructResultDescriptor : public CallInterfaceDescriptor {
417 DECLARE_DESCRIPTOR(RegExpConstructResultDescriptor, CallInterfaceDescriptor)
421 class LoadGlobalViaContextDescriptor : public CallInterfaceDescriptor {
423 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalViaContextDescriptor,
424 CallInterfaceDescriptor)
426 static const Register SlotRegister();
427 static const Register NameRegister();
431 class StoreGlobalViaContextDescriptor : public CallInterfaceDescriptor {
433 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreGlobalViaContextDescriptor,
434 CallInterfaceDescriptor)
436 static const Register SlotRegister();
437 static const Register NameRegister();
438 static const Register ValueRegister();
442 class TransitionElementsKindDescriptor : public CallInterfaceDescriptor {
444 DECLARE_DESCRIPTOR(TransitionElementsKindDescriptor, CallInterfaceDescriptor)
448 class AllocateHeapNumberDescriptor : public CallInterfaceDescriptor {
450 DECLARE_DESCRIPTOR(AllocateHeapNumberDescriptor, CallInterfaceDescriptor)
454 class ArrayConstructorConstantArgCountDescriptor
455 : public CallInterfaceDescriptor {
457 DECLARE_DESCRIPTOR(ArrayConstructorConstantArgCountDescriptor,
458 CallInterfaceDescriptor)
462 class ArrayConstructorDescriptor : public CallInterfaceDescriptor {
464 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArrayConstructorDescriptor,
465 CallInterfaceDescriptor)
469 class InternalArrayConstructorConstantArgCountDescriptor
470 : public CallInterfaceDescriptor {
472 DECLARE_DESCRIPTOR(InternalArrayConstructorConstantArgCountDescriptor,
473 CallInterfaceDescriptor)
477 class InternalArrayConstructorDescriptor : public CallInterfaceDescriptor {
479 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
480 InternalArrayConstructorDescriptor, CallInterfaceDescriptor)
484 class CompareDescriptor : public CallInterfaceDescriptor {
486 DECLARE_DESCRIPTOR(CompareDescriptor, CallInterfaceDescriptor)
490 class CompareNilDescriptor : public CallInterfaceDescriptor {
492 DECLARE_DESCRIPTOR(CompareNilDescriptor, CallInterfaceDescriptor)
496 class ToBooleanDescriptor : public CallInterfaceDescriptor {
498 DECLARE_DESCRIPTOR(ToBooleanDescriptor, CallInterfaceDescriptor)
502 class BinaryOpDescriptor : public CallInterfaceDescriptor {
504 DECLARE_DESCRIPTOR(BinaryOpDescriptor, CallInterfaceDescriptor)
508 class BinaryOpWithAllocationSiteDescriptor : public CallInterfaceDescriptor {
510 DECLARE_DESCRIPTOR(BinaryOpWithAllocationSiteDescriptor,
511 CallInterfaceDescriptor)
515 class StringAddDescriptor : public CallInterfaceDescriptor {
517 DECLARE_DESCRIPTOR(StringAddDescriptor, CallInterfaceDescriptor)
521 class KeyedDescriptor : public CallInterfaceDescriptor {
523 DECLARE_DESCRIPTOR(KeyedDescriptor, CallInterfaceDescriptor)
527 class NamedDescriptor : public CallInterfaceDescriptor {
529 DECLARE_DESCRIPTOR(NamedDescriptor, CallInterfaceDescriptor)
533 class CallHandlerDescriptor : public CallInterfaceDescriptor {
535 DECLARE_DESCRIPTOR(CallHandlerDescriptor, CallInterfaceDescriptor)
539 class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor {
541 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentAdaptorDescriptor,
542 CallInterfaceDescriptor)
546 class ApiFunctionDescriptor : public CallInterfaceDescriptor {
548 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiFunctionDescriptor,
549 CallInterfaceDescriptor)
553 class ApiAccessorDescriptor : public CallInterfaceDescriptor {
555 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiAccessorDescriptor,
556 CallInterfaceDescriptor)
560 class ApiGetterDescriptor : public CallInterfaceDescriptor {
562 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiGetterDescriptor,
563 CallInterfaceDescriptor)
565 static const Register function_address();
569 class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor {
571 DECLARE_DESCRIPTOR(ArgumentsAccessReadDescriptor, CallInterfaceDescriptor)
573 static const Register index();
574 static const Register parameter_count();
578 class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor {
580 DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor,
581 CallInterfaceDescriptor)
585 class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
587 DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
589 static const Register exponent();
593 class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
595 DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
597 static const Register exponent();
601 class MathRoundVariantCallFromOptimizedCodeDescriptor
602 : public CallInterfaceDescriptor {
604 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
605 MathRoundVariantCallFromOptimizedCodeDescriptor, CallInterfaceDescriptor)
609 class MathRoundVariantCallFromUnoptimizedCodeDescriptor
610 : public CallInterfaceDescriptor {
612 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
613 MathRoundVariantCallFromUnoptimizedCodeDescriptor,
614 CallInterfaceDescriptor)
618 class ContextOnlyDescriptor : public CallInterfaceDescriptor {
620 DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
624 class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
626 DECLARE_DESCRIPTOR(GrowArrayElementsDescriptor, CallInterfaceDescriptor)
628 enum RegisterInfo { kObjectIndex, kKeyIndex };
629 static const Register ObjectRegister();
630 static const Register KeyRegister();
633 #undef DECLARE_DESCRIPTOR
636 // We define the association between CallDescriptors::Key and the specialized
637 // descriptor here to reduce boilerplate and mistakes.
638 #define DEF_KEY(name) \
639 CallDescriptors::Key name##Descriptor::key() { return CallDescriptors::name; }
640 INTERFACE_DESCRIPTOR_LIST(DEF_KEY)
643 } // namespace v8::internal
646 #if V8_TARGET_ARCH_ARM64
647 #include "src/arm64/interface-descriptors-arm64.h"
648 #elif V8_TARGET_ARCH_ARM
649 #include "src/arm/interface-descriptors-arm.h"
652 #endif // V8_CALL_INTERFACE_DESCRIPTOR_H_