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) \
30 V(FastCloneShallowArray) \
31 V(FastCloneShallowObject) \
32 V(CreateAllocationSite) \
35 V(CallFunctionWithFeedback) \
36 V(CallFunctionWithFeedbackAndVector) \
38 V(RegExpConstructResult) \
39 V(TransitionElementsKind) \
40 V(AllocateHeapNumber) \
41 V(ArrayConstructorConstantArgCount) \
43 V(InternalArrayConstructorConstantArgCount) \
44 V(InternalArrayConstructor) \
49 V(BinaryOpWithAllocationSite) \
58 V(ArgumentsAccessRead) \
59 V(StoreArrayLiteralElement) \
60 V(LoadGlobalViaContext) \
61 V(StoreGlobalViaContext) \
65 V(GrowArrayElements) \
66 V(MathRoundVariantCallFromUnoptimizedCode) \
67 V(MathRoundVariantCallFromOptimizedCode)
70 class CallInterfaceDescriptorData {
72 CallInterfaceDescriptorData()
73 : register_param_count_(-1), function_type_(nullptr) {}
75 // A copy of the passed in registers and param_representations is made
76 // and owned by the CallInterfaceDescriptorData.
78 void InitializePlatformIndependent(Type::FunctionType* function_type) {
79 function_type_ = function_type;
82 // TODO(mvstanton): Instead of taking parallel arrays register and
83 // param_representations, how about a struct that puts the representation
84 // and register side by side (eg, RegRep(r1, Representation::Tagged()).
85 // The same should go for the CodeStubDescriptor class.
86 void InitializePlatformSpecific(
87 int register_parameter_count, Register* registers,
88 PlatformInterfaceDescriptor* platform_descriptor = NULL);
90 bool IsInitialized() const { return register_param_count_ >= 0; }
92 int param_count() const { return function_type_->Arity(); }
93 int register_param_count() const { return register_param_count_; }
94 Register register_param(int index) const { return register_params_[index]; }
95 Register* register_params() const { return register_params_.get(); }
96 Type* param_type(int index) const { return function_type_->Parameter(index); }
97 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
98 return platform_specific_descriptor_;
101 Type::FunctionType* function_type() const { return function_type_; }
104 int register_param_count_;
106 // The Register params are allocated dynamically by the
107 // InterfaceDescriptor, and freed on destruction. This is because static
108 // arrays of Registers cause creation of runtime static initializers
109 // which we don't want.
110 base::SmartArrayPointer<Register> register_params_;
112 // Specifies types for parameters and return
113 Type::FunctionType* function_type_;
115 PlatformInterfaceDescriptor* platform_specific_descriptor_;
117 DISALLOW_COPY_AND_ASSIGN(CallInterfaceDescriptorData);
121 class CallDescriptors {
124 #define DEF_ENUM(name) name,
125 INTERFACE_DESCRIPTOR_LIST(DEF_ENUM)
127 NUMBER_OF_DESCRIPTORS
132 class CallInterfaceDescriptor {
134 CallInterfaceDescriptor() : data_(NULL) {}
135 virtual ~CallInterfaceDescriptor() {}
137 CallInterfaceDescriptor(Isolate* isolate, CallDescriptors::Key key)
138 : data_(isolate->call_descriptor_data(key)) {}
140 int GetParameterCount() const { return data()->param_count(); }
142 int GetRegisterParameterCount() const {
143 return data()->register_param_count();
146 int GetStackParameterCount() const {
147 return data()->function_type()->Arity() - data()->register_param_count();
150 Register GetRegisterParameter(int index) const {
151 return data()->register_param(index);
154 Type* GetParameterType(int index) const {
155 DCHECK(index < data()->param_count());
156 return data()->param_type(index);
159 // Some platforms have extra information to associate with the descriptor.
160 PlatformInterfaceDescriptor* platform_specific_descriptor() const {
161 return data()->platform_specific_descriptor();
164 Type::FunctionType* GetFunctionType() const {
165 return data()->function_type();
168 static const Register ContextRegister();
170 const char* DebugName(Isolate* isolate) const;
172 static Type::FunctionType* BuildDefaultFunctionType(Isolate* isolate,
173 int paramater_count);
176 const CallInterfaceDescriptorData* data() const { return data_; }
178 virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType(
179 Isolate* isolate, int register_param_count) {
180 return BuildDefaultFunctionType(isolate, register_param_count);
183 virtual void InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
187 void Initialize(Isolate* isolate, CallDescriptors::Key key) {
188 if (!data()->IsInitialized()) {
189 CallInterfaceDescriptorData* d = isolate->call_descriptor_data(key);
190 InitializePlatformSpecific(d);
191 Type::FunctionType* function_type =
192 BuildCallInterfaceDescriptorFunctionType(isolate,
193 d->register_param_count());
194 d->InitializePlatformIndependent(function_type);
199 const CallInterfaceDescriptorData* data_;
203 #define DECLARE_DESCRIPTOR(name, base) \
204 explicit name(Isolate* isolate) : base(isolate, key()) { \
205 Initialize(isolate, key()); \
209 void InitializePlatformSpecific(CallInterfaceDescriptorData* data) override; \
210 name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {} \
213 static inline CallDescriptors::Key key();
216 #define DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(name, base) \
217 DECLARE_DESCRIPTOR(name, base) \
219 virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType( \
220 Isolate* isolate, int register_param_count) override; \
223 // LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
224 class LoadDescriptor : public CallInterfaceDescriptor {
226 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadDescriptor,
227 CallInterfaceDescriptor)
229 enum ParameterIndices { kReceiverIndex, kNameIndex, kSlotIndex };
230 static const Register ReceiverRegister();
231 static const Register NameRegister();
232 static const Register SlotRegister();
236 class StoreDescriptor : public CallInterfaceDescriptor {
238 DECLARE_DESCRIPTOR(StoreDescriptor, CallInterfaceDescriptor)
240 enum ParameterIndices {
246 static const Register ReceiverRegister();
247 static const Register NameRegister();
248 static const Register ValueRegister();
252 class StoreTransitionDescriptor : public StoreDescriptor {
254 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreTransitionDescriptor,
257 // Extends StoreDescriptor with Map parameter.
258 enum ParameterIndices {
266 // MapRegister() is no_reg on ia32, instead it's on the stack.
267 static const Register MapRegister();
271 class InstanceofDescriptor : public CallInterfaceDescriptor {
273 DECLARE_DESCRIPTOR(InstanceofDescriptor, CallInterfaceDescriptor)
275 enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount };
276 static const Register left();
277 static const Register right();
281 class VectorStoreICTrampolineDescriptor : public StoreDescriptor {
283 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
284 VectorStoreICTrampolineDescriptor, StoreDescriptor)
286 enum ParameterIndices { kReceiverIndex, kNameIndex, kValueIndex, kSlotIndex };
288 static const Register SlotRegister();
292 class VectorStoreICDescriptor : public VectorStoreICTrampolineDescriptor {
294 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
295 VectorStoreICDescriptor, VectorStoreICTrampolineDescriptor)
297 enum ParameterIndices {
305 static const Register VectorRegister();
309 class LoadWithVectorDescriptor : public LoadDescriptor {
311 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadWithVectorDescriptor,
314 enum ParameterIndices {
321 static const Register VectorRegister();
325 class FastNewClosureDescriptor : public CallInterfaceDescriptor {
327 DECLARE_DESCRIPTOR(FastNewClosureDescriptor, CallInterfaceDescriptor)
331 class FastNewContextDescriptor : public CallInterfaceDescriptor {
333 DECLARE_DESCRIPTOR(FastNewContextDescriptor, CallInterfaceDescriptor)
337 class ToNumberDescriptor : public CallInterfaceDescriptor {
339 DECLARE_DESCRIPTOR(ToNumberDescriptor, CallInterfaceDescriptor)
343 class ToObjectDescriptor : public CallInterfaceDescriptor {
345 enum ParameterIndices { kReceiverIndex };
347 DECLARE_DESCRIPTOR(ToObjectDescriptor, CallInterfaceDescriptor)
349 static const Register ReceiverRegister();
353 class NumberToStringDescriptor : public CallInterfaceDescriptor {
355 DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
359 class TypeofDescriptor : public CallInterfaceDescriptor {
361 DECLARE_DESCRIPTOR(TypeofDescriptor, CallInterfaceDescriptor)
365 class FastCloneShallowArrayDescriptor : public CallInterfaceDescriptor {
367 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastCloneShallowArrayDescriptor,
368 CallInterfaceDescriptor)
372 class FastCloneShallowObjectDescriptor : public CallInterfaceDescriptor {
374 DECLARE_DESCRIPTOR(FastCloneShallowObjectDescriptor, CallInterfaceDescriptor)
378 class CreateAllocationSiteDescriptor : public CallInterfaceDescriptor {
380 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateAllocationSiteDescriptor,
381 CallInterfaceDescriptor)
385 class CreateWeakCellDescriptor : public CallInterfaceDescriptor {
387 enum ParameterIndices {
394 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateWeakCellDescriptor,
395 CallInterfaceDescriptor)
399 class CallFunctionDescriptor : public CallInterfaceDescriptor {
401 DECLARE_DESCRIPTOR(CallFunctionDescriptor, CallInterfaceDescriptor)
405 class CallFunctionWithFeedbackDescriptor : public CallInterfaceDescriptor {
407 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
408 CallFunctionWithFeedbackDescriptor, CallInterfaceDescriptor)
412 class CallFunctionWithFeedbackAndVectorDescriptor
413 : public CallInterfaceDescriptor {
415 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
416 CallFunctionWithFeedbackAndVectorDescriptor, CallInterfaceDescriptor)
420 class CallConstructDescriptor : public CallInterfaceDescriptor {
422 DECLARE_DESCRIPTOR(CallConstructDescriptor, CallInterfaceDescriptor)
426 class RegExpConstructResultDescriptor : public CallInterfaceDescriptor {
428 DECLARE_DESCRIPTOR(RegExpConstructResultDescriptor, CallInterfaceDescriptor)
432 class LoadGlobalViaContextDescriptor : public CallInterfaceDescriptor {
434 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalViaContextDescriptor,
435 CallInterfaceDescriptor)
437 static const Register SlotRegister();
441 class StoreGlobalViaContextDescriptor : public CallInterfaceDescriptor {
443 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreGlobalViaContextDescriptor,
444 CallInterfaceDescriptor)
446 static const Register SlotRegister();
447 static const Register ValueRegister();
451 class TransitionElementsKindDescriptor : public CallInterfaceDescriptor {
453 DECLARE_DESCRIPTOR(TransitionElementsKindDescriptor, CallInterfaceDescriptor)
457 class AllocateHeapNumberDescriptor : public CallInterfaceDescriptor {
459 DECLARE_DESCRIPTOR(AllocateHeapNumberDescriptor, CallInterfaceDescriptor)
463 class ArrayConstructorConstantArgCountDescriptor
464 : public CallInterfaceDescriptor {
466 DECLARE_DESCRIPTOR(ArrayConstructorConstantArgCountDescriptor,
467 CallInterfaceDescriptor)
471 class ArrayConstructorDescriptor : public CallInterfaceDescriptor {
473 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArrayConstructorDescriptor,
474 CallInterfaceDescriptor)
478 class InternalArrayConstructorConstantArgCountDescriptor
479 : public CallInterfaceDescriptor {
481 DECLARE_DESCRIPTOR(InternalArrayConstructorConstantArgCountDescriptor,
482 CallInterfaceDescriptor)
486 class InternalArrayConstructorDescriptor : public CallInterfaceDescriptor {
488 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
489 InternalArrayConstructorDescriptor, CallInterfaceDescriptor)
493 class CompareDescriptor : public CallInterfaceDescriptor {
495 DECLARE_DESCRIPTOR(CompareDescriptor, CallInterfaceDescriptor)
499 class CompareNilDescriptor : public CallInterfaceDescriptor {
501 DECLARE_DESCRIPTOR(CompareNilDescriptor, CallInterfaceDescriptor)
505 class ToBooleanDescriptor : public CallInterfaceDescriptor {
507 DECLARE_DESCRIPTOR(ToBooleanDescriptor, CallInterfaceDescriptor)
511 class BinaryOpDescriptor : public CallInterfaceDescriptor {
513 DECLARE_DESCRIPTOR(BinaryOpDescriptor, CallInterfaceDescriptor)
517 class BinaryOpWithAllocationSiteDescriptor : public CallInterfaceDescriptor {
519 DECLARE_DESCRIPTOR(BinaryOpWithAllocationSiteDescriptor,
520 CallInterfaceDescriptor)
524 class StringAddDescriptor : public CallInterfaceDescriptor {
526 DECLARE_DESCRIPTOR(StringAddDescriptor, CallInterfaceDescriptor)
530 class KeyedDescriptor : public CallInterfaceDescriptor {
532 DECLARE_DESCRIPTOR(KeyedDescriptor, CallInterfaceDescriptor)
536 class NamedDescriptor : public CallInterfaceDescriptor {
538 DECLARE_DESCRIPTOR(NamedDescriptor, CallInterfaceDescriptor)
542 class CallHandlerDescriptor : public CallInterfaceDescriptor {
544 DECLARE_DESCRIPTOR(CallHandlerDescriptor, CallInterfaceDescriptor)
548 class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor {
550 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentAdaptorDescriptor,
551 CallInterfaceDescriptor)
555 class ApiFunctionDescriptor : public CallInterfaceDescriptor {
557 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiFunctionDescriptor,
558 CallInterfaceDescriptor)
562 class ApiAccessorDescriptor : public CallInterfaceDescriptor {
564 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiAccessorDescriptor,
565 CallInterfaceDescriptor)
569 class ApiGetterDescriptor : public CallInterfaceDescriptor {
571 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiGetterDescriptor,
572 CallInterfaceDescriptor)
574 static const Register function_address();
578 class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor {
580 DECLARE_DESCRIPTOR(ArgumentsAccessReadDescriptor, CallInterfaceDescriptor)
582 static const Register index();
583 static const Register parameter_count();
587 class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor {
589 DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor,
590 CallInterfaceDescriptor)
594 class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
596 DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
598 static const Register exponent();
602 class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
604 DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
606 static const Register exponent();
610 class MathRoundVariantCallFromOptimizedCodeDescriptor
611 : public CallInterfaceDescriptor {
613 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
614 MathRoundVariantCallFromOptimizedCodeDescriptor, CallInterfaceDescriptor)
618 class MathRoundVariantCallFromUnoptimizedCodeDescriptor
619 : public CallInterfaceDescriptor {
621 DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
622 MathRoundVariantCallFromUnoptimizedCodeDescriptor,
623 CallInterfaceDescriptor)
627 class ContextOnlyDescriptor : public CallInterfaceDescriptor {
629 DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
633 class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
635 DECLARE_DESCRIPTOR(GrowArrayElementsDescriptor, CallInterfaceDescriptor)
637 enum RegisterInfo { kObjectIndex, kKeyIndex };
638 static const Register ObjectRegister();
639 static const Register KeyRegister();
642 #undef DECLARE_DESCRIPTOR
645 // We define the association between CallDescriptors::Key and the specialized
646 // descriptor here to reduce boilerplate and mistakes.
647 #define DEF_KEY(name) \
648 CallDescriptors::Key name##Descriptor::key() { return CallDescriptors::name; }
649 INTERFACE_DESCRIPTOR_LIST(DEF_KEY)
652 } // namespace v8::internal
655 #if V8_TARGET_ARCH_ARM64
656 #include "src/arm64/interface-descriptors-arm64.h"
657 #elif V8_TARGET_ARCH_ARM
658 #include "src/arm/interface-descriptors-arm.h"
661 #endif // V8_CALL_INTERFACE_DESCRIPTOR_H_