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