• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MajorKeyFromKey(uint32_t key)102   static Major MajorKeyFromKey(uint32_t key) {
103     return static_cast<Major>(MajorKeyBits::decode(key));
104   }
MinorKeyFromKey(uint32_t key)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 
NoCacheKey()112   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
113 
114   static const char* MajorName(Major major_key);
115 
CodeStub(Isolate * isolate)116   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
~CodeStub()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.
SometimesSetsUpAFrame()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 
GetStackParameterCount()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;
MinorKey()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 
isolate()152   Isolate* isolate() const { return isolate_; }
set_isolate(Isolate * 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:
CodeStub(uint32_t key,Isolate * isolate)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.
NeedsImmovableCode()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
PrintState(std::ostream & os)176   virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
177 
178   // Computes the key based on major and minor.
GetKey()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.
Activate(Code * code)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:
PlatformCodeStub(Isolate * isolate)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 
SetMissHandler(Runtime::FunctionId id)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 
set_call_descriptor(CallInterfaceDescriptor d)302   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
call_descriptor()303   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
304 
GetRegisterParameterCount()305   int GetRegisterParameterCount() const {
306     return call_descriptor().GetRegisterParameterCount();
307   }
308 
GetStackParameterCount()309   int GetStackParameterCount() const {
310     return call_descriptor().GetStackParameterCount();
311   }
312 
GetParameterCount()313   int GetParameterCount() const {
314     return call_descriptor().GetParameterCount();
315   }
316 
GetRegisterParameter(int index)317   Register GetRegisterParameter(int index) const {
318     return call_descriptor().GetRegisterParameter(index);
319   }
320 
GetParameterType(int index)321   MachineType GetParameterType(int index) const {
322     return call_descriptor().GetParameterType(index);
323   }
324 
miss_handler()325   ExternalReference miss_handler() const {
326     DCHECK(has_miss_handler_);
327     return miss_handler_;
328   }
329 
miss_handler_id()330   Runtime::FunctionId miss_handler_id() const {
331     DCHECK(has_miss_handler_);
332     return miss_handler_id_;
333   }
334 
has_miss_handler()335   bool has_miss_handler() const {
336     return has_miss_handler_;
337   }
338 
GetHandlerParameterCount()339   int GetHandlerParameterCount() const {
340     int params = GetParameterCount();
341     if (PassesArgumentsToDeoptimizationHandler()) {
342       params += 1;
343     }
344     return params;
345   }
346 
hint_stack_parameter_count()347   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
stack_parameter_count()348   Register stack_parameter_count() const { return stack_parameter_count_; }
function_mode()349   StubFunctionMode function_mode() const { return function_mode_; }
deoptimization_handler()350   Address deoptimization_handler() const { return deoptimization_handler_; }
351 
352  private:
PassesArgumentsToDeoptimizationHandler()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 
GetStackParameterCount()378   int GetStackParameterCount() const override {
379     return GetCallInterfaceDescriptor().GetStackParameterCount();
380   }
381 
382  protected:
TurboFanCodeStub(Isolate * isolate)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:
StoreInterceptorStub(Isolate * isolate)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:
LoadIndexedInterceptorStub(Isolate * isolate)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:
KeyedLoadSloppyArgumentsStub(Isolate * isolate)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:
KeyedStoreSloppyArgumentsStub(Isolate * isolate,KeyedAccessStoreMode mode)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 
CallApiCallbackStub(Isolate * isolate,int argc)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:
argc()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.
CallApiGetterStub(Isolate * isolate)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 };
JSEntryStub(Isolate * isolate,StackFrame::Type type)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 
JSEntryStub(Isolate * isolate,SpecialTarget target)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 
PrintName(std::ostream & os)516   void PrintName(std::ostream& os) const override {  // NOLINT
517     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
518                                        : "JSConstructEntryStub");
519   }
520 
type()521   StackFrame::Type type() const {
522     return StackFrameTypeBits::decode(minor_key_);
523   }
524 
special_target()525   SpecialTarget special_target() const {
526     return SpecialTargetBits::decode(minor_key_);
527   }
528 
EntryTrampoline()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:
StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)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 
is_js_array()564   bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
565 
elements_kind()566   ElementsKind elements_kind() const {
567     return ElementsKindBits::decode(minor_key_);
568   }
569 
store_mode()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:
StoreSlowElementStub(Isolate * isolate,KeyedAccessStoreMode mode)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:
StoreInArrayLiteralSlowStub(Isolate * isolate,KeyedAccessStoreMode mode)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:
ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)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 
from_kind()618   ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
to_kind()619   ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
is_jsarray()620   bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
store_mode()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:
ProfileEntryHookStub(Isolate * isolate)638   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
639 
640   // The profile entry hook function is not allowed to cause a GC.
SometimesSetsUpAFrame()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