• 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/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 
MajorKeyFromKey(uint32_t key)182   static Major MajorKeyFromKey(uint32_t key) {
183     return static_cast<Major>(MajorKeyBits::decode(key));
184   }
MinorKeyFromKey(uint32_t key)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.
GetMajorKey(Code * code_stub)190   static Major GetMajorKey(Code* code_stub) {
191     return MajorKeyFromKey(code_stub->stub_key());
192   }
193 
NoCacheKey()194   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
195 
196   static const char* MajorName(Major major_key);
197 
CodeStub(Isolate * isolate)198   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
~CodeStub()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.
SometimesSetsUpAFrame()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 
GetStackParameterCount()217   virtual int GetStackParameterCount() const {
218     return GetCallInterfaceDescriptor().GetStackParameterCount();
219   }
220 
InitializeDescriptor(CodeStubDescriptor * descriptor)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;
MinorKey()230   uint32_t MinorKey() const { return minor_key_; }
231 
232   // BinaryOpStub needs to override this.
233   virtual Code::Kind GetCodeKind() const;
234 
GetExtraICState()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 
isolate()244   Isolate* isolate() const { return isolate_; }
245 
246   void DeleteStubFromCacheForTesting();
247 
248  protected:
CodeStub(uint32_t key,Isolate * isolate)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.
NeedsImmovableCode()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
PrintState(std::ostream & os)261   virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
262 
263   // Computes the key based on major and minor.
GetKey()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.
FinishCode(Handle<Code> code)277   virtual void FinishCode(Handle<Code> code) { }
278 
279   // Activate newly generated stub. Is called after
280   // registering stub in the stub cache.
Activate(Code * code)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.
AddToSpecialCache(Handle<Code> new_object)286   virtual void AddToSpecialCache(Handle<Code> new_object) { }
287 
288   // Find code in a specialized cache, work is delegated to the specific stub.
FindCodeInSpecialCache(Code ** code_out)289   virtual bool FindCodeInSpecialCache(Code** code_out) {
290     return false;
291   }
292 
293   // If a stub uses a special cache override this.
UseSpecialCache()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:
PlatformCodeStub(Isolate * isolate)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 
SetMissHandler(Runtime::FunctionId id)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 
set_call_descriptor(CallInterfaceDescriptor d)429   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
call_descriptor()430   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
431 
GetRegisterParameterCount()432   int GetRegisterParameterCount() const {
433     return call_descriptor().GetRegisterParameterCount();
434   }
435 
GetStackParameterCount()436   int GetStackParameterCount() const {
437     return call_descriptor().GetStackParameterCount();
438   }
439 
GetParameterCount()440   int GetParameterCount() const {
441     return call_descriptor().GetParameterCount();
442   }
443 
GetRegisterParameter(int index)444   Register GetRegisterParameter(int index) const {
445     return call_descriptor().GetRegisterParameter(index);
446   }
447 
GetParameterType(int index)448   MachineType GetParameterType(int index) const {
449     return call_descriptor().GetParameterType(index);
450   }
451 
miss_handler()452   ExternalReference miss_handler() const {
453     DCHECK(has_miss_handler_);
454     return miss_handler_;
455   }
456 
miss_handler_id()457   Runtime::FunctionId miss_handler_id() const {
458     DCHECK(has_miss_handler_);
459     return miss_handler_id_;
460   }
461 
has_miss_handler()462   bool has_miss_handler() const {
463     return has_miss_handler_;
464   }
465 
GetHandlerParameterCount()466   int GetHandlerParameterCount() const {
467     int params = GetParameterCount();
468     if (PassesArgumentsToDeoptimizationHandler()) {
469       params += 1;
470     }
471     return params;
472   }
473 
hint_stack_parameter_count()474   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
stack_parameter_count()475   Register stack_parameter_count() const { return stack_parameter_count_; }
function_mode()476   StubFunctionMode function_mode() const { return function_mode_; }
deoptimization_handler()477   Address deoptimization_handler() const { return deoptimization_handler_; }
478 
479  private:
PassesArgumentsToDeoptimizationHandler()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>
GetUninitialized(Isolate * isolate)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 
IsUninitialized()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)
CodeStub(isolate)528       : CodeStub(isolate) {
529     minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
530   }
531 
set_sub_minor_key(uint32_t key)532   void set_sub_minor_key(uint32_t key) {
533     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
534   }
535 
sub_minor_key()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 
GetStackParameterCount()555   int GetStackParameterCount() const override {
556     return GetCallInterfaceDescriptor().GetStackParameterCount();
557   }
558 
559  protected:
TurboFanCodeStub(Isolate * isolate)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:
~RuntimeCallHelper()572   virtual ~RuntimeCallHelper() {}
573 
574   virtual void BeforeCall(MacroAssembler* masm) const = 0;
575 
576   virtual void AfterCall(MacroAssembler* masm) const = 0;
577 
578  protected:
RuntimeCallHelper()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:
StubRuntimeCallHelper()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:
NopRuntimeCallHelper()630   NopRuntimeCallHelper() {}
631 
BeforeCall(MacroAssembler * masm)632   void BeforeCall(MacroAssembler* masm) const override {}
633 
AfterCall(MacroAssembler * masm)634   void AfterCall(MacroAssembler* masm) const override {}
635 };
636 
637 
638 class StringLengthStub : public TurboFanCodeStub {
639  public:
StringLengthStub(Isolate * isolate)640   explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
641 
GetCodeKind()642   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
AddWithFeedbackStub(Isolate * isolate)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:
SubtractWithFeedbackStub(Isolate * isolate)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:
MultiplyWithFeedbackStub(Isolate * isolate)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:
DivideWithFeedbackStub(Isolate * isolate)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:
ModulusWithFeedbackStub(Isolate * isolate)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:
StoreInterceptorStub(Isolate * isolate)700   explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
701 
GetCodeKind()702   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
LoadIndexedInterceptorStub(Isolate * isolate)711   explicit LoadIndexedInterceptorStub(Isolate* isolate)
712       : TurboFanCodeStub(isolate) {}
713 
GetCodeKind()714   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
GetPropertyStub(Isolate * isolate)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:
NumberToStringStub(Isolate * isolate)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:
CreateAllocationSiteStub(Isolate * isolate)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:
CreateWeakCellStub(Isolate * isolate)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:
GrowArrayElementsStub(Isolate * isolate,ElementsKind kind)760   GrowArrayElementsStub(Isolate* isolate, ElementsKind kind)
761       : TurboFanCodeStub(isolate) {
762     minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind));
763   }
764 
elements_kind()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 
MathPowStub(Isolate * isolate,ExponentType exponent_type)812   MathPowStub(Isolate* isolate, ExponentType exponent_type)
813       : PlatformCodeStub(isolate) {
814     minor_key_ = ExponentTypeBits::encode(exponent_type);
815   }
816 
GetCallInterfaceDescriptor()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:
exponent_type()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:
CallICStub(Isolate * isolate,ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)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 
convert_mode()852   ConvertReceiverMode convert_mode() const {
853     return ConvertModeBits::decode(minor_key_);
854   }
tail_call_mode()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:
KeyedLoadSloppyArgumentsStub(Isolate * isolate)868   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
869       : TurboFanCodeStub(isolate) {}
870 
GetCodeKind()871   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
KeyedStoreSloppyArgumentsStub(Isolate * isolate,KeyedAccessStoreMode mode)884   explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
885                                          KeyedAccessStoreMode mode)
886       : TurboFanCodeStub(isolate) {
887     minor_key_ = CommonStoreModeBits::encode(mode);
888   }
889 
GetCodeKind()890   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
StoreGlobalStub(Isolate * isolate,PropertyCellType type,Maybe<PropertyCellConstantType> constant_type,bool check_global)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 
GetCodeKind()911   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()912   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
913 
property_cell_placeholder(Isolate * isolate)914   static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
915     return isolate->factory()->uninitialized_value();
916   }
917 
global_map_placeholder(Isolate * isolate)918   static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
919     return isolate->factory()->termination_exception();
920   }
921 
GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,Handle<PropertyCell> cell)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 
cell_type()934   PropertyCellType cell_type() const {
935     return CellTypeBits::decode(minor_key_);
936   }
937 
constant_type()938   PropertyCellConstantType constant_type() const {
939     DCHECK(PropertyCellType::kConstantType == cell_type());
940     return ConstantTypeBits::decode(minor_key_);
941   }
942 
check_global()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.
CallApiCallbackStub(Isolate * isolate,bool is_store,bool call_data_undefined,bool is_lazy)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.
CallApiCallbackStub(Isolate * isolate,int argc,bool call_data_undefined,bool is_lazy)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:
CallApiCallbackStub(Isolate * isolate,int argc,bool is_store,bool call_data_undefined,bool is_lazy)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 
is_store()983   bool is_store() const { return IsStoreBits::decode(minor_key_); }
is_lazy()984   bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
call_data_undefined()985   bool call_data_undefined() const {
986     return CallDataUndefinedBits::decode(minor_key_);
987   }
argc()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:
CallApiGetterStub(Isolate * isolate)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:
BinaryOpICStub(Isolate * isolate,Token::Value op)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 
BinaryOpICStub(Isolate * isolate,const BinaryOpICState & state)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 
GetCodeKind()1024   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1025 
GetExtraICState()1026   ExtraICState GetExtraICState() const final {
1027     return static_cast<ExtraICState>(sub_minor_key());
1028   }
1029 
state()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:
BinaryOpICWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)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 
GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site)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 
GetCodeKind()1063   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1064 
GetExtraICState()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:
state()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:
BinaryOpWithAllocationSiteStub(Isolate * isolate,Token::Value op)1086   BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op)
1087       : BinaryOpICStub(isolate, op) {}
1088 
BinaryOpWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1089   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1090       : BinaryOpICStub(isolate, state) {}
1091 
GetCodeKind()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:
StringAddStub(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)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 
flags()1107   StringAddFlags flags() const {
1108     return StringAddFlagsBits::decode(minor_key_);
1109   }
1110 
pretenure_flag()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:
CompareICStub(Isolate * isolate,Token::Value op,CompareICState::State left,CompareICState::State right,CompareICState::State state)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.
CompareICStub(Isolate * isolate,Token::Value op)1138   CompareICStub(Isolate* isolate, Token::Value op)
1139       : CompareICStub(isolate, op, CompareICState::UNINITIALIZED,
1140                       CompareICState::UNINITIALIZED,
1141                       CompareICState::UNINITIALIZED) {}
1142 
CompareICStub(Isolate * isolate,ExtraICState extra_ic_state)1143   CompareICStub(Isolate* isolate, ExtraICState extra_ic_state)
1144       : PlatformCodeStub(isolate) {
1145     minor_key_ = extra_ic_state;
1146   }
1147 
GetExtraICState()1148   ExtraICState GetExtraICState() const final {
1149     return static_cast<ExtraICState>(minor_key_);
1150   }
1151 
set_known_map(Handle<Map> map)1152   void set_known_map(Handle<Map> map) { known_map_ = map; }
1153 
1154   InlineCacheState GetICState() const;
1155 
op()1156   Token::Value op() const {
1157     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1158   }
1159 
left()1160   CompareICState::State left() const {
1161     return LeftStateBits::decode(minor_key_);
1162   }
right()1163   CompareICState::State right() const {
1164     return RightStateBits::decode(minor_key_);
1165   }
state()1166   CompareICState::State state() const { return StateBits::decode(minor_key_); }
1167 
1168  private:
GetCodeKind()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 
strict()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.
UseSpecialCache()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)
PlatformCodeStub(isolate)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:
save_doubles()1224   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
argv_in_register()1225   bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
is_builtin_exit()1226   bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); }
result_size()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:
JSEntryStub(Isolate * isolate,StackFrame::Type type)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 
PrintName(std::ostream & os)1252   void PrintName(std::ostream& os) const override {  // NOLINT
1253     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1254                                        : "JSConstructEntryStub");
1255   }
1256 
type()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:
RegExpExecStub(Isolate * isolate)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:
CallConstructStub(Isolate * isolate)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)
object_(object)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:
CallICTrampolineStub(Isolate * isolate,ConvertReceiverMode convert_mode,TailCallMode tail_call_mode)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 
convert_mode()1375   ConvertReceiverMode convert_mode() const {
1376     return ConvertModeBits::decode(minor_key_);
1377   }
tail_call_mode()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)
PlatformCodeStub(isolate)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 
SometimesSetsUpAFrame()1402   bool SometimesSetsUpAFrame() override { return false; }
1403 
1404  private:
source()1405   Register source() const {
1406     return Register::from_code(SourceRegisterBits::decode(minor_key_));
1407   }
destination()1408   Register destination() const {
1409     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
1410   }
is_truncating()1411   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
skip_fastpath()1412   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
offset()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:
ScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)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 
GetCodeKind()1445   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
1446 
context_index()1447   int context_index() const { return ContextIndexBits::decode(minor_key_); }
1448 
slot_index()1449   int slot_index() const { return SlotIndexBits::decode(minor_key_); }
1450 
Accepted(const ScriptContextTable::LookupResult * lookup_result)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:
LoadScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)1469   LoadScriptContextFieldStub(
1470       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
1471       : ScriptContextFieldStub(isolate, lookup_result) {}
1472 
GetExtraICState()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:
StoreScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)1483   StoreScriptContextFieldStub(
1484       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
1485       : ScriptContextFieldStub(isolate, lookup_result) {}
1486 
GetExtraICState()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:
StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)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 
is_js_array()1506   bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
1507 
elements_kind()1508   ElementsKind elements_kind() const {
1509     return ElementsKindBits::decode(minor_key_);
1510   }
1511 
store_mode()1512   KeyedAccessStoreMode store_mode() const {
1513     return CommonStoreModeBits::decode(minor_key_);
1514   }
1515 
GetCodeKind()1516   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
TransitionElementsKindStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind)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 
from_kind()1538   ElementsKind from_kind() const {
1539     return FromKindBits::decode(sub_minor_key());
1540   }
1541 
to_kind()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:
AllocateHeapNumberStub(Isolate * isolate)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:
CommonArrayConstructorStub(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)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 
set_sub_minor_key(uint32_t key)1577   void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
1578 
sub_minor_key()1579   uint32_t sub_minor_key() const { return minor_key_; }
1580 
CommonArrayConstructorStub(uint32_t key,Isolate * isolate)1581   CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
1582       : TurboFanCodeStub(key, isolate) {}
1583 
1584  public:
elements_kind()1585   ElementsKind elements_kind() const {
1586     return ElementsKindBits::decode(sub_minor_key());
1587   }
1588 
override_mode()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)
CommonArrayConstructorStub(isolate,kind,override_mode)1609       : CommonArrayConstructorStub(isolate, kind, override_mode) {}
1610 
1611  private:
PrintName(std::ostream & os)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:
InternalArrayNoArgumentConstructorStub(Isolate * isolate,ElementsKind kind)1624   InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
1625       : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
1626 
1627  private:
PrintName(std::ostream & os)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)
CommonArrayConstructorStub(isolate,kind,override_mode)1642       : CommonArrayConstructorStub(isolate, kind, override_mode) {}
1643 
1644  private:
PrintName(std::ostream & os)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:
InternalArraySingleArgumentConstructorStub(Isolate * isolate,ElementsKind kind)1657   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
1658                                              ElementsKind kind)
1659       : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
1660 
1661  private:
PrintName(std::ostream & os)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:
ArrayNArgumentsConstructorStub(Isolate * isolate)1673   explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
1674       : PlatformCodeStub(isolate) {}
1675 
GetCallInterfaceDescriptor()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:
StoreSlowElementStub(Isolate * isolate,KeyedAccessStoreMode mode)1686   StoreSlowElementStub(Isolate* isolate, KeyedAccessStoreMode mode)
1687       : TurboFanCodeStub(isolate) {
1688     minor_key_ = CommonStoreModeBits::encode(mode);
1689   }
1690 
GetCodeKind()1691   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
ToBooleanICStub(Isolate * isolate,ExtraICState state)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);
hints()1707   ToBooleanHints hints() const {
1708     return ToBooleanHints(HintsBits::decode(sub_minor_key()));
1709   }
1710 
GetCodeKind()1711   Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
1712   void PrintState(std::ostream& os) const override;  // NOLINT
1713 
SometimesSetsUpAFrame()1714   bool SometimesSetsUpAFrame() override { return false; }
1715 
GetUninitialized(Isolate * isolate)1716   static Handle<Code> GetUninitialized(Isolate* isolate) {
1717     return ToBooleanICStub(isolate, UNINITIALIZED).GetCode();
1718   }
1719 
GetExtraICState()1720   ExtraICState GetExtraICState() const override { return hints(); }
1721 
GetICState()1722   InlineCacheState GetICState() const {
1723     if (hints() == ToBooleanHint::kNone) {
1724       return ::v8::internal::UNINITIALIZED;
1725     } else {
1726       return MONOMORPHIC;
1727     }
1728   }
1729 
1730  private:
ToBooleanICStub(Isolate * isolate,InitializationState init_state)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:
ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)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 
from_kind()1754   ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
to_kind()1755   ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
is_jsarray()1756   bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
store_mode()1757   KeyedAccessStoreMode store_mode() const {
1758     return CommonStoreModeBits::decode(minor_key_);
1759   }
1760 
GetCodeKind()1761   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()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:
StubFailureTrampolineStub(Isolate * isolate,StubFunctionMode function_mode)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:
function_mode()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:
ProfileEntryHookStub(Isolate * isolate)1798   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1799 
1800   // The profile entry hook function is not allowed to cause a GC.
SometimesSetsUpAFrame()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:
StoreBufferOverflowStub(Isolate * isolate,SaveFPRegsMode save_fp)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);
SometimesSetsUpAFrame()1826   bool SometimesSetsUpAFrame() override { return false; }
1827 
1828  private:
save_doubles()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:
SubStringStub(Isolate * isolate)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