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