[builtins] Unify the various versions of [[Call]] with a Call builtin.
[platform/upstream/v8.git] / src / code-stubs.h
1 // Copyright 2012 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_CODE_STUBS_H_
6 #define V8_CODE_STUBS_H_
7
8 #include "src/allocation.h"
9 #include "src/assembler.h"
10 #include "src/codegen.h"
11 #include "src/globals.h"
12 #include "src/ic/ic-state.h"
13 #include "src/interface-descriptors.h"
14 #include "src/macro-assembler.h"
15 #include "src/ostreams.h"
16
17 namespace v8 {
18 namespace internal {
19
20 // List of code stubs used on all platforms.
21 #define CODE_STUB_LIST_ALL_PLATFORMS(V)     \
22   /* PlatformCodeStubs */                   \
23   V(ArgumentsAccess)                        \
24   V(ArrayConstructor)                       \
25   V(BinaryOpICWithAllocationSite)           \
26   V(CallApiFunction)                        \
27   V(CallApiAccessor)                        \
28   V(CallApiGetter)                          \
29   V(CallConstruct)                          \
30   V(CallFunction)                           \
31   V(CallIC)                                 \
32   V(CallIC_Array)                           \
33   V(CEntry)                                 \
34   V(CompareIC)                              \
35   V(DoubleToI)                              \
36   V(FunctionPrototype)                      \
37   V(InstanceOf)                             \
38   V(InternalArrayConstructor)               \
39   V(JSEntry)                                \
40   V(KeyedLoadICTrampoline)                  \
41   V(LoadICTrampoline)                       \
42   V(CallICTrampoline)                       \
43   V(CallIC_ArrayTrampoline)                 \
44   V(LoadIndexedInterceptor)                 \
45   V(LoadIndexedString)                      \
46   V(MathPow)                                \
47   V(ProfileEntryHook)                       \
48   V(RecordWrite)                            \
49   V(RegExpExec)                             \
50   V(StoreArrayLiteralElement)               \
51   V(StoreBufferOverflow)                    \
52   V(StoreElement)                           \
53   V(StringCompare)                          \
54   V(StubFailureTrampoline)                  \
55   V(SubString)                              \
56   V(ToNumber)                               \
57   V(ToString)                               \
58   V(ToObject)                               \
59   V(VectorStoreICTrampoline)                \
60   V(VectorKeyedStoreICTrampoline)           \
61   V(VectorStoreIC)                          \
62   V(VectorKeyedStoreIC)                     \
63   /* HydrogenCodeStubs */                   \
64   V(AllocateHeapNumber)                     \
65   V(ArrayNArgumentsConstructor)             \
66   V(ArrayNoArgumentConstructor)             \
67   V(ArraySingleArgumentConstructor)         \
68   V(BinaryOpIC)                             \
69   V(BinaryOpWithAllocationSite)             \
70   V(CompareNilIC)                           \
71   V(CreateAllocationSite)                   \
72   V(CreateWeakCell)                         \
73   V(ElementsTransitionAndStore)             \
74   V(FastCloneShallowArray)                  \
75   V(FastCloneShallowObject)                 \
76   V(FastNewClosure)                         \
77   V(FastNewContext)                         \
78   V(GrowArrayElements)                      \
79   V(InternalArrayNArgumentsConstructor)     \
80   V(InternalArrayNoArgumentConstructor)     \
81   V(InternalArraySingleArgumentConstructor) \
82   V(KeyedLoadGeneric)                       \
83   V(LoadGlobalViaContext)                   \
84   V(LoadScriptContextField)                 \
85   V(LoadDictionaryElement)                  \
86   V(NameDictionaryLookup)                   \
87   V(NumberToString)                         \
88   V(Typeof)                                 \
89   V(RegExpConstructResult)                  \
90   V(StoreFastElement)                       \
91   V(StoreGlobalViaContext)                  \
92   V(StoreScriptContextField)                \
93   V(StringAdd)                              \
94   V(ToBoolean)                              \
95   V(TransitionElementsKind)                 \
96   V(KeyedLoadIC)                            \
97   V(LoadIC)                                 \
98   /* TurboFanCodeStubs */                   \
99   V(StringLengthTF)                         \
100   V(StringAddTF)                            \
101   /* TurboFanICs */                         \
102   V(MathFloor)                              \
103   /* IC Handler stubs */                    \
104   V(ArrayBufferViewLoadField)               \
105   V(LoadConstant)                           \
106   V(LoadFastElement)                        \
107   V(LoadField)                              \
108   V(KeyedLoadSloppyArguments)               \
109   V(KeyedStoreSloppyArguments)              \
110   V(StoreField)                             \
111   V(StoreGlobal)                            \
112   V(StoreTransition)                        \
113   V(StringLength)
114
115 // List of code stubs only used on ARM 32 bits platforms.
116 #if V8_TARGET_ARCH_ARM
117 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
118
119 #else
120 #define CODE_STUB_LIST_ARM(V)
121 #endif
122
123 // List of code stubs only used on ARM 64 bits platforms.
124 #if V8_TARGET_ARCH_ARM64
125 #define CODE_STUB_LIST_ARM64(V) \
126   V(DirectCEntry)               \
127   V(RestoreRegistersState)      \
128   V(StoreRegistersState)
129
130 #else
131 #define CODE_STUB_LIST_ARM64(V)
132 #endif
133
134 // List of code stubs only used on PPC platforms.
135 #ifdef V8_TARGET_ARCH_PPC
136 #define CODE_STUB_LIST_PPC(V) \
137   V(DirectCEntry)             \
138   V(StoreRegistersState)      \
139   V(RestoreRegistersState)
140 #else
141 #define CODE_STUB_LIST_PPC(V)
142 #endif
143
144 // List of code stubs only used on MIPS platforms.
145 #if V8_TARGET_ARCH_MIPS
146 #define CODE_STUB_LIST_MIPS(V) \
147   V(DirectCEntry)              \
148   V(RestoreRegistersState)     \
149   V(StoreRegistersState)
150 #elif V8_TARGET_ARCH_MIPS64
151 #define CODE_STUB_LIST_MIPS(V) \
152   V(DirectCEntry)              \
153   V(RestoreRegistersState)     \
154   V(StoreRegistersState)
155 #else
156 #define CODE_STUB_LIST_MIPS(V)
157 #endif
158
159 // Combined list of code stubs.
160 #define CODE_STUB_LIST(V)         \
161   CODE_STUB_LIST_ALL_PLATFORMS(V) \
162   CODE_STUB_LIST_ARM(V)           \
163   CODE_STUB_LIST_ARM64(V)         \
164   CODE_STUB_LIST_PPC(V)           \
165   CODE_STUB_LIST_MIPS(V)
166
167 static const int kHasReturnedMinusZeroSentinel = 1;
168
169 // Stub is base classes of all stubs.
170 class CodeStub BASE_EMBEDDED {
171  public:
172   enum Major {
173     // TODO(mvstanton): eliminate the NoCache key by getting rid
174     //                  of the non-monomorphic-cache.
175     NoCache = 0,  // marker for stubs that do custom caching]
176 #define DEF_ENUM(name) name,
177     CODE_STUB_LIST(DEF_ENUM)
178 #undef DEF_ENUM
179     NUMBER_OF_IDS
180   };
181
182   // Retrieve the code for the stub. Generate the code if needed.
183   Handle<Code> GetCode();
184
185   // Retrieve the code for the stub, make and return a copy of the code.
186   Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
187
188   static Major MajorKeyFromKey(uint32_t key) {
189     return static_cast<Major>(MajorKeyBits::decode(key));
190   }
191   static uint32_t MinorKeyFromKey(uint32_t key) {
192     return MinorKeyBits::decode(key);
193   }
194
195   // Gets the major key from a code object that is a code stub or binary op IC.
196   static Major GetMajorKey(Code* code_stub) {
197     return MajorKeyFromKey(code_stub->stub_key());
198   }
199
200   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
201
202   static const char* MajorName(Major major_key);
203
204   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
205   virtual ~CodeStub() {}
206
207   static void GenerateStubsAheadOfTime(Isolate* isolate);
208   static void GenerateFPStubs(Isolate* isolate);
209
210   // Some stubs put untagged junk on the stack that cannot be scanned by the
211   // GC.  This means that we must be statically sure that no GC can occur while
212   // they are running.  If that is the case they should override this to return
213   // true, which will cause an assertion if we try to call something that can
214   // GC or if we try to put a stack frame on top of the junk, which would not
215   // result in a traversable stack.
216   virtual bool SometimesSetsUpAFrame() { return true; }
217
218   // Lookup the code in the (possibly custom) cache.
219   bool FindCodeInCache(Code** code_out);
220
221   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
222
223   virtual int GetStackParameterCount() const {
224     return GetCallInterfaceDescriptor().GetStackParameterCount();
225   }
226
227   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
228
229   static void InitializeDescriptor(Isolate* isolate, uint32_t key,
230                                    CodeStubDescriptor* desc);
231
232   static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
233
234   // Returns information for computing the number key.
235   virtual Major MajorKey() const = 0;
236   uint32_t MinorKey() const { return minor_key_; }
237
238   // BinaryOpStub needs to override this.
239   virtual Code::Kind GetCodeKind() const;
240
241   virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
242   virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
243   virtual Code::StubType GetStubType() const { return Code::NORMAL; }
244
245   friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
246     s.PrintName(os);
247     return os;
248   }
249
250   Isolate* isolate() const { return isolate_; }
251
252  protected:
253   CodeStub(uint32_t key, Isolate* isolate)
254       : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
255
256   // Generates the assembler code for the stub.
257   virtual Handle<Code> GenerateCode() = 0;
258
259   // Returns whether the code generated for this stub needs to be allocated as
260   // a fixed (non-moveable) code object.
261   virtual bool NeedsImmovableCode() { return false; }
262
263   virtual void PrintName(std::ostream& os) const;        // NOLINT
264   virtual void PrintBaseName(std::ostream& os) const;    // NOLINT
265   virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
266
267   // Computes the key based on major and minor.
268   uint32_t GetKey() {
269     DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
270     return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
271   }
272
273   uint32_t minor_key_;
274
275  private:
276   // Perform bookkeeping required after code generation when stub code is
277   // initially generated.
278   void RecordCodeGeneration(Handle<Code> code);
279
280   // Finish the code object after it has been generated.
281   virtual void FinishCode(Handle<Code> code) { }
282
283   // Activate newly generated stub. Is called after
284   // registering stub in the stub cache.
285   virtual void Activate(Code* code) { }
286
287   // Add the code to a specialized cache, specific to an individual
288   // stub type. Please note, this method must add the code object to a
289   // roots object, otherwise we will remove the code during GC.
290   virtual void AddToSpecialCache(Handle<Code> new_object) { }
291
292   // Find code in a specialized cache, work is delegated to the specific stub.
293   virtual bool FindCodeInSpecialCache(Code** code_out) {
294     return false;
295   }
296
297   // If a stub uses a special cache override this.
298   virtual bool UseSpecialCache() { return false; }
299
300   // We use this dispatch to statically instantiate the correct code stub for
301   // the given stub key and call the passed function with that code stub.
302   typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
303   static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
304                        DispatchedCall call);
305
306   static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
307
308   STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
309   class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
310   class MinorKeyBits: public BitField<uint32_t,
311       kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
312
313   friend class BreakPointIterator;
314
315   Isolate* isolate_;
316 };
317
318
319 #define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
320  public:                                                        \
321   NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
322                                                                 \
323  private:                                                       \
324   DISALLOW_COPY_AND_ASSIGN(NAME)
325
326
327 #define DEFINE_CODE_STUB(NAME, SUPER)                      \
328  protected:                                                \
329   inline Major MajorKey() const override { return NAME; }; \
330   DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
331
332
333 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)  \
334  private:                                       \
335   void Generate(MacroAssembler* masm) override; \
336   DEFINE_CODE_STUB(NAME, SUPER)
337
338
339 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER)                        \
340  public:                                                              \
341   void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
342   Handle<Code> GenerateCode() override;                               \
343   DEFINE_CODE_STUB(NAME, SUPER)
344
345 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                          \
346  public:                                                                \
347   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
348     return DESC##Descriptor(isolate());                                 \
349   };                                                                    \
350   DEFINE_CODE_STUB(NAME, SUPER)
351
352 #define DEFINE_TURBOFAN_IC(NAME, SUPER, DESC)                           \
353  public:                                                                \
354   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
355     if (GetCallMode() == CALL_FROM_OPTIMIZED_CODE) {                    \
356       return DESC##CallFromOptimizedCodeDescriptor(isolate());          \
357     } else {                                                            \
358       return DESC##CallFromUnoptimizedCodeDescriptor(isolate());        \
359     }                                                                   \
360   };                                                                    \
361                                                                         \
362  protected:                                                             \
363   DEFINE_CODE_STUB(NAME, SUPER)
364
365 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
366  public:                                      \
367   Handle<Code> GenerateCode() override;       \
368   DEFINE_CODE_STUB(NAME, SUPER)
369
370 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                          \
371  public:                                                                \
372   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
373     return NAME##Descriptor(isolate());                                 \
374   }
375
376 // There are some code stubs we just can't describe right now with a
377 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
378 // An attempt to retrieve a descriptor will fail.
379 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                         \
380  public:                                                                \
381   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
382     UNREACHABLE();                                                      \
383     return CallInterfaceDescriptor();                                   \
384   }
385
386
387 class PlatformCodeStub : public CodeStub {
388  public:
389   // Retrieve the code for the stub. Generate the code if needed.
390   Handle<Code> GenerateCode() override;
391
392  protected:
393   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
394
395   // Generates the assembler code for the stub.
396   virtual void Generate(MacroAssembler* masm) = 0;
397
398   DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
399 };
400
401
402 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
403
404
405 class CodeStubDescriptor {
406  public:
407   explicit CodeStubDescriptor(CodeStub* stub);
408
409   CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
410
411   void Initialize(Address deoptimization_handler = NULL,
412                   int hint_stack_parameter_count = -1,
413                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
414   void Initialize(Register stack_parameter_count,
415                   Address deoptimization_handler = NULL,
416                   int hint_stack_parameter_count = -1,
417                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
418
419   void SetMissHandler(ExternalReference handler) {
420     miss_handler_ = handler;
421     has_miss_handler_ = true;
422     // Our miss handler infrastructure doesn't currently support
423     // variable stack parameter counts.
424     DCHECK(!stack_parameter_count_.is_valid());
425   }
426
427   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
428   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
429
430   int GetRegisterParameterCount() const {
431     return call_descriptor().GetRegisterParameterCount();
432   }
433
434   int GetStackParameterCount() const {
435     return call_descriptor().GetStackParameterCount();
436   }
437
438   int GetParameterCount() const {
439     return call_descriptor().GetParameterCount();
440   }
441
442   Register GetRegisterParameter(int index) const {
443     return call_descriptor().GetRegisterParameter(index);
444   }
445
446   Type* GetParameterType(int index) const {
447     return call_descriptor().GetParameterType(index);
448   }
449
450   ExternalReference miss_handler() const {
451     DCHECK(has_miss_handler_);
452     return miss_handler_;
453   }
454
455   bool has_miss_handler() const {
456     return has_miss_handler_;
457   }
458
459   int GetHandlerParameterCount() const {
460     int params = GetParameterCount();
461     if (PassesArgumentsToDeoptimizationHandler()) {
462       params += 1;
463     }
464     return params;
465   }
466
467   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
468   Register stack_parameter_count() const { return stack_parameter_count_; }
469   StubFunctionMode function_mode() const { return function_mode_; }
470   Address deoptimization_handler() const { return deoptimization_handler_; }
471
472  private:
473   bool PassesArgumentsToDeoptimizationHandler() const {
474     return stack_parameter_count_.is_valid();
475   }
476
477   CallInterfaceDescriptor call_descriptor_;
478   Register stack_parameter_count_;
479   // If hint_stack_parameter_count_ > 0, the code stub can optimize the
480   // return sequence. Default value is -1, which means it is ignored.
481   int hint_stack_parameter_count_;
482   StubFunctionMode function_mode_;
483
484   Address deoptimization_handler_;
485
486   ExternalReference miss_handler_;
487   bool has_miss_handler_;
488 };
489
490
491 class HydrogenCodeStub : public CodeStub {
492  public:
493   enum InitializationState {
494     UNINITIALIZED,
495     INITIALIZED
496   };
497
498   template<class SubClass>
499   static Handle<Code> GetUninitialized(Isolate* isolate) {
500     SubClass::GenerateAheadOfTime(isolate);
501     return SubClass().GetCode(isolate);
502   }
503
504   // Retrieve the code for the stub. Generate the code if needed.
505   Handle<Code> GenerateCode() override = 0;
506
507   bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
508
509   Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
510
511   template<class StateType>
512   void TraceTransition(StateType from, StateType to);
513
514  protected:
515   explicit HydrogenCodeStub(Isolate* isolate,
516                             InitializationState state = INITIALIZED)
517       : CodeStub(isolate) {
518     minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
519   }
520
521   void set_sub_minor_key(uint32_t key) {
522     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
523   }
524
525   uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
526
527   static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
528
529  private:
530   class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
531   class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
532
533   void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
534
535   DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
536 };
537
538
539 class TurboFanCodeStub : public CodeStub {
540  public:
541   // Retrieve the code for the stub. Generate the code if needed.
542   Handle<Code> GenerateCode() override;
543
544   virtual int GetStackParameterCount() const override {
545     return GetCallInterfaceDescriptor().GetStackParameterCount();
546   }
547
548   Code::StubType GetStubType() const override { return Code::FAST; }
549
550  protected:
551   explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
552
553  private:
554   DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
555 };
556
557
558 class TurboFanIC : public TurboFanCodeStub {
559  public:
560   enum CallMode { CALL_FROM_UNOPTIMIZED_CODE, CALL_FROM_OPTIMIZED_CODE };
561
562  protected:
563   explicit TurboFanIC(Isolate* isolate, CallMode mode)
564       : TurboFanCodeStub(isolate) {
565     minor_key_ = CallModeBits::encode(mode);
566   }
567
568   CallMode GetCallMode() const { return CallModeBits::decode(minor_key_); }
569
570   void set_sub_minor_key(uint32_t key) {
571     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
572   }
573
574   uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
575
576   static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
577
578  private:
579   class CallModeBits : public BitField<CallMode, 0, 1> {};
580   class SubMinorKeyBits : public BitField<int, 1, kSubMinorKeyBits> {};
581   DEFINE_CODE_STUB_BASE(TurboFanIC, TurboFanCodeStub);
582 };
583
584
585 // Helper interface to prepare to/restore after making runtime calls.
586 class RuntimeCallHelper {
587  public:
588   virtual ~RuntimeCallHelper() {}
589
590   virtual void BeforeCall(MacroAssembler* masm) const = 0;
591
592   virtual void AfterCall(MacroAssembler* masm) const = 0;
593
594  protected:
595   RuntimeCallHelper() {}
596
597  private:
598   DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
599 };
600
601
602 } }  // namespace v8::internal
603
604 #if V8_TARGET_ARCH_IA32
605 #include "src/ia32/code-stubs-ia32.h"
606 #elif V8_TARGET_ARCH_X64
607 #include "src/x64/code-stubs-x64.h"
608 #elif V8_TARGET_ARCH_ARM64
609 #include "src/arm64/code-stubs-arm64.h"
610 #elif V8_TARGET_ARCH_ARM
611 #include "src/arm/code-stubs-arm.h"
612 #elif V8_TARGET_ARCH_PPC
613 #include "src/ppc/code-stubs-ppc.h"
614 #elif V8_TARGET_ARCH_MIPS
615 #include "src/mips/code-stubs-mips.h"
616 #elif V8_TARGET_ARCH_MIPS64
617 #include "src/mips64/code-stubs-mips64.h"
618 #elif V8_TARGET_ARCH_X87
619 #include "src/x87/code-stubs-x87.h"
620 #else
621 #error Unsupported target architecture.
622 #endif
623
624 namespace v8 {
625 namespace internal {
626
627
628 // RuntimeCallHelper implementation used in stubs: enters/leaves a
629 // newly created internal frame before/after the runtime call.
630 class StubRuntimeCallHelper : public RuntimeCallHelper {
631  public:
632   StubRuntimeCallHelper() {}
633
634   virtual void BeforeCall(MacroAssembler* masm) const;
635
636   virtual void AfterCall(MacroAssembler* masm) const;
637 };
638
639
640 // Trivial RuntimeCallHelper implementation.
641 class NopRuntimeCallHelper : public RuntimeCallHelper {
642  public:
643   NopRuntimeCallHelper() {}
644
645   virtual void BeforeCall(MacroAssembler* masm) const {}
646
647   virtual void AfterCall(MacroAssembler* masm) const {}
648 };
649
650
651 class MathFloorStub : public TurboFanIC {
652  public:
653   explicit MathFloorStub(Isolate* isolate, TurboFanIC::CallMode mode)
654       : TurboFanIC(isolate, mode) {}
655   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
656   DEFINE_TURBOFAN_IC(MathFloor, TurboFanIC, MathRoundVariant);
657 };
658
659
660 class StringLengthTFStub : public TurboFanCodeStub {
661  public:
662   explicit StringLengthTFStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
663
664   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
665   InlineCacheState GetICState() const override { return MONOMORPHIC; }
666   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
667
668   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
669   DEFINE_CODE_STUB(StringLengthTF, TurboFanCodeStub);
670 };
671
672
673 enum StringAddFlags {
674   // Omit both parameter checks.
675   STRING_ADD_CHECK_NONE = 0,
676   // Check left parameter.
677   STRING_ADD_CHECK_LEFT = 1 << 0,
678   // Check right parameter.
679   STRING_ADD_CHECK_RIGHT = 1 << 1,
680   // Check both parameters.
681   STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
682 };
683
684
685 std::ostream& operator<<(std::ostream& os, const StringAddFlags& flags);
686
687
688 class StringAddTFStub : public TurboFanCodeStub {
689  public:
690   StringAddTFStub(Isolate* isolate, StringAddFlags flags,
691                   PretenureFlag pretenure_flag)
692       : TurboFanCodeStub(isolate) {
693     minor_key_ = StringAddFlagsBits::encode(flags) |
694                  PretenureFlagBits::encode(pretenure_flag);
695   }
696
697   StringAddFlags flags() const {
698     return StringAddFlagsBits::decode(MinorKey());
699   }
700
701   PretenureFlag pretenure_flag() const {
702     return PretenureFlagBits::decode(MinorKey());
703   }
704
705  private:
706   class StringAddFlagsBits : public BitField<StringAddFlags, 0, 2> {};
707   class PretenureFlagBits : public BitField<PretenureFlag, 2, 1> {};
708
709   void PrintBaseName(std::ostream& os) const override;  // NOLINT
710
711   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
712   DEFINE_CODE_STUB(StringAddTF, TurboFanCodeStub);
713 };
714
715
716 class NumberToStringStub final : public HydrogenCodeStub {
717  public:
718   explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
719
720   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
721   static const int kNumber = 0;
722
723   DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
724   DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
725 };
726
727
728 class TypeofStub final : public HydrogenCodeStub {
729  public:
730   explicit TypeofStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
731
732   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
733   static const int kObject = 0;
734
735   static void GenerateAheadOfTime(Isolate* isolate);
736
737   DEFINE_CALL_INTERFACE_DESCRIPTOR(Typeof);
738   DEFINE_HYDROGEN_CODE_STUB(Typeof, HydrogenCodeStub);
739 };
740
741
742 class FastNewClosureStub : public HydrogenCodeStub {
743  public:
744   FastNewClosureStub(Isolate* isolate, LanguageMode language_mode,
745                      FunctionKind kind)
746       : HydrogenCodeStub(isolate) {
747     DCHECK(IsValidFunctionKind(kind));
748     set_sub_minor_key(LanguageModeBits::encode(language_mode) |
749                       FunctionKindBits::encode(kind));
750   }
751
752   LanguageMode language_mode() const {
753     return LanguageModeBits::decode(sub_minor_key());
754   }
755
756   FunctionKind kind() const {
757     return FunctionKindBits::decode(sub_minor_key());
758   }
759
760  private:
761   STATIC_ASSERT(LANGUAGE_END == 3);
762   class LanguageModeBits : public BitField<LanguageMode, 0, 2> {};
763   class FunctionKindBits : public BitField<FunctionKind, 2, 8> {};
764
765   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
766   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
767 };
768
769
770 class FastNewContextStub final : public HydrogenCodeStub {
771  public:
772   static const int kMaximumSlots = 64;
773
774   FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
775     DCHECK(slots >= 0 && slots <= kMaximumSlots);
776     set_sub_minor_key(SlotsBits::encode(slots));
777   }
778
779   int slots() const { return SlotsBits::decode(sub_minor_key()); }
780
781   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
782   static const int kFunction = 0;
783
784  private:
785   class SlotsBits : public BitField<int, 0, 8> {};
786
787   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
788   DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
789 };
790
791
792 class FastCloneShallowArrayStub : public HydrogenCodeStub {
793  public:
794   FastCloneShallowArrayStub(Isolate* isolate,
795                             AllocationSiteMode allocation_site_mode)
796       : HydrogenCodeStub(isolate) {
797     set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
798   }
799
800   AllocationSiteMode allocation_site_mode() const {
801     return AllocationSiteModeBits::decode(sub_minor_key());
802   }
803
804  private:
805   class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
806
807   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
808   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
809 };
810
811
812 class FastCloneShallowObjectStub : public HydrogenCodeStub {
813  public:
814   // Maximum number of properties in copied object.
815   static const int kMaximumClonedProperties = 6;
816
817   FastCloneShallowObjectStub(Isolate* isolate, int length)
818       : HydrogenCodeStub(isolate) {
819     DCHECK_GE(length, 0);
820     DCHECK_LE(length, kMaximumClonedProperties);
821     set_sub_minor_key(LengthBits::encode(length));
822   }
823
824   int length() const { return LengthBits::decode(sub_minor_key()); }
825
826  private:
827   class LengthBits : public BitField<int, 0, 4> {};
828
829   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
830   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
831 };
832
833
834 class CreateAllocationSiteStub : public HydrogenCodeStub {
835  public:
836   explicit CreateAllocationSiteStub(Isolate* isolate)
837       : HydrogenCodeStub(isolate) { }
838
839   static void GenerateAheadOfTime(Isolate* isolate);
840
841   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
842   DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
843 };
844
845
846 class CreateWeakCellStub : public HydrogenCodeStub {
847  public:
848   explicit CreateWeakCellStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
849
850   static void GenerateAheadOfTime(Isolate* isolate);
851
852   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
853   DEFINE_HYDROGEN_CODE_STUB(CreateWeakCell, HydrogenCodeStub);
854 };
855
856
857 class GrowArrayElementsStub : public HydrogenCodeStub {
858  public:
859   GrowArrayElementsStub(Isolate* isolate, bool is_js_array, ElementsKind kind)
860       : HydrogenCodeStub(isolate) {
861     set_sub_minor_key(ElementsKindBits::encode(kind) |
862                       IsJsArrayBits::encode(is_js_array));
863   }
864
865   ElementsKind elements_kind() const {
866     return ElementsKindBits::decode(sub_minor_key());
867   }
868
869   bool is_js_array() const { return IsJsArrayBits::decode(sub_minor_key()); }
870
871  private:
872   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
873   class IsJsArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
874
875   DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
876   DEFINE_HYDROGEN_CODE_STUB(GrowArrayElements, HydrogenCodeStub);
877 };
878
879
880 class InstanceOfStub final : public PlatformCodeStub {
881  public:
882   explicit InstanceOfStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
883
884  private:
885   DEFINE_CALL_INTERFACE_DESCRIPTOR(InstanceOf);
886   DEFINE_PLATFORM_CODE_STUB(InstanceOf, PlatformCodeStub);
887 };
888
889
890 enum AllocationSiteOverrideMode {
891   DONT_OVERRIDE,
892   DISABLE_ALLOCATION_SITES,
893   LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
894 };
895
896
897 class ArrayConstructorStub: public PlatformCodeStub {
898  public:
899   enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
900
901   ArrayConstructorStub(Isolate* isolate, int argument_count);
902
903   explicit ArrayConstructorStub(Isolate* isolate);
904
905  private:
906   ArgumentCountKey argument_count() const {
907     return ArgumentCountBits::decode(minor_key_);
908   }
909
910   void GenerateDispatchToArrayStub(MacroAssembler* masm,
911                                    AllocationSiteOverrideMode mode);
912
913   void PrintName(std::ostream& os) const override;  // NOLINT
914
915   class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
916
917   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
918   DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
919 };
920
921
922 class InternalArrayConstructorStub: public PlatformCodeStub {
923  public:
924   explicit InternalArrayConstructorStub(Isolate* isolate);
925
926  private:
927   void GenerateCase(MacroAssembler* masm, ElementsKind kind);
928
929   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
930   DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
931 };
932
933
934 class MathPowStub: public PlatformCodeStub {
935  public:
936   enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
937
938   MathPowStub(Isolate* isolate, ExponentType exponent_type)
939       : PlatformCodeStub(isolate) {
940     minor_key_ = ExponentTypeBits::encode(exponent_type);
941   }
942
943   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
944     if (exponent_type() == TAGGED) {
945       return MathPowTaggedDescriptor(isolate());
946     } else if (exponent_type() == INTEGER) {
947       return MathPowIntegerDescriptor(isolate());
948     }
949     // A CallInterfaceDescriptor doesn't specify double registers (yet).
950     return ContextOnlyDescriptor(isolate());
951   }
952
953  private:
954   ExponentType exponent_type() const {
955     return ExponentTypeBits::decode(minor_key_);
956   }
957
958   class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
959
960   DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
961 };
962
963
964 class CallICStub: public PlatformCodeStub {
965  public:
966   CallICStub(Isolate* isolate, const CallICState& state)
967       : PlatformCodeStub(isolate) {
968     minor_key_ = state.GetExtraICState();
969   }
970
971   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
972
973   InlineCacheState GetICState() const override { return DEFAULT; }
974
975   ExtraICState GetExtraICState() const final {
976     return static_cast<ExtraICState>(minor_key_);
977   }
978
979  protected:
980   bool CallAsMethod() const {
981     return state().call_type() == CallICState::METHOD;
982   }
983
984   int arg_count() const { return state().arg_count(); }
985
986   CallICState state() const {
987     return CallICState(static_cast<ExtraICState>(minor_key_));
988   }
989
990   // Code generation helpers.
991   void GenerateMiss(MacroAssembler* masm);
992
993  private:
994   void PrintState(std::ostream& os) const override;  // NOLINT
995
996   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
997   DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
998 };
999
1000
1001 class CallIC_ArrayStub: public CallICStub {
1002  public:
1003   CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
1004       : CallICStub(isolate, state_in) {}
1005
1006   InlineCacheState GetICState() const final { return MONOMORPHIC; }
1007
1008  private:
1009   void PrintState(std::ostream& os) const override;  // NOLINT
1010
1011   DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
1012 };
1013
1014
1015 // TODO(verwaest): Translate to hydrogen code stub.
1016 class FunctionPrototypeStub : public PlatformCodeStub {
1017  public:
1018   explicit FunctionPrototypeStub(Isolate* isolate)
1019       : PlatformCodeStub(isolate) {}
1020
1021   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1022
1023   // TODO(mvstanton): only the receiver register is accessed. When this is
1024   // translated to a hydrogen code stub, a new CallInterfaceDescriptor
1025   // should be created that just uses that register for more efficient code.
1026   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1027     return LoadWithVectorDescriptor(isolate());
1028   }
1029
1030   DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
1031 };
1032
1033
1034 // TODO(mvstanton): Translate to hydrogen code stub.
1035 class LoadIndexedInterceptorStub : public PlatformCodeStub {
1036  public:
1037   explicit LoadIndexedInterceptorStub(Isolate* isolate)
1038       : PlatformCodeStub(isolate) {}
1039
1040   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1041   Code::StubType GetStubType() const override { return Code::FAST; }
1042
1043   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1044   DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
1045 };
1046
1047
1048 class LoadIndexedStringStub : public PlatformCodeStub {
1049  public:
1050   explicit LoadIndexedStringStub(Isolate* isolate)
1051       : PlatformCodeStub(isolate) {}
1052
1053   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1054   Code::StubType GetStubType() const override { return Code::FAST; }
1055
1056   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1057   DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
1058 };
1059
1060
1061 class HandlerStub : public HydrogenCodeStub {
1062  public:
1063   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1064   ExtraICState GetExtraICState() const override { return kind(); }
1065   InlineCacheState GetICState() const override { return MONOMORPHIC; }
1066
1067   void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
1068
1069   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1070
1071  protected:
1072   explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1073
1074   virtual Code::Kind kind() const = 0;
1075
1076   DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1077 };
1078
1079
1080 class LoadFieldStub: public HandlerStub {
1081  public:
1082   LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
1083     int property_index_key = index.GetFieldAccessStubKey();
1084     set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1085   }
1086
1087   FieldIndex index() const {
1088     int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
1089     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1090   }
1091
1092  protected:
1093   Code::Kind kind() const override { return Code::LOAD_IC; }
1094   Code::StubType GetStubType() const override { return Code::FAST; }
1095
1096  private:
1097   class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
1098
1099   DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1100 };
1101
1102
1103 class ArrayBufferViewLoadFieldStub : public HandlerStub {
1104  public:
1105   ArrayBufferViewLoadFieldStub(Isolate* isolate, FieldIndex index)
1106       : HandlerStub(isolate) {
1107     int property_index_key = index.GetFieldAccessStubKey();
1108     set_sub_minor_key(
1109         ArrayBufferViewLoadFieldByIndexBits::encode(property_index_key));
1110   }
1111
1112   FieldIndex index() const {
1113     int property_index_key =
1114         ArrayBufferViewLoadFieldByIndexBits::decode(sub_minor_key());
1115     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1116   }
1117
1118  protected:
1119   Code::Kind kind() const override { return Code::LOAD_IC; }
1120   Code::StubType GetStubType() const override { return Code::FAST; }
1121
1122  private:
1123   class ArrayBufferViewLoadFieldByIndexBits : public BitField<int, 0, 13> {};
1124
1125   DEFINE_HANDLER_CODE_STUB(ArrayBufferViewLoadField, HandlerStub);
1126 };
1127
1128
1129 class KeyedLoadSloppyArgumentsStub : public HandlerStub {
1130  public:
1131   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
1132       : HandlerStub(isolate) {}
1133
1134  protected:
1135   Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
1136   Code::StubType GetStubType() const override { return Code::FAST; }
1137
1138  private:
1139   DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
1140 };
1141
1142
1143 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
1144
1145 class KeyedStoreSloppyArgumentsStub : public HandlerStub {
1146  public:
1147   explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
1148                                          KeyedAccessStoreMode mode)
1149       : HandlerStub(isolate) {
1150     set_sub_minor_key(CommonStoreModeBits::encode(mode));
1151   }
1152
1153  protected:
1154   Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
1155   Code::StubType GetStubType() const override { return Code::FAST; }
1156
1157  private:
1158   DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
1159 };
1160
1161
1162 class LoadConstantStub : public HandlerStub {
1163  public:
1164   LoadConstantStub(Isolate* isolate, int constant_index)
1165       : HandlerStub(isolate) {
1166     set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1167   }
1168
1169   int constant_index() const {
1170     return ConstantIndexBits::decode(sub_minor_key());
1171   }
1172
1173  protected:
1174   Code::Kind kind() const override { return Code::LOAD_IC; }
1175   Code::StubType GetStubType() const override { return Code::FAST; }
1176
1177  private:
1178   class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1179
1180   DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1181 };
1182
1183
1184 class StringLengthStub: public HandlerStub {
1185  public:
1186   explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
1187
1188  protected:
1189   Code::Kind kind() const override { return Code::LOAD_IC; }
1190   Code::StubType GetStubType() const override { return Code::FAST; }
1191
1192   DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
1193 };
1194
1195
1196 class StoreFieldStub : public HandlerStub {
1197  public:
1198   StoreFieldStub(Isolate* isolate, FieldIndex index,
1199                  Representation representation)
1200       : HandlerStub(isolate) {
1201     int property_index_key = index.GetFieldAccessStubKey();
1202     uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1203     set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1204                       RepresentationBits::encode(repr));
1205   }
1206
1207   FieldIndex index() const {
1208     int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1209     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1210   }
1211
1212   Representation representation() {
1213     uint8_t repr = RepresentationBits::decode(sub_minor_key());
1214     return PropertyDetails::DecodeRepresentation(repr);
1215   }
1216
1217  protected:
1218   Code::Kind kind() const override { return Code::STORE_IC; }
1219   Code::StubType GetStubType() const override { return Code::FAST; }
1220
1221  private:
1222   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1223   class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1224
1225   DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1226 };
1227
1228
1229 // Register and parameter access methods are specified here instead of in
1230 // the CallInterfaceDescriptor because the stub uses a different descriptor
1231 // if FLAG_vector_stores is on.
1232 class StoreTransitionHelper {
1233  public:
1234   static Register ReceiverRegister() {
1235     return StoreTransitionDescriptor::ReceiverRegister();
1236   }
1237
1238   static Register NameRegister() {
1239     return StoreTransitionDescriptor::NameRegister();
1240   }
1241
1242   static Register ValueRegister() {
1243     return StoreTransitionDescriptor::ValueRegister();
1244   }
1245
1246   static Register SlotRegister() {
1247     DCHECK(FLAG_vector_stores);
1248     return VectorStoreTransitionDescriptor::SlotRegister();
1249   }
1250
1251   static Register VectorRegister() {
1252     DCHECK(FLAG_vector_stores);
1253     return VectorStoreTransitionDescriptor::VectorRegister();
1254   }
1255
1256   static Register MapRegister() {
1257     return FLAG_vector_stores ? VectorStoreTransitionDescriptor::MapRegister()
1258                               : StoreTransitionDescriptor::MapRegister();
1259   }
1260
1261   static int ReceiverIndex() {
1262     return StoreTransitionDescriptor::kReceiverIndex;
1263   }
1264
1265   static int NameIndex() { return StoreTransitionDescriptor::kReceiverIndex; }
1266
1267   static int ValueIndex() { return StoreTransitionDescriptor::kValueIndex; }
1268
1269   static int SlotIndex() {
1270     DCHECK(FLAG_vector_stores);
1271     return VectorStoreTransitionDescriptor::kSlotIndex;
1272   }
1273
1274   static int VectorIndex() {
1275     DCHECK(FLAG_vector_stores);
1276     return VectorStoreTransitionDescriptor::kVectorIndex;
1277   }
1278
1279   static int MapIndex() {
1280     if (FLAG_vector_stores) {
1281       return VectorStoreTransitionDescriptor::kMapIndex;
1282     }
1283     return StoreTransitionDescriptor::kMapIndex;
1284   }
1285
1286   // Some platforms push Slot, Vector, Map on the stack instead of in
1287   // registers.
1288   static bool UsesStackArgs() { return MapRegister().is(no_reg); }
1289 };
1290
1291
1292 class StoreTransitionStub : public HandlerStub {
1293  public:
1294   enum StoreMode {
1295     StoreMapOnly,
1296     StoreMapAndValue,
1297     ExtendStorageAndStoreMapAndValue
1298   };
1299
1300   explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
1301     set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
1302   }
1303
1304   StoreTransitionStub(Isolate* isolate, FieldIndex index,
1305                       Representation representation, StoreMode store_mode)
1306       : HandlerStub(isolate) {
1307     DCHECK(store_mode != StoreMapOnly);
1308     int property_index_key = index.GetFieldAccessStubKey();
1309     uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1310     set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1311                       RepresentationBits::encode(repr) |
1312                       StoreModeBits::encode(store_mode));
1313   }
1314
1315   FieldIndex index() const {
1316     DCHECK(store_mode() != StoreMapOnly);
1317     int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1318     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1319   }
1320
1321   Representation representation() {
1322     DCHECK(store_mode() != StoreMapOnly);
1323     uint8_t repr = RepresentationBits::decode(sub_minor_key());
1324     return PropertyDetails::DecodeRepresentation(repr);
1325   }
1326
1327   StoreMode store_mode() const {
1328     return StoreModeBits::decode(sub_minor_key());
1329   }
1330
1331   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1332
1333  protected:
1334   Code::Kind kind() const override { return Code::STORE_IC; }
1335   Code::StubType GetStubType() const override { return Code::FAST; }
1336
1337  private:
1338   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1339   class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1340   class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1341
1342   DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1343 };
1344
1345
1346 class StoreGlobalStub : public HandlerStub {
1347  public:
1348   StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1349                   Maybe<PropertyCellConstantType> constant_type,
1350                   bool check_global)
1351       : HandlerStub(isolate) {
1352     PropertyCellConstantType encoded_constant_type =
1353         constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1354     set_sub_minor_key(CellTypeBits::encode(type) |
1355                       ConstantTypeBits::encode(encoded_constant_type) |
1356                       CheckGlobalBits::encode(check_global));
1357   }
1358
1359   static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
1360     return isolate->factory()->uninitialized_value();
1361   }
1362
1363   static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1364     return isolate->factory()->termination_exception();
1365   }
1366
1367   Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1368                                        Handle<PropertyCell> cell) {
1369     Code::FindAndReplacePattern pattern;
1370     if (check_global()) {
1371       pattern.Add(handle(global_map_placeholder(isolate())->map()),
1372                   Map::WeakCellForMap(Handle<Map>(global->map())));
1373     }
1374     pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1375                 isolate()->factory()->NewWeakCell(cell));
1376     return CodeStub::GetCodeCopy(pattern);
1377   }
1378
1379   Code::Kind kind() const override { return Code::STORE_IC; }
1380
1381   PropertyCellType cell_type() const {
1382     return CellTypeBits::decode(sub_minor_key());
1383   }
1384
1385   PropertyCellConstantType constant_type() const {
1386     DCHECK(PropertyCellType::kConstantType == cell_type());
1387     return ConstantTypeBits::decode(sub_minor_key());
1388   }
1389
1390   bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1391
1392   Representation representation() {
1393     return Representation::FromKind(
1394         RepresentationBits::decode(sub_minor_key()));
1395   }
1396
1397   void set_representation(Representation r) {
1398     set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1399   }
1400
1401  private:
1402   class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1403   class ConstantTypeBits : public BitField<PropertyCellConstantType, 2, 2> {};
1404   class RepresentationBits : public BitField<Representation::Kind, 4, 8> {};
1405   class CheckGlobalBits : public BitField<bool, 12, 1> {};
1406
1407   DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1408 };
1409
1410
1411 class LoadGlobalViaContextStub final : public PlatformCodeStub {
1412  public:
1413   static const int kMaximumDepth = 15;
1414
1415   LoadGlobalViaContextStub(Isolate* isolate, int depth)
1416       : PlatformCodeStub(isolate) {
1417     minor_key_ = DepthBits::encode(depth);
1418   }
1419
1420   int depth() const { return DepthBits::decode(minor_key_); }
1421
1422  private:
1423   class DepthBits : public BitField<int, 0, 4> {};
1424   STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1425
1426   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalViaContext);
1427   DEFINE_PLATFORM_CODE_STUB(LoadGlobalViaContext, PlatformCodeStub);
1428 };
1429
1430
1431 class StoreGlobalViaContextStub final : public PlatformCodeStub {
1432  public:
1433   static const int kMaximumDepth = 15;
1434
1435   StoreGlobalViaContextStub(Isolate* isolate, int depth,
1436                             LanguageMode language_mode)
1437       : PlatformCodeStub(isolate) {
1438     minor_key_ =
1439         DepthBits::encode(depth) | LanguageModeBits::encode(language_mode);
1440   }
1441
1442   int depth() const { return DepthBits::decode(minor_key_); }
1443   LanguageMode language_mode() const {
1444     return LanguageModeBits::decode(minor_key_);
1445   }
1446
1447  private:
1448   class DepthBits : public BitField<int, 0, 4> {};
1449   STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1450   class LanguageModeBits : public BitField<LanguageMode, 4, 2> {};
1451   STATIC_ASSERT(LANGUAGE_END == 3);
1452
1453   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreGlobalViaContext);
1454   DEFINE_PLATFORM_CODE_STUB(StoreGlobalViaContext, PlatformCodeStub);
1455 };
1456
1457
1458 class CallApiFunctionStub : public PlatformCodeStub {
1459  public:
1460   explicit CallApiFunctionStub(Isolate* isolate, bool call_data_undefined)
1461       : PlatformCodeStub(isolate) {
1462     minor_key_ = CallDataUndefinedBits::encode(call_data_undefined);
1463   }
1464
1465  private:
1466   bool call_data_undefined() const {
1467     return CallDataUndefinedBits::decode(minor_key_);
1468   }
1469
1470   class CallDataUndefinedBits : public BitField<bool, 0, 1> {};
1471
1472   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1473   DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1474 };
1475
1476
1477 class CallApiAccessorStub : public PlatformCodeStub {
1478  public:
1479   CallApiAccessorStub(Isolate* isolate, bool is_store, bool call_data_undefined)
1480       : PlatformCodeStub(isolate) {
1481     minor_key_ = IsStoreBits::encode(is_store) |
1482                  CallDataUndefinedBits::encode(call_data_undefined) |
1483                  ArgumentBits::encode(is_store ? 1 : 0);
1484   }
1485
1486  protected:
1487   // For CallApiFunctionWithFixedArgsStub, see below.
1488   static const int kArgBits = 3;
1489   CallApiAccessorStub(Isolate* isolate, int argc, bool call_data_undefined)
1490       : PlatformCodeStub(isolate) {
1491     minor_key_ = IsStoreBits::encode(false) |
1492                  CallDataUndefinedBits::encode(call_data_undefined) |
1493                  ArgumentBits::encode(argc);
1494   }
1495
1496  private:
1497   bool is_store() const { return IsStoreBits::decode(minor_key_); }
1498   bool call_data_undefined() const {
1499     return CallDataUndefinedBits::decode(minor_key_);
1500   }
1501   int argc() const { return ArgumentBits::decode(minor_key_); }
1502
1503   class IsStoreBits: public BitField<bool, 0, 1> {};
1504   class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1505   class ArgumentBits : public BitField<int, 2, kArgBits> {};
1506
1507   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiAccessor);
1508   DEFINE_PLATFORM_CODE_STUB(CallApiAccessor, PlatformCodeStub);
1509 };
1510
1511
1512 // TODO(dcarney): see if it's possible to remove this later without performance
1513 // degradation.
1514 // This is not a real stub, but a way of generating the CallApiAccessorStub
1515 // (which has the same abi) which makes it clear that it is not an accessor.
1516 class CallApiFunctionWithFixedArgsStub : public CallApiAccessorStub {
1517  public:
1518   static const int kMaxFixedArgs = (1 << kArgBits) - 1;
1519   CallApiFunctionWithFixedArgsStub(Isolate* isolate, int argc,
1520                                    bool call_data_undefined)
1521       : CallApiAccessorStub(isolate, argc, call_data_undefined) {
1522     DCHECK(0 <= argc && argc <= kMaxFixedArgs);
1523   }
1524 };
1525
1526
1527 typedef ApiAccessorDescriptor ApiFunctionWithFixedArgsDescriptor;
1528
1529
1530 class CallApiGetterStub : public PlatformCodeStub {
1531  public:
1532   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1533
1534   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1535   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1536 };
1537
1538
1539 class BinaryOpICStub : public HydrogenCodeStub {
1540  public:
1541   BinaryOpICStub(Isolate* isolate, Token::Value op, Strength strength)
1542       : HydrogenCodeStub(isolate, UNINITIALIZED) {
1543     BinaryOpICState state(isolate, op, strength);
1544     set_sub_minor_key(state.GetExtraICState());
1545   }
1546
1547   BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1548       : HydrogenCodeStub(isolate) {
1549     set_sub_minor_key(state.GetExtraICState());
1550   }
1551
1552   static void GenerateAheadOfTime(Isolate* isolate);
1553
1554   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1555
1556   InlineCacheState GetICState() const final { return state().GetICState(); }
1557
1558   ExtraICState GetExtraICState() const final {
1559     return static_cast<ExtraICState>(sub_minor_key());
1560   }
1561
1562   BinaryOpICState state() const {
1563     return BinaryOpICState(isolate(), GetExtraICState());
1564   }
1565
1566   void PrintState(std::ostream& os) const final;  // NOLINT
1567
1568   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1569   static const int kLeft = 0;
1570   static const int kRight = 1;
1571
1572  private:
1573   static void GenerateAheadOfTime(Isolate* isolate,
1574                                   const BinaryOpICState& state);
1575
1576   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1577   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1578 };
1579
1580
1581 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1582 // call support for stubs in Hydrogen.
1583 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
1584  public:
1585   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1586                                    const BinaryOpICState& state)
1587       : PlatformCodeStub(isolate) {
1588     minor_key_ = state.GetExtraICState();
1589   }
1590
1591   static void GenerateAheadOfTime(Isolate* isolate);
1592
1593   Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1594     Code::FindAndReplacePattern pattern;
1595     pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1596     return CodeStub::GetCodeCopy(pattern);
1597   }
1598
1599   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1600
1601   InlineCacheState GetICState() const override { return state().GetICState(); }
1602
1603   ExtraICState GetExtraICState() const override {
1604     return static_cast<ExtraICState>(minor_key_);
1605   }
1606
1607   void PrintState(std::ostream& os) const override;  // NOLINT
1608
1609  private:
1610   BinaryOpICState state() const {
1611     return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1612   }
1613
1614   static void GenerateAheadOfTime(Isolate* isolate,
1615                                   const BinaryOpICState& state);
1616
1617   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1618   DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1619 };
1620
1621
1622 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
1623  public:
1624   BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op,
1625                                  Strength strength)
1626       : BinaryOpICStub(isolate, op, strength) {}
1627
1628   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1629       : BinaryOpICStub(isolate, state) {}
1630
1631   Code::Kind GetCodeKind() const final { return Code::STUB; }
1632
1633   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1634   static const int kAllocationSite = 0;
1635   static const int kLeft = 1;
1636   static const int kRight = 2;
1637
1638   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1639   DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1640 };
1641
1642
1643 class StringAddStub final : public HydrogenCodeStub {
1644  public:
1645   StringAddStub(Isolate* isolate, StringAddFlags flags,
1646                 PretenureFlag pretenure_flag)
1647       : HydrogenCodeStub(isolate) {
1648     set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1649                       PretenureFlagBits::encode(pretenure_flag));
1650   }
1651
1652   StringAddFlags flags() const {
1653     return StringAddFlagsBits::decode(sub_minor_key());
1654   }
1655
1656   PretenureFlag pretenure_flag() const {
1657     return PretenureFlagBits::decode(sub_minor_key());
1658   }
1659
1660   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1661   static const int kLeft = 0;
1662   static const int kRight = 1;
1663
1664  private:
1665   class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1666   class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1667
1668   void PrintBaseName(std::ostream& os) const override;  // NOLINT
1669
1670   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1671   DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1672 };
1673
1674
1675 class CompareICStub : public PlatformCodeStub {
1676  public:
1677   CompareICStub(Isolate* isolate, Token::Value op, Strength strength,
1678                 CompareICState::State left, CompareICState::State right,
1679                 CompareICState::State state)
1680       : PlatformCodeStub(isolate) {
1681     DCHECK(Token::IsCompareOp(op));
1682     minor_key_ = OpBits::encode(op - Token::EQ) |
1683                  StrengthBits::encode(is_strong(strength)) |
1684                  LeftStateBits::encode(left) | RightStateBits::encode(right) |
1685                  StateBits::encode(state);
1686   }
1687
1688   void set_known_map(Handle<Map> map) { known_map_ = map; }
1689
1690   InlineCacheState GetICState() const override;
1691
1692   Token::Value op() const {
1693     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1694   }
1695
1696   Strength strength() const {
1697     return StrengthBits::decode(minor_key_) ? Strength::STRONG : Strength::WEAK;
1698   }
1699
1700   CompareICState::State left() const {
1701     return LeftStateBits::decode(minor_key_);
1702   }
1703   CompareICState::State right() const {
1704     return RightStateBits::decode(minor_key_);
1705   }
1706   CompareICState::State state() const { return StateBits::decode(minor_key_); }
1707
1708  private:
1709   Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
1710
1711   void GenerateSmis(MacroAssembler* masm);
1712   void GenerateNumbers(MacroAssembler* masm);
1713   void GenerateInternalizedStrings(MacroAssembler* masm);
1714   void GenerateStrings(MacroAssembler* masm);
1715   void GenerateUniqueNames(MacroAssembler* masm);
1716   void GenerateObjects(MacroAssembler* masm);
1717   void GenerateMiss(MacroAssembler* masm);
1718   void GenerateKnownObjects(MacroAssembler* masm);
1719   void GenerateGeneric(MacroAssembler* masm);
1720
1721   bool strict() const { return op() == Token::EQ_STRICT; }
1722   Condition GetCondition() const;
1723
1724   void AddToSpecialCache(Handle<Code> new_object) override;
1725   bool FindCodeInSpecialCache(Code** code_out) override;
1726   bool UseSpecialCache() override {
1727     return state() == CompareICState::KNOWN_OBJECT;
1728   }
1729
1730   class OpBits : public BitField<int, 0, 3> {};
1731   class StrengthBits : public BitField<bool, 3, 1> {};
1732   class LeftStateBits : public BitField<CompareICState::State, 4, 4> {};
1733   class RightStateBits : public BitField<CompareICState::State, 8, 4> {};
1734   class StateBits : public BitField<CompareICState::State, 12, 4> {};
1735
1736   Handle<Map> known_map_;
1737
1738   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1739   DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1740 };
1741
1742
1743 class CompareNilICStub : public HydrogenCodeStub  {
1744  public:
1745   Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1746   Type* GetInputType(Zone* zone, Handle<Map> map);
1747
1748   CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1749     set_sub_minor_key(NilValueBits::encode(nil));
1750   }
1751
1752   CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1753                    InitializationState init_state = INITIALIZED)
1754       : HydrogenCodeStub(isolate, init_state) {
1755     set_sub_minor_key(ic_state);
1756   }
1757
1758   static Handle<Code> GetUninitialized(Isolate* isolate,
1759                                        NilValue nil) {
1760     return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1761   }
1762
1763   InlineCacheState GetICState() const override {
1764     State state = this->state();
1765     if (state.Contains(GENERIC)) {
1766       return MEGAMORPHIC;
1767     } else if (state.Contains(MONOMORPHIC_MAP)) {
1768       return MONOMORPHIC;
1769     } else {
1770       return PREMONOMORPHIC;
1771     }
1772   }
1773
1774   Code::Kind GetCodeKind() const override { return Code::COMPARE_NIL_IC; }
1775
1776   ExtraICState GetExtraICState() const override { return sub_minor_key(); }
1777
1778   void UpdateStatus(Handle<Object> object);
1779
1780   bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1781
1782   NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1783
1784   void ClearState() {
1785     set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1786   }
1787
1788   void PrintState(std::ostream& os) const override;     // NOLINT
1789   void PrintBaseName(std::ostream& os) const override;  // NOLINT
1790
1791  private:
1792   CompareNilICStub(Isolate* isolate, NilValue nil,
1793                    InitializationState init_state)
1794       : HydrogenCodeStub(isolate, init_state) {
1795     set_sub_minor_key(NilValueBits::encode(nil));
1796   }
1797
1798   enum CompareNilType {
1799     UNDEFINED,
1800     NULL_TYPE,
1801     MONOMORPHIC_MAP,
1802     GENERIC,
1803     NUMBER_OF_TYPES
1804   };
1805
1806   // At most 6 different types can be distinguished, because the Code object
1807   // only has room for a single byte to hold a set and there are two more
1808   // boolean flags we need to store. :-P
1809   STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1810
1811   class State : public EnumSet<CompareNilType, byte> {
1812    public:
1813     State() : EnumSet<CompareNilType, byte>(0) { }
1814     explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1815   };
1816   friend std::ostream& operator<<(std::ostream& os, const State& s);
1817
1818   State state() const { return State(TypesBits::decode(sub_minor_key())); }
1819
1820   class NilValueBits : public BitField<NilValue, 0, 1> {};
1821   class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1822
1823   friend class CompareNilIC;
1824
1825   DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1826   DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1827 };
1828
1829
1830 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s);
1831
1832
1833 class CEntryStub : public PlatformCodeStub {
1834  public:
1835   CEntryStub(Isolate* isolate, int result_size,
1836              SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1837       : PlatformCodeStub(isolate) {
1838     minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1839     DCHECK(result_size == 1 || result_size == 2);
1840 #if _WIN64 || V8_TARGET_ARCH_PPC
1841     minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1842 #endif  // _WIN64
1843   }
1844
1845   // The version of this stub that doesn't save doubles is generated ahead of
1846   // time, so it's OK to call it from other stubs that can't cope with GC during
1847   // their code generation.  On machines that always have gp registers (x64) we
1848   // can generate both variants ahead of time.
1849   static void GenerateAheadOfTime(Isolate* isolate);
1850
1851  private:
1852   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1853 #if _WIN64 || V8_TARGET_ARCH_PPC
1854   int result_size() const { return ResultSizeBits::decode(minor_key_); }
1855 #endif  // _WIN64
1856
1857   bool NeedsImmovableCode() override;
1858
1859   class SaveDoublesBits : public BitField<bool, 0, 1> {};
1860   class ResultSizeBits : public BitField<int, 1, 3> {};
1861
1862   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1863   DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1864 };
1865
1866
1867 class JSEntryStub : public PlatformCodeStub {
1868  public:
1869   JSEntryStub(Isolate* isolate, StackFrame::Type type)
1870       : PlatformCodeStub(isolate) {
1871     DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1872     minor_key_ = StackFrameTypeBits::encode(type);
1873   }
1874
1875  private:
1876   void FinishCode(Handle<Code> code) override;
1877
1878   void PrintName(std::ostream& os) const override {  // NOLINT
1879     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1880                                        : "JSConstructEntryStub");
1881   }
1882
1883   StackFrame::Type type() const {
1884     return StackFrameTypeBits::decode(minor_key_);
1885   }
1886
1887   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1888
1889   int handler_offset_;
1890
1891   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1892   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1893 };
1894
1895
1896 class ArgumentsAccessStub: public PlatformCodeStub {
1897  public:
1898   enum Type {
1899     READ_ELEMENT,
1900     NEW_SLOPPY_FAST,
1901     NEW_SLOPPY_SLOW,
1902     NEW_STRICT
1903   };
1904
1905   ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1906     minor_key_ = TypeBits::encode(type);
1907   }
1908
1909   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1910     if (type() == READ_ELEMENT) {
1911       return ArgumentsAccessReadDescriptor(isolate());
1912     }
1913     return ContextOnlyDescriptor(isolate());
1914   }
1915
1916  private:
1917   Type type() const { return TypeBits::decode(minor_key_); }
1918
1919   void GenerateReadElement(MacroAssembler* masm);
1920   void GenerateNewStrict(MacroAssembler* masm);
1921   void GenerateNewSloppyFast(MacroAssembler* masm);
1922   void GenerateNewSloppySlow(MacroAssembler* masm);
1923
1924   void PrintName(std::ostream& os) const override;  // NOLINT
1925
1926   class TypeBits : public BitField<Type, 0, 2> {};
1927
1928   DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
1929 };
1930
1931
1932 class RegExpExecStub: public PlatformCodeStub {
1933  public:
1934   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1935
1936   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1937   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1938 };
1939
1940
1941 class RegExpConstructResultStub final : public HydrogenCodeStub {
1942  public:
1943   explicit RegExpConstructResultStub(Isolate* isolate)
1944       : HydrogenCodeStub(isolate) { }
1945
1946   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1947   static const int kLength = 0;
1948   static const int kIndex = 1;
1949   static const int kInput = 2;
1950
1951   DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1952   DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1953 };
1954
1955
1956 // TODO(bmeurer): Deprecate the CallFunctionStub in favor of the more general
1957 // Invoke family of builtins.
1958 class CallFunctionStub: public PlatformCodeStub {
1959  public:
1960   CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1961       : PlatformCodeStub(isolate) {
1962     DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1963     minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1964   }
1965
1966  private:
1967   int argc() const { return ArgcBits::decode(minor_key_); }
1968   int flags() const { return FlagBits::decode(minor_key_); }
1969
1970   bool CallAsMethod() const {
1971     return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1972   }
1973
1974   bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1975
1976   void PrintName(std::ostream& os) const override;  // NOLINT
1977
1978   // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1979   class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1980   class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1981   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1982
1983   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1984   DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1985 };
1986
1987
1988 class CallConstructStub: public PlatformCodeStub {
1989  public:
1990   CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1991       : PlatformCodeStub(isolate) {
1992     minor_key_ = FlagBits::encode(flags);
1993   }
1994
1995   void FinishCode(Handle<Code> code) override {
1996     code->set_has_function_cache(RecordCallTarget());
1997   }
1998
1999  private:
2000   CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
2001
2002   bool RecordCallTarget() const {
2003     return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
2004   }
2005
2006   bool IsSuperConstructorCall() const {
2007     return (flags() & SUPER_CONSTRUCTOR_CALL) != 0;
2008   }
2009
2010   void PrintName(std::ostream& os) const override;  // NOLINT
2011
2012   class FlagBits : public BitField<CallConstructorFlags, 0, 2> {};
2013
2014   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
2015   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
2016 };
2017
2018
2019 enum StringIndexFlags {
2020   // Accepts smis or heap numbers.
2021   STRING_INDEX_IS_NUMBER,
2022
2023   // Accepts smis or heap numbers that are valid array indices
2024   // (ECMA-262 15.4). Invalid indices are reported as being out of
2025   // range.
2026   STRING_INDEX_IS_ARRAY_INDEX
2027 };
2028
2029
2030 enum ReceiverCheckMode {
2031   // We don't know anything about the receiver.
2032   RECEIVER_IS_UNKNOWN,
2033
2034   // We know the receiver is a string.
2035   RECEIVER_IS_STRING
2036 };
2037
2038
2039 enum EmbedMode {
2040   // The code being generated is part of an IC handler, which may MISS
2041   // to an IC in failure cases.
2042   PART_OF_IC_HANDLER,
2043
2044   NOT_PART_OF_IC_HANDLER
2045 };
2046
2047
2048 // Generates code implementing String.prototype.charCodeAt.
2049 //
2050 // Only supports the case when the receiver is a string and the index
2051 // is a number (smi or heap number) that is a valid index into the
2052 // string. Additional index constraints are specified by the
2053 // flags. Otherwise, bails out to the provided labels.
2054 //
2055 // Register usage: |object| may be changed to another string in a way
2056 // that doesn't affect charCodeAt/charAt semantics, |index| is
2057 // preserved, |scratch| and |result| are clobbered.
2058 class StringCharCodeAtGenerator {
2059  public:
2060   StringCharCodeAtGenerator(Register object, Register index, Register result,
2061                             Label* receiver_not_string, Label* index_not_number,
2062                             Label* index_out_of_range,
2063                             StringIndexFlags index_flags,
2064                             ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2065       : object_(object),
2066         index_(index),
2067         result_(result),
2068         receiver_not_string_(receiver_not_string),
2069         index_not_number_(index_not_number),
2070         index_out_of_range_(index_out_of_range),
2071         index_flags_(index_flags),
2072         check_mode_(check_mode) {
2073     DCHECK(!result_.is(object_));
2074     DCHECK(!result_.is(index_));
2075   }
2076
2077   // Generates the fast case code. On the fallthrough path |result|
2078   // register contains the result.
2079   void GenerateFast(MacroAssembler* masm);
2080
2081   // Generates the slow case code. Must not be naturally
2082   // reachable. Expected to be put after a ret instruction (e.g., in
2083   // deferred code). Always jumps back to the fast case.
2084   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2085                     const RuntimeCallHelper& call_helper);
2086
2087   // Skip handling slow case and directly jump to bailout.
2088   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2089     masm->bind(&index_not_smi_);
2090     masm->bind(&call_runtime_);
2091     masm->jmp(bailout);
2092   }
2093
2094  private:
2095   Register object_;
2096   Register index_;
2097   Register result_;
2098
2099   Label* receiver_not_string_;
2100   Label* index_not_number_;
2101   Label* index_out_of_range_;
2102
2103   StringIndexFlags index_flags_;
2104   ReceiverCheckMode check_mode_;
2105
2106   Label call_runtime_;
2107   Label index_not_smi_;
2108   Label got_smi_index_;
2109   Label exit_;
2110
2111   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
2112 };
2113
2114
2115 // Generates code for creating a one-char string from a char code.
2116 class StringCharFromCodeGenerator {
2117  public:
2118   StringCharFromCodeGenerator(Register code,
2119                               Register result)
2120       : code_(code),
2121         result_(result) {
2122     DCHECK(!code_.is(result_));
2123   }
2124
2125   // Generates the fast case code. On the fallthrough path |result|
2126   // register contains the result.
2127   void GenerateFast(MacroAssembler* masm);
2128
2129   // Generates the slow case code. Must not be naturally
2130   // reachable. Expected to be put after a ret instruction (e.g., in
2131   // deferred code). Always jumps back to the fast case.
2132   void GenerateSlow(MacroAssembler* masm,
2133                     const RuntimeCallHelper& call_helper);
2134
2135   // Skip handling slow case and directly jump to bailout.
2136   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2137     masm->bind(&slow_case_);
2138     masm->jmp(bailout);
2139   }
2140
2141  private:
2142   Register code_;
2143   Register result_;
2144
2145   Label slow_case_;
2146   Label exit_;
2147
2148   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
2149 };
2150
2151
2152 // Generates code implementing String.prototype.charAt.
2153 //
2154 // Only supports the case when the receiver is a string and the index
2155 // is a number (smi or heap number) that is a valid index into the
2156 // string. Additional index constraints are specified by the
2157 // flags. Otherwise, bails out to the provided labels.
2158 //
2159 // Register usage: |object| may be changed to another string in a way
2160 // that doesn't affect charCodeAt/charAt semantics, |index| is
2161 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
2162 class StringCharAtGenerator {
2163  public:
2164   StringCharAtGenerator(Register object, Register index, Register scratch,
2165                         Register result, Label* receiver_not_string,
2166                         Label* index_not_number, Label* index_out_of_range,
2167                         StringIndexFlags index_flags,
2168                         ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2169       : char_code_at_generator_(object, index, scratch, receiver_not_string,
2170                                 index_not_number, index_out_of_range,
2171                                 index_flags, check_mode),
2172         char_from_code_generator_(scratch, result) {}
2173
2174   // Generates the fast case code. On the fallthrough path |result|
2175   // register contains the result.
2176   void GenerateFast(MacroAssembler* masm) {
2177     char_code_at_generator_.GenerateFast(masm);
2178     char_from_code_generator_.GenerateFast(masm);
2179   }
2180
2181   // Generates the slow case code. Must not be naturally
2182   // reachable. Expected to be put after a ret instruction (e.g., in
2183   // deferred code). Always jumps back to the fast case.
2184   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2185                     const RuntimeCallHelper& call_helper) {
2186     char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
2187     char_from_code_generator_.GenerateSlow(masm, call_helper);
2188   }
2189
2190   // Skip handling slow case and directly jump to bailout.
2191   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2192     char_code_at_generator_.SkipSlow(masm, bailout);
2193     char_from_code_generator_.SkipSlow(masm, bailout);
2194   }
2195
2196  private:
2197   StringCharCodeAtGenerator char_code_at_generator_;
2198   StringCharFromCodeGenerator char_from_code_generator_;
2199
2200   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
2201 };
2202
2203
2204 class LoadDictionaryElementStub : public HydrogenCodeStub {
2205  public:
2206   explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
2207       : HydrogenCodeStub(isolate) {
2208     minor_key_ = state.GetExtraICState();
2209   }
2210
2211   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2212     return LoadWithVectorDescriptor(isolate());
2213   }
2214
2215   LanguageMode language_mode() const {
2216     return LoadICState::GetLanguageMode(MinorKey());
2217   }
2218
2219   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
2220 };
2221
2222
2223 class KeyedLoadGenericStub : public HydrogenCodeStub {
2224  public:
2225   explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
2226       : HydrogenCodeStub(isolate) {
2227     minor_key_ = state.GetExtraICState();
2228   }
2229
2230   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2231   InlineCacheState GetICState() const override { return GENERIC; }
2232
2233   LanguageMode language_mode() const {
2234     return LoadICState::GetLanguageMode(MinorKey());
2235   }
2236
2237   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2238
2239   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
2240 };
2241
2242
2243 class LoadICTrampolineStub : public PlatformCodeStub {
2244  public:
2245   LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2246       : PlatformCodeStub(isolate) {
2247     minor_key_ = state.GetExtraICState();
2248   }
2249
2250   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2251
2252   InlineCacheState GetICState() const final { return DEFAULT; }
2253
2254   ExtraICState GetExtraICState() const final {
2255     return static_cast<ExtraICState>(minor_key_);
2256   }
2257
2258  protected:
2259   LoadICState state() const {
2260     return LoadICState(static_cast<ExtraICState>(minor_key_));
2261   }
2262
2263   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2264   DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
2265 };
2266
2267
2268 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
2269  public:
2270   explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2271       : LoadICTrampolineStub(isolate, state) {}
2272
2273   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2274
2275   DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2276 };
2277
2278
2279 class VectorStoreICTrampolineStub : public PlatformCodeStub {
2280  public:
2281   VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2282       : PlatformCodeStub(isolate) {
2283     minor_key_ = state.GetExtraICState();
2284   }
2285
2286   Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
2287
2288   InlineCacheState GetICState() const final { return DEFAULT; }
2289
2290   ExtraICState GetExtraICState() const final {
2291     return static_cast<ExtraICState>(minor_key_);
2292   }
2293
2294  protected:
2295   StoreICState state() const {
2296     return StoreICState(static_cast<ExtraICState>(minor_key_));
2297   }
2298
2299  private:
2300   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
2301   DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
2302 };
2303
2304
2305 class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
2306  public:
2307   VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2308       : VectorStoreICTrampolineStub(isolate, state) {}
2309
2310   Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2311
2312   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
2313                             VectorStoreICTrampolineStub);
2314 };
2315
2316
2317 class CallICTrampolineStub : public PlatformCodeStub {
2318  public:
2319   CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2320       : PlatformCodeStub(isolate) {
2321     minor_key_ = state.GetExtraICState();
2322   }
2323
2324   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2325
2326   InlineCacheState GetICState() const final { return DEFAULT; }
2327
2328   ExtraICState GetExtraICState() const final {
2329     return static_cast<ExtraICState>(minor_key_);
2330   }
2331
2332  protected:
2333   CallICState state() const {
2334     return CallICState(static_cast<ExtraICState>(minor_key_));
2335   }
2336
2337   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2338   DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2339 };
2340
2341
2342 class CallIC_ArrayTrampolineStub : public CallICTrampolineStub {
2343  public:
2344   CallIC_ArrayTrampolineStub(Isolate* isolate, const CallICState& state)
2345       : CallICTrampolineStub(isolate, state) {}
2346
2347  private:
2348   DEFINE_PLATFORM_CODE_STUB(CallIC_ArrayTrampoline, CallICTrampolineStub);
2349 };
2350
2351
2352 class LoadICStub : public PlatformCodeStub {
2353  public:
2354   explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2355       : PlatformCodeStub(isolate) {
2356     minor_key_ = state.GetExtraICState();
2357   }
2358
2359   void GenerateForTrampoline(MacroAssembler* masm);
2360
2361   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2362   InlineCacheState GetICState() const final { return DEFAULT; }
2363   ExtraICState GetExtraICState() const final {
2364     return static_cast<ExtraICState>(minor_key_);
2365   }
2366
2367   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2368   DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2369
2370  protected:
2371   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2372 };
2373
2374
2375 class KeyedLoadICStub : public PlatformCodeStub {
2376  public:
2377   explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
2378       : PlatformCodeStub(isolate) {
2379     minor_key_ = state.GetExtraICState();
2380   }
2381
2382   void GenerateForTrampoline(MacroAssembler* masm);
2383
2384   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2385   InlineCacheState GetICState() const final { return DEFAULT; }
2386   ExtraICState GetExtraICState() const final {
2387     return static_cast<ExtraICState>(minor_key_);
2388   }
2389
2390   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2391   DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2392
2393  protected:
2394   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2395 };
2396
2397
2398 class VectorStoreICStub : public PlatformCodeStub {
2399  public:
2400   VectorStoreICStub(Isolate* isolate, const StoreICState& state)
2401       : PlatformCodeStub(isolate) {
2402     minor_key_ = state.GetExtraICState();
2403   }
2404
2405   void GenerateForTrampoline(MacroAssembler* masm);
2406
2407   Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2408   InlineCacheState GetICState() const final { return DEFAULT; }
2409   ExtraICState GetExtraICState() const final {
2410     return static_cast<ExtraICState>(minor_key_);
2411   }
2412
2413   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2414   DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);
2415
2416  protected:
2417   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2418 };
2419
2420
2421 class VectorKeyedStoreICStub : public PlatformCodeStub {
2422  public:
2423   VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2424       : PlatformCodeStub(isolate) {
2425     minor_key_ = state.GetExtraICState();
2426   }
2427
2428   void GenerateForTrampoline(MacroAssembler* masm);
2429
2430   Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2431   InlineCacheState GetICState() const final { return DEFAULT; }
2432   virtual ExtraICState GetExtraICState() const final {
2433     return static_cast<ExtraICState>(minor_key_);
2434   }
2435
2436   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2437   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
2438
2439  protected:
2440   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2441 };
2442
2443
2444 class DoubleToIStub : public PlatformCodeStub {
2445  public:
2446   DoubleToIStub(Isolate* isolate, Register source, Register destination,
2447                 int offset, bool is_truncating, bool skip_fastpath = false)
2448       : PlatformCodeStub(isolate) {
2449     minor_key_ = SourceRegisterBits::encode(source.code()) |
2450                  DestinationRegisterBits::encode(destination.code()) |
2451                  OffsetBits::encode(offset) |
2452                  IsTruncatingBits::encode(is_truncating) |
2453                  SkipFastPathBits::encode(skip_fastpath) |
2454                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2455   }
2456
2457   bool SometimesSetsUpAFrame() override { return false; }
2458
2459  private:
2460   Register source() const {
2461     return Register::from_code(SourceRegisterBits::decode(minor_key_));
2462   }
2463   Register destination() const {
2464     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2465   }
2466   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
2467   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
2468   int offset() const { return OffsetBits::decode(minor_key_); }
2469
2470   static const int kBitsPerRegisterNumber = 6;
2471   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2472   class SourceRegisterBits:
2473       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
2474   class DestinationRegisterBits:
2475       public BitField<int, kBitsPerRegisterNumber,
2476         kBitsPerRegisterNumber> {};  // NOLINT
2477   class IsTruncatingBits:
2478       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
2479   class OffsetBits:
2480       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
2481   class SkipFastPathBits:
2482       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
2483   class SSE3Bits:
2484       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
2485
2486   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2487   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2488 };
2489
2490
2491 class ScriptContextFieldStub : public HandlerStub {
2492  public:
2493   ScriptContextFieldStub(Isolate* isolate,
2494                          const ScriptContextTable::LookupResult* lookup_result)
2495       : HandlerStub(isolate) {
2496     DCHECK(Accepted(lookup_result));
2497     set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
2498                       SlotIndexBits::encode(lookup_result->slot_index));
2499   }
2500
2501   int context_index() const {
2502     return ContextIndexBits::decode(sub_minor_key());
2503   }
2504
2505   int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2506
2507   static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2508     return ContextIndexBits::is_valid(lookup_result->context_index) &&
2509            SlotIndexBits::is_valid(lookup_result->slot_index);
2510   }
2511
2512  private:
2513   static const int kContextIndexBits = 13;
2514   static const int kSlotIndexBits = 13;
2515   class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2516   class SlotIndexBits
2517       : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2518
2519   Code::StubType GetStubType() const override { return Code::FAST; }
2520
2521   DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2522 };
2523
2524
2525 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2526  public:
2527   LoadScriptContextFieldStub(
2528       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2529       : ScriptContextFieldStub(isolate, lookup_result) {}
2530
2531  private:
2532   Code::Kind kind() const override { return Code::LOAD_IC; }
2533
2534   DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2535 };
2536
2537
2538 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2539  public:
2540   StoreScriptContextFieldStub(
2541       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2542       : ScriptContextFieldStub(isolate, lookup_result) {}
2543
2544  private:
2545   Code::Kind kind() const override { return Code::STORE_IC; }
2546
2547   DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2548 };
2549
2550
2551 class LoadFastElementStub : public HandlerStub {
2552  public:
2553   LoadFastElementStub(Isolate* isolate, bool is_js_array,
2554                       ElementsKind elements_kind,
2555                       bool convert_hole_to_undefined = false)
2556       : HandlerStub(isolate) {
2557     set_sub_minor_key(
2558         ElementsKindBits::encode(elements_kind) |
2559         IsJSArrayBits::encode(is_js_array) |
2560         CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2561   }
2562
2563   Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2564
2565   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2566   bool convert_hole_to_undefined() const {
2567     return CanConvertHoleToUndefined::decode(sub_minor_key());
2568   }
2569
2570   ElementsKind elements_kind() const {
2571     return ElementsKindBits::decode(sub_minor_key());
2572   }
2573
2574  private:
2575   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2576   class IsJSArrayBits: public BitField<bool, 8, 1> {};
2577   class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2578
2579   DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
2580 };
2581
2582
2583 class StoreFastElementStub : public HydrogenCodeStub {
2584  public:
2585   StoreFastElementStub(Isolate* isolate, bool is_js_array,
2586                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
2587       : HydrogenCodeStub(isolate) {
2588     set_sub_minor_key(CommonStoreModeBits::encode(mode) |
2589                       ElementsKindBits::encode(elements_kind) |
2590                       IsJSArrayBits::encode(is_js_array));
2591   }
2592
2593   static void GenerateAheadOfTime(Isolate* isolate);
2594
2595   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2596
2597   ElementsKind elements_kind() const {
2598     return ElementsKindBits::decode(sub_minor_key());
2599   }
2600
2601   KeyedAccessStoreMode store_mode() const {
2602     return CommonStoreModeBits::decode(sub_minor_key());
2603   }
2604
2605   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2606     if (FLAG_vector_stores) {
2607       return VectorStoreICDescriptor(isolate());
2608     }
2609     return StoreDescriptor(isolate());
2610   }
2611
2612   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2613
2614  private:
2615   class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2616   class IsJSArrayBits : public BitField<bool, 11, 1> {};
2617
2618   DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2619 };
2620
2621
2622 class TransitionElementsKindStub : public HydrogenCodeStub {
2623  public:
2624   TransitionElementsKindStub(Isolate* isolate,
2625                              ElementsKind from_kind,
2626                              ElementsKind to_kind,
2627                              bool is_js_array) : HydrogenCodeStub(isolate) {
2628     set_sub_minor_key(FromKindBits::encode(from_kind) |
2629                       ToKindBits::encode(to_kind) |
2630                       IsJSArrayBits::encode(is_js_array));
2631   }
2632
2633   ElementsKind from_kind() const {
2634     return FromKindBits::decode(sub_minor_key());
2635   }
2636
2637   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2638
2639   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2640
2641  private:
2642   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2643   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2644   class IsJSArrayBits: public BitField<bool, 16, 1> {};
2645
2646   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2647   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2648 };
2649
2650
2651 class AllocateHeapNumberStub final : public HydrogenCodeStub {
2652  public:
2653   explicit AllocateHeapNumberStub(Isolate* isolate)
2654       : HydrogenCodeStub(isolate) {}
2655
2656  private:
2657   DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2658   DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2659 };
2660
2661
2662 class ArrayConstructorStubBase : public HydrogenCodeStub {
2663  public:
2664   ArrayConstructorStubBase(Isolate* isolate,
2665                            ElementsKind kind,
2666                            AllocationSiteOverrideMode override_mode)
2667       : HydrogenCodeStub(isolate) {
2668     // It only makes sense to override local allocation site behavior
2669     // if there is a difference between the global allocation site policy
2670     // for an ElementsKind and the desired usage of the stub.
2671     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2672            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2673     set_sub_minor_key(ElementsKindBits::encode(kind) |
2674                       AllocationSiteOverrideModeBits::encode(override_mode));
2675   }
2676
2677   ElementsKind elements_kind() const {
2678     return ElementsKindBits::decode(sub_minor_key());
2679   }
2680
2681   AllocationSiteOverrideMode override_mode() const {
2682     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2683   }
2684
2685   static void GenerateStubsAheadOfTime(Isolate* isolate);
2686
2687   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2688   static const int kConstructor = 0;
2689   static const int kAllocationSite = 1;
2690
2691  protected:
2692   std::ostream& BasePrintName(std::ostream& os,
2693                               const char* name) const;  // NOLINT
2694
2695  private:
2696   // Ensure data fits within available bits.
2697   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2698
2699   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2700   class AllocationSiteOverrideModeBits: public
2701       BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2702
2703   DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2704 };
2705
2706
2707 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2708  public:
2709   ArrayNoArgumentConstructorStub(
2710       Isolate* isolate,
2711       ElementsKind kind,
2712       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2713       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2714   }
2715
2716  private:
2717   void PrintName(std::ostream& os) const override {  // NOLINT
2718     BasePrintName(os, "ArrayNoArgumentConstructorStub");
2719   }
2720
2721   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2722   DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2723                             ArrayConstructorStubBase);
2724 };
2725
2726
2727 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2728  public:
2729   ArraySingleArgumentConstructorStub(
2730       Isolate* isolate,
2731       ElementsKind kind,
2732       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2733       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2734   }
2735
2736  private:
2737   void PrintName(std::ostream& os) const override {  // NOLINT
2738     BasePrintName(os, "ArraySingleArgumentConstructorStub");
2739   }
2740
2741   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2742   DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2743                             ArrayConstructorStubBase);
2744 };
2745
2746
2747 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2748  public:
2749   ArrayNArgumentsConstructorStub(
2750       Isolate* isolate,
2751       ElementsKind kind,
2752       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2753       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2754   }
2755
2756  private:
2757   void PrintName(std::ostream& os) const override {  // NOLINT
2758     BasePrintName(os, "ArrayNArgumentsConstructorStub");
2759   }
2760
2761   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2762   DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2763                             ArrayConstructorStubBase);
2764 };
2765
2766
2767 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2768  public:
2769   InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2770       : HydrogenCodeStub(isolate) {
2771     set_sub_minor_key(ElementsKindBits::encode(kind));
2772   }
2773
2774   static void GenerateStubsAheadOfTime(Isolate* isolate);
2775
2776   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2777   static const int kConstructor = 0;
2778
2779   ElementsKind elements_kind() const {
2780     return ElementsKindBits::decode(sub_minor_key());
2781   }
2782
2783  private:
2784   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2785
2786   DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2787 };
2788
2789
2790 class InternalArrayNoArgumentConstructorStub : public
2791     InternalArrayConstructorStubBase {
2792  public:
2793   InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2794                                          ElementsKind kind)
2795       : InternalArrayConstructorStubBase(isolate, kind) { }
2796
2797   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2798   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2799                             InternalArrayConstructorStubBase);
2800 };
2801
2802
2803 class InternalArraySingleArgumentConstructorStub : public
2804     InternalArrayConstructorStubBase {
2805  public:
2806   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2807                                              ElementsKind kind)
2808       : InternalArrayConstructorStubBase(isolate, kind) { }
2809
2810   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2811   DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2812                             InternalArrayConstructorStubBase);
2813 };
2814
2815
2816 class InternalArrayNArgumentsConstructorStub : public
2817     InternalArrayConstructorStubBase {
2818  public:
2819   InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2820       : InternalArrayConstructorStubBase(isolate, kind) { }
2821
2822   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2823   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2824                             InternalArrayConstructorStubBase);
2825 };
2826
2827
2828 class StoreElementStub : public PlatformCodeStub {
2829  public:
2830   StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
2831                    KeyedAccessStoreMode mode)
2832       : PlatformCodeStub(isolate) {
2833     minor_key_ = ElementsKindBits::encode(elements_kind) |
2834                  CommonStoreModeBits::encode(mode);
2835   }
2836
2837   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2838     if (FLAG_vector_stores) {
2839       return VectorStoreICDescriptor(isolate());
2840     }
2841     return StoreDescriptor(isolate());
2842   }
2843
2844   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2845
2846  private:
2847   ElementsKind elements_kind() const {
2848     return ElementsKindBits::decode(minor_key_);
2849   }
2850
2851   class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2852
2853   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2854 };
2855
2856
2857 class ToBooleanStub: public HydrogenCodeStub {
2858  public:
2859   enum Type {
2860     UNDEFINED,
2861     BOOLEAN,
2862     NULL_TYPE,
2863     SMI,
2864     SPEC_OBJECT,
2865     STRING,
2866     SYMBOL,
2867     HEAP_NUMBER,
2868     SIMD_VALUE,
2869     NUMBER_OF_TYPES
2870   };
2871
2872   enum ResultMode {
2873     RESULT_AS_SMI,             // For Smi(1) on truthy value, Smi(0) otherwise.
2874     RESULT_AS_ODDBALL,         // For {true} on truthy value, {false} otherwise.
2875     RESULT_AS_INVERSE_ODDBALL  // For {false} on truthy value, {true} otherwise.
2876   };
2877
2878   // At most 16 different types can be distinguished, because the Code object
2879   // only has room for two bytes to hold a set of these types. :-P
2880   STATIC_ASSERT(NUMBER_OF_TYPES <= 16);
2881
2882   class Types : public EnumSet<Type, uint16_t> {
2883    public:
2884     Types() : EnumSet<Type, uint16_t>(0) {}
2885     explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
2886
2887     bool UpdateStatus(Handle<Object> object);
2888     bool NeedsMap() const;
2889     bool CanBeUndetectable() const {
2890       return Contains(ToBooleanStub::SPEC_OBJECT);
2891     }
2892     bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2893
2894     static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2895   };
2896
2897   ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2898       : HydrogenCodeStub(isolate) {
2899     set_sub_minor_key(TypesBits::encode(types.ToIntegral()) |
2900                       ResultModeBits::encode(mode));
2901   }
2902
2903   ToBooleanStub(Isolate* isolate, ExtraICState state)
2904       : HydrogenCodeStub(isolate) {
2905     set_sub_minor_key(TypesBits::encode(static_cast<uint16_t>(state)) |
2906                       ResultModeBits::encode(RESULT_AS_SMI));
2907   }
2908
2909   bool UpdateStatus(Handle<Object> object);
2910   Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2911   ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2912
2913   Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2914   void PrintState(std::ostream& os) const override;  // NOLINT
2915
2916   bool SometimesSetsUpAFrame() override { return false; }
2917
2918   static Handle<Code> GetUninitialized(Isolate* isolate) {
2919     return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2920   }
2921
2922   ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
2923
2924   InlineCacheState GetICState() const override {
2925     if (types().IsEmpty()) {
2926       return ::v8::internal::UNINITIALIZED;
2927     } else {
2928       return MONOMORPHIC;
2929     }
2930   }
2931
2932  private:
2933   ToBooleanStub(Isolate* isolate, InitializationState init_state)
2934       : HydrogenCodeStub(isolate, init_state) {
2935     set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2936   }
2937
2938   class TypesBits : public BitField<uint16_t, 0, NUMBER_OF_TYPES> {};
2939   class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2940
2941   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2942   DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2943 };
2944
2945
2946 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
2947
2948
2949 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2950  public:
2951   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2952                                  ElementsKind to_kind, bool is_jsarray,
2953                                  KeyedAccessStoreMode store_mode)
2954       : HydrogenCodeStub(isolate) {
2955     set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
2956                       FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2957                       IsJSArrayBits::encode(is_jsarray));
2958   }
2959
2960   ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2961   ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2962   bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2963   KeyedAccessStoreMode store_mode() const {
2964     return CommonStoreModeBits::decode(sub_minor_key());
2965   }
2966
2967   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
2968   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2969
2970  private:
2971   class FromBits : public BitField<ElementsKind, 3, 8> {};
2972   class ToBits : public BitField<ElementsKind, 11, 8> {};
2973   class IsJSArrayBits : public BitField<bool, 19, 1> {};
2974
2975   DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2976 };
2977
2978
2979 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2980  public:
2981   explicit StoreArrayLiteralElementStub(Isolate* isolate)
2982       : PlatformCodeStub(isolate) { }
2983
2984   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2985   DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2986 };
2987
2988
2989 class StubFailureTrampolineStub : public PlatformCodeStub {
2990  public:
2991   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2992       : PlatformCodeStub(isolate) {
2993     minor_key_ = FunctionModeField::encode(function_mode);
2994   }
2995
2996   static void GenerateAheadOfTime(Isolate* isolate);
2997
2998  private:
2999   StubFunctionMode function_mode() const {
3000     return FunctionModeField::decode(minor_key_);
3001   }
3002
3003   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
3004
3005   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
3006   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
3007 };
3008
3009
3010 class ProfileEntryHookStub : public PlatformCodeStub {
3011  public:
3012   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3013
3014   // The profile entry hook function is not allowed to cause a GC.
3015   bool SometimesSetsUpAFrame() override { return false; }
3016
3017   // Generates a call to the entry hook if it's enabled.
3018   static void MaybeCallEntryHook(MacroAssembler* masm);
3019
3020  private:
3021   static void EntryHookTrampoline(intptr_t function,
3022                                   intptr_t stack_pointer,
3023                                   Isolate* isolate);
3024
3025   // ProfileEntryHookStub is called at the start of a function, so it has the
3026   // same register set.
3027   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
3028   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
3029 };
3030
3031
3032 class StoreBufferOverflowStub : public PlatformCodeStub {
3033  public:
3034   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
3035       : PlatformCodeStub(isolate) {
3036     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
3037   }
3038
3039   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
3040   bool SometimesSetsUpAFrame() override { return false; }
3041
3042  private:
3043   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
3044
3045   class SaveDoublesBits : public BitField<bool, 0, 1> {};
3046
3047   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
3048   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
3049 };
3050
3051
3052 class SubStringStub : public PlatformCodeStub {
3053  public:
3054   explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3055
3056   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
3057   DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
3058 };
3059
3060
3061 class ToNumberStub final : public PlatformCodeStub {
3062  public:
3063   explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3064
3065   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
3066   DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
3067 };
3068
3069
3070 class ToStringStub final : public PlatformCodeStub {
3071  public:
3072   explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3073
3074   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToString);
3075   DEFINE_PLATFORM_CODE_STUB(ToString, PlatformCodeStub);
3076 };
3077
3078
3079 class ToObjectStub final : public HydrogenCodeStub {
3080  public:
3081   explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
3082
3083   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
3084   DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
3085 };
3086
3087
3088 class StringCompareStub : public PlatformCodeStub {
3089  public:
3090   explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3091
3092   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
3093   DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
3094 };
3095
3096
3097 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
3098 #undef DEFINE_PLATFORM_CODE_STUB
3099 #undef DEFINE_HANDLER_CODE_STUB
3100 #undef DEFINE_HYDROGEN_CODE_STUB
3101 #undef DEFINE_CODE_STUB
3102 #undef DEFINE_CODE_STUB_BASE
3103
3104 extern Representation RepresentationFromType(Type* type);
3105 } }  // namespace v8::internal
3106
3107 #endif  // V8_CODE_STUBS_H_