Correctify instanceof and make it optimizable.
[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(ToObject)                               \
58   V(VectorStoreICTrampoline)                \
59   V(VectorKeyedStoreICTrampoline)           \
60   V(VectorStoreIC)                          \
61   V(VectorKeyedStoreIC)                     \
62   /* HydrogenCodeStubs */                   \
63   V(AllocateHeapNumber)                     \
64   V(ArrayNArgumentsConstructor)             \
65   V(ArrayNoArgumentConstructor)             \
66   V(ArraySingleArgumentConstructor)         \
67   V(BinaryOpIC)                             \
68   V(BinaryOpWithAllocationSite)             \
69   V(CompareNilIC)                           \
70   V(CreateAllocationSite)                   \
71   V(CreateWeakCell)                         \
72   V(ElementsTransitionAndStore)             \
73   V(FastCloneShallowArray)                  \
74   V(FastCloneShallowObject)                 \
75   V(FastNewClosure)                         \
76   V(FastNewContext)                         \
77   V(GrowArrayElements)                      \
78   V(InternalArrayNArgumentsConstructor)     \
79   V(InternalArrayNoArgumentConstructor)     \
80   V(InternalArraySingleArgumentConstructor) \
81   V(KeyedLoadGeneric)                       \
82   V(LoadGlobalViaContext)                   \
83   V(LoadScriptContextField)                 \
84   V(LoadDictionaryElement)                  \
85   V(NameDictionaryLookup)                   \
86   V(NumberToString)                         \
87   V(Typeof)                                 \
88   V(RegExpConstructResult)                  \
89   V(StoreFastElement)                       \
90   V(StoreGlobalViaContext)                  \
91   V(StoreScriptContextField)                \
92   V(StringAdd)                              \
93   V(ToBoolean)                              \
94   V(TransitionElementsKind)                 \
95   V(KeyedLoadIC)                            \
96   V(LoadIC)                                 \
97   /* TurboFanCodeStubs */                   \
98   V(StringLengthTF)                         \
99   V(StringAddTF)                            \
100   /* TurboFanICs */                         \
101   V(MathFloor)                              \
102   /* IC Handler stubs */                    \
103   V(ArrayBufferViewLoadField)               \
104   V(LoadConstant)                           \
105   V(LoadFastElement)                        \
106   V(LoadField)                              \
107   V(KeyedLoadSloppyArguments)               \
108   V(KeyedStoreSloppyArguments)              \
109   V(StoreField)                             \
110   V(StoreGlobal)                            \
111   V(StoreTransition)                        \
112   V(StringLength)                           \
113   V(RestParamAccess)
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 KeyedStoreSloppyArgumentsStub : public HandlerStub {
1144  public:
1145   explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate)
1146       : HandlerStub(isolate) {}
1147
1148  protected:
1149   Code::Kind kind() const override { return Code::KEYED_STORE_IC; }
1150   Code::StubType GetStubType() const override { return Code::FAST; }
1151
1152  private:
1153   DEFINE_HANDLER_CODE_STUB(KeyedStoreSloppyArguments, HandlerStub);
1154 };
1155
1156
1157 class LoadConstantStub : public HandlerStub {
1158  public:
1159   LoadConstantStub(Isolate* isolate, int constant_index)
1160       : HandlerStub(isolate) {
1161     set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1162   }
1163
1164   int constant_index() const {
1165     return ConstantIndexBits::decode(sub_minor_key());
1166   }
1167
1168  protected:
1169   Code::Kind kind() const override { return Code::LOAD_IC; }
1170   Code::StubType GetStubType() const override { return Code::FAST; }
1171
1172  private:
1173   class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1174
1175   DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1176 };
1177
1178
1179 class StringLengthStub: public HandlerStub {
1180  public:
1181   explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
1182
1183  protected:
1184   Code::Kind kind() const override { return Code::LOAD_IC; }
1185   Code::StubType GetStubType() const override { return Code::FAST; }
1186
1187   DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
1188 };
1189
1190
1191 class StoreFieldStub : public HandlerStub {
1192  public:
1193   StoreFieldStub(Isolate* isolate, FieldIndex index,
1194                  Representation representation)
1195       : HandlerStub(isolate) {
1196     int property_index_key = index.GetFieldAccessStubKey();
1197     uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1198     set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1199                       RepresentationBits::encode(repr));
1200   }
1201
1202   FieldIndex index() const {
1203     int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1204     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1205   }
1206
1207   Representation representation() {
1208     uint8_t repr = RepresentationBits::decode(sub_minor_key());
1209     return PropertyDetails::DecodeRepresentation(repr);
1210   }
1211
1212  protected:
1213   Code::Kind kind() const override { return Code::STORE_IC; }
1214   Code::StubType GetStubType() const override { return Code::FAST; }
1215
1216  private:
1217   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1218   class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1219
1220   DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
1221 };
1222
1223
1224 // Register and parameter access methods are specified here instead of in
1225 // the CallInterfaceDescriptor because the stub uses a different descriptor
1226 // if FLAG_vector_stores is on.
1227 class StoreTransitionHelper {
1228  public:
1229   static Register ReceiverRegister() {
1230     return StoreTransitionDescriptor::ReceiverRegister();
1231   }
1232
1233   static Register NameRegister() {
1234     return StoreTransitionDescriptor::NameRegister();
1235   }
1236
1237   static Register ValueRegister() {
1238     return StoreTransitionDescriptor::ValueRegister();
1239   }
1240
1241   static Register SlotRegister() {
1242     DCHECK(FLAG_vector_stores);
1243     return VectorStoreTransitionDescriptor::SlotRegister();
1244   }
1245
1246   static Register VectorRegister() {
1247     DCHECK(FLAG_vector_stores);
1248     return VectorStoreTransitionDescriptor::VectorRegister();
1249   }
1250
1251   static Register MapRegister() {
1252     return FLAG_vector_stores ? VectorStoreTransitionDescriptor::MapRegister()
1253                               : StoreTransitionDescriptor::MapRegister();
1254   }
1255
1256   static int ReceiverIndex() {
1257     return StoreTransitionDescriptor::kReceiverIndex;
1258   }
1259
1260   static int NameIndex() { return StoreTransitionDescriptor::kReceiverIndex; }
1261
1262   static int ValueIndex() { return StoreTransitionDescriptor::kValueIndex; }
1263
1264   static int SlotIndex() {
1265     DCHECK(FLAG_vector_stores);
1266     return VectorStoreTransitionDescriptor::kSlotIndex;
1267   }
1268
1269   static int VectorIndex() {
1270     DCHECK(FLAG_vector_stores);
1271     return VectorStoreTransitionDescriptor::kVectorIndex;
1272   }
1273
1274   static int MapIndex() {
1275     if (FLAG_vector_stores) {
1276       return VectorStoreTransitionDescriptor::kMapIndex;
1277     }
1278     return StoreTransitionDescriptor::kMapIndex;
1279   }
1280
1281   // Some platforms push Slot, Vector, Map on the stack instead of in
1282   // registers.
1283   static bool UsesStackArgs() { return MapRegister().is(no_reg); }
1284 };
1285
1286
1287 class StoreTransitionStub : public HandlerStub {
1288  public:
1289   enum StoreMode {
1290     StoreMapOnly,
1291     StoreMapAndValue,
1292     ExtendStorageAndStoreMapAndValue
1293   };
1294
1295   explicit StoreTransitionStub(Isolate* isolate) : HandlerStub(isolate) {
1296     set_sub_minor_key(StoreModeBits::encode(StoreMapOnly));
1297   }
1298
1299   StoreTransitionStub(Isolate* isolate, FieldIndex index,
1300                       Representation representation, StoreMode store_mode)
1301       : HandlerStub(isolate) {
1302     DCHECK(store_mode != StoreMapOnly);
1303     int property_index_key = index.GetFieldAccessStubKey();
1304     uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
1305     set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
1306                       RepresentationBits::encode(repr) |
1307                       StoreModeBits::encode(store_mode));
1308   }
1309
1310   FieldIndex index() const {
1311     DCHECK(store_mode() != StoreMapOnly);
1312     int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
1313     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1314   }
1315
1316   Representation representation() {
1317     DCHECK(store_mode() != StoreMapOnly);
1318     uint8_t repr = RepresentationBits::decode(sub_minor_key());
1319     return PropertyDetails::DecodeRepresentation(repr);
1320   }
1321
1322   StoreMode store_mode() const {
1323     return StoreModeBits::decode(sub_minor_key());
1324   }
1325
1326   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1327
1328  protected:
1329   Code::Kind kind() const override { return Code::STORE_IC; }
1330   Code::StubType GetStubType() const override { return Code::FAST; }
1331
1332  private:
1333   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1334   class RepresentationBits : public BitField<uint8_t, 13, 4> {};
1335   class StoreModeBits : public BitField<StoreMode, 17, 2> {};
1336
1337   DEFINE_HANDLER_CODE_STUB(StoreTransition, HandlerStub);
1338 };
1339
1340
1341 class StoreGlobalStub : public HandlerStub {
1342  public:
1343   StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1344                   Maybe<PropertyCellConstantType> constant_type,
1345                   bool check_global)
1346       : HandlerStub(isolate) {
1347     PropertyCellConstantType encoded_constant_type =
1348         constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1349     set_sub_minor_key(CellTypeBits::encode(type) |
1350                       ConstantTypeBits::encode(encoded_constant_type) |
1351                       CheckGlobalBits::encode(check_global));
1352   }
1353
1354   static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
1355     return isolate->factory()->uninitialized_value();
1356   }
1357
1358   static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1359     return isolate->factory()->termination_exception();
1360   }
1361
1362   Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1363                                        Handle<PropertyCell> cell) {
1364     Code::FindAndReplacePattern pattern;
1365     if (check_global()) {
1366       pattern.Add(handle(global_map_placeholder(isolate())->map()),
1367                   Map::WeakCellForMap(Handle<Map>(global->map())));
1368     }
1369     pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1370                 isolate()->factory()->NewWeakCell(cell));
1371     return CodeStub::GetCodeCopy(pattern);
1372   }
1373
1374   Code::Kind kind() const override { return Code::STORE_IC; }
1375
1376   PropertyCellType cell_type() const {
1377     return CellTypeBits::decode(sub_minor_key());
1378   }
1379
1380   PropertyCellConstantType constant_type() const {
1381     DCHECK(PropertyCellType::kConstantType == cell_type());
1382     return ConstantTypeBits::decode(sub_minor_key());
1383   }
1384
1385   bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1386
1387   Representation representation() {
1388     return Representation::FromKind(
1389         RepresentationBits::decode(sub_minor_key()));
1390   }
1391
1392   void set_representation(Representation r) {
1393     set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1394   }
1395
1396  private:
1397   class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1398   class ConstantTypeBits : public BitField<PropertyCellConstantType, 2, 2> {};
1399   class RepresentationBits : public BitField<Representation::Kind, 4, 8> {};
1400   class CheckGlobalBits : public BitField<bool, 12, 1> {};
1401
1402   DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1403 };
1404
1405
1406 class LoadGlobalViaContextStub final : public PlatformCodeStub {
1407  public:
1408   static const int kMaximumDepth = 15;
1409
1410   LoadGlobalViaContextStub(Isolate* isolate, int depth)
1411       : PlatformCodeStub(isolate) {
1412     minor_key_ = DepthBits::encode(depth);
1413   }
1414
1415   int depth() const { return DepthBits::decode(minor_key_); }
1416
1417  private:
1418   class DepthBits : public BitField<int, 0, 4> {};
1419   STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1420
1421   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalViaContext);
1422   DEFINE_PLATFORM_CODE_STUB(LoadGlobalViaContext, PlatformCodeStub);
1423 };
1424
1425
1426 class StoreGlobalViaContextStub final : public PlatformCodeStub {
1427  public:
1428   static const int kMaximumDepth = 15;
1429
1430   StoreGlobalViaContextStub(Isolate* isolate, int depth,
1431                             LanguageMode language_mode)
1432       : PlatformCodeStub(isolate) {
1433     minor_key_ =
1434         DepthBits::encode(depth) | LanguageModeBits::encode(language_mode);
1435   }
1436
1437   int depth() const { return DepthBits::decode(minor_key_); }
1438   LanguageMode language_mode() const {
1439     return LanguageModeBits::decode(minor_key_);
1440   }
1441
1442  private:
1443   class DepthBits : public BitField<int, 0, 4> {};
1444   STATIC_ASSERT(DepthBits::kMax == kMaximumDepth);
1445   class LanguageModeBits : public BitField<LanguageMode, 4, 2> {};
1446   STATIC_ASSERT(LANGUAGE_END == 3);
1447
1448   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreGlobalViaContext);
1449   DEFINE_PLATFORM_CODE_STUB(StoreGlobalViaContext, PlatformCodeStub);
1450 };
1451
1452
1453 class CallApiFunctionStub : public PlatformCodeStub {
1454  public:
1455   explicit CallApiFunctionStub(Isolate* isolate, bool call_data_undefined)
1456       : PlatformCodeStub(isolate) {
1457     minor_key_ = CallDataUndefinedBits::encode(call_data_undefined);
1458   }
1459
1460  private:
1461   bool call_data_undefined() const {
1462     return CallDataUndefinedBits::decode(minor_key_);
1463   }
1464
1465   class CallDataUndefinedBits : public BitField<bool, 0, 1> {};
1466
1467   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1468   DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1469 };
1470
1471
1472 class CallApiAccessorStub : public PlatformCodeStub {
1473  public:
1474   CallApiAccessorStub(Isolate* isolate, bool is_store, bool call_data_undefined)
1475       : PlatformCodeStub(isolate) {
1476     minor_key_ = IsStoreBits::encode(is_store) |
1477                  CallDataUndefinedBits::encode(call_data_undefined) |
1478                  ArgumentBits::encode(is_store ? 1 : 0);
1479   }
1480
1481  protected:
1482   // For CallApiFunctionWithFixedArgsStub, see below.
1483   static const int kArgBits = 3;
1484   CallApiAccessorStub(Isolate* isolate, int argc, bool call_data_undefined)
1485       : PlatformCodeStub(isolate) {
1486     minor_key_ = IsStoreBits::encode(false) |
1487                  CallDataUndefinedBits::encode(call_data_undefined) |
1488                  ArgumentBits::encode(argc);
1489   }
1490
1491  private:
1492   bool is_store() const { return IsStoreBits::decode(minor_key_); }
1493   bool call_data_undefined() const {
1494     return CallDataUndefinedBits::decode(minor_key_);
1495   }
1496   int argc() const { return ArgumentBits::decode(minor_key_); }
1497
1498   class IsStoreBits: public BitField<bool, 0, 1> {};
1499   class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1500   class ArgumentBits : public BitField<int, 2, kArgBits> {};
1501
1502   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiAccessor);
1503   DEFINE_PLATFORM_CODE_STUB(CallApiAccessor, PlatformCodeStub);
1504 };
1505
1506
1507 // TODO(dcarney): see if it's possible to remove this later without performance
1508 // degradation.
1509 // This is not a real stub, but a way of generating the CallApiAccessorStub
1510 // (which has the same abi) which makes it clear that it is not an accessor.
1511 class CallApiFunctionWithFixedArgsStub : public CallApiAccessorStub {
1512  public:
1513   static const int kMaxFixedArgs = (1 << kArgBits) - 1;
1514   CallApiFunctionWithFixedArgsStub(Isolate* isolate, int argc,
1515                                    bool call_data_undefined)
1516       : CallApiAccessorStub(isolate, argc, call_data_undefined) {
1517     DCHECK(0 <= argc && argc <= kMaxFixedArgs);
1518   }
1519 };
1520
1521
1522 typedef ApiAccessorDescriptor ApiFunctionWithFixedArgsDescriptor;
1523
1524
1525 class CallApiGetterStub : public PlatformCodeStub {
1526  public:
1527   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1528
1529   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1530   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1531 };
1532
1533
1534 class BinaryOpICStub : public HydrogenCodeStub {
1535  public:
1536   BinaryOpICStub(Isolate* isolate, Token::Value op, Strength strength)
1537       : HydrogenCodeStub(isolate, UNINITIALIZED) {
1538     BinaryOpICState state(isolate, op, strength);
1539     set_sub_minor_key(state.GetExtraICState());
1540   }
1541
1542   BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1543       : HydrogenCodeStub(isolate) {
1544     set_sub_minor_key(state.GetExtraICState());
1545   }
1546
1547   static void GenerateAheadOfTime(Isolate* isolate);
1548
1549   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1550
1551   InlineCacheState GetICState() const final { return state().GetICState(); }
1552
1553   ExtraICState GetExtraICState() const final {
1554     return static_cast<ExtraICState>(sub_minor_key());
1555   }
1556
1557   BinaryOpICState state() const {
1558     return BinaryOpICState(isolate(), GetExtraICState());
1559   }
1560
1561   void PrintState(std::ostream& os) const final;  // NOLINT
1562
1563   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1564   static const int kLeft = 0;
1565   static const int kRight = 1;
1566
1567  private:
1568   static void GenerateAheadOfTime(Isolate* isolate,
1569                                   const BinaryOpICState& state);
1570
1571   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1572   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1573 };
1574
1575
1576 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1577 // call support for stubs in Hydrogen.
1578 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
1579  public:
1580   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1581                                    const BinaryOpICState& state)
1582       : PlatformCodeStub(isolate) {
1583     minor_key_ = state.GetExtraICState();
1584   }
1585
1586   static void GenerateAheadOfTime(Isolate* isolate);
1587
1588   Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1589     Code::FindAndReplacePattern pattern;
1590     pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1591     return CodeStub::GetCodeCopy(pattern);
1592   }
1593
1594   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1595
1596   InlineCacheState GetICState() const override { return state().GetICState(); }
1597
1598   ExtraICState GetExtraICState() const override {
1599     return static_cast<ExtraICState>(minor_key_);
1600   }
1601
1602   void PrintState(std::ostream& os) const override;  // NOLINT
1603
1604  private:
1605   BinaryOpICState state() const {
1606     return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1607   }
1608
1609   static void GenerateAheadOfTime(Isolate* isolate,
1610                                   const BinaryOpICState& state);
1611
1612   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1613   DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1614 };
1615
1616
1617 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
1618  public:
1619   BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op,
1620                                  Strength strength)
1621       : BinaryOpICStub(isolate, op, strength) {}
1622
1623   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1624       : BinaryOpICStub(isolate, state) {}
1625
1626   Code::Kind GetCodeKind() const final { return Code::STUB; }
1627
1628   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1629   static const int kAllocationSite = 0;
1630   static const int kLeft = 1;
1631   static const int kRight = 2;
1632
1633   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1634   DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1635 };
1636
1637
1638 class StringAddStub final : public HydrogenCodeStub {
1639  public:
1640   StringAddStub(Isolate* isolate, StringAddFlags flags,
1641                 PretenureFlag pretenure_flag)
1642       : HydrogenCodeStub(isolate) {
1643     set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1644                       PretenureFlagBits::encode(pretenure_flag));
1645   }
1646
1647   StringAddFlags flags() const {
1648     return StringAddFlagsBits::decode(sub_minor_key());
1649   }
1650
1651   PretenureFlag pretenure_flag() const {
1652     return PretenureFlagBits::decode(sub_minor_key());
1653   }
1654
1655   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1656   static const int kLeft = 0;
1657   static const int kRight = 1;
1658
1659  private:
1660   class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1661   class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1662
1663   void PrintBaseName(std::ostream& os) const override;  // NOLINT
1664
1665   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1666   DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1667 };
1668
1669
1670 class CompareICStub : public PlatformCodeStub {
1671  public:
1672   CompareICStub(Isolate* isolate, Token::Value op, Strength strength,
1673                 CompareICState::State left, CompareICState::State right,
1674                 CompareICState::State state)
1675       : PlatformCodeStub(isolate) {
1676     DCHECK(Token::IsCompareOp(op));
1677     minor_key_ = OpBits::encode(op - Token::EQ) |
1678                  StrengthBits::encode(is_strong(strength)) |
1679                  LeftStateBits::encode(left) | RightStateBits::encode(right) |
1680                  StateBits::encode(state);
1681   }
1682
1683   void set_known_map(Handle<Map> map) { known_map_ = map; }
1684
1685   InlineCacheState GetICState() const override;
1686
1687   Token::Value op() const {
1688     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1689   }
1690
1691   Strength strength() const {
1692     return StrengthBits::decode(minor_key_) ? Strength::STRONG : Strength::WEAK;
1693   }
1694
1695   CompareICState::State left() const {
1696     return LeftStateBits::decode(minor_key_);
1697   }
1698   CompareICState::State right() const {
1699     return RightStateBits::decode(minor_key_);
1700   }
1701   CompareICState::State state() const { return StateBits::decode(minor_key_); }
1702
1703  private:
1704   Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
1705
1706   void GenerateSmis(MacroAssembler* masm);
1707   void GenerateNumbers(MacroAssembler* masm);
1708   void GenerateInternalizedStrings(MacroAssembler* masm);
1709   void GenerateStrings(MacroAssembler* masm);
1710   void GenerateUniqueNames(MacroAssembler* masm);
1711   void GenerateObjects(MacroAssembler* masm);
1712   void GenerateMiss(MacroAssembler* masm);
1713   void GenerateKnownObjects(MacroAssembler* masm);
1714   void GenerateGeneric(MacroAssembler* masm);
1715
1716   bool strict() const { return op() == Token::EQ_STRICT; }
1717   Condition GetCondition() const;
1718
1719   void AddToSpecialCache(Handle<Code> new_object) override;
1720   bool FindCodeInSpecialCache(Code** code_out) override;
1721   bool UseSpecialCache() override {
1722     return state() == CompareICState::KNOWN_OBJECT;
1723   }
1724
1725   class OpBits : public BitField<int, 0, 3> {};
1726   class StrengthBits : public BitField<bool, 3, 1> {};
1727   class LeftStateBits : public BitField<CompareICState::State, 4, 4> {};
1728   class RightStateBits : public BitField<CompareICState::State, 8, 4> {};
1729   class StateBits : public BitField<CompareICState::State, 12, 4> {};
1730
1731   Handle<Map> known_map_;
1732
1733   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1734   DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1735 };
1736
1737
1738 class CompareNilICStub : public HydrogenCodeStub  {
1739  public:
1740   Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1741   Type* GetInputType(Zone* zone, Handle<Map> map);
1742
1743   CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1744     set_sub_minor_key(NilValueBits::encode(nil));
1745   }
1746
1747   CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1748                    InitializationState init_state = INITIALIZED)
1749       : HydrogenCodeStub(isolate, init_state) {
1750     set_sub_minor_key(ic_state);
1751   }
1752
1753   static Handle<Code> GetUninitialized(Isolate* isolate,
1754                                        NilValue nil) {
1755     return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1756   }
1757
1758   InlineCacheState GetICState() const override {
1759     State state = this->state();
1760     if (state.Contains(GENERIC)) {
1761       return MEGAMORPHIC;
1762     } else if (state.Contains(MONOMORPHIC_MAP)) {
1763       return MONOMORPHIC;
1764     } else {
1765       return PREMONOMORPHIC;
1766     }
1767   }
1768
1769   Code::Kind GetCodeKind() const override { return Code::COMPARE_NIL_IC; }
1770
1771   ExtraICState GetExtraICState() const override { return sub_minor_key(); }
1772
1773   void UpdateStatus(Handle<Object> object);
1774
1775   bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1776
1777   NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1778
1779   void ClearState() {
1780     set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1781   }
1782
1783   void PrintState(std::ostream& os) const override;     // NOLINT
1784   void PrintBaseName(std::ostream& os) const override;  // NOLINT
1785
1786  private:
1787   CompareNilICStub(Isolate* isolate, NilValue nil,
1788                    InitializationState init_state)
1789       : HydrogenCodeStub(isolate, init_state) {
1790     set_sub_minor_key(NilValueBits::encode(nil));
1791   }
1792
1793   enum CompareNilType {
1794     UNDEFINED,
1795     NULL_TYPE,
1796     MONOMORPHIC_MAP,
1797     GENERIC,
1798     NUMBER_OF_TYPES
1799   };
1800
1801   // At most 6 different types can be distinguished, because the Code object
1802   // only has room for a single byte to hold a set and there are two more
1803   // boolean flags we need to store. :-P
1804   STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1805
1806   class State : public EnumSet<CompareNilType, byte> {
1807    public:
1808     State() : EnumSet<CompareNilType, byte>(0) { }
1809     explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1810   };
1811   friend std::ostream& operator<<(std::ostream& os, const State& s);
1812
1813   State state() const { return State(TypesBits::decode(sub_minor_key())); }
1814
1815   class NilValueBits : public BitField<NilValue, 0, 1> {};
1816   class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1817
1818   friend class CompareNilIC;
1819
1820   DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1821   DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1822 };
1823
1824
1825 std::ostream& operator<<(std::ostream& os, const CompareNilICStub::State& s);
1826
1827
1828 class CEntryStub : public PlatformCodeStub {
1829  public:
1830   CEntryStub(Isolate* isolate, int result_size,
1831              SaveFPRegsMode save_doubles = kDontSaveFPRegs)
1832       : PlatformCodeStub(isolate) {
1833     minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1834     DCHECK(result_size == 1 || result_size == 2);
1835 #if _WIN64 || V8_TARGET_ARCH_PPC
1836     minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1837 #endif  // _WIN64
1838   }
1839
1840   // The version of this stub that doesn't save doubles is generated ahead of
1841   // time, so it's OK to call it from other stubs that can't cope with GC during
1842   // their code generation.  On machines that always have gp registers (x64) we
1843   // can generate both variants ahead of time.
1844   static void GenerateAheadOfTime(Isolate* isolate);
1845
1846  private:
1847   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1848 #if _WIN64 || V8_TARGET_ARCH_PPC
1849   int result_size() const { return ResultSizeBits::decode(minor_key_); }
1850 #endif  // _WIN64
1851
1852   bool NeedsImmovableCode() override;
1853
1854   class SaveDoublesBits : public BitField<bool, 0, 1> {};
1855   class ResultSizeBits : public BitField<int, 1, 3> {};
1856
1857   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1858   DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1859 };
1860
1861
1862 class JSEntryStub : public PlatformCodeStub {
1863  public:
1864   JSEntryStub(Isolate* isolate, StackFrame::Type type)
1865       : PlatformCodeStub(isolate) {
1866     DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1867     minor_key_ = StackFrameTypeBits::encode(type);
1868   }
1869
1870  private:
1871   void FinishCode(Handle<Code> code) override;
1872
1873   void PrintName(std::ostream& os) const override {  // NOLINT
1874     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1875                                        : "JSConstructEntryStub");
1876   }
1877
1878   StackFrame::Type type() const {
1879     return StackFrameTypeBits::decode(minor_key_);
1880   }
1881
1882   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1883
1884   int handler_offset_;
1885
1886   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1887   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1888 };
1889
1890
1891 class ArgumentsAccessStub: public PlatformCodeStub {
1892  public:
1893   enum Type {
1894     READ_ELEMENT,
1895     NEW_SLOPPY_FAST,
1896     NEW_SLOPPY_SLOW,
1897     NEW_STRICT
1898   };
1899
1900   ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1901     minor_key_ = TypeBits::encode(type);
1902   }
1903
1904   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1905     if (type() == READ_ELEMENT) {
1906       return ArgumentsAccessReadDescriptor(isolate());
1907     }
1908     return ContextOnlyDescriptor(isolate());
1909   }
1910
1911  private:
1912   Type type() const { return TypeBits::decode(minor_key_); }
1913
1914   void GenerateReadElement(MacroAssembler* masm);
1915   void GenerateNewStrict(MacroAssembler* masm);
1916   void GenerateNewSloppyFast(MacroAssembler* masm);
1917   void GenerateNewSloppySlow(MacroAssembler* masm);
1918
1919   void PrintName(std::ostream& os) const override;  // NOLINT
1920
1921   class TypeBits : public BitField<Type, 0, 2> {};
1922
1923   DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
1924 };
1925
1926
1927 class RestParamAccessStub: public PlatformCodeStub {
1928  public:
1929   explicit RestParamAccessStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1930
1931   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1932     return ContextOnlyDescriptor(isolate());
1933   }
1934
1935  private:
1936   void GenerateNew(MacroAssembler* masm);
1937
1938   void PrintName(std::ostream& os) const override;  // NOLINT
1939
1940   DEFINE_PLATFORM_CODE_STUB(RestParamAccess, PlatformCodeStub);
1941 };
1942
1943
1944 class RegExpExecStub: public PlatformCodeStub {
1945  public:
1946   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1947
1948   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1949   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1950 };
1951
1952
1953 class RegExpConstructResultStub final : public HydrogenCodeStub {
1954  public:
1955   explicit RegExpConstructResultStub(Isolate* isolate)
1956       : HydrogenCodeStub(isolate) { }
1957
1958   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1959   static const int kLength = 0;
1960   static const int kIndex = 1;
1961   static const int kInput = 2;
1962
1963   DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1964   DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1965 };
1966
1967
1968 class CallFunctionStub: public PlatformCodeStub {
1969  public:
1970   CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1971       : PlatformCodeStub(isolate) {
1972     DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1973     minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1974   }
1975
1976  private:
1977   int argc() const { return ArgcBits::decode(minor_key_); }
1978   int flags() const { return FlagBits::decode(minor_key_); }
1979
1980   bool CallAsMethod() const {
1981     return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1982   }
1983
1984   bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1985
1986   void PrintName(std::ostream& os) const override;  // NOLINT
1987
1988   // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1989   class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1990   class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1991   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1992
1993   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1994   DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1995 };
1996
1997
1998 class CallConstructStub: public PlatformCodeStub {
1999  public:
2000   CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
2001       : PlatformCodeStub(isolate) {
2002     minor_key_ = FlagBits::encode(flags);
2003   }
2004
2005   void FinishCode(Handle<Code> code) override {
2006     code->set_has_function_cache(RecordCallTarget());
2007   }
2008
2009  private:
2010   CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
2011
2012   bool RecordCallTarget() const {
2013     return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
2014   }
2015
2016   bool IsSuperConstructorCall() const {
2017     return (flags() & SUPER_CONSTRUCTOR_CALL) != 0;
2018   }
2019
2020   void PrintName(std::ostream& os) const override;  // NOLINT
2021
2022   class FlagBits : public BitField<CallConstructorFlags, 0, 2> {};
2023
2024   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
2025   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
2026 };
2027
2028
2029 enum StringIndexFlags {
2030   // Accepts smis or heap numbers.
2031   STRING_INDEX_IS_NUMBER,
2032
2033   // Accepts smis or heap numbers that are valid array indices
2034   // (ECMA-262 15.4). Invalid indices are reported as being out of
2035   // range.
2036   STRING_INDEX_IS_ARRAY_INDEX
2037 };
2038
2039
2040 enum ReceiverCheckMode {
2041   // We don't know anything about the receiver.
2042   RECEIVER_IS_UNKNOWN,
2043
2044   // We know the receiver is a string.
2045   RECEIVER_IS_STRING
2046 };
2047
2048
2049 enum EmbedMode {
2050   // The code being generated is part of an IC handler, which may MISS
2051   // to an IC in failure cases.
2052   PART_OF_IC_HANDLER,
2053
2054   NOT_PART_OF_IC_HANDLER
2055 };
2056
2057
2058 // Generates code implementing String.prototype.charCodeAt.
2059 //
2060 // Only supports the case when the receiver is a string and the index
2061 // is a number (smi or heap number) that is a valid index into the
2062 // string. Additional index constraints are specified by the
2063 // flags. Otherwise, bails out to the provided labels.
2064 //
2065 // Register usage: |object| may be changed to another string in a way
2066 // that doesn't affect charCodeAt/charAt semantics, |index| is
2067 // preserved, |scratch| and |result| are clobbered.
2068 class StringCharCodeAtGenerator {
2069  public:
2070   StringCharCodeAtGenerator(Register object, Register index, Register result,
2071                             Label* receiver_not_string, Label* index_not_number,
2072                             Label* index_out_of_range,
2073                             StringIndexFlags index_flags,
2074                             ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2075       : object_(object),
2076         index_(index),
2077         result_(result),
2078         receiver_not_string_(receiver_not_string),
2079         index_not_number_(index_not_number),
2080         index_out_of_range_(index_out_of_range),
2081         index_flags_(index_flags),
2082         check_mode_(check_mode) {
2083     DCHECK(!result_.is(object_));
2084     DCHECK(!result_.is(index_));
2085   }
2086
2087   // Generates the fast case code. On the fallthrough path |result|
2088   // register contains the result.
2089   void GenerateFast(MacroAssembler* masm);
2090
2091   // Generates the slow case code. Must not be naturally
2092   // reachable. Expected to be put after a ret instruction (e.g., in
2093   // deferred code). Always jumps back to the fast case.
2094   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2095                     const RuntimeCallHelper& call_helper);
2096
2097   // Skip handling slow case and directly jump to bailout.
2098   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2099     masm->bind(&index_not_smi_);
2100     masm->bind(&call_runtime_);
2101     masm->jmp(bailout);
2102   }
2103
2104  private:
2105   Register object_;
2106   Register index_;
2107   Register result_;
2108
2109   Label* receiver_not_string_;
2110   Label* index_not_number_;
2111   Label* index_out_of_range_;
2112
2113   StringIndexFlags index_flags_;
2114   ReceiverCheckMode check_mode_;
2115
2116   Label call_runtime_;
2117   Label index_not_smi_;
2118   Label got_smi_index_;
2119   Label exit_;
2120
2121   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
2122 };
2123
2124
2125 // Generates code for creating a one-char string from a char code.
2126 class StringCharFromCodeGenerator {
2127  public:
2128   StringCharFromCodeGenerator(Register code,
2129                               Register result)
2130       : code_(code),
2131         result_(result) {
2132     DCHECK(!code_.is(result_));
2133   }
2134
2135   // Generates the fast case code. On the fallthrough path |result|
2136   // register contains the result.
2137   void GenerateFast(MacroAssembler* masm);
2138
2139   // Generates the slow case code. Must not be naturally
2140   // reachable. Expected to be put after a ret instruction (e.g., in
2141   // deferred code). Always jumps back to the fast case.
2142   void GenerateSlow(MacroAssembler* masm,
2143                     const RuntimeCallHelper& call_helper);
2144
2145   // Skip handling slow case and directly jump to bailout.
2146   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2147     masm->bind(&slow_case_);
2148     masm->jmp(bailout);
2149   }
2150
2151  private:
2152   Register code_;
2153   Register result_;
2154
2155   Label slow_case_;
2156   Label exit_;
2157
2158   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
2159 };
2160
2161
2162 // Generates code implementing String.prototype.charAt.
2163 //
2164 // Only supports the case when the receiver is a string and the index
2165 // is a number (smi or heap number) that is a valid index into the
2166 // string. Additional index constraints are specified by the
2167 // flags. Otherwise, bails out to the provided labels.
2168 //
2169 // Register usage: |object| may be changed to another string in a way
2170 // that doesn't affect charCodeAt/charAt semantics, |index| is
2171 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
2172 class StringCharAtGenerator {
2173  public:
2174   StringCharAtGenerator(Register object, Register index, Register scratch,
2175                         Register result, Label* receiver_not_string,
2176                         Label* index_not_number, Label* index_out_of_range,
2177                         StringIndexFlags index_flags,
2178                         ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
2179       : char_code_at_generator_(object, index, scratch, receiver_not_string,
2180                                 index_not_number, index_out_of_range,
2181                                 index_flags, check_mode),
2182         char_from_code_generator_(scratch, result) {}
2183
2184   // Generates the fast case code. On the fallthrough path |result|
2185   // register contains the result.
2186   void GenerateFast(MacroAssembler* masm) {
2187     char_code_at_generator_.GenerateFast(masm);
2188     char_from_code_generator_.GenerateFast(masm);
2189   }
2190
2191   // Generates the slow case code. Must not be naturally
2192   // reachable. Expected to be put after a ret instruction (e.g., in
2193   // deferred code). Always jumps back to the fast case.
2194   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
2195                     const RuntimeCallHelper& call_helper) {
2196     char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
2197     char_from_code_generator_.GenerateSlow(masm, call_helper);
2198   }
2199
2200   // Skip handling slow case and directly jump to bailout.
2201   void SkipSlow(MacroAssembler* masm, Label* bailout) {
2202     char_code_at_generator_.SkipSlow(masm, bailout);
2203     char_from_code_generator_.SkipSlow(masm, bailout);
2204   }
2205
2206  private:
2207   StringCharCodeAtGenerator char_code_at_generator_;
2208   StringCharFromCodeGenerator char_from_code_generator_;
2209
2210   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
2211 };
2212
2213
2214 class LoadDictionaryElementStub : public HydrogenCodeStub {
2215  public:
2216   explicit LoadDictionaryElementStub(Isolate* isolate, const LoadICState& state)
2217       : HydrogenCodeStub(isolate) {
2218     minor_key_ = state.GetExtraICState();
2219   }
2220
2221   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2222     return LoadWithVectorDescriptor(isolate());
2223   }
2224
2225   LanguageMode language_mode() const {
2226     return LoadICState::GetLanguageMode(MinorKey());
2227   }
2228
2229   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
2230 };
2231
2232
2233 class KeyedLoadGenericStub : public HydrogenCodeStub {
2234  public:
2235   explicit KeyedLoadGenericStub(Isolate* isolate, const LoadICState& state)
2236       : HydrogenCodeStub(isolate) {
2237     minor_key_ = state.GetExtraICState();
2238   }
2239
2240   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2241   InlineCacheState GetICState() const override { return GENERIC; }
2242
2243   LanguageMode language_mode() const {
2244     return LoadICState::GetLanguageMode(MinorKey());
2245   }
2246
2247   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2248
2249   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
2250 };
2251
2252
2253 class LoadICTrampolineStub : public PlatformCodeStub {
2254  public:
2255   LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2256       : PlatformCodeStub(isolate) {
2257     minor_key_ = state.GetExtraICState();
2258   }
2259
2260   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2261
2262   InlineCacheState GetICState() const final { return DEFAULT; }
2263
2264   ExtraICState GetExtraICState() const final {
2265     return static_cast<ExtraICState>(minor_key_);
2266   }
2267
2268  protected:
2269   LoadICState state() const {
2270     return LoadICState(static_cast<ExtraICState>(minor_key_));
2271   }
2272
2273   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
2274   DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
2275 };
2276
2277
2278 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
2279  public:
2280   explicit KeyedLoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
2281       : LoadICTrampolineStub(isolate, state) {}
2282
2283   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2284
2285   DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
2286 };
2287
2288
2289 class VectorStoreICTrampolineStub : public PlatformCodeStub {
2290  public:
2291   VectorStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2292       : PlatformCodeStub(isolate) {
2293     minor_key_ = state.GetExtraICState();
2294   }
2295
2296   Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
2297
2298   InlineCacheState GetICState() const final { return DEFAULT; }
2299
2300   ExtraICState GetExtraICState() const final {
2301     return static_cast<ExtraICState>(minor_key_);
2302   }
2303
2304  protected:
2305   StoreICState state() const {
2306     return StoreICState(static_cast<ExtraICState>(minor_key_));
2307   }
2308
2309  private:
2310   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreICTrampoline);
2311   DEFINE_PLATFORM_CODE_STUB(VectorStoreICTrampoline, PlatformCodeStub);
2312 };
2313
2314
2315 class VectorKeyedStoreICTrampolineStub : public VectorStoreICTrampolineStub {
2316  public:
2317   VectorKeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2318       : VectorStoreICTrampolineStub(isolate, state) {}
2319
2320   Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2321
2322   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreICTrampoline,
2323                             VectorStoreICTrampolineStub);
2324 };
2325
2326
2327 class CallICTrampolineStub : public PlatformCodeStub {
2328  public:
2329   CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2330       : PlatformCodeStub(isolate) {
2331     minor_key_ = state.GetExtraICState();
2332   }
2333
2334   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2335
2336   InlineCacheState GetICState() const final { return DEFAULT; }
2337
2338   ExtraICState GetExtraICState() const final {
2339     return static_cast<ExtraICState>(minor_key_);
2340   }
2341
2342  protected:
2343   CallICState state() const {
2344     return CallICState(static_cast<ExtraICState>(minor_key_));
2345   }
2346
2347   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2348   DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2349 };
2350
2351
2352 class CallIC_ArrayTrampolineStub : public CallICTrampolineStub {
2353  public:
2354   CallIC_ArrayTrampolineStub(Isolate* isolate, const CallICState& state)
2355       : CallICTrampolineStub(isolate, state) {}
2356
2357  private:
2358   DEFINE_PLATFORM_CODE_STUB(CallIC_ArrayTrampoline, CallICTrampolineStub);
2359 };
2360
2361
2362 class LoadICStub : public PlatformCodeStub {
2363  public:
2364   explicit LoadICStub(Isolate* isolate, const LoadICState& state)
2365       : PlatformCodeStub(isolate) {
2366     minor_key_ = state.GetExtraICState();
2367   }
2368
2369   void GenerateForTrampoline(MacroAssembler* masm);
2370
2371   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2372   InlineCacheState GetICState() const final { return DEFAULT; }
2373   ExtraICState GetExtraICState() const final {
2374     return static_cast<ExtraICState>(minor_key_);
2375   }
2376
2377   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2378   DEFINE_PLATFORM_CODE_STUB(LoadIC, PlatformCodeStub);
2379
2380  protected:
2381   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2382 };
2383
2384
2385 class KeyedLoadICStub : public PlatformCodeStub {
2386  public:
2387   explicit KeyedLoadICStub(Isolate* isolate, const LoadICState& state)
2388       : PlatformCodeStub(isolate) {
2389     minor_key_ = state.GetExtraICState();
2390   }
2391
2392   void GenerateForTrampoline(MacroAssembler* masm);
2393
2394   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2395   InlineCacheState GetICState() const final { return DEFAULT; }
2396   ExtraICState GetExtraICState() const final {
2397     return static_cast<ExtraICState>(minor_key_);
2398   }
2399
2400   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2401   DEFINE_PLATFORM_CODE_STUB(KeyedLoadIC, PlatformCodeStub);
2402
2403  protected:
2404   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2405 };
2406
2407
2408 class VectorStoreICStub : public PlatformCodeStub {
2409  public:
2410   VectorStoreICStub(Isolate* isolate, const StoreICState& state)
2411       : PlatformCodeStub(isolate) {
2412     minor_key_ = state.GetExtraICState();
2413   }
2414
2415   void GenerateForTrampoline(MacroAssembler* masm);
2416
2417   Code::Kind GetCodeKind() const final { return Code::STORE_IC; }
2418   InlineCacheState GetICState() const final { return DEFAULT; }
2419   ExtraICState GetExtraICState() const final {
2420     return static_cast<ExtraICState>(minor_key_);
2421   }
2422
2423   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2424   DEFINE_PLATFORM_CODE_STUB(VectorStoreIC, PlatformCodeStub);
2425
2426  protected:
2427   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2428 };
2429
2430
2431 class VectorKeyedStoreICStub : public PlatformCodeStub {
2432  public:
2433   VectorKeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2434       : PlatformCodeStub(isolate) {
2435     minor_key_ = state.GetExtraICState();
2436   }
2437
2438   void GenerateForTrampoline(MacroAssembler* masm);
2439
2440   Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2441   InlineCacheState GetICState() const final { return DEFAULT; }
2442   virtual ExtraICState GetExtraICState() const final {
2443     return static_cast<ExtraICState>(minor_key_);
2444   }
2445
2446   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorStoreIC);
2447   DEFINE_PLATFORM_CODE_STUB(VectorKeyedStoreIC, PlatformCodeStub);
2448
2449  protected:
2450   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2451 };
2452
2453
2454 class DoubleToIStub : public PlatformCodeStub {
2455  public:
2456   DoubleToIStub(Isolate* isolate, Register source, Register destination,
2457                 int offset, bool is_truncating, bool skip_fastpath = false)
2458       : PlatformCodeStub(isolate) {
2459     minor_key_ = SourceRegisterBits::encode(source.code()) |
2460                  DestinationRegisterBits::encode(destination.code()) |
2461                  OffsetBits::encode(offset) |
2462                  IsTruncatingBits::encode(is_truncating) |
2463                  SkipFastPathBits::encode(skip_fastpath) |
2464                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2465   }
2466
2467   bool SometimesSetsUpAFrame() override { return false; }
2468
2469  private:
2470   Register source() const {
2471     return Register::from_code(SourceRegisterBits::decode(minor_key_));
2472   }
2473   Register destination() const {
2474     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2475   }
2476   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
2477   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
2478   int offset() const { return OffsetBits::decode(minor_key_); }
2479
2480   static const int kBitsPerRegisterNumber = 6;
2481   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2482   class SourceRegisterBits:
2483       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
2484   class DestinationRegisterBits:
2485       public BitField<int, kBitsPerRegisterNumber,
2486         kBitsPerRegisterNumber> {};  // NOLINT
2487   class IsTruncatingBits:
2488       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
2489   class OffsetBits:
2490       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
2491   class SkipFastPathBits:
2492       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
2493   class SSE3Bits:
2494       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
2495
2496   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2497   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2498 };
2499
2500
2501 class ScriptContextFieldStub : public HandlerStub {
2502  public:
2503   ScriptContextFieldStub(Isolate* isolate,
2504                          const ScriptContextTable::LookupResult* lookup_result)
2505       : HandlerStub(isolate) {
2506     DCHECK(Accepted(lookup_result));
2507     set_sub_minor_key(ContextIndexBits::encode(lookup_result->context_index) |
2508                       SlotIndexBits::encode(lookup_result->slot_index));
2509   }
2510
2511   int context_index() const {
2512     return ContextIndexBits::decode(sub_minor_key());
2513   }
2514
2515   int slot_index() const { return SlotIndexBits::decode(sub_minor_key()); }
2516
2517   static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2518     return ContextIndexBits::is_valid(lookup_result->context_index) &&
2519            SlotIndexBits::is_valid(lookup_result->slot_index);
2520   }
2521
2522  private:
2523   static const int kContextIndexBits = 13;
2524   static const int kSlotIndexBits = 13;
2525   class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2526   class SlotIndexBits
2527       : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2528
2529   Code::StubType GetStubType() const override { return Code::FAST; }
2530
2531   DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, HandlerStub);
2532 };
2533
2534
2535 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2536  public:
2537   LoadScriptContextFieldStub(
2538       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2539       : ScriptContextFieldStub(isolate, lookup_result) {}
2540
2541  private:
2542   Code::Kind kind() const override { return Code::LOAD_IC; }
2543
2544   DEFINE_HANDLER_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2545 };
2546
2547
2548 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2549  public:
2550   StoreScriptContextFieldStub(
2551       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2552       : ScriptContextFieldStub(isolate, lookup_result) {}
2553
2554  private:
2555   Code::Kind kind() const override { return Code::STORE_IC; }
2556
2557   DEFINE_HANDLER_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2558 };
2559
2560
2561 class LoadFastElementStub : public HandlerStub {
2562  public:
2563   LoadFastElementStub(Isolate* isolate, bool is_js_array,
2564                       ElementsKind elements_kind,
2565                       bool convert_hole_to_undefined = false)
2566       : HandlerStub(isolate) {
2567     set_sub_minor_key(
2568         ElementsKindBits::encode(elements_kind) |
2569         IsJSArrayBits::encode(is_js_array) |
2570         CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2571   }
2572
2573   Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2574
2575   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2576   bool convert_hole_to_undefined() const {
2577     return CanConvertHoleToUndefined::decode(sub_minor_key());
2578   }
2579
2580   ElementsKind elements_kind() const {
2581     return ElementsKindBits::decode(sub_minor_key());
2582   }
2583
2584  private:
2585   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2586   class IsJSArrayBits: public BitField<bool, 8, 1> {};
2587   class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2588
2589   DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
2590 };
2591
2592
2593 class StoreFastElementStub : public HydrogenCodeStub {
2594  public:
2595   StoreFastElementStub(Isolate* isolate, bool is_js_array,
2596                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
2597       : HydrogenCodeStub(isolate) {
2598     set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
2599                       IsJSArrayBits::encode(is_js_array) |
2600                       StoreModeBits::encode(mode));
2601   }
2602
2603   static void GenerateAheadOfTime(Isolate* isolate);
2604
2605   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2606
2607   ElementsKind elements_kind() const {
2608     return ElementsKindBits::decode(sub_minor_key());
2609   }
2610
2611   KeyedAccessStoreMode store_mode() const {
2612     return StoreModeBits::decode(sub_minor_key());
2613   }
2614
2615   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2616     if (FLAG_vector_stores) {
2617       return VectorStoreICDescriptor(isolate());
2618     }
2619     return StoreDescriptor(isolate());
2620   }
2621
2622  private:
2623   class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
2624   class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
2625   class IsJSArrayBits: public BitField<bool,                12, 1> {};
2626
2627   DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
2628 };
2629
2630
2631 class TransitionElementsKindStub : public HydrogenCodeStub {
2632  public:
2633   TransitionElementsKindStub(Isolate* isolate,
2634                              ElementsKind from_kind,
2635                              ElementsKind to_kind,
2636                              bool is_js_array) : HydrogenCodeStub(isolate) {
2637     set_sub_minor_key(FromKindBits::encode(from_kind) |
2638                       ToKindBits::encode(to_kind) |
2639                       IsJSArrayBits::encode(is_js_array));
2640   }
2641
2642   ElementsKind from_kind() const {
2643     return FromKindBits::decode(sub_minor_key());
2644   }
2645
2646   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2647
2648   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2649
2650  private:
2651   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2652   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2653   class IsJSArrayBits: public BitField<bool, 16, 1> {};
2654
2655   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2656   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2657 };
2658
2659
2660 class AllocateHeapNumberStub final : public HydrogenCodeStub {
2661  public:
2662   explicit AllocateHeapNumberStub(Isolate* isolate)
2663       : HydrogenCodeStub(isolate) {}
2664
2665  private:
2666   DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2667   DEFINE_HYDROGEN_CODE_STUB(AllocateHeapNumber, HydrogenCodeStub);
2668 };
2669
2670
2671 class ArrayConstructorStubBase : public HydrogenCodeStub {
2672  public:
2673   ArrayConstructorStubBase(Isolate* isolate,
2674                            ElementsKind kind,
2675                            AllocationSiteOverrideMode override_mode)
2676       : HydrogenCodeStub(isolate) {
2677     // It only makes sense to override local allocation site behavior
2678     // if there is a difference between the global allocation site policy
2679     // for an ElementsKind and the desired usage of the stub.
2680     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2681            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2682     set_sub_minor_key(ElementsKindBits::encode(kind) |
2683                       AllocationSiteOverrideModeBits::encode(override_mode));
2684   }
2685
2686   ElementsKind elements_kind() const {
2687     return ElementsKindBits::decode(sub_minor_key());
2688   }
2689
2690   AllocationSiteOverrideMode override_mode() const {
2691     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2692   }
2693
2694   static void GenerateStubsAheadOfTime(Isolate* isolate);
2695
2696   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2697   static const int kConstructor = 0;
2698   static const int kAllocationSite = 1;
2699
2700  protected:
2701   std::ostream& BasePrintName(std::ostream& os,
2702                               const char* name) const;  // NOLINT
2703
2704  private:
2705   // Ensure data fits within available bits.
2706   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2707
2708   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2709   class AllocationSiteOverrideModeBits: public
2710       BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2711
2712   DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2713 };
2714
2715
2716 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2717  public:
2718   ArrayNoArgumentConstructorStub(
2719       Isolate* isolate,
2720       ElementsKind kind,
2721       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2722       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2723   }
2724
2725  private:
2726   void PrintName(std::ostream& os) const override {  // NOLINT
2727     BasePrintName(os, "ArrayNoArgumentConstructorStub");
2728   }
2729
2730   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2731   DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2732                             ArrayConstructorStubBase);
2733 };
2734
2735
2736 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2737  public:
2738   ArraySingleArgumentConstructorStub(
2739       Isolate* isolate,
2740       ElementsKind kind,
2741       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2742       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2743   }
2744
2745  private:
2746   void PrintName(std::ostream& os) const override {  // NOLINT
2747     BasePrintName(os, "ArraySingleArgumentConstructorStub");
2748   }
2749
2750   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2751   DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2752                             ArrayConstructorStubBase);
2753 };
2754
2755
2756 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2757  public:
2758   ArrayNArgumentsConstructorStub(
2759       Isolate* isolate,
2760       ElementsKind kind,
2761       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
2762       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2763   }
2764
2765  private:
2766   void PrintName(std::ostream& os) const override {  // NOLINT
2767     BasePrintName(os, "ArrayNArgumentsConstructorStub");
2768   }
2769
2770   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2771   DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2772                             ArrayConstructorStubBase);
2773 };
2774
2775
2776 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2777  public:
2778   InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2779       : HydrogenCodeStub(isolate) {
2780     set_sub_minor_key(ElementsKindBits::encode(kind));
2781   }
2782
2783   static void GenerateStubsAheadOfTime(Isolate* isolate);
2784
2785   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2786   static const int kConstructor = 0;
2787
2788   ElementsKind elements_kind() const {
2789     return ElementsKindBits::decode(sub_minor_key());
2790   }
2791
2792  private:
2793   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2794
2795   DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2796 };
2797
2798
2799 class InternalArrayNoArgumentConstructorStub : public
2800     InternalArrayConstructorStubBase {
2801  public:
2802   InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2803                                          ElementsKind kind)
2804       : InternalArrayConstructorStubBase(isolate, kind) { }
2805
2806   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2807   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2808                             InternalArrayConstructorStubBase);
2809 };
2810
2811
2812 class InternalArraySingleArgumentConstructorStub : public
2813     InternalArrayConstructorStubBase {
2814  public:
2815   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2816                                              ElementsKind kind)
2817       : InternalArrayConstructorStubBase(isolate, kind) { }
2818
2819   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2820   DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2821                             InternalArrayConstructorStubBase);
2822 };
2823
2824
2825 class InternalArrayNArgumentsConstructorStub : public
2826     InternalArrayConstructorStubBase {
2827  public:
2828   InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2829       : InternalArrayConstructorStubBase(isolate, kind) { }
2830
2831   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2832   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2833                             InternalArrayConstructorStubBase);
2834 };
2835
2836
2837 class StoreElementStub : public PlatformCodeStub {
2838  public:
2839   StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2840       : PlatformCodeStub(isolate) {
2841     minor_key_ = ElementsKindBits::encode(elements_kind);
2842   }
2843
2844   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2845     if (FLAG_vector_stores) {
2846       return VectorStoreICDescriptor(isolate());
2847     }
2848     return StoreDescriptor(isolate());
2849   }
2850
2851  private:
2852   ElementsKind elements_kind() const {
2853     return ElementsKindBits::decode(minor_key_);
2854   }
2855
2856   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2857
2858   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2859 };
2860
2861
2862 class ToBooleanStub: public HydrogenCodeStub {
2863  public:
2864   enum Type {
2865     UNDEFINED,
2866     BOOLEAN,
2867     NULL_TYPE,
2868     SMI,
2869     SPEC_OBJECT,
2870     STRING,
2871     SYMBOL,
2872     HEAP_NUMBER,
2873     SIMD_VALUE,
2874     NUMBER_OF_TYPES
2875   };
2876
2877   enum ResultMode {
2878     RESULT_AS_SMI,             // For Smi(1) on truthy value, Smi(0) otherwise.
2879     RESULT_AS_ODDBALL,         // For {true} on truthy value, {false} otherwise.
2880     RESULT_AS_INVERSE_ODDBALL  // For {false} on truthy value, {true} otherwise.
2881   };
2882
2883   // At most 16 different types can be distinguished, because the Code object
2884   // only has room for two bytes to hold a set of these types. :-P
2885   STATIC_ASSERT(NUMBER_OF_TYPES <= 16);
2886
2887   class Types : public EnumSet<Type, uint16_t> {
2888    public:
2889     Types() : EnumSet<Type, uint16_t>(0) {}
2890     explicit Types(uint16_t bits) : EnumSet<Type, uint16_t>(bits) {}
2891
2892     bool UpdateStatus(Handle<Object> object);
2893     bool NeedsMap() const;
2894     bool CanBeUndetectable() const {
2895       return Contains(ToBooleanStub::SPEC_OBJECT);
2896     }
2897     bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2898
2899     static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2900   };
2901
2902   ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
2903       : HydrogenCodeStub(isolate) {
2904     set_sub_minor_key(TypesBits::encode(types.ToIntegral()) |
2905                       ResultModeBits::encode(mode));
2906   }
2907
2908   ToBooleanStub(Isolate* isolate, ExtraICState state)
2909       : HydrogenCodeStub(isolate) {
2910     set_sub_minor_key(TypesBits::encode(static_cast<uint16_t>(state)) |
2911                       ResultModeBits::encode(RESULT_AS_SMI));
2912   }
2913
2914   bool UpdateStatus(Handle<Object> object);
2915   Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
2916   ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2917
2918   Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2919   void PrintState(std::ostream& os) const override;  // NOLINT
2920
2921   bool SometimesSetsUpAFrame() override { return false; }
2922
2923   static Handle<Code> GetUninitialized(Isolate* isolate) {
2924     return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2925   }
2926
2927   ExtraICState GetExtraICState() const override { return types().ToIntegral(); }
2928
2929   InlineCacheState GetICState() const override {
2930     if (types().IsEmpty()) {
2931       return ::v8::internal::UNINITIALIZED;
2932     } else {
2933       return MONOMORPHIC;
2934     }
2935   }
2936
2937  private:
2938   ToBooleanStub(Isolate* isolate, InitializationState init_state)
2939       : HydrogenCodeStub(isolate, init_state) {
2940     set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2941   }
2942
2943   class TypesBits : public BitField<uint16_t, 0, NUMBER_OF_TYPES> {};
2944   class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2945
2946   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2947   DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2948 };
2949
2950
2951 std::ostream& operator<<(std::ostream& os, const ToBooleanStub::Types& t);
2952
2953
2954 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2955  public:
2956   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2957                                  ElementsKind to_kind, bool is_jsarray,
2958                                  KeyedAccessStoreMode store_mode)
2959       : HydrogenCodeStub(isolate) {
2960     set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2961                       IsJSArrayBits::encode(is_jsarray) |
2962                       StoreModeBits::encode(store_mode));
2963   }
2964
2965   ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
2966   ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
2967   bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
2968   KeyedAccessStoreMode store_mode() const {
2969     return StoreModeBits::decode(sub_minor_key());
2970   }
2971
2972   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
2973
2974  private:
2975   class FromBits : public BitField<ElementsKind, 0, 8> {};
2976   class ToBits : public BitField<ElementsKind, 8, 8> {};
2977   class IsJSArrayBits : public BitField<bool, 16, 1> {};
2978   class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
2979
2980   DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2981 };
2982
2983
2984 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2985  public:
2986   explicit StoreArrayLiteralElementStub(Isolate* isolate)
2987       : PlatformCodeStub(isolate) { }
2988
2989   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2990   DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2991 };
2992
2993
2994 class StubFailureTrampolineStub : public PlatformCodeStub {
2995  public:
2996   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2997       : PlatformCodeStub(isolate) {
2998     minor_key_ = FunctionModeField::encode(function_mode);
2999   }
3000
3001   static void GenerateAheadOfTime(Isolate* isolate);
3002
3003  private:
3004   StubFunctionMode function_mode() const {
3005     return FunctionModeField::decode(minor_key_);
3006   }
3007
3008   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
3009
3010   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
3011   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
3012 };
3013
3014
3015 class ProfileEntryHookStub : public PlatformCodeStub {
3016  public:
3017   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3018
3019   // The profile entry hook function is not allowed to cause a GC.
3020   bool SometimesSetsUpAFrame() override { return false; }
3021
3022   // Generates a call to the entry hook if it's enabled.
3023   static void MaybeCallEntryHook(MacroAssembler* masm);
3024
3025  private:
3026   static void EntryHookTrampoline(intptr_t function,
3027                                   intptr_t stack_pointer,
3028                                   Isolate* isolate);
3029
3030   // ProfileEntryHookStub is called at the start of a function, so it has the
3031   // same register set.
3032   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
3033   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
3034 };
3035
3036
3037 class StoreBufferOverflowStub : public PlatformCodeStub {
3038  public:
3039   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
3040       : PlatformCodeStub(isolate) {
3041     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
3042   }
3043
3044   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
3045   bool SometimesSetsUpAFrame() override { return false; }
3046
3047  private:
3048   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
3049
3050   class SaveDoublesBits : public BitField<bool, 0, 1> {};
3051
3052   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
3053   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
3054 };
3055
3056
3057 class SubStringStub : public PlatformCodeStub {
3058  public:
3059   explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3060
3061   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
3062   DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
3063 };
3064
3065
3066 class ToNumberStub final : public PlatformCodeStub {
3067  public:
3068   explicit ToNumberStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3069
3070   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
3071   DEFINE_PLATFORM_CODE_STUB(ToNumber, PlatformCodeStub);
3072 };
3073
3074
3075 class ToObjectStub final : public HydrogenCodeStub {
3076  public:
3077   explicit ToObjectStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
3078
3079   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToObject);
3080   DEFINE_HYDROGEN_CODE_STUB(ToObject, HydrogenCodeStub);
3081 };
3082
3083
3084 class StringCompareStub : public PlatformCodeStub {
3085  public:
3086   explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
3087
3088   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
3089   DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
3090 };
3091
3092
3093 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
3094 #undef DEFINE_PLATFORM_CODE_STUB
3095 #undef DEFINE_HANDLER_CODE_STUB
3096 #undef DEFINE_HYDROGEN_CODE_STUB
3097 #undef DEFINE_CODE_STUB
3098 #undef DEFINE_CODE_STUB_BASE
3099
3100 extern Representation RepresentationFromType(Type* type);
3101 } }  // namespace v8::internal
3102
3103 #endif  // V8_CODE_STUBS_H_