bd7a3593338d0c3ffffcb829c5d760b937cf7444
[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 class CallFunctionStub: public PlatformCodeStub {
1957  public:
1958   CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1959       : PlatformCodeStub(isolate) {
1960     DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1961     minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1962   }
1963
1964  private:
1965   int argc() const { return ArgcBits::decode(minor_key_); }
1966   int flags() const { return FlagBits::decode(minor_key_); }
1967
1968   bool CallAsMethod() const {
1969     return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1970   }
1971
1972   bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1973
1974   void PrintName(std::ostream& os) const override;  // NOLINT
1975
1976   // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1977   class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1978   class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1979   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1980
1981   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1982   DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1983 };
1984
1985
1986 class CallConstructStub: public PlatformCodeStub {
1987  public:
1988   CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1989       : PlatformCodeStub(isolate) {
1990     minor_key_ = FlagBits::encode(flags);
1991   }
1992
1993   void FinishCode(Handle<Code> code) override {
1994     code->set_has_function_cache(RecordCallTarget());
1995   }
1996
1997  private:
1998   CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
1999
2000   bool RecordCallTarget() const {
2001     return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
2002   }
2003
2004   bool IsSuperConstructorCall() const {
2005     return (flags() & SUPER_CONSTRUCTOR_CALL) != 0;
2006   }
2007
2008   void PrintName(std::ostream& os) const override;  // NOLINT
2009
2010   class FlagBits : public BitField<CallConstructorFlags, 0, 2> {};
2011
2012   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
2013   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
2014 };
2015
2016
2017 enum StringIndexFlags {
2018   // Accepts smis or heap numbers.
2019   STRING_INDEX_IS_NUMBER,
2020
2021   // Accepts smis or heap numbers that are valid array indices
2022   // (ECMA-262 15.4). Invalid indices are reported as being out of
2023   // range.
2024   STRING_INDEX_IS_ARRAY_INDEX
2025 };
2026
2027
2028 enum ReceiverCheckMode {
2029   // We don't know anything about the receiver.
2030   RECEIVER_IS_UNKNOWN,
2031
2032   // We know the receiver is a string.
2033   RECEIVER_IS_STRING
2034 };
2035
2036
2037 enum EmbedMode {
2038   // The code being generated is part of an IC handler, which may MISS
2039   // to an IC in failure cases.
2040   PART_OF_IC_HANDLER,
2041
2042   NOT_PART_OF_IC_HANDLER
2043 };
2044
2045
2046 // Generates code implementing String.prototype.charCodeAt.
2047 //
2048 // Only supports the case when the receiver is a string and the index
2049 // is a number (smi or heap number) that is a valid index into the
2050 // string. Additional index constraints are specified by the
2051 // flags. Otherwise, bails out to the provided labels.
2052 //
2053 // Register usage: |object| may be changed to another string in a way
2054 // that doesn't affect charCodeAt/charAt semantics, |index| is
2055 // preserved, |scratch| and |result| are clobbered.
2056 class StringCharCodeAtGenerator {
2057  public:
2058   StringCharCodeAtGenerator(Register object, Register index, Register result,
2059                             Label* receiver_not_string, Label* index_not_number,
2060                             Label* index_out_of_range,
2061                             StringIndexFlags index_flags,
2062                             ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2063       : object_(object),
2064         index_(index),
2065         result_(result),
2066         receiver_not_string_(receiver_not_string),
2067         index_not_number_(index_not_number),
2068         index_out_of_range_(index_out_of_range),
2069         index_flags_(index_flags),
2070         check_mode_(check_mode) {
2071     DCHECK(!result_.is(object_));
2072     DCHECK(!result_.is(index_));
2073   }
2074
2075   // Generates the fast case code. On the fallthrough path |result|
2076   // register contains the result.
2077   void GenerateFast(MacroAssembler* masm);
2078
2079   // Generates the slow case code. Must not be naturally
2080   // reachable. Expected to be put after a ret instruction (e.g., in
2081   // deferred code). Always jumps back to the fast case.
2082   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2083                     const RuntimeCallHelper& call_helper);
2084
2085   // Skip handling slow case and directly jump to bailout.
2086   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2087     masm->bind(&index_not_smi_);
2088     masm->bind(&call_runtime_);
2089     masm->jmp(bailout);
2090   }
2091
2092  private:
2093   Register object_;
2094   Register index_;
2095   Register result_;
2096
2097   Label* receiver_not_string_;
2098   Label* index_not_number_;
2099   Label* index_out_of_range_;
2100
2101   StringIndexFlags index_flags_;
2102   ReceiverCheckMode check_mode_;
2103
2104   Label call_runtime_;
2105   Label index_not_smi_;
2106   Label got_smi_index_;
2107   Label exit_;
2108
2109   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
2110 };
2111
2112
2113 // Generates code for creating a one-char string from a char code.
2114 class StringCharFromCodeGenerator {
2115  public:
2116   StringCharFromCodeGenerator(Register code,
2117                               Register result)
2118       : code_(code),
2119         result_(result) {
2120     DCHECK(!code_.is(result_));
2121   }
2122
2123   // Generates the fast case code. On the fallthrough path |result|
2124   // register contains the result.
2125   void GenerateFast(MacroAssembler* masm);
2126
2127   // Generates the slow case code. Must not be naturally
2128   // reachable. Expected to be put after a ret instruction (e.g., in
2129   // deferred code). Always jumps back to the fast case.
2130   void GenerateSlow(MacroAssembler* masm,
2131                     const RuntimeCallHelper& call_helper);
2132
2133   // Skip handling slow case and directly jump to bailout.
2134   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2135     masm->bind(&slow_case_);
2136     masm->jmp(bailout);
2137   }
2138
2139  private:
2140   Register code_;
2141   Register result_;
2142
2143   Label slow_case_;
2144   Label exit_;
2145
2146   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
2147 };
2148
2149
2150 // Generates code implementing String.prototype.charAt.
2151 //
2152 // Only supports the case when the receiver is a string and the index
2153 // is a number (smi or heap number) that is a valid index into the
2154 // string. Additional index constraints are specified by the
2155 // flags. Otherwise, bails out to the provided labels.
2156 //
2157 // Register usage: |object| may be changed to another string in a way
2158 // that doesn't affect charCodeAt/charAt semantics, |index| is
2159 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
2160 class StringCharAtGenerator {
2161  public:
2162   StringCharAtGenerator(Register object, Register index, Register scratch,
2163                         Register result, Label* receiver_not_string,
2164                         Label* index_not_number, Label* index_out_of_range,
2165                         StringIndexFlags index_flags,
2166                         ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2167       : char_code_at_generator_(object, index, scratch, receiver_not_string,
2168                                 index_not_number, index_out_of_range,
2169                                 index_flags, check_mode),
2170         char_from_code_generator_(scratch, result) {}
2171
2172   // Generates the fast case code. On the fallthrough path |result|
2173   // register contains the result.
2174   void GenerateFast(MacroAssembler* masm) {
2175     char_code_at_generator_.GenerateFast(masm);
2176     char_from_code_generator_.GenerateFast(masm);
2177   }
2178
2179   // Generates the slow case code. Must not be naturally
2180   // reachable. Expected to be put after a ret instruction (e.g., in
2181   // deferred code). Always jumps back to the fast case.
2182   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2183                     const RuntimeCallHelper& call_helper) {
2184     char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
2185     char_from_code_generator_.GenerateSlow(masm, call_helper);
2186   }
2187
2188   // Skip handling slow case and directly jump to bailout.
2189   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2190     char_code_at_generator_.SkipSlow(masm, bailout);
2191     char_from_code_generator_.SkipSlow(masm, bailout);
2192   }
2193
2194  private:
2195   StringCharCodeAtGenerator char_code_at_generator_;
2196   StringCharFromCodeGenerator char_from_code_generator_;
2197
2198   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
2199 };
2200
2201
2202 class LoadDictionaryElementStub : public HydrogenCodeStub {
2203  public:
2204   explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
2205       : HydrogenCodeStub(isolate) {
2206     minor_key_ = state.GetExtraICState();
2207   }
2208
2209   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2210     return LoadWithVectorDescriptor(isolate());
2211   }
2212
2213   LanguageMode language_mode() const {
2214     return LoadICState::GetLanguageMode(MinorKey());
2215   }
2216
2217   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
2218 };
2219
2220
2221 class KeyedLoadGenericStub : public HydrogenCodeStub {
2222  public:
2223   explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
2224       : HydrogenCodeStub(isolate) {
2225     minor_key_ = state.GetExtraICState();
2226   }
2227
2228   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2229   InlineCacheState GetICState() const override { return GENERIC; }
2230
2231   LanguageMode language_mode() const {
2232     return LoadICState::GetLanguageMode(MinorKey());
2233   }
2234
2235   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2236
2237   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
2238 };
2239
2240
2241 class LoadICTrampolineStub : public PlatformCodeStub {
2242  public:
2243   LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2244       : PlatformCodeStub(isolate) {
2245     minor_key_ = state.GetExtraICState();
2246   }
2247
2248   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2249
2250   InlineCacheState GetICState() const final { return DEFAULT; }
2251
2252   ExtraICState GetExtraICState() const final {
2253     return static_cast<ExtraICState>(minor_key_);
2254   }
2255
2256  protected:
2257   LoadICState state() const {
2258     return LoadICState(static_cast<ExtraICState>(minor_key_));
2259   }
2260
2261   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2262   DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
2263 };
2264
2265
2266 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
2267  public:
2268   explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2269       : LoadICTrampolineStub(isolate, state) {}
2270
2271   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2272
2273   DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2274 };
2275
2276
2277 class VectorStoreICTrampolineStub : public PlatformCodeStub {
2278  public:
2279   VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2280       : PlatformCodeStub(isolate) {
2281     minor_key_ = state.GetExtraICState();
2282   }
2283
2284   Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
2285
2286   InlineCacheState GetICState() const final { return DEFAULT; }
2287
2288   ExtraICState GetExtraICState() const final {
2289     return static_cast<ExtraICState>(minor_key_);
2290   }
2291
2292  protected:
2293   StoreICState state() const {
2294     return StoreICState(static_cast<ExtraICState>(minor_key_));
2295   }
2296
2297  private:
2298   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
2299   DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
2300 };
2301
2302
2303 class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
2304  public:
2305   VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2306       : VectorStoreICTrampolineStub(isolate, state) {}
2307
2308   Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2309
2310   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
2311                             VectorStoreICTrampolineStub);
2312 };
2313
2314
2315 class CallICTrampolineStub : public PlatformCodeStub {
2316  public:
2317   CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2318       : PlatformCodeStub(isolate) {
2319     minor_key_ = state.GetExtraICState();
2320   }
2321
2322   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2323
2324   InlineCacheState GetICState() const final { return DEFAULT; }
2325
2326   ExtraICState GetExtraICState() const final {
2327     return static_cast<ExtraICState>(minor_key_);
2328   }
2329
2330  protected:
2331   CallICState state() const {
2332     return CallICState(static_cast<ExtraICState>(minor_key_));
2333   }
2334
2335   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2336   DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2337 };
2338
2339
2340 class CallIC_ArrayTrampolineStub : public CallICTrampolineStub {
2341  public:
2342   CallIC_ArrayTrampolineStub(Isolate* isolate, const CallICState& state)
2343       : CallICTrampolineStub(isolate, state) {}
2344
2345  private:
2346   DEFINE_PLATFORM_CODE_STUB(CallIC_ArrayTrampoline, CallICTrampolineStub);
2347 };
2348
2349
2350 class LoadICStub : public PlatformCodeStub {
2351  public:
2352   explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2353       : PlatformCodeStub(isolate) {
2354     minor_key_ = state.GetExtraICState();
2355   }
2356
2357   void GenerateForTrampoline(MacroAssembler* masm);
2358
2359   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2360   InlineCacheState GetICState() const final { return DEFAULT; }
2361   ExtraICState GetExtraICState() const final {
2362     return static_cast<ExtraICState>(minor_key_);
2363   }
2364
2365   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2366   DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2367
2368  protected:
2369   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2370 };
2371
2372
2373 class KeyedLoadICStub : public PlatformCodeStub {
2374  public:
2375   explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
2376       : PlatformCodeStub(isolate) {
2377     minor_key_ = state.GetExtraICState();
2378   }
2379
2380   void GenerateForTrampoline(MacroAssembler* masm);
2381
2382   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2383   InlineCacheState GetICState() const final { return DEFAULT; }
2384   ExtraICState GetExtraICState() const final {
2385     return static_cast<ExtraICState>(minor_key_);
2386   }
2387
2388   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2389   DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2390
2391  protected:
2392   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2393 };
2394
2395
2396 class VectorStoreICStub : public PlatformCodeStub {
2397  public:
2398   VectorStoreICStub(Isolate* isolate, const StoreICState& state)
2399       : PlatformCodeStub(isolate) {
2400     minor_key_ = state.GetExtraICState();
2401   }
2402
2403   void GenerateForTrampoline(MacroAssembler* masm);
2404
2405   Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2406   InlineCacheState GetICState() const final { return DEFAULT; }
2407   ExtraICState GetExtraICState() const final {
2408     return static_cast<ExtraICState>(minor_key_);
2409   }
2410
2411   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2412   DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);
2413
2414  protected:
2415   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2416 };
2417
2418
2419 class VectorKeyedStoreICStub : public PlatformCodeStub {
2420  public:
2421   VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2422       : PlatformCodeStub(isolate) {
2423     minor_key_ = state.GetExtraICState();
2424   }
2425
2426   void GenerateForTrampoline(MacroAssembler* masm);
2427
2428   Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2429   InlineCacheState GetICState() const final { return DEFAULT; }
2430   virtual ExtraICState GetExtraICState() const final {
2431     return static_cast<ExtraICState>(minor_key_);
2432   }
2433
2434   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2435   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
2436
2437  protected:
2438   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2439 };
2440
2441
2442 class DoubleToIStub : public PlatformCodeStub {
2443  public:
2444   DoubleToIStub(Isolate* isolate, Register source, Register destination,
2445                 int offset, bool is_truncating, bool skip_fastpath = false)
2446       : PlatformCodeStub(isolate) {
2447     minor_key_ = SourceRegisterBits::encode(source.code()) |
2448                  DestinationRegisterBits::encode(destination.code()) |
2449                  OffsetBits::encode(offset) |
2450                  IsTruncatingBits::encode(is_truncating) |
2451                  SkipFastPathBits::encode(skip_fastpath) |
2452                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2453   }
2454
2455   bool SometimesSetsUpAFrame() override { return false; }
2456
2457  private:
2458   Register source() const {
2459     return Register::from_code(SourceRegisterBits::decode(minor_key_));
2460   }
2461   Register destination() const {
2462     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2463   }
2464   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
2465   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
2466   int offset() const { return OffsetBits::decode(minor_key_); }
2467
2468   static const int kBitsPerRegisterNumber = 6;
2469   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2470   class SourceRegisterBits:
2471       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
2472   class DestinationRegisterBits:
2473       public BitField<int, kBitsPerRegisterNumber,
2474         kBitsPerRegisterNumber> {};  // NOLINT
2475   class IsTruncatingBits:
2476       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
2477   class OffsetBits:
2478       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
2479   class SkipFastPathBits:
2480       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
2481   class SSE3Bits:
2482       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
2483
2484   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2485   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2486 };
2487
2488
2489 class ScriptContextFieldStub : public HandlerStub {
2490  public:
2491   ScriptContextFieldStub(Isolate* isolate,
2492                          const ScriptContextTable::LookupResult* lookup_result)
2493       : HandlerStub(isolate) {
2494     DCHECK(Accepted(lookup_result));
2495     set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
2496                       SlotIndexBits::encode(lookup_result->slot_index));
2497   }
2498
2499   int context_index() const {
2500     return ContextIndexBits::decode(sub_minor_key());
2501   }
2502
2503   int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2504
2505   static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2506     return ContextIndexBits::is_valid(lookup_result->context_index) &&
2507            SlotIndexBits::is_valid(lookup_result->slot_index);
2508   }
2509
2510  private:
2511   static const int kContextIndexBits = 13;
2512   static const int kSlotIndexBits = 13;
2513   class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2514   class SlotIndexBits
2515       : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2516
2517   Code::StubType GetStubType() const override { return Code::FAST; }
2518
2519   DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2520 };
2521
2522
2523 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2524  public:
2525   LoadScriptContextFieldStub(
2526       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2527       : ScriptContextFieldStub(isolate, lookup_result) {}
2528
2529  private:
2530   Code::Kind kind() const override { return Code::LOAD_IC; }
2531
2532   DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2533 };
2534
2535
2536 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2537  public:
2538   StoreScriptContextFieldStub(
2539       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2540       : ScriptContextFieldStub(isolate, lookup_result) {}
2541
2542  private:
2543   Code::Kind kind() const override { return Code::STORE_IC; }
2544
2545   DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2546 };
2547
2548
2549 class LoadFastElementStub : public HandlerStub {
2550  public:
2551   LoadFastElementStub(Isolate* isolate, bool is_js_array,
2552                       ElementsKind elements_kind,
2553                       bool convert_hole_to_undefined = false)
2554       : HandlerStub(isolate) {
2555     set_sub_minor_key(
2556         ElementsKindBits::encode(elements_kind) |
2557         IsJSArrayBits::encode(is_js_array) |
2558         CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2559   }
2560
2561   Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2562
2563   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2564   bool convert_hole_to_undefined() const {
2565     return CanConvertHoleToUndefined::decode(sub_minor_key());
2566   }
2567
2568   ElementsKind elements_kind() const {
2569     return ElementsKindBits::decode(sub_minor_key());
2570   }
2571
2572  private:
2573   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2574   class IsJSArrayBits: public BitField<bool, 8, 1> {};
2575   class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2576
2577   DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
2578 };
2579
2580
2581 class StoreFastElementStub : public HydrogenCodeStub {
2582  public:
2583   StoreFastElementStub(Isolate* isolate, bool is_js_array,
2584                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
2585       : HydrogenCodeStub(isolate) {
2586     set_sub_minor_key(CommonStoreModeBits::encode(mode) |
2587                       ElementsKindBits::encode(elements_kind) |
2588                       IsJSArrayBits::encode(is_js_array));
2589   }
2590
2591   static void GenerateAheadOfTime(Isolate* isolate);
2592
2593   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2594
2595   ElementsKind elements_kind() const {
2596     return ElementsKindBits::decode(sub_minor_key());
2597   }
2598
2599   KeyedAccessStoreMode store_mode() const {
2600     return CommonStoreModeBits::decode(sub_minor_key());
2601   }
2602
2603   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2604     if (FLAG_vector_stores) {
2605       return VectorStoreICDescriptor(isolate());
2606     }
2607     return StoreDescriptor(isolate());
2608   }
2609
2610   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2611
2612  private:
2613   class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2614   class IsJSArrayBits : public BitField<bool, 11, 1> {};
2615
2616   DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2617 };
2618
2619
2620 class TransitionElementsKindStub : public HydrogenCodeStub {
2621  public:
2622   TransitionElementsKindStub(Isolate* isolate,
2623                              ElementsKind from_kind,
2624                              ElementsKind to_kind,
2625                              bool is_js_array) : HydrogenCodeStub(isolate) {
2626     set_sub_minor_key(FromKindBits::encode(from_kind) |
2627                       ToKindBits::encode(to_kind) |
2628                       IsJSArrayBits::encode(is_js_array));
2629   }
2630
2631   ElementsKind from_kind() const {
2632     return FromKindBits::decode(sub_minor_key());
2633   }
2634
2635   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2636
2637   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2638
2639  private:
2640   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2641   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2642   class IsJSArrayBits: public BitField<bool, 16, 1> {};
2643
2644   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2645   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2646 };
2647
2648
2649 class AllocateHeapNumberStub final : public HydrogenCodeStub {
2650  public:
2651   explicit AllocateHeapNumberStub(Isolate* isolate)
2652       : HydrogenCodeStub(isolate) {}
2653
2654  private:
2655   DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2656   DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2657 };
2658
2659
2660 class ArrayConstructorStubBase : public HydrogenCodeStub {
2661  public:
2662   ArrayConstructorStubBase(Isolate* isolate,
2663                            ElementsKind kind,
2664                            AllocationSiteOverrideMode override_mode)
2665       : HydrogenCodeStub(isolate) {
2666     // It only makes sense to override local allocation site behavior
2667     // if there is a difference between the global allocation site policy
2668     // for an ElementsKind and the desired usage of the stub.
2669     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2670            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2671     set_sub_minor_key(ElementsKindBits::encode(kind) |
2672                       AllocationSiteOverrideModeBits::encode(override_mode));
2673   }
2674
2675   ElementsKind elements_kind() const {
2676     return ElementsKindBits::decode(sub_minor_key());
2677   }
2678
2679   AllocationSiteOverrideMode override_mode() const {
2680     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2681   }
2682
2683   static void GenerateStubsAheadOfTime(Isolate* isolate);
2684
2685   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2686   static const int kConstructor = 0;
2687   static const int kAllocationSite = 1;
2688
2689  protected:
2690   std::ostream& BasePrintName(std::ostream& os,
2691                               const char* name) const;  // NOLINT
2692
2693  private:
2694   // Ensure data fits within available bits.
2695   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2696
2697   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2698   class AllocationSiteOverrideModeBits: public
2699       BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2700
2701   DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2702 };
2703
2704
2705 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2706  public:
2707   ArrayNoArgumentConstructorStub(
2708       Isolate* isolate,
2709       ElementsKind kind,
2710       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2711       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2712   }
2713
2714  private:
2715   void PrintName(std::ostream& os) const override {  // NOLINT
2716     BasePrintName(os, "ArrayNoArgumentConstructorStub");
2717   }
2718
2719   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2720   DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2721                             ArrayConstructorStubBase);
2722 };
2723
2724
2725 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2726  public:
2727   ArraySingleArgumentConstructorStub(
2728       Isolate* isolate,
2729       ElementsKind kind,
2730       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2731       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2732   }
2733
2734  private:
2735   void PrintName(std::ostream& os) const override {  // NOLINT
2736     BasePrintName(os, "ArraySingleArgumentConstructorStub");
2737   }
2738
2739   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2740   DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2741                             ArrayConstructorStubBase);
2742 };
2743
2744
2745 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2746  public:
2747   ArrayNArgumentsConstructorStub(
2748       Isolate* isolate,
2749       ElementsKind kind,
2750       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2751       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2752   }
2753
2754  private:
2755   void PrintName(std::ostream& os) const override {  // NOLINT
2756     BasePrintName(os, "ArrayNArgumentsConstructorStub");
2757   }
2758
2759   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2760   DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2761                             ArrayConstructorStubBase);
2762 };
2763
2764
2765 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2766  public:
2767   InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2768       : HydrogenCodeStub(isolate) {
2769     set_sub_minor_key(ElementsKindBits::encode(kind));
2770   }
2771
2772   static void GenerateStubsAheadOfTime(Isolate* isolate);
2773
2774   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2775   static const int kConstructor = 0;
2776
2777   ElementsKind elements_kind() const {
2778     return ElementsKindBits::decode(sub_minor_key());
2779   }
2780
2781  private:
2782   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2783
2784   DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2785 };
2786
2787
2788 class InternalArrayNoArgumentConstructorStub : public
2789     InternalArrayConstructorStubBase {
2790  public:
2791   InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2792                                          ElementsKind kind)
2793       : InternalArrayConstructorStubBase(isolate, kind) { }
2794
2795   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2796   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2797                             InternalArrayConstructorStubBase);
2798 };
2799
2800
2801 class InternalArraySingleArgumentConstructorStub : public
2802     InternalArrayConstructorStubBase {
2803  public:
2804   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2805                                              ElementsKind kind)
2806       : InternalArrayConstructorStubBase(isolate, kind) { }
2807
2808   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2809   DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2810                             InternalArrayConstructorStubBase);
2811 };
2812
2813
2814 class InternalArrayNArgumentsConstructorStub : public
2815     InternalArrayConstructorStubBase {
2816  public:
2817   InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2818       : InternalArrayConstructorStubBase(isolate, kind) { }
2819
2820   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2821   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2822                             InternalArrayConstructorStubBase);
2823 };
2824
2825
2826 class StoreElementStub : public PlatformCodeStub {
2827  public:
2828   StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
2829                    KeyedAccessStoreMode mode)
2830       : PlatformCodeStub(isolate) {
2831     minor_key_ = ElementsKindBits::encode(elements_kind) |
2832                  CommonStoreModeBits::encode(mode);
2833   }
2834
2835   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2836     if (FLAG_vector_stores) {
2837       return VectorStoreICDescriptor(isolate());
2838     }
2839     return StoreDescriptor(isolate());
2840   }
2841
2842   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2843
2844  private:
2845   ElementsKind elements_kind() const {
2846     return ElementsKindBits::decode(minor_key_);
2847   }
2848
2849   class ElementsKindBits : public BitField<ElementsKind, 3, 8> {};
2850
2851   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2852 };
2853
2854
2855 class ToBooleanStub: public HydrogenCodeStub {
2856  public:
2857   enum Type {
2858     UNDEFINED,
2859     BOOLEAN,
2860     NULL_TYPE,
2861     SMI,
2862     SPEC_OBJECT,
2863     STRING,
2864     SYMBOL,
2865     HEAP_NUMBER,
2866     SIMD_VALUE,
2867     NUMBER_OF_TYPES
2868   };
2869
2870   enum ResultMode {
2871     RESULT_AS_SMI,             // For Smi(1) on truthy value, Smi(0) otherwise.
2872     RESULT_AS_ODDBALL,         // For {true} on truthy value, {false} otherwise.
2873     RESULT_AS_INVERSE_ODDBALL  // For {false} on truthy value, {true} otherwise.
2874   };
2875
2876   // At most 16 different types can be distinguished, because the Code object
2877   // only has room for two bytes to hold a set of these types. :-P
2878   STATIC_ASSERT(NUMBER_OF_TYPES <= 16);
2879
2880   class Types : public EnumSet<Type, uint16_t> {
2881    public:
2882     Types() : EnumSet<Type, uint16_t>(0) {}
2883     explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
2884
2885     bool UpdateStatus(Handle<Object> object);
2886     bool NeedsMap() const;
2887     bool CanBeUndetectable() const {
2888       return Contains(ToBooleanStub::SPEC_OBJECT);
2889     }
2890     bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2891
2892     static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2893   };
2894
2895   ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2896       : HydrogenCodeStub(isolate) {
2897     set_sub_minor_key(TypesBits::encode(types.ToIntegral()) |
2898                       ResultModeBits::encode(mode));
2899   }
2900
2901   ToBooleanStub(Isolate* isolate, ExtraICState state)
2902       : HydrogenCodeStub(isolate) {
2903     set_sub_minor_key(TypesBits::encode(static_cast<uint16_t>(state)) |
2904                       ResultModeBits::encode(RESULT_AS_SMI));
2905   }
2906
2907   bool UpdateStatus(Handle<Object> object);
2908   Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2909   ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2910
2911   Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2912   void PrintState(std::ostream& os) const override;  // NOLINT
2913
2914   bool SometimesSetsUpAFrame() override { return false; }
2915
2916   static Handle<Code> GetUninitialized(Isolate* isolate) {
2917     return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2918   }
2919
2920   ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
2921
2922   InlineCacheState GetICState() const override {
2923     if (types().IsEmpty()) {
2924       return ::v8::internal::UNINITIALIZED;
2925     } else {
2926       return MONOMORPHIC;
2927     }
2928   }
2929
2930  private:
2931   ToBooleanStub(Isolate* isolate, InitializationState init_state)
2932       : HydrogenCodeStub(isolate, init_state) {
2933     set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2934   }
2935
2936   class TypesBits : public BitField<uint16_t, 0, NUMBER_OF_TYPES> {};
2937   class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2938
2939   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2940   DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2941 };
2942
2943
2944 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
2945
2946
2947 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2948  public:
2949   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2950                                  ElementsKind to_kind, bool is_jsarray,
2951                                  KeyedAccessStoreMode store_mode)
2952       : HydrogenCodeStub(isolate) {
2953     set_sub_minor_key(CommonStoreModeBits::encode(store_mode) |
2954                       FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2955                       IsJSArrayBits::encode(is_jsarray));
2956   }
2957
2958   ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2959   ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2960   bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2961   KeyedAccessStoreMode store_mode() const {
2962     return CommonStoreModeBits::decode(sub_minor_key());
2963   }
2964
2965   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
2966   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2967
2968  private:
2969   class FromBits : public BitField<ElementsKind, 3, 8> {};
2970   class ToBits : public BitField<ElementsKind, 11, 8> {};
2971   class IsJSArrayBits : public BitField<bool, 19, 1> {};
2972
2973   DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2974 };
2975
2976
2977 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2978  public:
2979   explicit StoreArrayLiteralElementStub(Isolate* isolate)
2980       : PlatformCodeStub(isolate) { }
2981
2982   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2983   DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2984 };
2985
2986
2987 class StubFailureTrampolineStub : public PlatformCodeStub {
2988  public:
2989   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2990       : PlatformCodeStub(isolate) {
2991     minor_key_ = FunctionModeField::encode(function_mode);
2992   }
2993
2994   static void GenerateAheadOfTime(Isolate* isolate);
2995
2996  private:
2997   StubFunctionMode function_mode() const {
2998     return FunctionModeField::decode(minor_key_);
2999   }
3000
3001   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
3002
3003   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
3004   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
3005 };
3006
3007
3008 class ProfileEntryHookStub : public PlatformCodeStub {
3009  public:
3010   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3011
3012   // The profile entry hook function is not allowed to cause a GC.
3013   bool SometimesSetsUpAFrame() override { return false; }
3014
3015   // Generates a call to the entry hook if it's enabled.
3016   static void MaybeCallEntryHook(MacroAssembler* masm);
3017
3018  private:
3019   static void EntryHookTrampoline(intptr_t function,
3020                                   intptr_t stack_pointer,
3021                                   Isolate* isolate);
3022
3023   // ProfileEntryHookStub is called at the start of a function, so it has the
3024   // same register set.
3025   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
3026   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
3027 };
3028
3029
3030 class StoreBufferOverflowStub : public PlatformCodeStub {
3031  public:
3032   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
3033       : PlatformCodeStub(isolate) {
3034     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
3035   }
3036
3037   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
3038   bool SometimesSetsUpAFrame() override { return false; }
3039
3040  private:
3041   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
3042
3043   class SaveDoublesBits : public BitField<bool, 0, 1> {};
3044
3045   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
3046   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
3047 };
3048
3049
3050 class SubStringStub : public PlatformCodeStub {
3051  public:
3052   explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3053
3054   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
3055   DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
3056 };
3057
3058
3059 class ToNumberStub final : public PlatformCodeStub {
3060  public:
3061   explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3062
3063   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
3064   DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
3065 };
3066
3067
3068 class ToStringStub final : public PlatformCodeStub {
3069  public:
3070   explicit ToStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3071
3072   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToString);
3073   DEFINE_PLATFORM_CODE_STUB(ToString, PlatformCodeStub);
3074 };
3075
3076
3077 class ToObjectStub final : public HydrogenCodeStub {
3078  public:
3079   explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
3080
3081   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
3082   DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
3083 };
3084
3085
3086 class StringCompareStub : public PlatformCodeStub {
3087  public:
3088   explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3089
3090   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
3091   DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
3092 };
3093
3094
3095 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
3096 #undef DEFINE_PLATFORM_CODE_STUB
3097 #undef DEFINE_HANDLER_CODE_STUB
3098 #undef DEFINE_HYDROGEN_CODE_STUB
3099 #undef DEFINE_CODE_STUB
3100 #undef DEFINE_CODE_STUB_BASE
3101
3102 extern Representation RepresentationFromType(Type* type);
3103 } }  // namespace v8::internal
3104
3105 #endif  // V8_CODE_STUBS_H_