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/interface-descriptors.h"
      9 #include "src/type-hints.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 
     14 // Forward declarations.
     15 class Isolate;
     16 namespace compiler {
     17 class CodeAssemblerState;
     18 }
     19 
     20 // List of code stubs used on all platforms.
     21 #define CODE_STUB_LIST_ALL_PLATFORMS(V)     \
     22   /* --- PlatformCodeStubs --- */           \
     23   V(CallApiCallback)                        \
     24   V(CallApiGetter)                          \
     25   V(JSEntry)                                \
     26   V(ProfileEntryHook)                       \
     27   /* --- TurboFanCodeStubs --- */           \
     28   V(StoreSlowElement)                       \
     29   V(StoreInArrayLiteralSlow)                \
     30   V(ElementsTransitionAndStore)             \
     31   V(KeyedLoadSloppyArguments)               \
     32   V(KeyedStoreSloppyArguments)              \
     33   V(StoreFastElement)                       \
     34   V(StoreInterceptor)                       \
     35   V(LoadIndexedInterceptor)
     36 
     37 // List of code stubs only used on ARM 32 bits platforms.
     38 #if V8_TARGET_ARCH_ARM
     39 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
     40 
     41 #else
     42 #define CODE_STUB_LIST_ARM(V)
     43 #endif
     44 
     45 // List of code stubs only used on ARM 64 bits platforms.
     46 #if V8_TARGET_ARCH_ARM64
     47 #define CODE_STUB_LIST_ARM64(V) V(DirectCEntry)
     48 
     49 #else
     50 #define CODE_STUB_LIST_ARM64(V)
     51 #endif
     52 
     53 // List of code stubs only used on PPC platforms.
     54 #ifdef V8_TARGET_ARCH_PPC
     55 #define CODE_STUB_LIST_PPC(V) V(DirectCEntry)
     56 #else
     57 #define CODE_STUB_LIST_PPC(V)
     58 #endif
     59 
     60 // List of code stubs only used on MIPS platforms.
     61 #if V8_TARGET_ARCH_MIPS
     62 #define CODE_STUB_LIST_MIPS(V) V(DirectCEntry)
     63 #elif V8_TARGET_ARCH_MIPS64
     64 #define CODE_STUB_LIST_MIPS(V) V(DirectCEntry)
     65 #else
     66 #define CODE_STUB_LIST_MIPS(V)
     67 #endif
     68 
     69 // List of code stubs only used on S390 platforms.
     70 #ifdef V8_TARGET_ARCH_S390
     71 #define CODE_STUB_LIST_S390(V) V(DirectCEntry)
     72 #else
     73 #define CODE_STUB_LIST_S390(V)
     74 #endif
     75 
     76 // Combined list of code stubs.
     77 #define CODE_STUB_LIST(V)         \
     78   CODE_STUB_LIST_ALL_PLATFORMS(V) \
     79   CODE_STUB_LIST_ARM(V)           \
     80   CODE_STUB_LIST_ARM64(V)         \
     81   CODE_STUB_LIST_PPC(V)           \
     82   CODE_STUB_LIST_MIPS(V)          \
     83   CODE_STUB_LIST_S390(V)
     84 
     85 static const int kHasReturnedMinusZeroSentinel = 1;
     86 
     87 class CodeStub : public ZoneObject {
     88  public:
     89   enum Major {
     90     // TODO(mvstanton): eliminate the NoCache key by getting rid
     91     //                  of the non-monomorphic-cache.
     92     NoCache = 0,  // marker for stubs that do custom caching]
     93 #define DEF_ENUM(name) name,
     94     CODE_STUB_LIST(DEF_ENUM)
     95 #undef DEF_ENUM
     96     NUMBER_OF_IDS
     97   };
     98 
     99   // Retrieve the code for the stub. Generate the code if needed.
    100   Handle<Code> GetCode();
    101 
    102   static Major MajorKeyFromKey(uint32_t key) {
    103     return static_cast<Major>(MajorKeyBits::decode(key));
    104   }
    105   static uint32_t MinorKeyFromKey(uint32_t key) {
    106     return MinorKeyBits::decode(key);
    107   }
    108 
    109   // Gets the major key from a code object that is a code stub or binary op IC.
    110   static Major GetMajorKey(const Code* code_stub);
    111 
    112   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
    113 
    114   static const char* MajorName(Major major_key);
    115 
    116   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
    117   virtual ~CodeStub() {}
    118 
    119   static void GenerateStubsAheadOfTime(Isolate* isolate);
    120 
    121   // Some stubs put untagged junk on the stack that cannot be scanned by the
    122   // GC.  This means that we must be statically sure that no GC can occur while
    123   // they are running.  If that is the case they should override this to return
    124   // true, which will cause an assertion if we try to call something that can
    125   // GC or if we try to put a stack frame on top of the junk, which would not
    126   // result in a traversable stack.
    127   virtual bool SometimesSetsUpAFrame() { return true; }
    128 
    129   // Lookup the code in the (possibly custom) cache.
    130   bool FindCodeInCache(Code** code_out);
    131 
    132   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
    133 
    134   virtual int GetStackParameterCount() const {
    135     return GetCallInterfaceDescriptor().GetStackParameterCount();
    136   }
    137 
    138   static void InitializeDescriptor(Isolate* isolate, uint32_t key,
    139                                    CodeStubDescriptor* desc);
    140 
    141   static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
    142 
    143   // Returns information for computing the number key.
    144   virtual Major MajorKey() const = 0;
    145   uint32_t MinorKey() const { return minor_key_; }
    146 
    147   friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
    148     s.PrintName(os);
    149     return os;
    150   }
    151 
    152   Isolate* isolate() const { return isolate_; }
    153   void set_isolate(Isolate* isolate) {
    154     DCHECK_NOT_NULL(isolate);
    155     DCHECK(isolate_ == nullptr || isolate_ == isolate);
    156     isolate_ = isolate;
    157   }
    158 
    159   void DeleteStubFromCacheForTesting();
    160 
    161  protected:
    162   CodeStub(uint32_t key, Isolate* isolate)
    163       : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
    164 
    165   // Generates the assembler code for the stub.
    166   virtual Handle<Code> GenerateCode() = 0;
    167 
    168   // Returns whether the code generated for this stub needs to be allocated as
    169   // a fixed (non-moveable) code object.
    170   // TODO(jgruber): Only required by DirectCEntryStub. Can be removed when/if
    171   // that is ported to a builtin.
    172   virtual Movability NeedsImmovableCode() { return kMovable; }
    173 
    174   virtual void PrintName(std::ostream& os) const;        // NOLINT
    175   virtual void PrintBaseName(std::ostream& os) const;    // NOLINT
    176   virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
    177 
    178   // Computes the key based on major and minor.
    179   uint32_t GetKey() {
    180     DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
    181     return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
    182   }
    183 
    184   uint32_t minor_key_;
    185 
    186  private:
    187   // Perform bookkeeping required after code generation when stub code is
    188   // initially generated.
    189   void RecordCodeGeneration(Handle<Code> code);
    190 
    191   // Activate newly generated stub. Is called after
    192   // registering stub in the stub cache.
    193   virtual void Activate(Code* code) { }
    194 
    195   // We use this dispatch to statically instantiate the correct code stub for
    196   // the given stub key and call the passed function with that code stub.
    197   typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
    198   static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
    199                        DispatchedCall call);
    200 
    201   static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
    202 
    203   STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
    204   class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
    205   class MinorKeyBits: public BitField<uint32_t,
    206       kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
    207 
    208   friend class BreakPointIterator;
    209 
    210   Isolate* isolate_;
    211 };
    212 
    213 
    214 #define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
    215  public:                                                        \
    216   NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
    217                                                                 \
    218  private:                                                       \
    219   DISALLOW_COPY_AND_ASSIGN(NAME)
    220 
    221 
    222 #define DEFINE_CODE_STUB(NAME, SUPER)                      \
    223  public:                                                   \
    224   inline Major MajorKey() const override { return NAME; }; \
    225                                                            \
    226   DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
    227 
    228 
    229 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)  \
    230  private:                                       \
    231   void Generate(MacroAssembler* masm) override; \
    232   DEFINE_CODE_STUB(NAME, SUPER)
    233 
    234 
    235 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                               \
    236  public:                                                                     \
    237   void GenerateAssembly(compiler::CodeAssemblerState* state) const override; \
    238   DEFINE_CODE_STUB(NAME, SUPER)
    239 
    240 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                          \
    241  public:                                                                \
    242   typedef NAME##Descriptor Descriptor;                                  \
    243   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    244     return Descriptor();                                                \
    245   }
    246 
    247 // There are some code stubs we just can't describe right now with a
    248 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
    249 // An attempt to retrieve a descriptor will fail.
    250 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                         \
    251  public:                                                                \
    252   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
    253     UNREACHABLE();                                                      \
    254     return CallInterfaceDescriptor();                                   \
    255   }
    256 
    257 
    258 class PlatformCodeStub : public CodeStub {
    259  public:
    260   // Retrieve the code for the stub. Generate the code if needed.
    261   Handle<Code> GenerateCode() override;
    262 
    263  protected:
    264   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
    265 
    266   // Generates the assembler code for the stub.
    267   virtual void Generate(MacroAssembler* masm) = 0;
    268 
    269   // Generates the exception handler table for the stub.
    270   virtual int GenerateHandlerTable(MacroAssembler* masm);
    271 
    272   DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
    273 };
    274 
    275 
    276 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
    277 
    278 
    279 class CodeStubDescriptor {
    280  public:
    281   explicit CodeStubDescriptor(CodeStub* stub);
    282 
    283   CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
    284 
    285   void Initialize(Address deoptimization_handler = kNullAddress,
    286                   int hint_stack_parameter_count = -1,
    287                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
    288   void Initialize(Register stack_parameter_count,
    289                   Address deoptimization_handler = kNullAddress,
    290                   int hint_stack_parameter_count = -1,
    291                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
    292 
    293   void SetMissHandler(Runtime::FunctionId id) {
    294     miss_handler_id_ = id;
    295     miss_handler_ = ExternalReference::Create(Runtime::FunctionForId(id));
    296     has_miss_handler_ = true;
    297     // Our miss handler infrastructure doesn't currently support
    298     // variable stack parameter counts.
    299     DCHECK(!stack_parameter_count_.is_valid());
    300   }
    301 
    302   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
    303   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
    304 
    305   int GetRegisterParameterCount() const {
    306     return call_descriptor().GetRegisterParameterCount();
    307   }
    308 
    309   int GetStackParameterCount() const {
    310     return call_descriptor().GetStackParameterCount();
    311   }
    312 
    313   int GetParameterCount() const {
    314     return call_descriptor().GetParameterCount();
    315   }
    316 
    317   Register GetRegisterParameter(int index) const {
    318     return call_descriptor().GetRegisterParameter(index);
    319   }
    320 
    321   MachineType GetParameterType(int index) const {
    322     return call_descriptor().GetParameterType(index);
    323   }
    324 
    325   ExternalReference miss_handler() const {
    326     DCHECK(has_miss_handler_);
    327     return miss_handler_;
    328   }
    329 
    330   Runtime::FunctionId miss_handler_id() const {
    331     DCHECK(has_miss_handler_);
    332     return miss_handler_id_;
    333   }
    334 
    335   bool has_miss_handler() const {
    336     return has_miss_handler_;
    337   }
    338 
    339   int GetHandlerParameterCount() const {
    340     int params = GetParameterCount();
    341     if (PassesArgumentsToDeoptimizationHandler()) {
    342       params += 1;
    343     }
    344     return params;
    345   }
    346 
    347   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
    348   Register stack_parameter_count() const { return stack_parameter_count_; }
    349   StubFunctionMode function_mode() const { return function_mode_; }
    350   Address deoptimization_handler() const { return deoptimization_handler_; }
    351 
    352  private:
    353   bool PassesArgumentsToDeoptimizationHandler() const {
    354     return stack_parameter_count_.is_valid();
    355   }
    356 
    357   Isolate* isolate_;
    358   CallInterfaceDescriptor call_descriptor_;
    359   Register stack_parameter_count_;
    360   // If hint_stack_parameter_count_ > 0, the code stub can optimize the
    361   // return sequence. Default value is -1, which means it is ignored.
    362   int hint_stack_parameter_count_;
    363   StubFunctionMode function_mode_;
    364 
    365   Address deoptimization_handler_;
    366 
    367   ExternalReference miss_handler_;
    368   Runtime::FunctionId miss_handler_id_;
    369   bool has_miss_handler_;
    370 };
    371 
    372 
    373 class TurboFanCodeStub : public CodeStub {
    374  public:
    375   // Retrieve the code for the stub. Generate the code if needed.
    376   Handle<Code> GenerateCode() override;
    377 
    378   int GetStackParameterCount() const override {
    379     return GetCallInterfaceDescriptor().GetStackParameterCount();
    380   }
    381 
    382  protected:
    383   explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
    384 
    385   virtual void GenerateAssembly(compiler::CodeAssemblerState* state) const = 0;
    386 
    387  private:
    388   DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
    389 };
    390 
    391 }  // namespace internal
    392 }  // namespace v8
    393 
    394 #if V8_TARGET_ARCH_IA32
    395 #elif V8_TARGET_ARCH_X64
    396 #elif V8_TARGET_ARCH_ARM64
    397 #include "src/arm64/code-stubs-arm64.h"
    398 #elif V8_TARGET_ARCH_ARM
    399 #include "src/arm/code-stubs-arm.h"
    400 #elif V8_TARGET_ARCH_PPC
    401 #include "src/ppc/code-stubs-ppc.h"
    402 #elif V8_TARGET_ARCH_MIPS
    403 #include "src/mips/code-stubs-mips.h"
    404 #elif V8_TARGET_ARCH_MIPS64
    405 #include "src/mips64/code-stubs-mips64.h"
    406 #elif V8_TARGET_ARCH_S390
    407 #include "src/s390/code-stubs-s390.h"
    408 #else
    409 #error Unsupported target architecture.
    410 #endif
    411 
    412 namespace v8 {
    413 namespace internal {
    414 
    415 // TODO(jgruber): Convert this stub into a builtin.
    416 class StoreInterceptorStub : public TurboFanCodeStub {
    417  public:
    418   explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
    419 
    420   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    421   DEFINE_TURBOFAN_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
    422 };
    423 
    424 // TODO(jgruber): Convert this stub into a builtin.
    425 class LoadIndexedInterceptorStub : public TurboFanCodeStub {
    426  public:
    427   explicit LoadIndexedInterceptorStub(Isolate* isolate)
    428       : TurboFanCodeStub(isolate) {}
    429 
    430   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
    431   DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
    432 };
    433 
    434 // TODO(jgruber): Convert this stub into a builtin.
    435 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
    436  public:
    437   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
    438       : TurboFanCodeStub(isolate) {}
    439 
    440  protected:
    441   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
    442   DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub);
    443 };
    444 
    445 
    446 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
    447 
    448 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
    449  public:
    450   explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
    451                                          KeyedAccessStoreMode mode)
    452       : TurboFanCodeStub(isolate) {
    453     minor_key_ = CommonStoreModeBits::encode(mode);
    454   }
    455 
    456  protected:
    457   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    458   DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
    459 };
    460 
    461 class CallApiCallbackStub : public PlatformCodeStub {
    462  public:
    463   static const int kArgBits = 7;
    464   static const int kArgMax = (1 << kArgBits) - 1;
    465 
    466   CallApiCallbackStub(Isolate* isolate, int argc)
    467       : PlatformCodeStub(isolate) {
    468     CHECK_LE(0, argc);  // The argc in {0, 1} cases are covered by builtins.
    469     CHECK_LE(argc, kArgMax);
    470     minor_key_ = ArgumentBits::encode(argc);
    471   }
    472 
    473  private:
    474   int argc() const { return ArgumentBits::decode(minor_key_); }
    475 
    476   class ArgumentBits : public BitField<int, 0, kArgBits> {};
    477 
    478   friend class Builtins;  // For generating the related builtin.
    479 
    480   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback);
    481   DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub);
    482 };
    483 
    484 // TODO(jgruber): This stub only exists to avoid code duplication between
    485 // code-stubs-<arch>.cc and builtins-<arch>.cc. If CallApiCallbackStub is ever
    486 // completely removed, CallApiGetterStub can also be deleted.
    487 class CallApiGetterStub : public PlatformCodeStub {
    488  private:
    489   // For generating the related builtin.
    490   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
    491   friend class Builtins;
    492 
    493   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
    494   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
    495 };
    496 
    497 class JSEntryStub : public PlatformCodeStub {
    498  public:
    499   enum class SpecialTarget { kNone, kRunMicrotasks };
    500   JSEntryStub(Isolate* isolate, StackFrame::Type type)
    501       : PlatformCodeStub(isolate) {
    502     DCHECK(type == StackFrame::ENTRY || type == StackFrame::CONSTRUCT_ENTRY);
    503     minor_key_ = StackFrameTypeBits::encode(type) |
    504                  SpecialTargetBits::encode(SpecialTarget::kNone);
    505   }
    506 
    507   JSEntryStub(Isolate* isolate, SpecialTarget target)
    508       : PlatformCodeStub(isolate) {
    509     minor_key_ = StackFrameTypeBits::encode(StackFrame::ENTRY) |
    510                  SpecialTargetBits::encode(target);
    511   }
    512 
    513  private:
    514   int GenerateHandlerTable(MacroAssembler* masm) override;
    515 
    516   void PrintName(std::ostream& os) const override {  // NOLINT
    517     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
    518                                        : "JSConstructEntryStub");
    519   }
    520 
    521   StackFrame::Type type() const {
    522     return StackFrameTypeBits::decode(minor_key_);
    523   }
    524 
    525   SpecialTarget special_target() const {
    526     return SpecialTargetBits::decode(minor_key_);
    527   }
    528 
    529   Handle<Code> EntryTrampoline() {
    530     switch (special_target()) {
    531       case SpecialTarget::kNone:
    532         return (type() == StackFrame::CONSTRUCT_ENTRY)
    533                    ? BUILTIN_CODE(isolate(), JSConstructEntryTrampoline)
    534                    : BUILTIN_CODE(isolate(), JSEntryTrampoline);
    535       case SpecialTarget::kRunMicrotasks:
    536         return BUILTIN_CODE(isolate(), RunMicrotasks);
    537     }
    538     UNREACHABLE();
    539     return Handle<Code>();
    540   }
    541 
    542   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
    543   class SpecialTargetBits
    544       : public BitField<SpecialTarget, StackFrameTypeBits::kNext, 1> {};
    545 
    546   int handler_offset_;
    547 
    548   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
    549   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
    550 };
    551 
    552 class StoreFastElementStub : public TurboFanCodeStub {
    553  public:
    554   StoreFastElementStub(Isolate* isolate, bool is_js_array,
    555                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
    556       : TurboFanCodeStub(isolate) {
    557     minor_key_ = CommonStoreModeBits::encode(mode) |
    558                  ElementsKindBits::encode(elements_kind) |
    559                  IsJSArrayBits::encode(is_js_array);
    560   }
    561 
    562   static void GenerateAheadOfTime(Isolate* isolate);
    563 
    564   bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
    565 
    566   ElementsKind elements_kind() const {
    567     return ElementsKindBits::decode(minor_key_);
    568   }
    569 
    570   KeyedAccessStoreMode store_mode() const {
    571     return CommonStoreModeBits::decode(minor_key_);
    572   }
    573 
    574  private:
    575   class ElementsKindBits
    576       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
    577   class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
    578 
    579   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    580   DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
    581 };
    582 
    583 class StoreSlowElementStub : public TurboFanCodeStub {
    584  public:
    585   StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode)
    586       : TurboFanCodeStub(isolate) {
    587     minor_key_ = CommonStoreModeBits::encode(mode);
    588   }
    589 
    590  private:
    591   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    592   DEFINE_TURBOFAN_CODE_STUB(StoreSlowElement, TurboFanCodeStub);
    593 };
    594 
    595 class StoreInArrayLiteralSlowStub : public TurboFanCodeStub {
    596  public:
    597   StoreInArrayLiteralSlowStub(Isolate* isolate, KeyedAccessStoreMode mode)
    598       : TurboFanCodeStub(isolate) {
    599     minor_key_ = CommonStoreModeBits::encode(mode);
    600   }
    601 
    602  private:
    603   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
    604   DEFINE_TURBOFAN_CODE_STUB(StoreInArrayLiteralSlow, TurboFanCodeStub);
    605 };
    606 
    607 class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
    608  public:
    609   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
    610                                  ElementsKind to_kind, bool is_jsarray,
    611                                  KeyedAccessStoreMode store_mode)
    612       : TurboFanCodeStub(isolate) {
    613     minor_key_ = CommonStoreModeBits::encode(store_mode) |
    614                  FromBits::encode(from_kind) | ToBits::encode(to_kind) |
    615                  IsJSArrayBits::encode(is_jsarray);
    616   }
    617 
    618   ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
    619   ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
    620   bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
    621   KeyedAccessStoreMode store_mode() const {
    622     return CommonStoreModeBits::decode(minor_key_);
    623   }
    624 
    625  private:
    626   class FromBits
    627       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
    628   class ToBits : public BitField<ElementsKind, 11, 8> {};
    629   class IsJSArrayBits : public BitField<bool, 19, 1> {};
    630 
    631   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
    632   DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
    633 };
    634 
    635 // TODO(jgruber): Convert this stub into a builtin.
    636 class ProfileEntryHookStub : public PlatformCodeStub {
    637  public:
    638   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
    639 
    640   // The profile entry hook function is not allowed to cause a GC.
    641   bool SometimesSetsUpAFrame() override { return false; }
    642 
    643   // Generates a call to the entry hook if it's enabled.
    644   static void MaybeCallEntryHook(MacroAssembler* masm);
    645   static void MaybeCallEntryHookDelayed(TurboAssembler* tasm, Zone* zone);
    646 
    647  private:
    648   static void EntryHookTrampoline(intptr_t function,
    649                                   intptr_t stack_pointer,
    650                                   Isolate* isolate);
    651 
    652   // ProfileEntryHookStub is called at the start of a function, so it has the
    653   // same register set.
    654   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
    655   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
    656 };
    657 
    658 
    659 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
    660 #undef DEFINE_PLATFORM_CODE_STUB
    661 #undef DEFINE_CODE_STUB
    662 #undef DEFINE_CODE_STUB_BASE
    663 
    664 }  // namespace internal
    665 }  // namespace v8
    666 
    667 #endif  // V8_CODE_STUBS_H_
    668