[stubs] Optimize LoadGlobalViaContextStub and StoreGlobalViaContextStub.
[platform/upstream/v8.git] / src / interface-descriptors.h
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.
4
5 #ifndef V8_CALL_INTERFACE_DESCRIPTOR_H_
6 #define V8_CALL_INTERFACE_DESCRIPTOR_H_
7
8 #include "src/assembler.h"
9 #include "src/macro-assembler.h"
10
11 namespace v8 {
12 namespace internal {
13
14 class PlatformInterfaceDescriptor;
15
16 #define INTERFACE_DESCRIPTOR_LIST(V)          \
17   V(Load)                                     \
18   V(Store)                                    \
19   V(StoreTransition)                          \
20   V(VectorStoreICTrampoline)                  \
21   V(VectorStoreIC)                            \
22   V(Instanceof)                               \
23   V(LoadWithVector)                           \
24   V(FastNewClosure)                           \
25   V(FastNewContext)                           \
26   V(ToNumber)                                 \
27   V(NumberToString)                           \
28   V(Typeof)                                   \
29   V(FastCloneShallowArray)                    \
30   V(FastCloneShallowObject)                   \
31   V(CreateAllocationSite)                     \
32   V(CreateWeakCell)                           \
33   V(CallFunction)                             \
34   V(CallFunctionWithFeedback)                 \
35   V(CallFunctionWithFeedbackAndVector)        \
36   V(CallConstruct)                            \
37   V(RegExpConstructResult)                    \
38   V(TransitionElementsKind)                   \
39   V(AllocateHeapNumber)                       \
40   V(ArrayConstructorConstantArgCount)         \
41   V(ArrayConstructor)                         \
42   V(InternalArrayConstructorConstantArgCount) \
43   V(InternalArrayConstructor)                 \
44   V(Compare)                                  \
45   V(CompareNil)                               \
46   V(ToBoolean)                                \
47   V(BinaryOp)                                 \
48   V(BinaryOpWithAllocationSite)               \
49   V(StringAdd)                                \
50   V(Keyed)                                    \
51   V(Named)                                    \
52   V(CallHandler)                              \
53   V(ArgumentAdaptor)                          \
54   V(ApiFunction)                              \
55   V(ApiAccessor)                              \
56   V(ApiGetter)                                \
57   V(ArgumentsAccessRead)                      \
58   V(StoreArrayLiteralElement)                 \
59   V(LoadGlobalViaContext)                     \
60   V(StoreGlobalViaContext)                    \
61   V(MathPowTagged)                            \
62   V(MathPowInteger)                           \
63   V(ContextOnly)                              \
64   V(GrowArrayElements)                        \
65   V(MathRoundVariantCallFromUnoptimizedCode)  \
66   V(MathRoundVariantCallFromOptimizedCode)
67
68
69 class CallInterfaceDescriptorData {
70  public:
71   CallInterfaceDescriptorData()
72       : register_param_count_(-1), function_type_(nullptr) {}
73
74   // A copy of the passed in registers and param_representations is made
75   // and owned by the CallInterfaceDescriptorData.
76
77   void InitializePlatformIndependent(Type::FunctionType* function_type) {
78     function_type_ = function_type;
79   }
80
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);
88
89   bool IsInitialized() const { return register_param_count_ >= 0; }
90
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_;
98   }
99
100   Type::FunctionType* function_type() const { return function_type_; }
101
102  private:
103   int register_param_count_;
104
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_;
110
111   // Specifies types for parameters and return
112   Type::FunctionType* function_type_;
113
114   PlatformInterfaceDescriptor* platform_specific_descriptor_;
115
116   DISALLOW_COPY_AND_ASSIGN(CallInterfaceDescriptorData);
117 };
118
119
120 class CallDescriptors {
121  public:
122   enum Key {
123 #define DEF_ENUM(name) name,
124     INTERFACE_DESCRIPTOR_LIST(DEF_ENUM)
125 #undef DEF_ENUM
126     NUMBER_OF_DESCRIPTORS
127   };
128 };
129
130
131 class CallInterfaceDescriptor {
132  public:
133   CallInterfaceDescriptor() : data_(NULL) {}
134   virtual ~CallInterfaceDescriptor() {}
135
136   CallInterfaceDescriptor(Isolate* isolate, CallDescriptors::Key key)
137       : data_(isolate->call_descriptor_data(key)) {}
138
139   int GetParameterCount() const { return data()->param_count(); }
140
141   int GetRegisterParameterCount() const {
142     return data()->register_param_count();
143   }
144
145   int GetStackParameterCount() const {
146     return data()->function_type()->Arity() - data()->register_param_count();
147   }
148
149   Register GetRegisterParameter(int index) const {
150     return data()->register_param(index);
151   }
152
153   Type* GetParameterType(int index) const {
154     DCHECK(index < data()->param_count());
155     return data()->param_type(index);
156   }
157
158   // Some platforms have extra information to associate with the descriptor.
159   PlatformInterfaceDescriptor* platform_specific_descriptor() const {
160     return data()->platform_specific_descriptor();
161   }
162
163   Type::FunctionType* GetFunctionType() const {
164     return data()->function_type();
165   }
166
167   static const Register ContextRegister();
168
169   const char* DebugName(Isolate* isolate) const;
170
171   static Type::FunctionType* BuildDefaultFunctionType(Isolate* isolate,
172                                                       int paramater_count);
173
174  protected:
175   const CallInterfaceDescriptorData* data() const { return data_; }
176
177   virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType(
178       Isolate* isolate, int register_param_count) {
179     return BuildDefaultFunctionType(isolate, register_param_count);
180   }
181
182   virtual void InitializePlatformSpecific(CallInterfaceDescriptorData* data) {
183     UNREACHABLE();
184   }
185
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);
194     }
195   }
196
197  private:
198   const CallInterfaceDescriptorData* data_;
199 };
200
201
202 #define DECLARE_DESCRIPTOR(name, base)                                         \
203   explicit name(Isolate* isolate) : base(isolate, key()) {                     \
204     Initialize(isolate, key());                                                \
205   }                                                                            \
206                                                                                \
207  protected:                                                                    \
208   void InitializePlatformSpecific(CallInterfaceDescriptorData* data) override; \
209   name(Isolate* isolate, CallDescriptors::Key key) : base(isolate, key) {}     \
210                                                                                \
211  public:                                                                       \
212   static inline CallDescriptors::Key key();
213
214
215 #define DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(name, base)        \
216   DECLARE_DESCRIPTOR(name, base)                                        \
217  protected:                                                             \
218   virtual Type::FunctionType* BuildCallInterfaceDescriptorFunctionType( \
219       Isolate* isolate, int register_param_count) override;             \
220                                                                         \
221  public:
222 // LoadDescriptor is used by all stubs that implement Load/KeyedLoad ICs.
223 class LoadDescriptor : public CallInterfaceDescriptor {
224  public:
225   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadDescriptor,
226                                                CallInterfaceDescriptor)
227
228   enum ParameterIndices { kReceiverIndex, kNameIndex, kSlotIndex };
229   static const Register ReceiverRegister();
230   static const Register NameRegister();
231   static const Register SlotRegister();
232 };
233
234
235 class StoreDescriptor : public CallInterfaceDescriptor {
236  public:
237   DECLARE_DESCRIPTOR(StoreDescriptor, CallInterfaceDescriptor)
238
239   enum ParameterIndices {
240     kReceiverIndex,
241     kNameIndex,
242     kValueIndex,
243     kParameterCount
244   };
245   static const Register ReceiverRegister();
246   static const Register NameRegister();
247   static const Register ValueRegister();
248 };
249
250
251 class StoreTransitionDescriptor : public StoreDescriptor {
252  public:
253   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreTransitionDescriptor,
254                                                StoreDescriptor)
255
256   // Extends StoreDescriptor with Map parameter.
257   enum ParameterIndices {
258     kReceiverIndex,
259     kNameIndex,
260     kValueIndex,
261     kMapIndex,
262     kParameterCount
263   };
264
265   // MapRegister() is no_reg on ia32, instead it's on the stack.
266   static const Register MapRegister();
267 };
268
269
270 class InstanceofDescriptor : public CallInterfaceDescriptor {
271  public:
272   DECLARE_DESCRIPTOR(InstanceofDescriptor, CallInterfaceDescriptor)
273
274   enum ParameterIndices { kLeftIndex, kRightIndex, kParameterCount };
275   static const Register left();
276   static const Register right();
277 };
278
279
280 class VectorStoreICTrampolineDescriptor : public StoreDescriptor {
281  public:
282   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
283       VectorStoreICTrampolineDescriptor, StoreDescriptor)
284
285   enum ParameterIndices { kReceiverIndex, kNameIndex, kValueIndex, kSlotIndex };
286
287   static const Register SlotRegister();
288 };
289
290
291 class VectorStoreICDescriptor : public VectorStoreICTrampolineDescriptor {
292  public:
293   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
294       VectorStoreICDescriptor, VectorStoreICTrampolineDescriptor)
295
296   enum ParameterIndices {
297     kReceiverIndex,
298     kNameIndex,
299     kValueIndex,
300     kSlotIndex,
301     kVectorIndex
302   };
303
304   static const Register VectorRegister();
305 };
306
307
308 class LoadWithVectorDescriptor : public LoadDescriptor {
309  public:
310   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadWithVectorDescriptor,
311                                                LoadDescriptor)
312
313   enum ParameterIndices {
314     kReceiverIndex,
315     kNameIndex,
316     kSlotIndex,
317     kVectorIndex
318   };
319
320   static const Register VectorRegister();
321 };
322
323
324 class FastNewClosureDescriptor : public CallInterfaceDescriptor {
325  public:
326   DECLARE_DESCRIPTOR(FastNewClosureDescriptor, CallInterfaceDescriptor)
327 };
328
329
330 class FastNewContextDescriptor : public CallInterfaceDescriptor {
331  public:
332   DECLARE_DESCRIPTOR(FastNewContextDescriptor, CallInterfaceDescriptor)
333 };
334
335
336 class ToNumberDescriptor : public CallInterfaceDescriptor {
337  public:
338   DECLARE_DESCRIPTOR(ToNumberDescriptor, CallInterfaceDescriptor)
339 };
340
341
342 class NumberToStringDescriptor : public CallInterfaceDescriptor {
343  public:
344   DECLARE_DESCRIPTOR(NumberToStringDescriptor, CallInterfaceDescriptor)
345 };
346
347
348 class TypeofDescriptor : public CallInterfaceDescriptor {
349  public:
350   DECLARE_DESCRIPTOR(TypeofDescriptor, CallInterfaceDescriptor)
351 };
352
353
354 class FastCloneShallowArrayDescriptor : public CallInterfaceDescriptor {
355  public:
356   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(FastCloneShallowArrayDescriptor,
357                                                CallInterfaceDescriptor)
358 };
359
360
361 class FastCloneShallowObjectDescriptor : public CallInterfaceDescriptor {
362  public:
363   DECLARE_DESCRIPTOR(FastCloneShallowObjectDescriptor, CallInterfaceDescriptor)
364 };
365
366
367 class CreateAllocationSiteDescriptor : public CallInterfaceDescriptor {
368  public:
369   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateAllocationSiteDescriptor,
370                                                CallInterfaceDescriptor)
371 };
372
373
374 class CreateWeakCellDescriptor : public CallInterfaceDescriptor {
375  public:
376   enum ParameterIndices {
377     kVectorIndex,
378     kSlotIndex,
379     kValueIndex,
380     kParameterCount
381   };
382
383   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(CreateWeakCellDescriptor,
384                                                CallInterfaceDescriptor)
385 };
386
387
388 class CallFunctionDescriptor : public CallInterfaceDescriptor {
389  public:
390   DECLARE_DESCRIPTOR(CallFunctionDescriptor, CallInterfaceDescriptor)
391 };
392
393
394 class CallFunctionWithFeedbackDescriptor : public CallInterfaceDescriptor {
395  public:
396   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
397       CallFunctionWithFeedbackDescriptor, CallInterfaceDescriptor)
398 };
399
400
401 class CallFunctionWithFeedbackAndVectorDescriptor
402     : public CallInterfaceDescriptor {
403  public:
404   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
405       CallFunctionWithFeedbackAndVectorDescriptor, CallInterfaceDescriptor)
406 };
407
408
409 class CallConstructDescriptor : public CallInterfaceDescriptor {
410  public:
411   DECLARE_DESCRIPTOR(CallConstructDescriptor, CallInterfaceDescriptor)
412 };
413
414
415 class RegExpConstructResultDescriptor : public CallInterfaceDescriptor {
416  public:
417   DECLARE_DESCRIPTOR(RegExpConstructResultDescriptor, CallInterfaceDescriptor)
418 };
419
420
421 class LoadGlobalViaContextDescriptor : public CallInterfaceDescriptor {
422  public:
423   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(LoadGlobalViaContextDescriptor,
424                                                CallInterfaceDescriptor)
425
426   static const Register SlotRegister();
427   static const Register NameRegister();
428 };
429
430
431 class StoreGlobalViaContextDescriptor : public CallInterfaceDescriptor {
432  public:
433   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(StoreGlobalViaContextDescriptor,
434                                                CallInterfaceDescriptor)
435
436   static const Register SlotRegister();
437   static const Register NameRegister();
438   static const Register ValueRegister();
439 };
440
441
442 class TransitionElementsKindDescriptor : public CallInterfaceDescriptor {
443  public:
444   DECLARE_DESCRIPTOR(TransitionElementsKindDescriptor, CallInterfaceDescriptor)
445 };
446
447
448 class AllocateHeapNumberDescriptor : public CallInterfaceDescriptor {
449  public:
450   DECLARE_DESCRIPTOR(AllocateHeapNumberDescriptor, CallInterfaceDescriptor)
451 };
452
453
454 class ArrayConstructorConstantArgCountDescriptor
455     : public CallInterfaceDescriptor {
456  public:
457   DECLARE_DESCRIPTOR(ArrayConstructorConstantArgCountDescriptor,
458                      CallInterfaceDescriptor)
459 };
460
461
462 class ArrayConstructorDescriptor : public CallInterfaceDescriptor {
463  public:
464   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArrayConstructorDescriptor,
465                                                CallInterfaceDescriptor)
466 };
467
468
469 class InternalArrayConstructorConstantArgCountDescriptor
470     : public CallInterfaceDescriptor {
471  public:
472   DECLARE_DESCRIPTOR(InternalArrayConstructorConstantArgCountDescriptor,
473                      CallInterfaceDescriptor)
474 };
475
476
477 class InternalArrayConstructorDescriptor : public CallInterfaceDescriptor {
478  public:
479   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
480       InternalArrayConstructorDescriptor, CallInterfaceDescriptor)
481 };
482
483
484 class CompareDescriptor : public CallInterfaceDescriptor {
485  public:
486   DECLARE_DESCRIPTOR(CompareDescriptor, CallInterfaceDescriptor)
487 };
488
489
490 class CompareNilDescriptor : public CallInterfaceDescriptor {
491  public:
492   DECLARE_DESCRIPTOR(CompareNilDescriptor, CallInterfaceDescriptor)
493 };
494
495
496 class ToBooleanDescriptor : public CallInterfaceDescriptor {
497  public:
498   DECLARE_DESCRIPTOR(ToBooleanDescriptor, CallInterfaceDescriptor)
499 };
500
501
502 class BinaryOpDescriptor : public CallInterfaceDescriptor {
503  public:
504   DECLARE_DESCRIPTOR(BinaryOpDescriptor, CallInterfaceDescriptor)
505 };
506
507
508 class BinaryOpWithAllocationSiteDescriptor : public CallInterfaceDescriptor {
509  public:
510   DECLARE_DESCRIPTOR(BinaryOpWithAllocationSiteDescriptor,
511                      CallInterfaceDescriptor)
512 };
513
514
515 class StringAddDescriptor : public CallInterfaceDescriptor {
516  public:
517   DECLARE_DESCRIPTOR(StringAddDescriptor, CallInterfaceDescriptor)
518 };
519
520
521 class KeyedDescriptor : public CallInterfaceDescriptor {
522  public:
523   DECLARE_DESCRIPTOR(KeyedDescriptor, CallInterfaceDescriptor)
524 };
525
526
527 class NamedDescriptor : public CallInterfaceDescriptor {
528  public:
529   DECLARE_DESCRIPTOR(NamedDescriptor, CallInterfaceDescriptor)
530 };
531
532
533 class CallHandlerDescriptor : public CallInterfaceDescriptor {
534  public:
535   DECLARE_DESCRIPTOR(CallHandlerDescriptor, CallInterfaceDescriptor)
536 };
537
538
539 class ArgumentAdaptorDescriptor : public CallInterfaceDescriptor {
540  public:
541   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ArgumentAdaptorDescriptor,
542                                                CallInterfaceDescriptor)
543 };
544
545
546 class ApiFunctionDescriptor : public CallInterfaceDescriptor {
547  public:
548   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiFunctionDescriptor,
549                                                CallInterfaceDescriptor)
550 };
551
552
553 class ApiAccessorDescriptor : public CallInterfaceDescriptor {
554  public:
555   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiAccessorDescriptor,
556                                                CallInterfaceDescriptor)
557 };
558
559
560 class ApiGetterDescriptor : public CallInterfaceDescriptor {
561  public:
562   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(ApiGetterDescriptor,
563                                                CallInterfaceDescriptor)
564
565   static const Register function_address();
566 };
567
568
569 class ArgumentsAccessReadDescriptor : public CallInterfaceDescriptor {
570  public:
571   DECLARE_DESCRIPTOR(ArgumentsAccessReadDescriptor, CallInterfaceDescriptor)
572
573   static const Register index();
574   static const Register parameter_count();
575 };
576
577
578 class StoreArrayLiteralElementDescriptor : public CallInterfaceDescriptor {
579  public:
580   DECLARE_DESCRIPTOR(StoreArrayLiteralElementDescriptor,
581                      CallInterfaceDescriptor)
582 };
583
584
585 class MathPowTaggedDescriptor : public CallInterfaceDescriptor {
586  public:
587   DECLARE_DESCRIPTOR(MathPowTaggedDescriptor, CallInterfaceDescriptor)
588
589   static const Register exponent();
590 };
591
592
593 class MathPowIntegerDescriptor : public CallInterfaceDescriptor {
594  public:
595   DECLARE_DESCRIPTOR(MathPowIntegerDescriptor, CallInterfaceDescriptor)
596
597   static const Register exponent();
598 };
599
600
601 class MathRoundVariantCallFromOptimizedCodeDescriptor
602     : public CallInterfaceDescriptor {
603  public:
604   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
605       MathRoundVariantCallFromOptimizedCodeDescriptor, CallInterfaceDescriptor)
606 };
607
608
609 class MathRoundVariantCallFromUnoptimizedCodeDescriptor
610     : public CallInterfaceDescriptor {
611  public:
612   DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
613       MathRoundVariantCallFromUnoptimizedCodeDescriptor,
614       CallInterfaceDescriptor)
615 };
616
617
618 class ContextOnlyDescriptor : public CallInterfaceDescriptor {
619  public:
620   DECLARE_DESCRIPTOR(ContextOnlyDescriptor, CallInterfaceDescriptor)
621 };
622
623
624 class GrowArrayElementsDescriptor : public CallInterfaceDescriptor {
625  public:
626   DECLARE_DESCRIPTOR(GrowArrayElementsDescriptor, CallInterfaceDescriptor)
627
628   enum RegisterInfo { kObjectIndex, kKeyIndex };
629   static const Register ObjectRegister();
630   static const Register KeyRegister();
631 };
632
633 #undef DECLARE_DESCRIPTOR
634
635
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)
641 #undef DEF_KEY
642 }
643 }  // namespace v8::internal
644
645
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"
650 #endif
651
652 #endif  // V8_CALL_INTERFACE_DESCRIPTOR_H_