Home | History | Annotate | Download | only in src
      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/factory.h"
     12 #include "src/find-and-replace-pattern.h"
     13 #include "src/globals.h"
     14 #include "src/ic/ic-state.h"
     15 #include "src/interface-descriptors.h"
     16 #include "src/macro-assembler.h"
     17 #include "src/ostreams.h"
     18 #include "src/type-hints.h"
     19 
     20 namespace v8 {
     21 namespace internal {
     22 
     23 // Forward declarations.
     24 class CodeStubAssembler;
     25 namespace compiler {
     26 class CodeAssemblerLabel;
     27 class CodeAssemblerState;
     28 class Node;
     29 }
     30 
     31 // List of code stubs used on all platforms.
     32 #define CODE_STUB_LIST_ALL_PLATFORMS(V)       \
     33   /* --- PlatformCodeStubs --- */             \
     34   V(ArrayConstructor)                         \
     35   V(BinaryOpICWithAllocationSite)             \
     36   V(CallApiCallback)                          \
     37   V(CallApiGetter)                            \
     38   V(CallConstruct)                            \
     39   V(CallIC)                                   \
     40   V(CEntry)                                   \
     41   V(CompareIC)                                \
     42   V(DoubleToI)                                \
     43   V(InternalArrayConstructor)                 \
     44   V(JSEntry)                                  \
     45   V(MathPow)                                  \
     46   V(ProfileEntryHook)                         \
     47   V(RecordWrite)                              \
     48   V(RegExpExec)                               \
     49   V(StoreBufferOverflow)                      \
     50   V(StoreSlowElement)                         \
     51   V(SubString)                                \
     52   V(NameDictionaryLookup)                     \
     53   /* This can be removed once there are no */ \
     54   /* more deopting Hydrogen stubs. */         \
     55   V(StubFailureTrampoline)                    \
     56   /* These are only called from FCG */        \
     57   /* They can be removed when only the TF  */ \
     58   /* version of the corresponding stub is  */ \
     59   /* used universally */                      \
     60   V(CallICTrampoline)                         \
     61   /* --- HydrogenCodeStubs --- */             \
     62   /* These should never be ported to TF */    \
     63   /* because they are either used only by */  \
     64   /* FCG/Crankshaft or are deprecated */      \
     65   V(BinaryOpIC)                               \
     66   V(BinaryOpWithAllocationSite)               \
     67   V(ToBooleanIC)                              \
     68   V(TransitionElementsKind)                   \
     69   /* --- TurboFanCodeStubs --- */             \
     70   V(AllocateHeapNumber)                       \
     71   V(ArrayNoArgumentConstructor)               \
     72   V(ArraySingleArgumentConstructor)           \
     73   V(ArrayNArgumentsConstructor)               \
     74   V(CreateAllocationSite)                     \
     75   V(CreateWeakCell)                           \
     76   V(StringLength)                             \
     77   V(AddWithFeedback)                          \
     78   V(SubtractWithFeedback)                     \
     79   V(MultiplyWithFeedback)                     \
     80   V(DivideWithFeedback)                       \
     81   V(ModulusWithFeedback)                      \
     82   V(InternalArrayNoArgumentConstructor)       \
     83   V(InternalArraySingleArgumentConstructor)   \
     84   V(ElementsTransitionAndStore)               \
     85   V(KeyedLoadSloppyArguments)                 \
     86   V(KeyedStoreSloppyArguments)                \
     87   V(LoadScriptContextField)                   \
     88   V(StoreScriptContextField)                  \
     89   V(NumberToString)                           \
     90   V(StringAdd)                                \
     91   V(GetProperty)                              \
     92   V(StoreFastElement)                         \
     93   V(StoreGlobal)                              \
     94   V(StoreInterceptor)                         \
     95   V(LoadIndexedInterceptor)                   \
     96   V(GrowArrayElements)
     97 
     98 // List of code stubs only used on ARM 32 bits platforms.
     99 #if V8_TARGET_ARCH_ARM
    100 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
    101 
    102 #else
    103 #define CODE_STUB_LIST_ARM(V)
    104 #endif
    105 
    106 // List of code stubs only used on ARM 64 bits platforms.
    107 #if V8_TARGET_ARCH_ARM64
    108 #define CODE_STUB_LIST_ARM64(V) \
    109   V(DirectCEntry)               \
    110   V(RestoreRegistersState)      \
    111   V(StoreRegistersState)
    112 
    113 #else
    114 #define CODE_STUB_LIST_ARM64(V)
    115 #endif
    116 
    117 // List of code stubs only used on PPC platforms.
    118 #ifdef V8_TARGET_ARCH_PPC
    119 #define CODE_STUB_LIST_PPC(V) \
    120   V(DirectCEntry)             \
    121   V(StoreRegistersState)      \
    122   V(RestoreRegistersState)
    123 #else
    124 #define CODE_STUB_LIST_PPC(V)
    125 #endif
    126 
    127 // List of code stubs only used on MIPS platforms.
    128 #if V8_TARGET_ARCH_MIPS
    129 #define CODE_STUB_LIST_MIPS(V) \
    130   V(DirectCEntry)              \
    131   V(RestoreRegistersState)     \
    132   V(StoreRegistersState)
    133 #elif V8_TARGET_ARCH_MIPS64
    134 #define CODE_STUB_LIST_MIPS(V) \
    135   V(DirectCEntry)              \
    136   V(RestoreRegistersState)     \
    137   V(StoreRegistersState)
    138 #else
    139 #define CODE_STUB_LIST_MIPS(V)
    140 #endif
    141 
    142 // List of code stubs only used on S390 platforms.
    143 #ifdef V8_TARGET_ARCH_S390
    144 #define CODE_STUB_LIST_S390(V) \
    145   V(DirectCEntry)              \
    146   V(StoreRegistersState)       \
    147   V(RestoreRegistersState)
    148 #else
    149 #define CODE_STUB_LIST_S390(V)
    150 #endif
    151 
    152 // Combined list of code stubs.
    153 #define CODE_STUB_LIST(V)         \
    154   CODE_STUB_LIST_ALL_PLATFORMS(V) \
    155   CODE_STUB_LIST_ARM(V)           \
    156   CODE_STUB_LIST_ARM64(V)         \
    157   CODE_STUB_LIST_PPC(V)           \
    158   CODE_STUB_LIST_MIPS(V)          \
    159   CODE_STUB_LIST_S390(V)
    160 
    161 static const int kHasReturnedMinusZeroSentinel = 1;
    162 
    163 // Stub is base classes of all stubs.
    164 class CodeStub BASE_EMBEDDED {
    165  public:
    166   enum Major {
    167     // TODO(mvstanton): eliminate the NoCache key by getting rid
    168     //                  of the non-monomorphic-cache.
    169     NoCache = 0,  // marker for stubs that do custom caching]
    170 #define DEF_ENUM(name) name,
    171     CODE_STUB_LIST(DEF_ENUM)
    172 #undef DEF_ENUM
    173     NUMBER_OF_IDS
    174   };
    175 
    176   // Retrieve the code for the stub. Generate the code if needed.
    177   Handle<Code> GetCode();
    178 
    179   // Retrieve the code for the stub, make and return a copy of the code.
    180   Handle<Code> GetCodeCopy(const FindAndReplacePattern& pattern);
    181 
    182   static Major MajorKeyFromKey(uint32_t key) {
    183     return static_cast<Major>(MajorKeyBits::decode(key));
    184   }
    185   static uint32_t MinorKeyFromKey(uint32_t key) {
    186     return MinorKeyBits::decode(key);
    187   }
    188 
    189   // Gets the major key from a code object that is a code stub or binary op IC.
    190   static Major GetMajorKey(Code* code_stub) {
    191     return MajorKeyFromKey(code_stub->stub_key());
    192   }
    193 
    194   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
    195 
    196   static const char* MajorName(Major major_key);
    197 
    198   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
    199   virtual ~CodeStub() {}
    200 
    201   static void GenerateStubsAheadOfTime(Isolate* isolate);
    202   static void GenerateFPStubs(Isolate* isolate);
    203 
    204   // Some stubs put untagged junk on the stack that cannot be scanned by the
    205   // GC.  This means that we must be statically sure that no GC can occur while
    206   // they are running.  If that is the case they should override this to return
    207   // true, which will cause an assertion if we try to call something that can
    208   // GC or if we try to put a stack frame on top of the junk, which would not
    209   // result in a traversable stack.
    210   virtual bool SometimesSetsUpAFrame() { return true; }
    211 
    212   // Lookup the code in the (possibly custom) cache.
    213   bool FindCodeInCache(Code** code_out);
    214 
    215   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
    216 
    217   virtual int GetStackParameterCount() const {
    218     return GetCallInterfaceDescriptor().GetStackParameterCount();
    219   }
    220 
    221   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
    222 
    223   static void InitializeDescriptor(Isolate* isolate, uint32_t key,
    224                                    CodeStubDescriptor* desc);
    225 
    226   static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
    227 
    228   // Returns information for computing the number key.
    229   virtual Major MajorKey() const = 0;
    230   uint32_t MinorKey() const { return minor_key_; }
    231 
    232   // BinaryOpStub needs to override this.
    233   virtual Code::Kind GetCodeKind() const;
    234 
    235   virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
    236 
    237   Code::Flags GetCodeFlags() const;
    238 
    239   friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
    240     s.PrintName(os);
    241     return os;
    242   }
    243 
    244   Isolate* isolate() const { return isolate_; }
    245 
    246   void DeleteStubFromCacheForTesting();
    247 
    248  protected:
    249   CodeStub(uint32_t key, Isolate* isolate)
    250       : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
    251 
    252   // Generates the assembler code for the stub.
    253   virtual Handle<Code> GenerateCode() = 0;
    254 
    255   // Returns whether the code generated for this stub needs to be allocated as
    256   // a fixed (non-moveable) code object.
    257   virtual bool NeedsImmovableCode() { return false; }
    258 
    259   virtual void PrintName(std::ostream& os) const;        // NOLINT
    260   virtual void PrintBaseName(std::ostream& os) const;    // NOLINT
    261   virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
    262 
    263   // Computes the key based on major and minor.
    264   uint32_t GetKey() {
    265     DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
    266     return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
    267   }
    268 
    269   uint32_t minor_key_;
    270 
    271  private:
    272   // Perform bookkeeping required after code generation when stub code is
    273   // initially generated.
    274   void RecordCodeGeneration(Handle<Code> code);
    275 
    276   // Finish the code object after it has been generated.
    277   virtual void FinishCode(Handle<Code> code) { }
    278 
    279   // Activate newly generated stub. Is called after
    280   // registering stub in the stub cache.
    281   virtual void Activate(Code* code) { }
    282 
    283   // Add the code to a specialized cache, specific to an individual
    284   // stub type. Please note, this method must add the code object to a
    285   // roots object, otherwise we will remove the code during GC.
    286   virtual void AddToSpecialCache(Handle<Code> new_object) { }
    287 
    288   // Find code in a specialized cache, work is delegated to the specific stub.
    289   virtual bool FindCodeInSpecialCache(Code** code_out) {
    290     return false;
    291   }
    292 
    293   // If a stub uses a special cache override this.
    294   virtual bool UseSpecialCache() { return false; }
    295 
    296   // We use this dispatch to statically instantiate the correct code stub for
    297   // the given stub key and call the passed function with that code stub.
    298   typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
    299   static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
    300                        DispatchedCall call);
    301 
    302   static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
    303 
    304   STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
    305   class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
    306   class MinorKeyBits: public BitField<uint32_t,
    307       kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
    308 
    309   friend class BreakPointIterator;
    310 
    311   Isolate* isolate_;
    312 };
    313 
    314 
    315 #define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
    316  public:                                                        \
    317   NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
    318                                                                 \
    319  private:                                                       \
    320   DISALLOW_COPY_AND_ASSIGN(NAME)
    321 
    322 
    323 #define DEFINE_CODE_STUB(NAME, SUPER)                      \
    324  public:                                                   \
    325   inline Major MajorKey() const override { return NAME; }; \
    326                                                            \
    327   DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
    328 
    329 
    330 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)  \
    331  private:                                       \
    332   void Generate(MacroAssembler* masm) override; \
    333   DEFINE_CODE_STUB(NAME, SUPER)
    334 
    335 
    336 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER)                        \
    337  public:                                                              \
    338   void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
    339   Handle<Code> GenerateCode() override;                               \
    340   DEFINE_CODE_STUB(NAME, SUPER)
    341 
    342 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                               \
    343  public:                                                                     \
    344   void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
    345   DEFINE_CODE_STUB(NAME, SUPER)
    346 
    347 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER)       \
    348  public:                                                                     \
    349   static compiler::Node* Generate(                                           \
    350       CodeStubAssembler* assembler, compiler::Node* left,                    \
    351       compiler::Node* right, compiler::Node* slot_id,                        \
    352       compiler::Node* feedback_vector, compiler::Node* context);             \
    353   void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
    354   DEFINE_CODE_STUB(NAME, SUPER)
    355 
    356 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER)        \
    357  public:                                                                     \
    358   static compiler::Node* Generate(                                           \
    359       CodeStubAssembler* assembler, compiler::Node* value,                   \
    360       compiler::Node* context, compiler::Node* feedback_vector,              \
    361       compiler::Node* slot_id);                                              \
    362   void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
    363   DEFINE_CODE_STUB(NAME, SUPER)
    364 
    365 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
    366  public:                                      \
    367   Handle<Code> GenerateCode() override;       \
    368   DEFINE_CODE_STUB(NAME, SUPER)
    369 
    370 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                          \
    371  public:                                                                \
    372   typedef NAME##Descriptor Descriptor;                                  \
    373   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    374     return Descriptor(isolate());                                       \
    375   }
    376 
    377 // There are some code stubs we just can't describe right now with a
    378 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
    379 // An attempt to retrieve a descriptor will fail.
    380 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                         \
    381  public:                                                                \
    382   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    383     UNREACHABLE();                                                      \
    384     return CallInterfaceDescriptor();                                   \
    385   }
    386 
    387 
    388 class PlatformCodeStub : public CodeStub {
    389  public:
    390   // Retrieve the code for the stub. Generate the code if needed.
    391   Handle<Code> GenerateCode() override;
    392 
    393  protected:
    394   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
    395 
    396   // Generates the assembler code for the stub.
    397   virtual void Generate(MacroAssembler* masm) = 0;
    398 
    399   DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
    400 };
    401 
    402 
    403 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
    404 
    405 
    406 class CodeStubDescriptor {
    407  public:
    408   explicit CodeStubDescriptor(CodeStub* stub);
    409 
    410   CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
    411 
    412   void Initialize(Address deoptimization_handler = NULL,
    413                   int hint_stack_parameter_count = -1,
    414                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
    415   void Initialize(Register stack_parameter_count,
    416                   Address deoptimization_handler = NULL,
    417                   int hint_stack_parameter_count = -1,
    418                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
    419 
    420   void SetMissHandler(Runtime::FunctionId id) {
    421     miss_handler_id_ = id;
    422     miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_);
    423     has_miss_handler_ = true;
    424     // Our miss handler infrastructure doesn't currently support
    425     // variable stack parameter counts.
    426     DCHECK(!stack_parameter_count_.is_valid());
    427   }
    428 
    429   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
    430   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
    431 
    432   int GetRegisterParameterCount() const {
    433     return call_descriptor().GetRegisterParameterCount();
    434   }
    435 
    436   int GetStackParameterCount() const {
    437     return call_descriptor().GetStackParameterCount();
    438   }
    439 
    440   int GetParameterCount() const {
    441     return call_descriptor().GetParameterCount();
    442   }
    443 
    444   Register GetRegisterParameter(int index) const {
    445     return call_descriptor().GetRegisterParameter(index);
    446   }
    447 
    448   MachineType GetParameterType(int index) const {
    449     return call_descriptor().GetParameterType(index);
    450   }
    451 
    452   ExternalReference miss_handler() const {
    453     DCHECK(has_miss_handler_);
    454     return miss_handler_;
    455   }
    456 
    457   Runtime::FunctionId miss_handler_id() const {
    458     DCHECK(has_miss_handler_);
    459     return miss_handler_id_;
    460   }
    461 
    462   bool has_miss_handler() const {
    463     return has_miss_handler_;
    464   }
    465 
    466   int GetHandlerParameterCount() const {
    467     int params = GetParameterCount();
    468     if (PassesArgumentsToDeoptimizationHandler()) {
    469       params += 1;
    470     }
    471     return params;
    472   }
    473 
    474   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
    475   Register stack_parameter_count() const { return stack_parameter_count_; }
    476   StubFunctionMode function_mode() const { return function_mode_; }
    477   Address deoptimization_handler() const { return deoptimization_handler_; }
    478 
    479  private:
    480   bool PassesArgumentsToDeoptimizationHandler() const {
    481     return stack_parameter_count_.is_valid();
    482   }
    483 
    484   Isolate* isolate_;
    485   CallInterfaceDescriptor call_descriptor_;
    486   Register stack_parameter_count_;
    487   // If hint_stack_parameter_count_ > 0, the code stub can optimize the
    488   // return sequence. Default value is -1, which means it is ignored.
    489   int hint_stack_parameter_count_;
    490   StubFunctionMode function_mode_;
    491 
    492   Address deoptimization_handler_;
    493 
    494   ExternalReference miss_handler_;
    495   Runtime::FunctionId miss_handler_id_;
    496   bool has_miss_handler_;
    497 };
    498 
    499 
    500 class HydrogenCodeStub : public CodeStub {
    501  public:
    502   enum InitializationState {
    503     UNINITIALIZED,
    504     INITIALIZED
    505   };
    506 
    507   template<class SubClass>
    508   static Handle<Code> GetUninitialized(Isolate* isolate) {
    509     SubClass::GenerateAheadOfTime(isolate);
    510     return SubClass().GetCode(isolate);
    511   }
    512 
    513   // Retrieve the code for the stub. Generate the code if needed.
    514   Handle<Code> GenerateCode() override = 0;
    515 
    516   bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
    517 
    518   Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
    519 
    520   Handle<Code> GenerateRuntimeTailCall(CodeStubDescriptor* descriptor);
    521 
    522   template<class StateType>
    523   void TraceTransition(StateType from, StateType to);
    524 
    525  protected:
    526   explicit HydrogenCodeStub(Isolate* isolate,
    527                             InitializationState state = INITIALIZED)
    528       : CodeStub(isolate) {
    529     minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
    530   }
    531 
    532   void set_sub_minor_key(uint32_t key) {
    533     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
    534   }
    535 
    536   uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
    537 
    538   static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
    539 
    540  private:
    541   class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
    542   class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
    543 
    544   void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
    545 
    546   DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
    547 };
    548 
    549 
    550 class TurboFanCodeStub : public CodeStub {
    551  public:
    552   // Retrieve the code for the stub. Generate the code if needed.
    553   Handle<Code> GenerateCode() override;
    554 
    555   int GetStackParameterCount() const override {
    556     return GetCallInterfaceDescriptor().GetStackParameterCount();
    557   }
    558 
    559  protected:
    560   explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
    561 
    562   virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0;
    563 
    564  private:
    565   DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
    566 };
    567 
    568 
    569 // Helper interface to prepare to/restore after making runtime calls.
    570 class RuntimeCallHelper {
    571  public:
    572   virtual ~RuntimeCallHelper() {}
    573 
    574   virtual void BeforeCall(MacroAssembler* masm) const = 0;
    575 
    576   virtual void AfterCall(MacroAssembler* masm) const = 0;
    577 
    578  protected:
    579   RuntimeCallHelper() {}
    580 
    581  private:
    582   DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
    583 };
    584 
    585 
    586 }  // namespace internal
    587 }  // namespace v8
    588 
    589 #if V8_TARGET_ARCH_IA32
    590 #include "src/ia32/code-stubs-ia32.h"
    591 #elif V8_TARGET_ARCH_X64
    592 #include "src/x64/code-stubs-x64.h"
    593 #elif V8_TARGET_ARCH_ARM64
    594 #include "src/arm64/code-stubs-arm64.h"
    595 #elif V8_TARGET_ARCH_ARM
    596 #include "src/arm/code-stubs-arm.h"
    597 #elif V8_TARGET_ARCH_PPC
    598 #include "src/ppc/code-stubs-ppc.h"
    599 #elif V8_TARGET_ARCH_MIPS
    600 #include "src/mips/code-stubs-mips.h"
    601 #elif V8_TARGET_ARCH_MIPS64
    602 #include "src/mips64/code-stubs-mips64.h"
    603 #elif V8_TARGET_ARCH_S390
    604 #include "src/s390/code-stubs-s390.h"
    605 #elif V8_TARGET_ARCH_X87
    606 #include "src/x87/code-stubs-x87.h"
    607 #else
    608 #error Unsupported target architecture.
    609 #endif
    610 
    611 namespace v8 {
    612 namespace internal {
    613 
    614 
    615 // RuntimeCallHelper implementation used in stubs: enters/leaves a
    616 // newly created internal frame before/after the runtime call.
    617 class StubRuntimeCallHelper : public RuntimeCallHelper {
    618  public:
    619   StubRuntimeCallHelper() {}
    620 
    621   void BeforeCall(MacroAssembler* masm) const override;
    622 
    623   void AfterCall(MacroAssembler* masm) const override;
    624 };
    625 
    626 
    627 // Trivial RuntimeCallHelper implementation.
    628 class NopRuntimeCallHelper : public RuntimeCallHelper {
    629  public:
    630   NopRuntimeCallHelper() {}
    631 
    632   void BeforeCall(MacroAssembler* masm) const override {}
    633 
    634   void AfterCall(MacroAssembler* masm) const override {}
    635 };
    636 
    637 
    638 class StringLengthStub : public TurboFanCodeStub {
    639  public:
    640   explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    641 
    642   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
    643   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
    644 
    645   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
    646   DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
    647 };
    648 
    649 class AddWithFeedbackStub final : public TurboFanCodeStub {
    650  public:
    651   explicit AddWithFeedbackStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    652 
    653   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
    654   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(AddWithFeedback,
    655                                                     TurboFanCodeStub);
    656 };
    657 
    658 class SubtractWithFeedbackStub final : public TurboFanCodeStub {
    659  public:
    660   explicit SubtractWithFeedbackStub(Isolate* isolate)
    661       : TurboFanCodeStub(isolate) {}
    662 
    663   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
    664   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(SubtractWithFeedback,
    665                                                     TurboFanCodeStub);
    666 };
    667 
    668 class MultiplyWithFeedbackStub final : public TurboFanCodeStub {
    669  public:
    670   explicit MultiplyWithFeedbackStub(Isolate* isolate)
    671       : TurboFanCodeStub(isolate) {}
    672 
    673   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
    674   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(MultiplyWithFeedback,
    675                                                     TurboFanCodeStub);
    676 };
    677 
    678 class DivideWithFeedbackStub final : public TurboFanCodeStub {
    679  public:
    680   explicit DivideWithFeedbackStub(Isolate* isolate)
    681       : TurboFanCodeStub(isolate) {}
    682 
    683   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
    684   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(DivideWithFeedback,
    685                                                     TurboFanCodeStub);
    686 };
    687 
    688 class ModulusWithFeedbackStub final : public TurboFanCodeStub {
    689  public:
    690   explicit ModulusWithFeedbackStub(Isolate* isolate)
    691       : TurboFanCodeStub(isolate) {}
    692 
    693   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
    694   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(ModulusWithFeedback,
    695                                                     TurboFanCodeStub);
    696 };
    697 
    698 class StoreInterceptorStub : public TurboFanCodeStub {
    699  public:
    700   explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    701 
    702   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
    703   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
    704 
    705   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    706   DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
    707 };
    708 
    709 class LoadIndexedInterceptorStub : public TurboFanCodeStub {
    710  public:
    711   explicit LoadIndexedInterceptorStub(Isolate* isolate)
    712       : TurboFanCodeStub(isolate) {}
    713 
    714   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
    715   ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
    716 
    717   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
    718   DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
    719 };
    720 
    721 // ES6 [[Get]] operation.
    722 class GetPropertyStub : public TurboFanCodeStub {
    723  public:
    724   explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    725 
    726   DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty);
    727   DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub);
    728 };
    729 
    730 class NumberToStringStub final : public TurboFanCodeStub {
    731  public:
    732   explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    733 
    734   DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
    735   DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub);
    736 };
    737 
    738 class CreateAllocationSiteStub : public TurboFanCodeStub {
    739  public:
    740   explicit CreateAllocationSiteStub(Isolate* isolate)
    741       : TurboFanCodeStub(isolate) {}
    742   static void GenerateAheadOfTime(Isolate* isolate);
    743 
    744   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
    745   DEFINE_TURBOFAN_CODE_STUB(CreateAllocationSite, TurboFanCodeStub);
    746 };
    747 
    748 class CreateWeakCellStub : public TurboFanCodeStub {
    749  public:
    750   explicit CreateWeakCellStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    751 
    752   static void GenerateAheadOfTime(Isolate* isolate);
    753 
    754   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
    755   DEFINE_TURBOFAN_CODE_STUB(CreateWeakCell, TurboFanCodeStub);
    756 };
    757 
    758 class GrowArrayElementsStub : public TurboFanCodeStub {
    759  public:
    760   GrowArrayElementsStub(Isolate* isolate, ElementsKind kind)
    761       : TurboFanCodeStub(isolate) {
    762     minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind));
    763   }
    764 
    765   ElementsKind elements_kind() const {
    766     return ElementsKindBits::decode(minor_key_);
    767   }
    768 
    769  private:
    770   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
    771 
    772   DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
    773   DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub);
    774 };
    775 
    776 enum AllocationSiteOverrideMode {
    777   DONT_OVERRIDE,
    778   DISABLE_ALLOCATION_SITES,
    779   LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
    780 };
    781 
    782 
    783 class ArrayConstructorStub: public PlatformCodeStub {
    784  public:
    785   explicit ArrayConstructorStub(Isolate* isolate);
    786 
    787  private:
    788   void GenerateDispatchToArrayStub(MacroAssembler* masm,
    789                                    AllocationSiteOverrideMode mode);
    790 
    791   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
    792   DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
    793 };
    794 
    795 
    796 class InternalArrayConstructorStub: public PlatformCodeStub {
    797  public:
    798   explicit InternalArrayConstructorStub(Isolate* isolate);
    799 
    800  private:
    801   void GenerateCase(MacroAssembler* masm, ElementsKind kind);
    802 
    803   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
    804   DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
    805 };
    806 
    807 
    808 class MathPowStub: public PlatformCodeStub {
    809  public:
    810   enum ExponentType { INTEGER, DOUBLE, TAGGED };
    811 
    812   MathPowStub(Isolate* isolate, ExponentType exponent_type)
    813       : PlatformCodeStub(isolate) {
    814     minor_key_ = ExponentTypeBits::encode(exponent_type);
    815   }
    816 
    817   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
    818     if (exponent_type() == TAGGED) {
    819       return MathPowTaggedDescriptor(isolate());
    820     } else if (exponent_type() == INTEGER) {
    821       return MathPowIntegerDescriptor(isolate());
    822     } else {
    823       // A CallInterfaceDescriptor doesn't specify double registers (yet).
    824       DCHECK_EQ(DOUBLE, exponent_type());
    825       return ContextOnlyDescriptor(isolate());
    826     }
    827   }
    828 
    829  private:
    830   ExponentType exponent_type() const {
    831     return ExponentTypeBits::decode(minor_key_);
    832   }
    833 
    834   class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
    835 
    836   DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
    837 };
    838 
    839 class CallICStub : public TurboFanCodeStub {
    840  public:
    841   CallICStub(Isolate* isolate, ConvertReceiverMode convert_mode,
    842              TailCallMode tail_call_mode)
    843       : TurboFanCodeStub(isolate) {
    844     minor_key_ = ConvertModeBits::encode(convert_mode) |
    845                  TailCallModeBits::encode(tail_call_mode);
    846   }
    847 
    848  protected:
    849   typedef BitField<ConvertReceiverMode, 0, 2> ConvertModeBits;
    850   typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits;
    851 
    852   ConvertReceiverMode convert_mode() const {
    853     return ConvertModeBits::decode(minor_key_);
    854   }
    855   TailCallMode tail_call_mode() const {
    856     return TailCallModeBits::decode(minor_key_);
    857   }
    858 
    859  private:
    860   void PrintState(std::ostream& os) const final;  // NOLINT
    861 
    862   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallIC);
    863   DEFINE_TURBOFAN_CODE_STUB(CallIC, TurboFanCodeStub);
    864 };
    865 
    866 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
    867  public:
    868   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
    869       : TurboFanCodeStub(isolate) {}
    870 
    871   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
    872   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
    873 
    874  protected:
    875   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
    876   DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub);
    877 };
    878 
    879 
    880 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
    881 
    882 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
    883  public:
    884   explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
    885                                          KeyedAccessStoreMode mode)
    886       : TurboFanCodeStub(isolate) {
    887     minor_key_ = CommonStoreModeBits::encode(mode);
    888   }
    889 
    890   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
    891   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
    892 
    893  protected:
    894   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    895   DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
    896 };
    897 
    898 class StoreGlobalStub : public TurboFanCodeStub {
    899  public:
    900   StoreGlobalStub(Isolate* isolate, PropertyCellType type,
    901                   Maybe<PropertyCellConstantType> constant_type,
    902                   bool check_global)
    903       : TurboFanCodeStub(isolate) {
    904     PropertyCellConstantType encoded_constant_type =
    905         constant_type.FromMaybe(PropertyCellConstantType::kSmi);
    906     minor_key_ = CellTypeBits::encode(type) |
    907                  ConstantTypeBits::encode(encoded_constant_type) |
    908                  CheckGlobalBits::encode(check_global);
    909   }
    910 
    911   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
    912   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
    913 
    914   static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
    915     return isolate->factory()->uninitialized_value();
    916   }
    917 
    918   static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
    919     return isolate->factory()->termination_exception();
    920   }
    921 
    922   Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,
    923                                        Handle<PropertyCell> cell) {
    924     FindAndReplacePattern pattern;
    925     if (check_global()) {
    926       pattern.Add(handle(global_map_placeholder(isolate())->map()),
    927                   Map::WeakCellForMap(Handle<Map>(global->map())));
    928     }
    929     pattern.Add(handle(property_cell_placeholder(isolate())->map()),
    930                 isolate()->factory()->NewWeakCell(cell));
    931     return CodeStub::GetCodeCopy(pattern);
    932   }
    933 
    934   PropertyCellType cell_type() const {
    935     return CellTypeBits::decode(minor_key_);
    936   }
    937 
    938   PropertyCellConstantType constant_type() const {
    939     DCHECK(PropertyCellType::kConstantType == cell_type());
    940     return ConstantTypeBits::decode(minor_key_);
    941   }
    942 
    943   bool check_global() const { return CheckGlobalBits::decode(minor_key_); }
    944 
    945  private:
    946   class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
    947   class ConstantTypeBits
    948       : public BitField<PropertyCellConstantType, CellTypeBits::kNext, 2> {};
    949   class CheckGlobalBits : public BitField<bool, ConstantTypeBits::kNext, 1> {};
    950 
    951   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    952   DEFINE_TURBOFAN_CODE_STUB(StoreGlobal, TurboFanCodeStub);
    953 };
    954 
    955 class CallApiCallbackStub : public PlatformCodeStub {
    956  public:
    957   static const int kArgBits = 3;
    958   static const int kArgMax = (1 << kArgBits) - 1;
    959 
    960   // CallApiCallbackStub for regular setters and getters.
    961   CallApiCallbackStub(Isolate* isolate, bool is_store, bool call_data_undefined,
    962                       bool is_lazy)
    963       : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store,
    964                             call_data_undefined, is_lazy) {}
    965 
    966   // CallApiCallbackStub for callback functions.
    967   CallApiCallbackStub(Isolate* isolate, int argc, bool call_data_undefined,
    968                       bool is_lazy)
    969       : CallApiCallbackStub(isolate, argc, false, call_data_undefined,
    970                             is_lazy) {}
    971 
    972  private:
    973   CallApiCallbackStub(Isolate* isolate, int argc, bool is_store,
    974                       bool call_data_undefined, bool is_lazy)
    975       : PlatformCodeStub(isolate) {
    976     CHECK(0 <= argc && argc <= kArgMax);
    977     minor_key_ = IsStoreBits::encode(is_store) |
    978                  CallDataUndefinedBits::encode(call_data_undefined) |
    979                  ArgumentBits::encode(argc) |
    980                  IsLazyAccessorBits::encode(is_lazy);
    981   }
    982 
    983   bool is_store() const { return IsStoreBits::decode(minor_key_); }
    984   bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
    985   bool call_data_undefined() const {
    986     return CallDataUndefinedBits::decode(minor_key_);
    987   }
    988   int argc() const { return ArgumentBits::decode(minor_key_); }
    989 
    990   class IsStoreBits: public BitField<bool, 0, 1> {};
    991   class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
    992   class ArgumentBits : public BitField<int, 2, kArgBits> {};
    993   class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {};
    994 
    995   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback);
    996   DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub);
    997 };
    998 
    999 
   1000 class CallApiGetterStub : public PlatformCodeStub {
   1001  public:
   1002   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
   1003 
   1004   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
   1005   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
   1006 };
   1007 
   1008 
   1009 class BinaryOpICStub : public HydrogenCodeStub {
   1010  public:
   1011   BinaryOpICStub(Isolate* isolate, Token::Value op)
   1012       : HydrogenCodeStub(isolate, UNINITIALIZED) {
   1013     BinaryOpICState state(isolate, op);
   1014     set_sub_minor_key(state.GetExtraICState());
   1015   }
   1016 
   1017   BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
   1018       : HydrogenCodeStub(isolate) {
   1019     set_sub_minor_key(state.GetExtraICState());
   1020   }
   1021 
   1022   static void GenerateAheadOfTime(Isolate* isolate);
   1023 
   1024   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
   1025 
   1026   ExtraICState GetExtraICState() const final {
   1027     return static_cast<ExtraICState>(sub_minor_key());
   1028   }
   1029 
   1030   BinaryOpICState state() const {
   1031     return BinaryOpICState(isolate(), GetExtraICState());
   1032   }
   1033 
   1034   void PrintState(std::ostream& os) const final;  // NOLINT
   1035 
   1036  private:
   1037   static void GenerateAheadOfTime(Isolate* isolate,
   1038                                   const BinaryOpICState& state);
   1039 
   1040   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
   1041   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
   1042 };
   1043 
   1044 
   1045 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
   1046 // call support for stubs in Hydrogen.
   1047 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
   1048  public:
   1049   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
   1050                                    const BinaryOpICState& state)
   1051       : PlatformCodeStub(isolate) {
   1052     minor_key_ = state.GetExtraICState();
   1053   }
   1054 
   1055   static void GenerateAheadOfTime(Isolate* isolate);
   1056 
   1057   Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
   1058     FindAndReplacePattern pattern;
   1059     pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
   1060     return CodeStub::GetCodeCopy(pattern);
   1061   }
   1062 
   1063   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
   1064 
   1065   ExtraICState GetExtraICState() const override {
   1066     return static_cast<ExtraICState>(minor_key_);
   1067   }
   1068 
   1069   void PrintState(std::ostream& os) const override;  // NOLINT
   1070 
   1071  private:
   1072   BinaryOpICState state() const {
   1073     return BinaryOpICState(isolate(), GetExtraICState());
   1074   }
   1075 
   1076   static void GenerateAheadOfTime(Isolate* isolate,
   1077                                   const BinaryOpICState& state);
   1078 
   1079   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
   1080   DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
   1081 };
   1082 
   1083 
   1084 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
   1085  public:
   1086   BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op)
   1087       : BinaryOpICStub(isolate, op) {}
   1088 
   1089   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
   1090       : BinaryOpICStub(isolate, state) {}
   1091 
   1092   Code::Kind GetCodeKind() const final { return Code::STUB; }
   1093 
   1094   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
   1095   DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
   1096 };
   1097 
   1098 class StringAddStub final : public TurboFanCodeStub {
   1099  public:
   1100   StringAddStub(Isolate* isolate, StringAddFlags flags,
   1101                 PretenureFlag pretenure_flag)
   1102       : TurboFanCodeStub(isolate) {
   1103     minor_key_ = (StringAddFlagsBits::encode(flags) |
   1104                   PretenureFlagBits::encode(pretenure_flag));
   1105   }
   1106 
   1107   StringAddFlags flags() const {
   1108     return StringAddFlagsBits::decode(minor_key_);
   1109   }
   1110 
   1111   PretenureFlag pretenure_flag() const {
   1112     return PretenureFlagBits::decode(minor_key_);
   1113   }
   1114 
   1115  private:
   1116   class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
   1117   class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
   1118 
   1119   void PrintBaseName(std::ostream& os) const override;  // NOLINT
   1120 
   1121   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
   1122   DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub);
   1123 };
   1124 
   1125 
   1126 class CompareICStub : public PlatformCodeStub {
   1127  public:
   1128   CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
   1129                 CompareICState::State right, CompareICState::State state)
   1130       : PlatformCodeStub(isolate) {
   1131     DCHECK(Token::IsCompareOp(op));
   1132     DCHECK(OpBits::is_valid(op - Token::EQ));
   1133     minor_key_ = OpBits::encode(op - Token::EQ) |
   1134                  LeftStateBits::encode(left) | RightStateBits::encode(right) |
   1135                  StateBits::encode(state);
   1136   }
   1137   // Creates uninitialized compare stub.
   1138   CompareICStub(Isolate* isolate, Token::Value op)
   1139       : CompareICStub(isolate, op, CompareICState::UNINITIALIZED,
   1140                       CompareICState::UNINITIALIZED,
   1141                       CompareICState::UNINITIALIZED) {}
   1142 
   1143   CompareICStub(Isolate* isolate, ExtraICState extra_ic_state)
   1144       : PlatformCodeStub(isolate) {
   1145     minor_key_ = extra_ic_state;
   1146   }
   1147 
   1148   ExtraICState GetExtraICState() const final {
   1149     return static_cast<ExtraICState>(minor_key_);
   1150   }
   1151 
   1152   void set_known_map(Handle<Map> map) { known_map_ = map; }
   1153 
   1154   InlineCacheState GetICState() const;
   1155 
   1156   Token::Value op() const {
   1157     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
   1158   }
   1159 
   1160   CompareICState::State left() const {
   1161     return LeftStateBits::decode(minor_key_);
   1162   }
   1163   CompareICState::State right() const {
   1164     return RightStateBits::decode(minor_key_);
   1165   }
   1166   CompareICState::State state() const { return StateBits::decode(minor_key_); }
   1167 
   1168  private:
   1169   Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
   1170 
   1171   void GenerateBooleans(MacroAssembler* masm);
   1172   void GenerateSmis(MacroAssembler* masm);
   1173   void GenerateNumbers(MacroAssembler* masm);
   1174   void GenerateInternalizedStrings(MacroAssembler* masm);
   1175   void GenerateStrings(MacroAssembler* masm);
   1176   void GenerateUniqueNames(MacroAssembler* masm);
   1177   void GenerateReceivers(MacroAssembler* masm);
   1178   void GenerateMiss(MacroAssembler* masm);
   1179   void GenerateKnownReceivers(MacroAssembler* masm);
   1180   void GenerateGeneric(MacroAssembler* masm);
   1181 
   1182   bool strict() const { return op() == Token::EQ_STRICT; }
   1183   Condition GetCondition() const;
   1184 
   1185   // Although we don't cache anything in the special cache we have to define
   1186   // this predicate to avoid appearance of code stubs with embedded maps in
   1187   // the global stub cache.
   1188   bool UseSpecialCache() override {
   1189     return state() == CompareICState::KNOWN_RECEIVER;
   1190   }
   1191 
   1192   class OpBits : public BitField<int, 0, 3> {};
   1193   class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
   1194   class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
   1195   class StateBits : public BitField<CompareICState::State, 11, 4> {};
   1196 
   1197   Handle<Map> known_map_;
   1198 
   1199   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
   1200   DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
   1201 };
   1202 
   1203 
   1204 class CEntryStub : public PlatformCodeStub {
   1205  public:
   1206   CEntryStub(Isolate* isolate, int result_size,
   1207              SaveFPRegsMode save_doubles = kDontSaveFPRegs,
   1208              ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false)
   1209       : PlatformCodeStub(isolate) {
   1210     minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
   1211                  FrameTypeBits::encode(builtin_exit_frame) |
   1212                  ArgvMode::encode(argv_mode == kArgvInRegister);
   1213     DCHECK(result_size == 1 || result_size == 2 || result_size == 3);
   1214     minor_key_ = ResultSizeBits::update(minor_key_, result_size);
   1215   }
   1216 
   1217   // The version of this stub that doesn't save doubles is generated ahead of
   1218   // time, so it's OK to call it from other stubs that can't cope with GC during
   1219   // their code generation.  On machines that always have gp registers (x64) we
   1220   // can generate both variants ahead of time.
   1221   static void GenerateAheadOfTime(Isolate* isolate);
   1222 
   1223  private:
   1224   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
   1225   bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
   1226   bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); }
   1227   int result_size() const { return ResultSizeBits::decode(minor_key_); }
   1228 
   1229   bool NeedsImmovableCode() override;
   1230 
   1231   class SaveDoublesBits : public BitField<bool, 0, 1> {};
   1232   class ArgvMode : public BitField<bool, 1, 1> {};
   1233   class FrameTypeBits : public BitField<bool, 2, 1> {};
   1234   class ResultSizeBits : public BitField<int, 3, 3> {};
   1235 
   1236   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
   1237   DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
   1238 };
   1239 
   1240 
   1241 class JSEntryStub : public PlatformCodeStub {
   1242  public:
   1243   JSEntryStub(Isolate* isolate, StackFrame::Type type)
   1244       : PlatformCodeStub(isolate) {
   1245     DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
   1246     minor_key_ = StackFrameTypeBits::encode(type);
   1247   }
   1248 
   1249  private:
   1250   void FinishCode(Handle<Code> code) override;
   1251 
   1252   void PrintName(std::ostream& os) const override {  // NOLINT
   1253     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
   1254                                        : "JSConstructEntryStub");
   1255   }
   1256 
   1257   StackFrame::Type type() const {
   1258     return StackFrameTypeBits::decode(minor_key_);
   1259   }
   1260 
   1261   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
   1262 
   1263   int handler_offset_;
   1264 
   1265   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
   1266   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
   1267 };
   1268 
   1269 
   1270 class RegExpExecStub: public PlatformCodeStub {
   1271  public:
   1272   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
   1273 
   1274   DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpExec);
   1275   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
   1276 };
   1277 
   1278 // TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
   1279 class CallConstructStub final : public PlatformCodeStub {
   1280  public:
   1281   explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
   1282 
   1283   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
   1284   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
   1285 };
   1286 
   1287 
   1288 enum ReceiverCheckMode {
   1289   // We don't know anything about the receiver.
   1290   RECEIVER_IS_UNKNOWN,
   1291 
   1292   // We know the receiver is a string.
   1293   RECEIVER_IS_STRING
   1294 };
   1295 
   1296 
   1297 enum EmbedMode {
   1298   // The code being generated is part of an IC handler, which may MISS
   1299   // to an IC in failure cases.
   1300   PART_OF_IC_HANDLER,
   1301 
   1302   NOT_PART_OF_IC_HANDLER
   1303 };
   1304 
   1305 
   1306 // Generates code implementing String.prototype.charCodeAt.
   1307 //
   1308 // Only supports the case when the receiver is a string and the index
   1309 // is a number (smi or heap number) that is a valid index into the
   1310 // string. Additional index constraints are specified by the
   1311 // flags. Otherwise, bails out to the provided labels.
   1312 //
   1313 // Register usage: |object| may be changed to another string in a way
   1314 // that doesn't affect charCodeAt/charAt semantics, |index| is
   1315 // preserved, |scratch| and |result| are clobbered.
   1316 class StringCharCodeAtGenerator {
   1317  public:
   1318   StringCharCodeAtGenerator(Register object, Register index, Register result,
   1319                             Label* receiver_not_string, Label* index_not_number,
   1320                             Label* index_out_of_range,
   1321                             ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
   1322       : object_(object),
   1323         index_(index),
   1324         result_(result),
   1325         receiver_not_string_(receiver_not_string),
   1326         index_not_number_(index_not_number),
   1327         index_out_of_range_(index_out_of_range),
   1328         check_mode_(check_mode) {
   1329     DCHECK(!result_.is(object_));
   1330     DCHECK(!result_.is(index_));
   1331   }
   1332 
   1333   // Generates the fast case code. On the fallthrough path |result|
   1334   // register contains the result.
   1335   void GenerateFast(MacroAssembler* masm);
   1336 
   1337   // Generates the slow case code. Must not be naturally
   1338   // reachable. Expected to be put after a ret instruction (e.g., in
   1339   // deferred code). Always jumps back to the fast case.
   1340   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
   1341                     const RuntimeCallHelper& call_helper);
   1342 
   1343  private:
   1344   Register object_;
   1345   Register index_;
   1346   Register result_;
   1347 
   1348   Label* receiver_not_string_;
   1349   Label* index_not_number_;
   1350   Label* index_out_of_range_;
   1351 
   1352   ReceiverCheckMode check_mode_;
   1353 
   1354   Label call_runtime_;
   1355   Label index_not_smi_;
   1356   Label got_smi_index_;
   1357   Label exit_;
   1358 
   1359   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
   1360 };
   1361 
   1362 class CallICTrampolineStub : public TurboFanCodeStub {
   1363  public:
   1364   CallICTrampolineStub(Isolate* isolate, ConvertReceiverMode convert_mode,
   1365                        TailCallMode tail_call_mode)
   1366       : TurboFanCodeStub(isolate) {
   1367     minor_key_ = ConvertModeBits::encode(convert_mode) |
   1368                  TailCallModeBits::encode(tail_call_mode);
   1369   }
   1370 
   1371  protected:
   1372   typedef BitField<ConvertReceiverMode, 0, 2> ConvertModeBits;
   1373   typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits;
   1374 
   1375   ConvertReceiverMode convert_mode() const {
   1376     return ConvertModeBits::decode(minor_key_);
   1377   }
   1378   TailCallMode tail_call_mode() const {
   1379     return TailCallModeBits::decode(minor_key_);
   1380   }
   1381 
   1382  private:
   1383   void PrintState(std::ostream& os) const override;  // NOLINT
   1384 
   1385   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallICTrampoline);
   1386   DEFINE_TURBOFAN_CODE_STUB(CallICTrampoline, TurboFanCodeStub);
   1387 };
   1388 
   1389 class DoubleToIStub : public PlatformCodeStub {
   1390  public:
   1391   DoubleToIStub(Isolate* isolate, Register source, Register destination,
   1392                 int offset, bool is_truncating, bool skip_fastpath = false)
   1393       : PlatformCodeStub(isolate) {
   1394     minor_key_ = SourceRegisterBits::encode(source.code()) |
   1395                  DestinationRegisterBits::encode(destination.code()) |
   1396                  OffsetBits::encode(offset) |
   1397                  IsTruncatingBits::encode(is_truncating) |
   1398                  SkipFastPathBits::encode(skip_fastpath) |
   1399                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
   1400   }
   1401 
   1402   bool SometimesSetsUpAFrame() override { return false; }
   1403 
   1404  private:
   1405   Register source() const {
   1406     return Register::from_code(SourceRegisterBits::decode(minor_key_));
   1407   }
   1408   Register destination() const {
   1409     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
   1410   }
   1411   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
   1412   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
   1413   int offset() const { return OffsetBits::decode(minor_key_); }
   1414 
   1415   static const int kBitsPerRegisterNumber = 6;
   1416   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
   1417   class SourceRegisterBits:
   1418       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
   1419   class DestinationRegisterBits:
   1420       public BitField<int, kBitsPerRegisterNumber,
   1421         kBitsPerRegisterNumber> {};  // NOLINT
   1422   class IsTruncatingBits:
   1423       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
   1424   class OffsetBits:
   1425       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
   1426   class SkipFastPathBits:
   1427       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
   1428   class SSE3Bits:
   1429       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
   1430 
   1431   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
   1432   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
   1433 };
   1434 
   1435 class ScriptContextFieldStub : public TurboFanCodeStub {
   1436  public:
   1437   ScriptContextFieldStub(Isolate* isolate,
   1438                          const ScriptContextTable::LookupResult* lookup_result)
   1439       : TurboFanCodeStub(isolate) {
   1440     DCHECK(Accepted(lookup_result));
   1441     minor_key_ = ContextIndexBits::encode(lookup_result->context_index) |
   1442                  SlotIndexBits::encode(lookup_result->slot_index);
   1443   }
   1444 
   1445   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
   1446 
   1447   int context_index() const { return ContextIndexBits::decode(minor_key_); }
   1448 
   1449   int slot_index() const { return SlotIndexBits::decode(minor_key_); }
   1450 
   1451   static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
   1452     return ContextIndexBits::is_valid(lookup_result->context_index) &&
   1453            SlotIndexBits::is_valid(lookup_result->slot_index);
   1454   }
   1455 
   1456  private:
   1457   static const int kContextIndexBits = 9;
   1458   static const int kSlotIndexBits = 12;
   1459   class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
   1460   class SlotIndexBits
   1461       : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
   1462 
   1463   DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub);
   1464 };
   1465 
   1466 
   1467 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
   1468  public:
   1469   LoadScriptContextFieldStub(
   1470       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
   1471       : ScriptContextFieldStub(isolate, lookup_result) {}
   1472 
   1473   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
   1474 
   1475  private:
   1476   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
   1477   DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
   1478 };
   1479 
   1480 
   1481 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
   1482  public:
   1483   StoreScriptContextFieldStub(
   1484       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
   1485       : ScriptContextFieldStub(isolate, lookup_result) {}
   1486 
   1487   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
   1488 
   1489  private:
   1490   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
   1491   DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
   1492 };
   1493 
   1494 class StoreFastElementStub : public TurboFanCodeStub {
   1495  public:
   1496   StoreFastElementStub(Isolate* isolate, bool is_js_array,
   1497                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
   1498       : TurboFanCodeStub(isolate) {
   1499     minor_key_ = CommonStoreModeBits::encode(mode) |
   1500                  ElementsKindBits::encode(elements_kind) |
   1501                  IsJSArrayBits::encode(is_js_array);
   1502   }
   1503 
   1504   static void GenerateAheadOfTime(Isolate* isolate);
   1505 
   1506   bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
   1507 
   1508   ElementsKind elements_kind() const {
   1509     return ElementsKindBits::decode(minor_key_);
   1510   }
   1511 
   1512   KeyedAccessStoreMode store_mode() const {
   1513     return CommonStoreModeBits::decode(minor_key_);
   1514   }
   1515 
   1516   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
   1517   ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
   1518 
   1519  private:
   1520   class ElementsKindBits
   1521       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
   1522   class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
   1523 
   1524   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
   1525   DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
   1526 };
   1527 
   1528 
   1529 class TransitionElementsKindStub : public HydrogenCodeStub {
   1530  public:
   1531   TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind,
   1532                              ElementsKind to_kind)
   1533       : HydrogenCodeStub(isolate) {
   1534     set_sub_minor_key(FromKindBits::encode(from_kind) |
   1535                       ToKindBits::encode(to_kind));
   1536   }
   1537 
   1538   ElementsKind from_kind() const {
   1539     return FromKindBits::decode(sub_minor_key());
   1540   }
   1541 
   1542   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
   1543 
   1544  private:
   1545   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
   1546   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
   1547 
   1548   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
   1549   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
   1550 };
   1551 
   1552 class AllocateHeapNumberStub : public TurboFanCodeStub {
   1553  public:
   1554   explicit AllocateHeapNumberStub(Isolate* isolate)
   1555       : TurboFanCodeStub(isolate) {}
   1556 
   1557   void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
   1558 
   1559   DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
   1560   DEFINE_TURBOFAN_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
   1561 };
   1562 
   1563 class CommonArrayConstructorStub : public TurboFanCodeStub {
   1564  protected:
   1565   CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind,
   1566                              AllocationSiteOverrideMode override_mode)
   1567       : TurboFanCodeStub(isolate) {
   1568     // It only makes sense to override local allocation site behavior
   1569     // if there is a difference between the global allocation site policy
   1570     // for an ElementsKind and the desired usage of the stub.
   1571     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
   1572            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
   1573     set_sub_minor_key(ElementsKindBits::encode(kind) |
   1574                       AllocationSiteOverrideModeBits::encode(override_mode));
   1575   }
   1576 
   1577   void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
   1578 
   1579   uint32_t sub_minor_key() const { return minor_key_; }
   1580 
   1581   CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
   1582       : TurboFanCodeStub(key, isolate) {}
   1583 
   1584  public:
   1585   ElementsKind elements_kind() const {
   1586     return ElementsKindBits::decode(sub_minor_key());
   1587   }
   1588 
   1589   AllocationSiteOverrideMode override_mode() const {
   1590     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
   1591   }
   1592 
   1593   static void GenerateStubsAheadOfTime(Isolate* isolate);
   1594 
   1595  private:
   1596   // Ensure data fits within available bits.
   1597   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
   1598 
   1599   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
   1600   class AllocationSiteOverrideModeBits
   1601       : public BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
   1602 };
   1603 
   1604 class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub {
   1605  public:
   1606   ArrayNoArgumentConstructorStub(
   1607       Isolate* isolate, ElementsKind kind,
   1608       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
   1609       : CommonArrayConstructorStub(isolate, kind, override_mode) {}
   1610 
   1611  private:
   1612   void PrintName(std::ostream& os) const override {  // NOLINT
   1613     os << "ArrayNoArgumentConstructorStub";
   1614   }
   1615 
   1616   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
   1617   DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor,
   1618                             CommonArrayConstructorStub);
   1619 };
   1620 
   1621 class InternalArrayNoArgumentConstructorStub
   1622     : public CommonArrayConstructorStub {
   1623  public:
   1624   InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
   1625       : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
   1626 
   1627  private:
   1628   void PrintName(std::ostream& os) const override {  // NOLINT
   1629     os << "InternalArrayNoArgumentConstructorStub";
   1630   }
   1631 
   1632   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
   1633   DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor,
   1634                             CommonArrayConstructorStub);
   1635 };
   1636 
   1637 class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub {
   1638  public:
   1639   ArraySingleArgumentConstructorStub(
   1640       Isolate* isolate, ElementsKind kind,
   1641       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
   1642       : CommonArrayConstructorStub(isolate, kind, override_mode) {}
   1643 
   1644  private:
   1645   void PrintName(std::ostream& os) const override {  // NOLINT
   1646     os << "ArraySingleArgumentConstructorStub";
   1647   }
   1648 
   1649   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
   1650   DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor,
   1651                             CommonArrayConstructorStub);
   1652 };
   1653 
   1654 class InternalArraySingleArgumentConstructorStub
   1655     : public CommonArrayConstructorStub {
   1656  public:
   1657   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
   1658                                              ElementsKind kind)
   1659       : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
   1660 
   1661  private:
   1662   void PrintName(std::ostream& os) const override {  // NOLINT
   1663     os << "InternalArraySingleArgumentConstructorStub";
   1664   }
   1665 
   1666   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
   1667   DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor,
   1668                             CommonArrayConstructorStub);
   1669 };
   1670 
   1671 class ArrayNArgumentsConstructorStub : public PlatformCodeStub {
   1672  public:
   1673   explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
   1674       : PlatformCodeStub(isolate) {}
   1675 
   1676   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
   1677     return ArrayNArgumentsConstructorDescriptor(isolate());
   1678   }
   1679 
   1680  private:
   1681   DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub);
   1682 };
   1683 
   1684 class StoreSlowElementStub : public TurboFanCodeStub {
   1685  public:
   1686   StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode)
   1687       : TurboFanCodeStub(isolate) {
   1688     minor_key_ = CommonStoreModeBits::encode(mode);
   1689   }
   1690 
   1691   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
   1692   ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
   1693 
   1694  private:
   1695   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
   1696   DEFINE_TURBOFAN_CODE_STUB(StoreSlowElement, TurboFanCodeStub);
   1697 };
   1698 
   1699 class ToBooleanICStub : public HydrogenCodeStub {
   1700  public:
   1701   ToBooleanICStub(Isolate* isolate, ExtraICState state)
   1702       : HydrogenCodeStub(isolate) {
   1703     set_sub_minor_key(HintsBits::encode(static_cast<uint16_t>(state)));
   1704   }
   1705 
   1706   bool UpdateStatus(Handle<Object> object);
   1707   ToBooleanHints hints() const {
   1708     return ToBooleanHints(HintsBits::decode(sub_minor_key()));
   1709   }
   1710 
   1711   Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
   1712   void PrintState(std::ostream& os) const override;  // NOLINT
   1713 
   1714   bool SometimesSetsUpAFrame() override { return false; }
   1715 
   1716   static Handle<Code> GetUninitialized(Isolate* isolate) {
   1717     return ToBooleanICStub(isolate, UNINITIALIZED).GetCode();
   1718   }
   1719 
   1720   ExtraICState GetExtraICState() const override { return hints(); }
   1721 
   1722   InlineCacheState GetICState() const {
   1723     if (hints() == ToBooleanHint::kNone) {
   1724       return ::v8::internal::UNINITIALIZED;
   1725     } else {
   1726       return MONOMORPHIC;
   1727     }
   1728   }
   1729 
   1730  private:
   1731   ToBooleanICStub(Isolate* isolate, InitializationState init_state)
   1732       : HydrogenCodeStub(isolate, init_state) {}
   1733 
   1734   static const int kNumHints = 8;
   1735   STATIC_ASSERT(static_cast<int>(ToBooleanHint::kAny) ==
   1736                 ((1 << kNumHints) - 1));
   1737   class HintsBits : public BitField<uint16_t, 0, kNumHints> {};
   1738 
   1739   DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
   1740   DEFINE_HYDROGEN_CODE_STUB(ToBooleanIC, HydrogenCodeStub);
   1741 };
   1742 
   1743 class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
   1744  public:
   1745   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
   1746                                  ElementsKind to_kind, bool is_jsarray,
   1747                                  KeyedAccessStoreMode store_mode)
   1748       : TurboFanCodeStub(isolate) {
   1749     minor_key_ = CommonStoreModeBits::encode(store_mode) |
   1750                  FromBits::encode(from_kind) | ToBits::encode(to_kind) |
   1751                  IsJSArrayBits::encode(is_jsarray);
   1752   }
   1753 
   1754   ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
   1755   ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
   1756   bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
   1757   KeyedAccessStoreMode store_mode() const {
   1758     return CommonStoreModeBits::decode(minor_key_);
   1759   }
   1760 
   1761   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
   1762   ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
   1763 
   1764  private:
   1765   class FromBits
   1766       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
   1767   class ToBits : public BitField<ElementsKind, 11, 8> {};
   1768   class IsJSArrayBits : public BitField<bool, 19, 1> {};
   1769 
   1770   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
   1771   DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
   1772 };
   1773 
   1774 
   1775 class StubFailureTrampolineStub : public PlatformCodeStub {
   1776  public:
   1777   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
   1778       : PlatformCodeStub(isolate) {
   1779     minor_key_ = FunctionModeField::encode(function_mode);
   1780   }
   1781 
   1782   static void GenerateAheadOfTime(Isolate* isolate);
   1783 
   1784  private:
   1785   StubFunctionMode function_mode() const {
   1786     return FunctionModeField::decode(minor_key_);
   1787   }
   1788 
   1789   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
   1790 
   1791   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
   1792   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
   1793 };
   1794 
   1795 
   1796 class ProfileEntryHookStub : public PlatformCodeStub {
   1797  public:
   1798   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
   1799 
   1800   // The profile entry hook function is not allowed to cause a GC.
   1801   bool SometimesSetsUpAFrame() override { return false; }
   1802 
   1803   // Generates a call to the entry hook if it's enabled.
   1804   static void MaybeCallEntryHook(MacroAssembler* masm);
   1805 
   1806  private:
   1807   static void EntryHookTrampoline(intptr_t function,
   1808                                   intptr_t stack_pointer,
   1809                                   Isolate* isolate);
   1810 
   1811   // ProfileEntryHookStub is called at the start of a function, so it has the
   1812   // same register set.
   1813   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
   1814   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
   1815 };
   1816 
   1817 
   1818 class StoreBufferOverflowStub : public PlatformCodeStub {
   1819  public:
   1820   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
   1821       : PlatformCodeStub(isolate) {
   1822     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
   1823   }
   1824 
   1825   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
   1826   bool SometimesSetsUpAFrame() override { return false; }
   1827 
   1828  private:
   1829   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
   1830 
   1831   class SaveDoublesBits : public BitField<bool, 0, 1> {};
   1832 
   1833   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
   1834   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
   1835 };
   1836 
   1837 class SubStringStub : public TurboFanCodeStub {
   1838  public:
   1839   explicit SubStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
   1840 
   1841   static compiler::Node* Generate(CodeStubAssembler* assembler,
   1842                                   compiler::Node* string, compiler::Node* from,
   1843                                   compiler::Node* to, compiler::Node* context);
   1844 
   1845   DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString);
   1846   DEFINE_TURBOFAN_CODE_STUB(SubString, TurboFanCodeStub);
   1847 };
   1848 
   1849 
   1850 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
   1851 #undef DEFINE_PLATFORM_CODE_STUB
   1852 #undef DEFINE_HANDLER_CODE_STUB
   1853 #undef DEFINE_HYDROGEN_CODE_STUB
   1854 #undef DEFINE_CODE_STUB
   1855 #undef DEFINE_CODE_STUB_BASE
   1856 
   1857 }  // namespace internal
   1858 }  // namespace v8
   1859 
   1860 #endif  // V8_CODE_STUBS_H_
   1861