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