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