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