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/code-stub-assembler.h"
11 #include "src/codegen.h"
12 #include "src/globals.h"
13 #include "src/ic/ic-state.h"
14 #include "src/interface-descriptors.h"
15 #include "src/macro-assembler.h"
16 #include "src/ostreams.h"
17 #include "src/type-hints.h"
18 
19 namespace v8 {
20 namespace internal {
21 
22 class ObjectLiteral;
23 
24 // List of code stubs used on all platforms.
25 #define CODE_STUB_LIST_ALL_PLATFORMS(V)       \
26   /* --- PlatformCodeStubs --- */             \
27   V(ArrayConstructor)                         \
28   V(BinaryOpICWithAllocationSite)             \
29   V(CallApiCallback)                          \
30   V(CallApiGetter)                            \
31   V(CallConstruct)                            \
32   V(CallIC)                                   \
33   V(CEntry)                                   \
34   V(CompareIC)                                \
35   V(DoubleToI)                                \
36   V(FunctionPrototype)                        \
37   V(InternalArrayConstructor)                 \
38   V(JSEntry)                                  \
39   V(LoadIndexedString)                        \
40   V(MathPow)                                  \
41   V(ProfileEntryHook)                         \
42   V(RecordWrite)                              \
43   V(RegExpExec)                               \
44   V(StoreBufferOverflow)                      \
45   V(StoreElement)                             \
46   V(SubString)                                \
47   V(KeyedStoreIC)                             \
48   V(LoadGlobalIC)                             \
49   V(FastNewObject)                            \
50   V(FastNewRestParameter)                     \
51   V(FastNewSloppyArguments)                   \
52   V(FastNewStrictArguments)                   \
53   V(NameDictionaryLookup)                     \
54   /* This can be removed once there are no */ \
55   /* more deopting Hydrogen stubs. */         \
56   V(StubFailureTrampoline)                    \
57   /* These are only called from FCG */        \
58   /* They can be removed when only the TF  */ \
59   /* version of the corresponding stub is  */ \
60   /* used universally */                      \
61   V(CallICTrampoline)                         \
62   V(KeyedStoreICTrampoline)                   \
63   /* --- HydrogenCodeStubs --- */             \
64   /* These builtins w/ JS linkage are */      \
65   /* just fast-cases of C++ builtins. They */ \
66   /* require varg support from TF */          \
67   V(FastArrayPush)                            \
68   V(FastFunctionBind)                         \
69   /* These will be ported/eliminated */       \
70   /* as part of the new IC system, ask */     \
71   /* ishell before doing anything  */         \
72   V(LoadConstant)                             \
73   V(LoadDictionaryElement)                    \
74   V(LoadFastElement)                          \
75   V(LoadField)                                \
76   /* These should never be ported to TF */    \
77   /* because they are either used only by */  \
78   /* FCG/Crankshaft or are deprecated */      \
79   V(BinaryOpIC)                               \
80   V(BinaryOpWithAllocationSite)               \
81   V(ToBooleanIC)                              \
82   V(TransitionElementsKind)                   \
83   /* --- TurboFanCodeStubs --- */             \
84   V(AllocateHeapNumber)                       \
85   V(AllocateFloat32x4)                        \
86   V(AllocateInt32x4)                          \
87   V(AllocateUint32x4)                         \
88   V(AllocateBool32x4)                         \
89   V(AllocateInt16x8)                          \
90   V(AllocateUint16x8)                         \
91   V(AllocateBool16x8)                         \
92   V(AllocateInt8x16)                          \
93   V(AllocateUint8x16)                         \
94   V(AllocateBool8x16)                         \
95   V(ArrayNoArgumentConstructor)               \
96   V(ArraySingleArgumentConstructor)           \
97   V(ArrayNArgumentsConstructor)               \
98   V(CreateAllocationSite)                     \
99   V(CreateWeakCell)                           \
100   V(StringLength)                             \
101   V(AddWithFeedback)                          \
102   V(SubtractWithFeedback)                     \
103   V(MultiplyWithFeedback)                     \
104   V(DivideWithFeedback)                       \
105   V(ModulusWithFeedback)                      \
106   V(Inc)                                      \
107   V(InternalArrayNoArgumentConstructor)       \
108   V(InternalArraySingleArgumentConstructor)   \
109   V(Dec)                                      \
110   V(ElementsTransitionAndStore)               \
111   V(FastCloneRegExp)                          \
112   V(FastCloneShallowArray)                    \
113   V(FastCloneShallowObject)                   \
114   V(FastNewClosure)                           \
115   V(FastNewFunctionContext)                   \
116   V(KeyedLoadSloppyArguments)                 \
117   V(KeyedStoreSloppyArguments)                \
118   V(LoadScriptContextField)                   \
119   V(StoreScriptContextField)                  \
120   V(NumberToString)                           \
121   V(StringAdd)                                \
122   V(GetProperty)                              \
123   V(LoadIC)                                   \
124   V(LoadICProtoArray)                         \
125   V(KeyedLoadICTF)                            \
126   V(StoreFastElement)                         \
127   V(StoreField)                               \
128   V(StoreGlobal)                              \
129   V(StoreIC)                                  \
130   V(KeyedStoreICTF)                           \
131   V(StoreInterceptor)                         \
132   V(StoreMap)                                 \
133   V(StoreTransition)                          \
134   V(LoadApiGetter)                            \
135   V(LoadIndexedInterceptor)                   \
136   V(GrowArrayElements)                        \
137   /* These are only called from FGC and */    \
138   /* can be removed when we use ignition */   \
139   /* only */                                  \
140   V(LoadICTrampoline)                         \
141   V(LoadGlobalICTrampoline)                   \
142   V(KeyedLoadICTrampolineTF)                  \
143   V(StoreICTrampoline)                        \
144   V(KeyedStoreICTrampolineTF)
145 
146 // List of code stubs only used on ARM 32 bits platforms.
147 #if V8_TARGET_ARCH_ARM
148 #define CODE_STUB_LIST_ARM(V) V(DirectCEntry)
149 
150 #else
151 #define CODE_STUB_LIST_ARM(V)
152 #endif
153 
154 // List of code stubs only used on ARM 64 bits platforms.
155 #if V8_TARGET_ARCH_ARM64
156 #define CODE_STUB_LIST_ARM64(V) \
157   V(DirectCEntry)               \
158   V(RestoreRegistersState)      \
159   V(StoreRegistersState)
160 
161 #else
162 #define CODE_STUB_LIST_ARM64(V)
163 #endif
164 
165 // List of code stubs only used on PPC platforms.
166 #ifdef V8_TARGET_ARCH_PPC
167 #define CODE_STUB_LIST_PPC(V) \
168   V(DirectCEntry)             \
169   V(StoreRegistersState)      \
170   V(RestoreRegistersState)
171 #else
172 #define CODE_STUB_LIST_PPC(V)
173 #endif
174 
175 // List of code stubs only used on MIPS platforms.
176 #if V8_TARGET_ARCH_MIPS
177 #define CODE_STUB_LIST_MIPS(V) \
178   V(DirectCEntry)              \
179   V(RestoreRegistersState)     \
180   V(StoreRegistersState)
181 #elif V8_TARGET_ARCH_MIPS64
182 #define CODE_STUB_LIST_MIPS(V) \
183   V(DirectCEntry)              \
184   V(RestoreRegistersState)     \
185   V(StoreRegistersState)
186 #else
187 #define CODE_STUB_LIST_MIPS(V)
188 #endif
189 
190 // List of code stubs only used on S390 platforms.
191 #ifdef V8_TARGET_ARCH_S390
192 #define CODE_STUB_LIST_S390(V) \
193   V(DirectCEntry)              \
194   V(StoreRegistersState)       \
195   V(RestoreRegistersState)
196 #else
197 #define CODE_STUB_LIST_S390(V)
198 #endif
199 
200 // Combined list of code stubs.
201 #define CODE_STUB_LIST(V)         \
202   CODE_STUB_LIST_ALL_PLATFORMS(V) \
203   CODE_STUB_LIST_ARM(V)           \
204   CODE_STUB_LIST_ARM64(V)         \
205   CODE_STUB_LIST_PPC(V)           \
206   CODE_STUB_LIST_MIPS(V)          \
207   CODE_STUB_LIST_S390(V)
208 
209 static const int kHasReturnedMinusZeroSentinel = 1;
210 
211 // Stub is base classes of all stubs.
212 class CodeStub BASE_EMBEDDED {
213  public:
214   enum Major {
215     // TODO(mvstanton): eliminate the NoCache key by getting rid
216     //                  of the non-monomorphic-cache.
217     NoCache = 0,  // marker for stubs that do custom caching]
218 #define DEF_ENUM(name) name,
219     CODE_STUB_LIST(DEF_ENUM)
220 #undef DEF_ENUM
221     NUMBER_OF_IDS
222   };
223 
224   // Retrieve the code for the stub. Generate the code if needed.
225   Handle<Code> GetCode();
226 
227   // Retrieve the code for the stub, make and return a copy of the code.
228   Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
229 
MajorKeyFromKey(uint32_t key)230   static Major MajorKeyFromKey(uint32_t key) {
231     return static_cast<Major>(MajorKeyBits::decode(key));
232   }
MinorKeyFromKey(uint32_t key)233   static uint32_t MinorKeyFromKey(uint32_t key) {
234     return MinorKeyBits::decode(key);
235   }
236 
237   // Gets the major key from a code object that is a code stub or binary op IC.
GetMajorKey(Code * code_stub)238   static Major GetMajorKey(Code* code_stub) {
239     return MajorKeyFromKey(code_stub->stub_key());
240   }
241 
NoCacheKey()242   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
243 
244   static const char* MajorName(Major major_key);
245 
CodeStub(Isolate * isolate)246   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
~CodeStub()247   virtual ~CodeStub() {}
248 
249   static void GenerateStubsAheadOfTime(Isolate* isolate);
250   static void GenerateFPStubs(Isolate* isolate);
251 
252   // Some stubs put untagged junk on the stack that cannot be scanned by the
253   // GC.  This means that we must be statically sure that no GC can occur while
254   // they are running.  If that is the case they should override this to return
255   // true, which will cause an assertion if we try to call something that can
256   // GC or if we try to put a stack frame on top of the junk, which would not
257   // result in a traversable stack.
SometimesSetsUpAFrame()258   virtual bool SometimesSetsUpAFrame() { return true; }
259 
260   // Lookup the code in the (possibly custom) cache.
261   bool FindCodeInCache(Code** code_out);
262 
263   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() const = 0;
264 
GetStackParameterCount()265   virtual int GetStackParameterCount() const {
266     return GetCallInterfaceDescriptor().GetStackParameterCount();
267   }
268 
InitializeDescriptor(CodeStubDescriptor * descriptor)269   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
270 
271   static void InitializeDescriptor(Isolate* isolate, uint32_t key,
272                                    CodeStubDescriptor* desc);
273 
274   static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
275 
276   // Returns information for computing the number key.
277   virtual Major MajorKey() const = 0;
MinorKey()278   uint32_t MinorKey() const { return minor_key_; }
279 
280   // BinaryOpStub needs to override this.
281   virtual Code::Kind GetCodeKind() const;
282 
GetExtraICState()283   virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
284 
285   Code::Flags GetCodeFlags() const;
286 
287   friend std::ostream& operator<<(std::ostream& os, const CodeStub& s) {
288     s.PrintName(os);
289     return os;
290   }
291 
isolate()292   Isolate* isolate() const { return isolate_; }
293 
294  protected:
CodeStub(uint32_t key,Isolate * isolate)295   CodeStub(uint32_t key, Isolate* isolate)
296       : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
297 
298   // Generates the assembler code for the stub.
299   virtual Handle<Code> GenerateCode() = 0;
300 
301   // Returns whether the code generated for this stub needs to be allocated as
302   // a fixed (non-moveable) code object.
NeedsImmovableCode()303   virtual bool NeedsImmovableCode() { return false; }
304 
305   virtual void PrintName(std::ostream& os) const;        // NOLINT
306   virtual void PrintBaseName(std::ostream& os) const;    // NOLINT
PrintState(std::ostream & os)307   virtual void PrintState(std::ostream& os) const { ; }  // NOLINT
308 
309   // Computes the key based on major and minor.
GetKey()310   uint32_t GetKey() {
311     DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
312     return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
313   }
314 
315   uint32_t minor_key_;
316 
317  private:
318   // Perform bookkeeping required after code generation when stub code is
319   // initially generated.
320   void RecordCodeGeneration(Handle<Code> code);
321 
322   // Finish the code object after it has been generated.
FinishCode(Handle<Code> code)323   virtual void FinishCode(Handle<Code> code) { }
324 
325   // Activate newly generated stub. Is called after
326   // registering stub in the stub cache.
Activate(Code * code)327   virtual void Activate(Code* code) { }
328 
329   // Add the code to a specialized cache, specific to an individual
330   // stub type. Please note, this method must add the code object to a
331   // roots object, otherwise we will remove the code during GC.
AddToSpecialCache(Handle<Code> new_object)332   virtual void AddToSpecialCache(Handle<Code> new_object) { }
333 
334   // Find code in a specialized cache, work is delegated to the specific stub.
FindCodeInSpecialCache(Code ** code_out)335   virtual bool FindCodeInSpecialCache(Code** code_out) {
336     return false;
337   }
338 
339   // If a stub uses a special cache override this.
UseSpecialCache()340   virtual bool UseSpecialCache() { return false; }
341 
342   // We use this dispatch to statically instantiate the correct code stub for
343   // the given stub key and call the passed function with that code stub.
344   typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
345   static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
346                        DispatchedCall call);
347 
348   static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
349 
350   STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
351   class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
352   class MinorKeyBits: public BitField<uint32_t,
353       kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
354 
355   friend class BreakPointIterator;
356 
357   Isolate* isolate_;
358 };
359 
360 
361 #define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
362  public:                                                        \
363   NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
364                                                                 \
365  private:                                                       \
366   DISALLOW_COPY_AND_ASSIGN(NAME)
367 
368 
369 #define DEFINE_CODE_STUB(NAME, SUPER)                      \
370  public:                                                   \
371   inline Major MajorKey() const override { return NAME; }; \
372                                                            \
373  protected:                                                \
374   DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
375 
376 
377 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)  \
378  private:                                       \
379   void Generate(MacroAssembler* masm) override; \
380   DEFINE_CODE_STUB(NAME, SUPER)
381 
382 
383 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER)                        \
384  public:                                                              \
385   void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
386   Handle<Code> GenerateCode() override;                               \
387   DEFINE_CODE_STUB(NAME, SUPER)
388 
389 #define DEFINE_TURBOFAN_CODE_STUB(NAME, SUPER)                        \
390  public:                                                              \
391   void GenerateAssembly(CodeStubAssembler* assembler) const override; \
392   DEFINE_CODE_STUB(NAME, SUPER)
393 
394 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB(NAME, SUPER)                       \
395  public:                                                                       \
396   static compiler::Node* Generate(CodeStubAssembler* assembler,                \
397                                   compiler::Node* left, compiler::Node* right, \
398                                   compiler::Node* context);                    \
399   void GenerateAssembly(CodeStubAssembler* assembler) const override {         \
400     assembler->Return(Generate(assembler, assembler->Parameter(0),             \
401                                assembler->Parameter(1),                        \
402                                assembler->Parameter(2)));                      \
403   }                                                                            \
404   DEFINE_CODE_STUB(NAME, SUPER)
405 
406 #define DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER)        \
407  public:                                                                      \
408   static compiler::Node* Generate(                                            \
409       CodeStubAssembler* assembler, compiler::Node* left,                     \
410       compiler::Node* right, compiler::Node* slot_id,                         \
411       compiler::Node* type_feedback_vector, compiler::Node* context);         \
412   void GenerateAssembly(CodeStubAssembler* assembler) const override {        \
413     assembler->Return(                                                        \
414         Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \
415                  assembler->Parameter(2), assembler->Parameter(3),            \
416                  assembler->Parameter(4)));                                   \
417   }                                                                           \
418   DEFINE_CODE_STUB(NAME, SUPER)
419 
420 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB(NAME, SUPER)                \
421  public:                                                               \
422   static compiler::Node* Generate(CodeStubAssembler* assembler,        \
423                                   compiler::Node* value,               \
424                                   compiler::Node* context);            \
425   void GenerateAssembly(CodeStubAssembler* assembler) const override { \
426     assembler->Return(Generate(assembler, assembler->Parameter(0),     \
427                                assembler->Parameter(1)));              \
428   }                                                                    \
429   DEFINE_CODE_STUB(NAME, SUPER)
430 
431 #define DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(NAME, SUPER)         \
432  public:                                                                      \
433   static compiler::Node* Generate(                                            \
434       CodeStubAssembler* assembler, compiler::Node* value,                    \
435       compiler::Node* context, compiler::Node* type_feedback_vector,          \
436       compiler::Node* slot_id);                                               \
437   void GenerateAssembly(CodeStubAssembler* assembler) const override {        \
438     assembler->Return(                                                        \
439         Generate(assembler, assembler->Parameter(0), assembler->Parameter(1), \
440                  assembler->Parameter(2), assembler->Parameter(3)));          \
441   }                                                                           \
442   DEFINE_CODE_STUB(NAME, SUPER)
443 
444 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER) \
445  public:                                      \
446   Handle<Code> GenerateCode() override;       \
447   DEFINE_CODE_STUB(NAME, SUPER)
448 
449 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                          \
450  public:                                                                \
451   typedef NAME##Descriptor Descriptor;                                  \
452   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
453     return Descriptor(isolate());                                       \
454   }
455 
456 // There are some code stubs we just can't describe right now with a
457 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
458 // An attempt to retrieve a descriptor will fail.
459 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                         \
460  public:                                                                \
461   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override { \
462     UNREACHABLE();                                                      \
463     return CallInterfaceDescriptor();                                   \
464   }
465 
466 
467 class PlatformCodeStub : public CodeStub {
468  public:
469   // Retrieve the code for the stub. Generate the code if needed.
470   Handle<Code> GenerateCode() override;
471 
472  protected:
PlatformCodeStub(Isolate * isolate)473   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
474 
475   // Generates the assembler code for the stub.
476   virtual void Generate(MacroAssembler* masm) = 0;
477 
478   DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
479 };
480 
481 
482 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
483 
484 
485 class CodeStubDescriptor {
486  public:
487   explicit CodeStubDescriptor(CodeStub* stub);
488 
489   CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
490 
491   void Initialize(Address deoptimization_handler = NULL,
492                   int hint_stack_parameter_count = -1,
493                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
494   void Initialize(Register stack_parameter_count,
495                   Address deoptimization_handler = NULL,
496                   int hint_stack_parameter_count = -1,
497                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
498 
SetMissHandler(Runtime::FunctionId id)499   void SetMissHandler(Runtime::FunctionId id) {
500     miss_handler_id_ = id;
501     miss_handler_ = ExternalReference(Runtime::FunctionForId(id), isolate_);
502     has_miss_handler_ = true;
503     // Our miss handler infrastructure doesn't currently support
504     // variable stack parameter counts.
505     DCHECK(!stack_parameter_count_.is_valid());
506   }
507 
set_call_descriptor(CallInterfaceDescriptor d)508   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
call_descriptor()509   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
510 
GetRegisterParameterCount()511   int GetRegisterParameterCount() const {
512     return call_descriptor().GetRegisterParameterCount();
513   }
514 
GetStackParameterCount()515   int GetStackParameterCount() const {
516     return call_descriptor().GetStackParameterCount();
517   }
518 
GetParameterCount()519   int GetParameterCount() const {
520     return call_descriptor().GetParameterCount();
521   }
522 
GetRegisterParameter(int index)523   Register GetRegisterParameter(int index) const {
524     return call_descriptor().GetRegisterParameter(index);
525   }
526 
GetParameterType(int index)527   MachineType GetParameterType(int index) const {
528     return call_descriptor().GetParameterType(index);
529   }
530 
miss_handler()531   ExternalReference miss_handler() const {
532     DCHECK(has_miss_handler_);
533     return miss_handler_;
534   }
535 
miss_handler_id()536   Runtime::FunctionId miss_handler_id() const {
537     DCHECK(has_miss_handler_);
538     return miss_handler_id_;
539   }
540 
has_miss_handler()541   bool has_miss_handler() const {
542     return has_miss_handler_;
543   }
544 
GetHandlerParameterCount()545   int GetHandlerParameterCount() const {
546     int params = GetParameterCount();
547     if (PassesArgumentsToDeoptimizationHandler()) {
548       params += 1;
549     }
550     return params;
551   }
552 
hint_stack_parameter_count()553   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
stack_parameter_count()554   Register stack_parameter_count() const { return stack_parameter_count_; }
function_mode()555   StubFunctionMode function_mode() const { return function_mode_; }
deoptimization_handler()556   Address deoptimization_handler() const { return deoptimization_handler_; }
557 
558  private:
PassesArgumentsToDeoptimizationHandler()559   bool PassesArgumentsToDeoptimizationHandler() const {
560     return stack_parameter_count_.is_valid();
561   }
562 
563   Isolate* isolate_;
564   CallInterfaceDescriptor call_descriptor_;
565   Register stack_parameter_count_;
566   // If hint_stack_parameter_count_ > 0, the code stub can optimize the
567   // return sequence. Default value is -1, which means it is ignored.
568   int hint_stack_parameter_count_;
569   StubFunctionMode function_mode_;
570 
571   Address deoptimization_handler_;
572 
573   ExternalReference miss_handler_;
574   Runtime::FunctionId miss_handler_id_;
575   bool has_miss_handler_;
576 };
577 
578 
579 class HydrogenCodeStub : public CodeStub {
580  public:
581   enum InitializationState {
582     UNINITIALIZED,
583     INITIALIZED
584   };
585 
586   template<class SubClass>
GetUninitialized(Isolate * isolate)587   static Handle<Code> GetUninitialized(Isolate* isolate) {
588     SubClass::GenerateAheadOfTime(isolate);
589     return SubClass().GetCode(isolate);
590   }
591 
592   // Retrieve the code for the stub. Generate the code if needed.
593   Handle<Code> GenerateCode() override = 0;
594 
IsUninitialized()595   bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
596 
597   Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
598 
599   Handle<Code> GenerateRuntimeTailCall(CodeStubDescriptor* descriptor);
600 
601   template<class StateType>
602   void TraceTransition(StateType from, StateType to);
603 
604  protected:
605   explicit HydrogenCodeStub(Isolate* isolate,
606                             InitializationState state = INITIALIZED)
CodeStub(isolate)607       : CodeStub(isolate) {
608     minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
609   }
610 
set_sub_minor_key(uint32_t key)611   void set_sub_minor_key(uint32_t key) {
612     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
613   }
614 
sub_minor_key()615   uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
616 
617   static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
618 
619  private:
620   class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
621   class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
622 
623   void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
624 
625   DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
626 };
627 
628 
629 class TurboFanCodeStub : public CodeStub {
630  public:
631   // Retrieve the code for the stub. Generate the code if needed.
632   Handle<Code> GenerateCode() override;
633 
GetStackParameterCount()634   int GetStackParameterCount() const override {
635     return GetCallInterfaceDescriptor().GetStackParameterCount();
636   }
637 
638  protected:
TurboFanCodeStub(Isolate * isolate)639   explicit TurboFanCodeStub(Isolate* isolate) : CodeStub(isolate) {}
640 
641   virtual void GenerateAssembly(CodeStubAssembler* assembler) const = 0;
642 
643  private:
644   DEFINE_CODE_STUB_BASE(TurboFanCodeStub, CodeStub);
645 };
646 
647 
648 // Helper interface to prepare to/restore after making runtime calls.
649 class RuntimeCallHelper {
650  public:
~RuntimeCallHelper()651   virtual ~RuntimeCallHelper() {}
652 
653   virtual void BeforeCall(MacroAssembler* masm) const = 0;
654 
655   virtual void AfterCall(MacroAssembler* masm) const = 0;
656 
657  protected:
RuntimeCallHelper()658   RuntimeCallHelper() {}
659 
660  private:
661   DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
662 };
663 
664 
665 }  // namespace internal
666 }  // namespace v8
667 
668 #if V8_TARGET_ARCH_IA32
669 #include "src/ia32/code-stubs-ia32.h"
670 #elif V8_TARGET_ARCH_X64
671 #include "src/x64/code-stubs-x64.h"
672 #elif V8_TARGET_ARCH_ARM64
673 #include "src/arm64/code-stubs-arm64.h"
674 #elif V8_TARGET_ARCH_ARM
675 #include "src/arm/code-stubs-arm.h"
676 #elif V8_TARGET_ARCH_PPC
677 #include "src/ppc/code-stubs-ppc.h"
678 #elif V8_TARGET_ARCH_MIPS
679 #include "src/mips/code-stubs-mips.h"
680 #elif V8_TARGET_ARCH_MIPS64
681 #include "src/mips64/code-stubs-mips64.h"
682 #elif V8_TARGET_ARCH_S390
683 #include "src/s390/code-stubs-s390.h"
684 #elif V8_TARGET_ARCH_X87
685 #include "src/x87/code-stubs-x87.h"
686 #else
687 #error Unsupported target architecture.
688 #endif
689 
690 namespace v8 {
691 namespace internal {
692 
693 
694 // RuntimeCallHelper implementation used in stubs: enters/leaves a
695 // newly created internal frame before/after the runtime call.
696 class StubRuntimeCallHelper : public RuntimeCallHelper {
697  public:
StubRuntimeCallHelper()698   StubRuntimeCallHelper() {}
699 
700   void BeforeCall(MacroAssembler* masm) const override;
701 
702   void AfterCall(MacroAssembler* masm) const override;
703 };
704 
705 
706 // Trivial RuntimeCallHelper implementation.
707 class NopRuntimeCallHelper : public RuntimeCallHelper {
708  public:
NopRuntimeCallHelper()709   NopRuntimeCallHelper() {}
710 
BeforeCall(MacroAssembler * masm)711   void BeforeCall(MacroAssembler* masm) const override {}
712 
AfterCall(MacroAssembler * masm)713   void AfterCall(MacroAssembler* masm) const override {}
714 };
715 
716 
717 class StringLengthStub : public TurboFanCodeStub {
718  public:
StringLengthStub(Isolate * isolate)719   explicit StringLengthStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
720 
GetCodeKind()721   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()722   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
723 
724   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
725   DEFINE_TURBOFAN_CODE_STUB(StringLength, TurboFanCodeStub);
726 };
727 
728 class AddWithFeedbackStub final : public TurboFanCodeStub {
729  public:
AddWithFeedbackStub(Isolate * isolate)730   explicit AddWithFeedbackStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
731 
732   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
733   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(AddWithFeedback,
734                                                     TurboFanCodeStub);
735 };
736 
737 class SubtractWithFeedbackStub final : public TurboFanCodeStub {
738  public:
SubtractWithFeedbackStub(Isolate * isolate)739   explicit SubtractWithFeedbackStub(Isolate* isolate)
740       : TurboFanCodeStub(isolate) {}
741 
742   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
743   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(SubtractWithFeedback,
744                                                     TurboFanCodeStub);
745 };
746 
747 class MultiplyWithFeedbackStub final : public TurboFanCodeStub {
748  public:
MultiplyWithFeedbackStub(Isolate * isolate)749   explicit MultiplyWithFeedbackStub(Isolate* isolate)
750       : TurboFanCodeStub(isolate) {}
751 
752   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
753   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(MultiplyWithFeedback,
754                                                     TurboFanCodeStub);
755 };
756 
757 class DivideWithFeedbackStub final : public TurboFanCodeStub {
758  public:
DivideWithFeedbackStub(Isolate * isolate)759   explicit DivideWithFeedbackStub(Isolate* isolate)
760       : TurboFanCodeStub(isolate) {}
761 
762   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
763   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(DivideWithFeedback,
764                                                     TurboFanCodeStub);
765 };
766 
767 class ModulusWithFeedbackStub final : public TurboFanCodeStub {
768  public:
ModulusWithFeedbackStub(Isolate * isolate)769   explicit ModulusWithFeedbackStub(Isolate* isolate)
770       : TurboFanCodeStub(isolate) {}
771 
772   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithVector);
773   DEFINE_TURBOFAN_BINARY_OP_CODE_STUB_WITH_FEEDBACK(ModulusWithFeedback,
774                                                     TurboFanCodeStub);
775 };
776 
777 class IncStub final : public TurboFanCodeStub {
778  public:
IncStub(Isolate * isolate)779   explicit IncStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
780 
781   DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
782   DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(Inc, TurboFanCodeStub);
783 };
784 
785 class DecStub final : public TurboFanCodeStub {
786  public:
DecStub(Isolate * isolate)787   explicit DecStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
788 
789   DEFINE_CALL_INTERFACE_DESCRIPTOR(CountOp);
790   DEFINE_TURBOFAN_UNARY_OP_CODE_STUB_WITH_FEEDBACK(Dec, TurboFanCodeStub);
791 };
792 
793 class StoreInterceptorStub : public TurboFanCodeStub {
794  public:
StoreInterceptorStub(Isolate * isolate)795   explicit StoreInterceptorStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
796 
797   void GenerateAssembly(CodeStubAssembler* assember) const override;
798 
GetCodeKind()799   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()800   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
801 
802   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
803   DEFINE_CODE_STUB(StoreInterceptor, TurboFanCodeStub);
804 };
805 
806 class LoadIndexedInterceptorStub : public TurboFanCodeStub {
807  public:
LoadIndexedInterceptorStub(Isolate * isolate)808   explicit LoadIndexedInterceptorStub(Isolate* isolate)
809       : TurboFanCodeStub(isolate) {}
810 
GetCodeKind()811   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()812   ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
813 
814   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
815   DEFINE_TURBOFAN_CODE_STUB(LoadIndexedInterceptor, TurboFanCodeStub);
816 };
817 
818 // ES6 [[Get]] operation.
819 class GetPropertyStub : public TurboFanCodeStub {
820  public:
GetPropertyStub(Isolate * isolate)821   explicit GetPropertyStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
822 
823   DEFINE_CALL_INTERFACE_DESCRIPTOR(GetProperty);
824   DEFINE_TURBOFAN_CODE_STUB(GetProperty, TurboFanCodeStub);
825 };
826 
827 class NumberToStringStub final : public TurboFanCodeStub {
828  public:
NumberToStringStub(Isolate * isolate)829   explicit NumberToStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
830 
831   DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
832   DEFINE_TURBOFAN_CODE_STUB(NumberToString, TurboFanCodeStub);
833 };
834 
835 class FastNewClosureStub : public TurboFanCodeStub {
836  public:
FastNewClosureStub(Isolate * isolate)837   explicit FastNewClosureStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
838 
839   static compiler::Node* Generate(CodeStubAssembler* assembler,
840                                   compiler::Node* shared_info,
841                                   compiler::Node* context);
842 
843   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
844   DEFINE_TURBOFAN_CODE_STUB(FastNewClosure, TurboFanCodeStub);
845 };
846 
847 class FastNewFunctionContextStub final : public TurboFanCodeStub {
848  public:
849   static const int kMaximumSlots = 0x8000;
850 
FastNewFunctionContextStub(Isolate * isolate)851   explicit FastNewFunctionContextStub(Isolate* isolate)
852       : TurboFanCodeStub(isolate) {}
853 
854   static compiler::Node* Generate(CodeStubAssembler* assembler,
855                                   compiler::Node* function,
856                                   compiler::Node* slots,
857                                   compiler::Node* context);
858 
859  private:
860   // FastNewFunctionContextStub can only allocate closures which fit in the
861   // new space.
862   STATIC_ASSERT(((kMaximumSlots + Context::MIN_CONTEXT_SLOTS) * kPointerSize +
863                  FixedArray::kHeaderSize) < kMaxRegularHeapObjectSize);
864 
865   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewFunctionContext);
866   DEFINE_TURBOFAN_CODE_STUB(FastNewFunctionContext, TurboFanCodeStub);
867 };
868 
869 
870 class FastNewObjectStub final : public PlatformCodeStub {
871  public:
FastNewObjectStub(Isolate * isolate)872   explicit FastNewObjectStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
873 
874   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewObject);
875   DEFINE_PLATFORM_CODE_STUB(FastNewObject, PlatformCodeStub);
876 };
877 
878 
879 // TODO(turbofan): This stub should be possible to write in TurboFan
880 // using the CodeStubAssembler very soon in a way that is as efficient
881 // and easy as the current handwritten version, which is partly a copy
882 // of the strict arguments object materialization code.
883 class FastNewRestParameterStub final : public PlatformCodeStub {
884  public:
885   explicit FastNewRestParameterStub(Isolate* isolate,
886                                     bool skip_stub_frame = false)
PlatformCodeStub(isolate)887       : PlatformCodeStub(isolate) {
888     minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
889   }
890 
891   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewRestParameter);
892   DEFINE_PLATFORM_CODE_STUB(FastNewRestParameter, PlatformCodeStub);
893 
skip_stub_frame()894   int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
895 
896  private:
897   class SkipStubFrameBits : public BitField<bool, 0, 1> {};
898 };
899 
900 
901 // TODO(turbofan): This stub should be possible to write in TurboFan
902 // using the CodeStubAssembler very soon in a way that is as efficient
903 // and easy as the current handwritten version.
904 class FastNewSloppyArgumentsStub final : public PlatformCodeStub {
905  public:
906   explicit FastNewSloppyArgumentsStub(Isolate* isolate,
907                                       bool skip_stub_frame = false)
PlatformCodeStub(isolate)908       : PlatformCodeStub(isolate) {
909     minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
910   }
911 
skip_stub_frame()912   int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
913 
914   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewSloppyArguments);
915   DEFINE_PLATFORM_CODE_STUB(FastNewSloppyArguments, PlatformCodeStub);
916 
917  private:
918   class SkipStubFrameBits : public BitField<bool, 0, 1> {};
919 };
920 
921 
922 // TODO(turbofan): This stub should be possible to write in TurboFan
923 // using the CodeStubAssembler very soon in a way that is as efficient
924 // and easy as the current handwritten version.
925 class FastNewStrictArgumentsStub final : public PlatformCodeStub {
926  public:
927   explicit FastNewStrictArgumentsStub(Isolate* isolate,
928                                       bool skip_stub_frame = false)
PlatformCodeStub(isolate)929       : PlatformCodeStub(isolate) {
930     minor_key_ = SkipStubFrameBits::encode(skip_stub_frame);
931   }
932 
933   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewStrictArguments);
934   DEFINE_PLATFORM_CODE_STUB(FastNewStrictArguments, PlatformCodeStub);
935 
skip_stub_frame()936   int skip_stub_frame() const { return SkipStubFrameBits::decode(minor_key_); }
937 
938  private:
939   class SkipStubFrameBits : public BitField<bool, 0, 1> {};
940 };
941 
942 class FastCloneRegExpStub final : public TurboFanCodeStub {
943  public:
FastCloneRegExpStub(Isolate * isolate)944   explicit FastCloneRegExpStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
945 
946   static compiler::Node* Generate(CodeStubAssembler* assembler,
947                                   compiler::Node* closure,
948                                   compiler::Node* literal_index,
949                                   compiler::Node* pattern,
950                                   compiler::Node* flags,
951                                   compiler::Node* context);
952 
953  private:
954   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneRegExp);
955   DEFINE_TURBOFAN_CODE_STUB(FastCloneRegExp, TurboFanCodeStub);
956 };
957 
958 class FastCloneShallowArrayStub : public TurboFanCodeStub {
959  public:
FastCloneShallowArrayStub(Isolate * isolate,AllocationSiteMode allocation_site_mode)960   FastCloneShallowArrayStub(Isolate* isolate,
961                             AllocationSiteMode allocation_site_mode)
962       : TurboFanCodeStub(isolate) {
963     minor_key_ = AllocationSiteModeBits::encode(allocation_site_mode);
964   }
965 
966   static compiler::Node* Generate(CodeStubAssembler* assembler,
967                                   compiler::Node* closure,
968                                   compiler::Node* literal_index,
969                                   compiler::Node* context,
970                                   CodeStubAssembler::Label* call_runtime,
971                                   AllocationSiteMode allocation_site_mode);
972 
allocation_site_mode()973   AllocationSiteMode allocation_site_mode() const {
974     return AllocationSiteModeBits::decode(minor_key_);
975   }
976 
977  private:
978   class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
979 
980   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
981   DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowArray, TurboFanCodeStub);
982 };
983 
984 class FastCloneShallowObjectStub : public TurboFanCodeStub {
985  public:
986   // Maximum number of properties in copied object.
987   static const int kMaximumClonedProperties = 6;
988 
FastCloneShallowObjectStub(Isolate * isolate,int length)989   FastCloneShallowObjectStub(Isolate* isolate, int length)
990       : TurboFanCodeStub(isolate) {
991     DCHECK_GE(length, 0);
992     DCHECK_LE(length, kMaximumClonedProperties);
993     minor_key_ = LengthBits::encode(LengthBits::encode(length));
994   }
995 
996   static compiler::Node* GenerateFastPath(
997       CodeStubAssembler* assembler,
998       compiler::CodeAssembler::Label* call_runtime, compiler::Node* closure,
999       compiler::Node* literals_index, compiler::Node* properties_count);
1000 
1001   static bool IsSupported(ObjectLiteral* expr);
1002   static int PropertiesCount(int literal_length);
1003 
length()1004   int length() const { return LengthBits::decode(minor_key_); }
1005 
1006  private:
1007   class LengthBits : public BitField<int, 0, 4> {};
1008 
1009   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
1010   DEFINE_TURBOFAN_CODE_STUB(FastCloneShallowObject, TurboFanCodeStub);
1011 };
1012 
1013 class CreateAllocationSiteStub : public TurboFanCodeStub {
1014  public:
CreateAllocationSiteStub(Isolate * isolate)1015   explicit CreateAllocationSiteStub(Isolate* isolate)
1016       : TurboFanCodeStub(isolate) {}
1017   static void GenerateAheadOfTime(Isolate* isolate);
1018 
1019   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
1020   DEFINE_TURBOFAN_CODE_STUB(CreateAllocationSite, TurboFanCodeStub);
1021 };
1022 
1023 class CreateWeakCellStub : public TurboFanCodeStub {
1024  public:
CreateWeakCellStub(Isolate * isolate)1025   explicit CreateWeakCellStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
1026 
1027   static void GenerateAheadOfTime(Isolate* isolate);
1028 
1029   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateWeakCell);
1030   DEFINE_TURBOFAN_CODE_STUB(CreateWeakCell, TurboFanCodeStub);
1031 };
1032 
1033 class GrowArrayElementsStub : public TurboFanCodeStub {
1034  public:
GrowArrayElementsStub(Isolate * isolate,ElementsKind kind)1035   GrowArrayElementsStub(Isolate* isolate, ElementsKind kind)
1036       : TurboFanCodeStub(isolate) {
1037     minor_key_ = ElementsKindBits::encode(GetHoleyElementsKind(kind));
1038   }
1039 
elements_kind()1040   ElementsKind elements_kind() const {
1041     return ElementsKindBits::decode(minor_key_);
1042   }
1043 
1044  private:
1045   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
1046 
1047   DEFINE_CALL_INTERFACE_DESCRIPTOR(GrowArrayElements);
1048   DEFINE_TURBOFAN_CODE_STUB(GrowArrayElements, TurboFanCodeStub);
1049 };
1050 
1051 class FastArrayPushStub : public HydrogenCodeStub {
1052  public:
FastArrayPushStub(Isolate * isolate)1053   explicit FastArrayPushStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1054 
1055  private:
1056   DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction);
1057   DEFINE_HYDROGEN_CODE_STUB(FastArrayPush, HydrogenCodeStub);
1058 };
1059 
1060 class FastFunctionBindStub : public HydrogenCodeStub {
1061  public:
FastFunctionBindStub(Isolate * isolate)1062   explicit FastFunctionBindStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1063 
1064  private:
1065   DEFINE_CALL_INTERFACE_DESCRIPTOR(VarArgFunction);
1066   DEFINE_HYDROGEN_CODE_STUB(FastFunctionBind, HydrogenCodeStub);
1067 };
1068 
1069 enum AllocationSiteOverrideMode {
1070   DONT_OVERRIDE,
1071   DISABLE_ALLOCATION_SITES,
1072   LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
1073 };
1074 
1075 
1076 class ArrayConstructorStub: public PlatformCodeStub {
1077  public:
1078   explicit ArrayConstructorStub(Isolate* isolate);
1079 
1080  private:
1081   void GenerateDispatchToArrayStub(MacroAssembler* masm,
1082                                    AllocationSiteOverrideMode mode);
1083 
1084   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
1085   DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
1086 };
1087 
1088 
1089 class InternalArrayConstructorStub: public PlatformCodeStub {
1090  public:
1091   explicit InternalArrayConstructorStub(Isolate* isolate);
1092 
1093  private:
1094   void GenerateCase(MacroAssembler* masm, ElementsKind kind);
1095 
1096   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNArgumentsConstructor);
1097   DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
1098 };
1099 
1100 
1101 class MathPowStub: public PlatformCodeStub {
1102  public:
1103   enum ExponentType { INTEGER, DOUBLE, TAGGED };
1104 
MathPowStub(Isolate * isolate,ExponentType exponent_type)1105   MathPowStub(Isolate* isolate, ExponentType exponent_type)
1106       : PlatformCodeStub(isolate) {
1107     minor_key_ = ExponentTypeBits::encode(exponent_type);
1108   }
1109 
GetCallInterfaceDescriptor()1110   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1111     if (exponent_type() == TAGGED) {
1112       return MathPowTaggedDescriptor(isolate());
1113     } else if (exponent_type() == INTEGER) {
1114       return MathPowIntegerDescriptor(isolate());
1115     } else {
1116       // A CallInterfaceDescriptor doesn't specify double registers (yet).
1117       DCHECK_EQ(DOUBLE, exponent_type());
1118       return ContextOnlyDescriptor(isolate());
1119     }
1120   }
1121 
1122  private:
exponent_type()1123   ExponentType exponent_type() const {
1124     return ExponentTypeBits::decode(minor_key_);
1125   }
1126 
1127   class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
1128 
1129   DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
1130 };
1131 
1132 
1133 class CallICStub: public PlatformCodeStub {
1134  public:
CallICStub(Isolate * isolate,const CallICState & state)1135   CallICStub(Isolate* isolate, const CallICState& state)
1136       : PlatformCodeStub(isolate) {
1137     minor_key_ = state.GetExtraICState();
1138   }
1139 
GetCodeKind()1140   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
1141 
GetExtraICState()1142   ExtraICState GetExtraICState() const final {
1143     return static_cast<ExtraICState>(minor_key_);
1144   }
1145 
1146  protected:
convert_mode()1147   ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
tail_call_mode()1148   TailCallMode tail_call_mode() const { return state().tail_call_mode(); }
1149 
state()1150   CallICState state() const { return CallICState(GetExtraICState()); }
1151 
1152   // Code generation helpers.
1153   void GenerateMiss(MacroAssembler* masm);
1154   void HandleArrayCase(MacroAssembler* masm, Label* miss);
1155 
1156  private:
1157   void PrintState(std::ostream& os) const override;  // NOLINT
1158 
1159   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedbackAndVector);
1160   DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
1161 };
1162 
1163 
1164 // TODO(verwaest): Translate to hydrogen code stub.
1165 class FunctionPrototypeStub : public PlatformCodeStub {
1166  public:
FunctionPrototypeStub(Isolate * isolate)1167   explicit FunctionPrototypeStub(Isolate* isolate)
1168       : PlatformCodeStub(isolate) {}
1169 
GetCodeKind()1170   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1171   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
1172 
1173   // TODO(mvstanton): only the receiver register is accessed. When this is
1174   // translated to a hydrogen code stub, a new CallInterfaceDescriptor
1175   // should be created that just uses that register for more efficient code.
GetCallInterfaceDescriptor()1176   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
1177     return LoadWithVectorDescriptor(isolate());
1178   }
1179 
1180   DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
1181 };
1182 
1183 
1184 class LoadIndexedStringStub : public PlatformCodeStub {
1185  public:
LoadIndexedStringStub(Isolate * isolate)1186   explicit LoadIndexedStringStub(Isolate* isolate)
1187       : PlatformCodeStub(isolate) {}
1188 
GetCodeKind()1189   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1190   ExtraICState GetExtraICState() const override { return Code::KEYED_LOAD_IC; }
1191 
1192   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1193   DEFINE_PLATFORM_CODE_STUB(LoadIndexedString, PlatformCodeStub);
1194 };
1195 
1196 
1197 class HandlerStub : public HydrogenCodeStub {
1198  public:
GetCodeKind()1199   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1200   ExtraICState GetExtraICState() const override { return kind(); }
1201 
1202   void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
1203 
1204   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override;
1205 
1206  protected:
HandlerStub(Isolate * isolate)1207   explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1208 
1209   virtual Code::Kind kind() const = 0;
1210 
1211   DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
1212 };
1213 
1214 
1215 class LoadFieldStub: public HandlerStub {
1216  public:
LoadFieldStub(Isolate * isolate,FieldIndex index)1217   LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
1218     int property_index_key = index.GetFieldAccessStubKey();
1219     set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
1220   }
1221 
index()1222   FieldIndex index() const {
1223     int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
1224     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1225   }
1226 
1227  protected:
kind()1228   Code::Kind kind() const override { return Code::LOAD_IC; }
1229 
1230  private:
1231   class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
1232 
1233   // TODO(ishell): The stub uses only kReceiver parameter.
1234   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1235   DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
1236 };
1237 
1238 class KeyedLoadSloppyArgumentsStub : public TurboFanCodeStub {
1239  public:
KeyedLoadSloppyArgumentsStub(Isolate * isolate)1240   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
1241       : TurboFanCodeStub(isolate) {}
1242 
GetCodeKind()1243   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1244   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
1245 
1246  protected:
1247   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1248   DEFINE_TURBOFAN_CODE_STUB(KeyedLoadSloppyArguments, TurboFanCodeStub);
1249 };
1250 
1251 
1252 class CommonStoreModeBits : public BitField<KeyedAccessStoreMode, 0, 3> {};
1253 
1254 class KeyedStoreSloppyArgumentsStub : public TurboFanCodeStub {
1255  public:
KeyedStoreSloppyArgumentsStub(Isolate * isolate,KeyedAccessStoreMode mode)1256   explicit KeyedStoreSloppyArgumentsStub(Isolate* isolate,
1257                                          KeyedAccessStoreMode mode)
1258       : TurboFanCodeStub(isolate) {
1259     minor_key_ = CommonStoreModeBits::encode(mode);
1260   }
1261 
GetCodeKind()1262   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1263   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1264 
1265  protected:
1266   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1267   DEFINE_TURBOFAN_CODE_STUB(KeyedStoreSloppyArguments, TurboFanCodeStub);
1268 };
1269 
1270 
1271 class LoadConstantStub : public HandlerStub {
1272  public:
LoadConstantStub(Isolate * isolate,int constant_index)1273   LoadConstantStub(Isolate* isolate, int constant_index)
1274       : HandlerStub(isolate) {
1275     set_sub_minor_key(ConstantIndexBits::encode(constant_index));
1276   }
1277 
constant_index()1278   int constant_index() const {
1279     return ConstantIndexBits::decode(sub_minor_key());
1280   }
1281 
1282  protected:
kind()1283   Code::Kind kind() const override { return Code::LOAD_IC; }
1284 
1285  private:
1286   class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
1287 
1288   // TODO(ishell): The stub uses only kReceiver parameter.
1289   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1290   DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
1291 };
1292 
1293 class LoadApiGetterStub : public TurboFanCodeStub {
1294  public:
LoadApiGetterStub(Isolate * isolate,bool receiver_is_holder,int index)1295   LoadApiGetterStub(Isolate* isolate, bool receiver_is_holder, int index)
1296       : TurboFanCodeStub(isolate) {
1297     // If that's not true, we need to ensure that the receiver is actually a
1298     // JSReceiver. http://crbug.com/609134
1299     DCHECK(receiver_is_holder);
1300     minor_key_ = IndexBits::encode(index) |
1301                  ReceiverIsHolderBits::encode(receiver_is_holder);
1302   }
1303 
GetCodeKind()1304   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1305   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
1306 
index()1307   int index() const { return IndexBits::decode(minor_key_); }
receiver_is_holder()1308   bool receiver_is_holder() const {
1309     return ReceiverIsHolderBits::decode(minor_key_);
1310   }
1311 
1312  private:
1313   class ReceiverIsHolderBits : public BitField<bool, 0, 1> {};
1314   class IndexBits : public BitField<int, 1, kDescriptorIndexBitCount> {};
1315 
1316   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1317   DEFINE_TURBOFAN_CODE_STUB(LoadApiGetter, TurboFanCodeStub);
1318 };
1319 
1320 class StoreFieldStub : public TurboFanCodeStub {
1321  public:
StoreFieldStub(Isolate * isolate,FieldIndex index,Representation representation)1322   StoreFieldStub(Isolate* isolate, FieldIndex index,
1323                  Representation representation)
1324       : TurboFanCodeStub(isolate) {
1325     int property_index_key = index.GetFieldAccessStubKey();
1326     minor_key_ = StoreFieldByIndexBits::encode(property_index_key) |
1327                  RepresentationBits::encode(representation.kind());
1328   }
1329 
GetCodeKind()1330   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1331   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1332 
index()1333   FieldIndex index() const {
1334     int property_index_key = StoreFieldByIndexBits::decode(minor_key_);
1335     return FieldIndex::FromFieldAccessStubKey(property_index_key);
1336   }
1337 
representation()1338   Representation representation() const {
1339     return Representation::FromKind(RepresentationBits::decode(minor_key_));
1340   }
1341 
1342  private:
1343   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
1344   class RepresentationBits
1345       : public BitField<Representation::Kind, StoreFieldByIndexBits::kNext, 4> {
1346   };
1347   STATIC_ASSERT(Representation::kNumRepresentations - 1 <
1348                 RepresentationBits::kMax);
1349 
1350   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1351   DEFINE_TURBOFAN_CODE_STUB(StoreField, TurboFanCodeStub);
1352 };
1353 
1354 class StoreMapStub : public TurboFanCodeStub {
1355  public:
StoreMapStub(Isolate * isolate)1356   explicit StoreMapStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
1357 
GetCodeKind()1358   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1359   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1360 
1361  private:
1362   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
1363   DEFINE_TURBOFAN_CODE_STUB(StoreMap, TurboFanCodeStub);
1364 };
1365 
1366 class StoreTransitionStub : public TurboFanCodeStub {
1367  public:
1368   enum StoreMode {
1369     StoreMapAndValue,
1370     ExtendStorageAndStoreMapAndValue
1371   };
1372 
StoreTransitionStub(Isolate * isolate,bool is_inobject,Representation representation,StoreMode store_mode)1373   StoreTransitionStub(Isolate* isolate, bool is_inobject,
1374                       Representation representation, StoreMode store_mode)
1375       : TurboFanCodeStub(isolate) {
1376     minor_key_ = IsInobjectBits::encode(is_inobject) |
1377                  RepresentationBits::encode(representation.kind()) |
1378                  StoreModeBits::encode(store_mode);
1379   }
1380 
GetCodeKind()1381   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1382   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1383 
is_inobject()1384   bool is_inobject() const { return IsInobjectBits::decode(minor_key_); }
1385 
representation()1386   Representation representation() const {
1387     return Representation::FromKind(RepresentationBits::decode(minor_key_));
1388   }
1389 
store_mode()1390   StoreMode store_mode() const { return StoreModeBits::decode(minor_key_); }
1391 
1392  private:
1393   class IsInobjectBits : public BitField<bool, 0, 1> {};
1394   class RepresentationBits
1395       : public BitField<Representation::Kind, IsInobjectBits::kNext, 4> {};
1396   STATIC_ASSERT(Representation::kNumRepresentations - 1 <
1397                 RepresentationBits::kMax);
1398   class StoreModeBits
1399       : public BitField<StoreMode, RepresentationBits::kNext, 1> {};
1400 
1401   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreNamedTransition);
1402   DEFINE_TURBOFAN_CODE_STUB(StoreTransition, TurboFanCodeStub);
1403 };
1404 
1405 class StoreGlobalStub : public TurboFanCodeStub {
1406  public:
StoreGlobalStub(Isolate * isolate,PropertyCellType type,Maybe<PropertyCellConstantType> constant_type,bool check_global)1407   StoreGlobalStub(Isolate* isolate, PropertyCellType type,
1408                   Maybe<PropertyCellConstantType> constant_type,
1409                   bool check_global)
1410       : TurboFanCodeStub(isolate) {
1411     PropertyCellConstantType encoded_constant_type =
1412         constant_type.FromMaybe(PropertyCellConstantType::kSmi);
1413     minor_key_ = CellTypeBits::encode(type) |
1414                  ConstantTypeBits::encode(encoded_constant_type) |
1415                  CheckGlobalBits::encode(check_global);
1416   }
1417 
GetCodeKind()1418   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()1419   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
1420 
property_cell_placeholder(Isolate * isolate)1421   static Handle<HeapObject> property_cell_placeholder(Isolate* isolate) {
1422     return isolate->factory()->uninitialized_value();
1423   }
1424 
global_map_placeholder(Isolate * isolate)1425   static Handle<HeapObject> global_map_placeholder(Isolate* isolate) {
1426     return isolate->factory()->termination_exception();
1427   }
1428 
GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,Handle<PropertyCell> cell)1429   Handle<Code> GetCodeCopyFromTemplate(Handle<JSGlobalObject> global,
1430                                        Handle<PropertyCell> cell) {
1431     Code::FindAndReplacePattern pattern;
1432     if (check_global()) {
1433       pattern.Add(handle(global_map_placeholder(isolate())->map()),
1434                   Map::WeakCellForMap(Handle<Map>(global->map())));
1435     }
1436     pattern.Add(handle(property_cell_placeholder(isolate())->map()),
1437                 isolate()->factory()->NewWeakCell(cell));
1438     return CodeStub::GetCodeCopy(pattern);
1439   }
1440 
cell_type()1441   PropertyCellType cell_type() const {
1442     return CellTypeBits::decode(minor_key_);
1443   }
1444 
constant_type()1445   PropertyCellConstantType constant_type() const {
1446     DCHECK(PropertyCellType::kConstantType == cell_type());
1447     return ConstantTypeBits::decode(minor_key_);
1448   }
1449 
check_global()1450   bool check_global() const { return CheckGlobalBits::decode(minor_key_); }
1451 
1452  private:
1453   class CellTypeBits : public BitField<PropertyCellType, 0, 2> {};
1454   class ConstantTypeBits
1455       : public BitField<PropertyCellConstantType, CellTypeBits::kNext, 2> {};
1456   class CheckGlobalBits : public BitField<bool, ConstantTypeBits::kNext, 1> {};
1457 
1458   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
1459   DEFINE_TURBOFAN_CODE_STUB(StoreGlobal, TurboFanCodeStub);
1460 };
1461 
1462 class CallApiCallbackStub : public PlatformCodeStub {
1463  public:
1464   static const int kArgBits = 3;
1465   static const int kArgMax = (1 << kArgBits) - 1;
1466 
1467   // CallApiCallbackStub for regular setters and getters.
CallApiCallbackStub(Isolate * isolate,bool is_store,bool call_data_undefined,bool is_lazy)1468   CallApiCallbackStub(Isolate* isolate, bool is_store, bool call_data_undefined,
1469                       bool is_lazy)
1470       : CallApiCallbackStub(isolate, is_store ? 1 : 0, is_store,
1471                             call_data_undefined, is_lazy) {}
1472 
1473   // CallApiCallbackStub for callback functions.
CallApiCallbackStub(Isolate * isolate,int argc,bool call_data_undefined,bool is_lazy)1474   CallApiCallbackStub(Isolate* isolate, int argc, bool call_data_undefined,
1475                       bool is_lazy)
1476       : CallApiCallbackStub(isolate, argc, false, call_data_undefined,
1477                             is_lazy) {}
1478 
1479  private:
CallApiCallbackStub(Isolate * isolate,int argc,bool is_store,bool call_data_undefined,bool is_lazy)1480   CallApiCallbackStub(Isolate* isolate, int argc, bool is_store,
1481                       bool call_data_undefined, bool is_lazy)
1482       : PlatformCodeStub(isolate) {
1483     CHECK(0 <= argc && argc <= kArgMax);
1484     minor_key_ = IsStoreBits::encode(is_store) |
1485                  CallDataUndefinedBits::encode(call_data_undefined) |
1486                  ArgumentBits::encode(argc) |
1487                  IsLazyAccessorBits::encode(is_lazy);
1488   }
1489 
is_store()1490   bool is_store() const { return IsStoreBits::decode(minor_key_); }
is_lazy()1491   bool is_lazy() const { return IsLazyAccessorBits::decode(minor_key_); }
call_data_undefined()1492   bool call_data_undefined() const {
1493     return CallDataUndefinedBits::decode(minor_key_);
1494   }
argc()1495   int argc() const { return ArgumentBits::decode(minor_key_); }
1496 
1497   class IsStoreBits: public BitField<bool, 0, 1> {};
1498   class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1499   class ArgumentBits : public BitField<int, 2, kArgBits> {};
1500   class IsLazyAccessorBits : public BitField<bool, 3 + kArgBits, 1> {};
1501 
1502   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiCallback);
1503   DEFINE_PLATFORM_CODE_STUB(CallApiCallback, PlatformCodeStub);
1504 };
1505 
1506 
1507 class CallApiGetterStub : public PlatformCodeStub {
1508  public:
CallApiGetterStub(Isolate * isolate)1509   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1510 
1511   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1512   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1513 };
1514 
1515 
1516 class BinaryOpICStub : public HydrogenCodeStub {
1517  public:
BinaryOpICStub(Isolate * isolate,Token::Value op)1518   BinaryOpICStub(Isolate* isolate, Token::Value op)
1519       : HydrogenCodeStub(isolate, UNINITIALIZED) {
1520     BinaryOpICState state(isolate, op);
1521     set_sub_minor_key(state.GetExtraICState());
1522   }
1523 
BinaryOpICStub(Isolate * isolate,const BinaryOpICState & state)1524   BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1525       : HydrogenCodeStub(isolate) {
1526     set_sub_minor_key(state.GetExtraICState());
1527   }
1528 
1529   static void GenerateAheadOfTime(Isolate* isolate);
1530 
GetCodeKind()1531   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1532 
GetExtraICState()1533   ExtraICState GetExtraICState() const final {
1534     return static_cast<ExtraICState>(sub_minor_key());
1535   }
1536 
state()1537   BinaryOpICState state() const {
1538     return BinaryOpICState(isolate(), GetExtraICState());
1539   }
1540 
1541   void PrintState(std::ostream& os) const final;  // NOLINT
1542 
1543  private:
1544   static void GenerateAheadOfTime(Isolate* isolate,
1545                                   const BinaryOpICState& state);
1546 
1547   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1548   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1549 };
1550 
1551 
1552 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1553 // call support for stubs in Hydrogen.
1554 class BinaryOpICWithAllocationSiteStub final : public PlatformCodeStub {
1555  public:
BinaryOpICWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1556   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1557                                    const BinaryOpICState& state)
1558       : PlatformCodeStub(isolate) {
1559     minor_key_ = state.GetExtraICState();
1560   }
1561 
1562   static void GenerateAheadOfTime(Isolate* isolate);
1563 
GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site)1564   Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1565     Code::FindAndReplacePattern pattern;
1566     pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1567     return CodeStub::GetCodeCopy(pattern);
1568   }
1569 
GetCodeKind()1570   Code::Kind GetCodeKind() const override { return Code::BINARY_OP_IC; }
1571 
GetExtraICState()1572   ExtraICState GetExtraICState() const override {
1573     return static_cast<ExtraICState>(minor_key_);
1574   }
1575 
1576   void PrintState(std::ostream& os) const override;  // NOLINT
1577 
1578  private:
state()1579   BinaryOpICState state() const {
1580     return BinaryOpICState(isolate(), GetExtraICState());
1581   }
1582 
1583   static void GenerateAheadOfTime(Isolate* isolate,
1584                                   const BinaryOpICState& state);
1585 
1586   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1587   DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1588 };
1589 
1590 
1591 class BinaryOpWithAllocationSiteStub final : public BinaryOpICStub {
1592  public:
BinaryOpWithAllocationSiteStub(Isolate * isolate,Token::Value op)1593   BinaryOpWithAllocationSiteStub(Isolate* isolate, Token::Value op)
1594       : BinaryOpICStub(isolate, op) {}
1595 
BinaryOpWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1596   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1597       : BinaryOpICStub(isolate, state) {}
1598 
GetCodeKind()1599   Code::Kind GetCodeKind() const final { return Code::STUB; }
1600 
1601   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1602   DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1603 };
1604 
1605 class StringAddStub final : public TurboFanCodeStub {
1606  public:
StringAddStub(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)1607   StringAddStub(Isolate* isolate, StringAddFlags flags,
1608                 PretenureFlag pretenure_flag)
1609       : TurboFanCodeStub(isolate) {
1610     minor_key_ = (StringAddFlagsBits::encode(flags) |
1611                   PretenureFlagBits::encode(pretenure_flag));
1612   }
1613 
flags()1614   StringAddFlags flags() const {
1615     return StringAddFlagsBits::decode(minor_key_);
1616   }
1617 
pretenure_flag()1618   PretenureFlag pretenure_flag() const {
1619     return PretenureFlagBits::decode(minor_key_);
1620   }
1621 
1622  private:
1623   class StringAddFlagsBits : public BitField<StringAddFlags, 0, 3> {};
1624   class PretenureFlagBits : public BitField<PretenureFlag, 3, 1> {};
1625 
1626   void PrintBaseName(std::ostream& os) const override;  // NOLINT
1627 
1628   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1629   DEFINE_TURBOFAN_CODE_STUB(StringAdd, TurboFanCodeStub);
1630 };
1631 
1632 
1633 class CompareICStub : public PlatformCodeStub {
1634  public:
CompareICStub(Isolate * isolate,Token::Value op,CompareICState::State left,CompareICState::State right,CompareICState::State state)1635   CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1636                 CompareICState::State right, CompareICState::State state)
1637       : PlatformCodeStub(isolate) {
1638     DCHECK(Token::IsCompareOp(op));
1639     DCHECK(OpBits::is_valid(op - Token::EQ));
1640     minor_key_ = OpBits::encode(op - Token::EQ) |
1641                  LeftStateBits::encode(left) | RightStateBits::encode(right) |
1642                  StateBits::encode(state);
1643   }
1644   // Creates uninitialized compare stub.
CompareICStub(Isolate * isolate,Token::Value op)1645   CompareICStub(Isolate* isolate, Token::Value op)
1646       : CompareICStub(isolate, op, CompareICState::UNINITIALIZED,
1647                       CompareICState::UNINITIALIZED,
1648                       CompareICState::UNINITIALIZED) {}
1649 
CompareICStub(Isolate * isolate,ExtraICState extra_ic_state)1650   CompareICStub(Isolate* isolate, ExtraICState extra_ic_state)
1651       : PlatformCodeStub(isolate) {
1652     minor_key_ = extra_ic_state;
1653   }
1654 
GetExtraICState()1655   ExtraICState GetExtraICState() const final {
1656     return static_cast<ExtraICState>(minor_key_);
1657   }
1658 
set_known_map(Handle<Map> map)1659   void set_known_map(Handle<Map> map) { known_map_ = map; }
1660 
1661   InlineCacheState GetICState() const;
1662 
op()1663   Token::Value op() const {
1664     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1665   }
1666 
left()1667   CompareICState::State left() const {
1668     return LeftStateBits::decode(minor_key_);
1669   }
right()1670   CompareICState::State right() const {
1671     return RightStateBits::decode(minor_key_);
1672   }
state()1673   CompareICState::State state() const { return StateBits::decode(minor_key_); }
1674 
1675  private:
GetCodeKind()1676   Code::Kind GetCodeKind() const override { return Code::COMPARE_IC; }
1677 
1678   void GenerateBooleans(MacroAssembler* masm);
1679   void GenerateSmis(MacroAssembler* masm);
1680   void GenerateNumbers(MacroAssembler* masm);
1681   void GenerateInternalizedStrings(MacroAssembler* masm);
1682   void GenerateStrings(MacroAssembler* masm);
1683   void GenerateUniqueNames(MacroAssembler* masm);
1684   void GenerateReceivers(MacroAssembler* masm);
1685   void GenerateMiss(MacroAssembler* masm);
1686   void GenerateKnownReceivers(MacroAssembler* masm);
1687   void GenerateGeneric(MacroAssembler* masm);
1688 
strict()1689   bool strict() const { return op() == Token::EQ_STRICT; }
1690   Condition GetCondition() const;
1691 
1692   // Although we don't cache anything in the special cache we have to define
1693   // this predicate to avoid appearance of code stubs with embedded maps in
1694   // the global stub cache.
UseSpecialCache()1695   bool UseSpecialCache() override {
1696     return state() == CompareICState::KNOWN_RECEIVER;
1697   }
1698 
1699   class OpBits : public BitField<int, 0, 3> {};
1700   class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1701   class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1702   class StateBits : public BitField<CompareICState::State, 11, 4> {};
1703 
1704   Handle<Map> known_map_;
1705 
1706   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1707   DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1708 };
1709 
1710 
1711 class CEntryStub : public PlatformCodeStub {
1712  public:
1713   CEntryStub(Isolate* isolate, int result_size,
1714              SaveFPRegsMode save_doubles = kDontSaveFPRegs,
1715              ArgvMode argv_mode = kArgvOnStack, bool builtin_exit_frame = false)
PlatformCodeStub(isolate)1716       : PlatformCodeStub(isolate) {
1717     minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs) |
1718                  FrameTypeBits::encode(builtin_exit_frame) |
1719                  ArgvMode::encode(argv_mode == kArgvInRegister);
1720     DCHECK(result_size == 1 || result_size == 2 || result_size == 3);
1721     minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1722   }
1723 
1724   // The version of this stub that doesn't save doubles is generated ahead of
1725   // time, so it's OK to call it from other stubs that can't cope with GC during
1726   // their code generation.  On machines that always have gp registers (x64) we
1727   // can generate both variants ahead of time.
1728   static void GenerateAheadOfTime(Isolate* isolate);
1729 
1730  private:
save_doubles()1731   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
argv_in_register()1732   bool argv_in_register() const { return ArgvMode::decode(minor_key_); }
is_builtin_exit()1733   bool is_builtin_exit() const { return FrameTypeBits::decode(minor_key_); }
result_size()1734   int result_size() const { return ResultSizeBits::decode(minor_key_); }
1735 
1736   bool NeedsImmovableCode() override;
1737 
1738   class SaveDoublesBits : public BitField<bool, 0, 1> {};
1739   class ArgvMode : public BitField<bool, 1, 1> {};
1740   class FrameTypeBits : public BitField<bool, 2, 1> {};
1741   class ResultSizeBits : public BitField<int, 3, 3> {};
1742 
1743   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1744   DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1745 };
1746 
1747 
1748 class JSEntryStub : public PlatformCodeStub {
1749  public:
JSEntryStub(Isolate * isolate,StackFrame::Type type)1750   JSEntryStub(Isolate* isolate, StackFrame::Type type)
1751       : PlatformCodeStub(isolate) {
1752     DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1753     minor_key_ = StackFrameTypeBits::encode(type);
1754   }
1755 
1756  private:
1757   void FinishCode(Handle<Code> code) override;
1758 
PrintName(std::ostream & os)1759   void PrintName(std::ostream& os) const override {  // NOLINT
1760     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1761                                        : "JSConstructEntryStub");
1762   }
1763 
type()1764   StackFrame::Type type() const {
1765     return StackFrameTypeBits::decode(minor_key_);
1766   }
1767 
1768   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1769 
1770   int handler_offset_;
1771 
1772   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1773   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1774 };
1775 
1776 
1777 class RegExpExecStub: public PlatformCodeStub {
1778  public:
RegExpExecStub(Isolate * isolate)1779   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1780 
1781   DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpExec);
1782   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1783 };
1784 
1785 // TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
1786 class CallConstructStub final : public PlatformCodeStub {
1787  public:
CallConstructStub(Isolate * isolate)1788   explicit CallConstructStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1789 
1790   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1791   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1792 };
1793 
1794 
1795 enum ReceiverCheckMode {
1796   // We don't know anything about the receiver.
1797   RECEIVER_IS_UNKNOWN,
1798 
1799   // We know the receiver is a string.
1800   RECEIVER_IS_STRING
1801 };
1802 
1803 
1804 enum EmbedMode {
1805   // The code being generated is part of an IC handler, which may MISS
1806   // to an IC in failure cases.
1807   PART_OF_IC_HANDLER,
1808 
1809   NOT_PART_OF_IC_HANDLER
1810 };
1811 
1812 
1813 // Generates code implementing String.prototype.charCodeAt.
1814 //
1815 // Only supports the case when the receiver is a string and the index
1816 // is a number (smi or heap number) that is a valid index into the
1817 // string. Additional index constraints are specified by the
1818 // flags. Otherwise, bails out to the provided labels.
1819 //
1820 // Register usage: |object| may be changed to another string in a way
1821 // that doesn't affect charCodeAt/charAt semantics, |index| is
1822 // preserved, |scratch| and |result| are clobbered.
1823 class StringCharCodeAtGenerator {
1824  public:
1825   StringCharCodeAtGenerator(Register object, Register index, Register result,
1826                             Label* receiver_not_string, Label* index_not_number,
1827                             Label* index_out_of_range,
1828                             ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
object_(object)1829       : object_(object),
1830         index_(index),
1831         result_(result),
1832         receiver_not_string_(receiver_not_string),
1833         index_not_number_(index_not_number),
1834         index_out_of_range_(index_out_of_range),
1835         check_mode_(check_mode) {
1836     DCHECK(!result_.is(object_));
1837     DCHECK(!result_.is(index_));
1838   }
1839 
1840   // Generates the fast case code. On the fallthrough path |result|
1841   // register contains the result.
1842   void GenerateFast(MacroAssembler* masm);
1843 
1844   // Generates the slow case code. Must not be naturally
1845   // reachable. Expected to be put after a ret instruction (e.g., in
1846   // deferred code). Always jumps back to the fast case.
1847   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
1848                     const RuntimeCallHelper& call_helper);
1849 
1850   // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1851   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1852     masm->bind(&index_not_smi_);
1853     masm->bind(&call_runtime_);
1854     masm->jmp(bailout);
1855   }
1856 
1857  private:
1858   Register object_;
1859   Register index_;
1860   Register result_;
1861 
1862   Label* receiver_not_string_;
1863   Label* index_not_number_;
1864   Label* index_out_of_range_;
1865 
1866   ReceiverCheckMode check_mode_;
1867 
1868   Label call_runtime_;
1869   Label index_not_smi_;
1870   Label got_smi_index_;
1871   Label exit_;
1872 
1873   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1874 };
1875 
1876 
1877 // Generates code for creating a one-char string from a char code.
1878 class StringCharFromCodeGenerator {
1879  public:
StringCharFromCodeGenerator(Register code,Register result)1880   StringCharFromCodeGenerator(Register code,
1881                               Register result)
1882       : code_(code),
1883         result_(result) {
1884     DCHECK(!code_.is(result_));
1885   }
1886 
1887   // Generates the fast case code. On the fallthrough path |result|
1888   // register contains the result.
1889   void GenerateFast(MacroAssembler* masm);
1890 
1891   // Generates the slow case code. Must not be naturally
1892   // reachable. Expected to be put after a ret instruction (e.g., in
1893   // deferred code). Always jumps back to the fast case.
1894   void GenerateSlow(MacroAssembler* masm,
1895                     const RuntimeCallHelper& call_helper);
1896 
1897   // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1898   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1899     masm->bind(&slow_case_);
1900     masm->jmp(bailout);
1901   }
1902 
1903  private:
1904   Register code_;
1905   Register result_;
1906 
1907   Label slow_case_;
1908   Label exit_;
1909 
1910   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1911 };
1912 
1913 
1914 // Generates code implementing String.prototype.charAt.
1915 //
1916 // Only supports the case when the receiver is a string and the index
1917 // is a number (smi or heap number) that is a valid index into the
1918 // string. Additional index constraints are specified by the
1919 // flags. Otherwise, bails out to the provided labels.
1920 //
1921 // Register usage: |object| may be changed to another string in a way
1922 // that doesn't affect charCodeAt/charAt semantics, |index| is
1923 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1924 class StringCharAtGenerator {
1925  public:
1926   StringCharAtGenerator(Register object, Register index, Register scratch,
1927                         Register result, Label* receiver_not_string,
1928                         Label* index_not_number, Label* index_out_of_range,
1929                         ReceiverCheckMode check_mode = RECEIVER_IS_UNKNOWN)
char_code_at_generator_(object,index,scratch,receiver_not_string,index_not_number,index_out_of_range,check_mode)1930       : char_code_at_generator_(object, index, scratch, receiver_not_string,
1931                                 index_not_number, index_out_of_range,
1932                                 check_mode),
1933         char_from_code_generator_(scratch, result) {}
1934 
1935   // Generates the fast case code. On the fallthrough path |result|
1936   // register contains the result.
GenerateFast(MacroAssembler * masm)1937   void GenerateFast(MacroAssembler* masm) {
1938     char_code_at_generator_.GenerateFast(masm);
1939     char_from_code_generator_.GenerateFast(masm);
1940   }
1941 
1942   // Generates the slow case code. Must not be naturally
1943   // reachable. Expected to be put after a ret instruction (e.g., in
1944   // deferred code). Always jumps back to the fast case.
GenerateSlow(MacroAssembler * masm,EmbedMode embed_mode,const RuntimeCallHelper & call_helper)1945   void GenerateSlow(MacroAssembler* masm, EmbedMode embed_mode,
1946                     const RuntimeCallHelper& call_helper) {
1947     char_code_at_generator_.GenerateSlow(masm, embed_mode, call_helper);
1948     char_from_code_generator_.GenerateSlow(masm, call_helper);
1949   }
1950 
1951   // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1952   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1953     char_code_at_generator_.SkipSlow(masm, bailout);
1954     char_from_code_generator_.SkipSlow(masm, bailout);
1955   }
1956 
1957  private:
1958   StringCharCodeAtGenerator char_code_at_generator_;
1959   StringCharFromCodeGenerator char_from_code_generator_;
1960 
1961   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1962 };
1963 
1964 
1965 class LoadDictionaryElementStub : public HydrogenCodeStub {
1966  public:
LoadDictionaryElementStub(Isolate * isolate)1967   explicit LoadDictionaryElementStub(Isolate* isolate)
1968       : HydrogenCodeStub(isolate) {}
1969 
1970   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
1971   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
1972 };
1973 
1974 class LoadICTrampolineStub : public TurboFanCodeStub {
1975  public:
LoadICTrampolineStub(Isolate * isolate)1976   explicit LoadICTrampolineStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
1977 
1978   void GenerateAssembly(CodeStubAssembler* assembler) const override;
1979 
GetCodeKind()1980   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
1981 
1982   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1983   DEFINE_CODE_STUB(LoadICTrampoline, TurboFanCodeStub);
1984 };
1985 
1986 class LoadGlobalICTrampolineStub : public TurboFanCodeStub {
1987  public:
LoadGlobalICTrampolineStub(Isolate * isolate,const LoadGlobalICState & state)1988   explicit LoadGlobalICTrampolineStub(Isolate* isolate,
1989                                       const LoadGlobalICState& state)
1990       : TurboFanCodeStub(isolate) {
1991     minor_key_ = state.GetExtraICState();
1992   }
1993 
1994   void GenerateAssembly(CodeStubAssembler* assembler) const override;
1995 
GetCodeKind()1996   Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
1997 
GetExtraICState()1998   ExtraICState GetExtraICState() const final {
1999     return static_cast<ExtraICState>(minor_key_);
2000   }
2001 
2002   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobal);
2003   DEFINE_CODE_STUB(LoadGlobalICTrampoline, TurboFanCodeStub);
2004 };
2005 
2006 class KeyedLoadICTrampolineTFStub : public LoadICTrampolineStub {
2007  public:
KeyedLoadICTrampolineTFStub(Isolate * isolate)2008   explicit KeyedLoadICTrampolineTFStub(Isolate* isolate)
2009       : LoadICTrampolineStub(isolate) {}
2010 
2011   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2012 
GetCodeKind()2013   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2014 
2015   DEFINE_CODE_STUB(KeyedLoadICTrampolineTF, LoadICTrampolineStub);
2016 };
2017 
2018 class StoreICTrampolineStub : public TurboFanCodeStub {
2019  public:
StoreICTrampolineStub(Isolate * isolate,const StoreICState & state)2020   StoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2021       : TurboFanCodeStub(isolate) {
2022     minor_key_ = state.GetExtraICState();
2023   }
2024 
2025   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2026 
GetCodeKind()2027   Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
2028 
GetExtraICState()2029   ExtraICState GetExtraICState() const final {
2030     return static_cast<ExtraICState>(minor_key_);
2031   }
2032 
2033  protected:
state()2034   StoreICState state() const { return StoreICState(GetExtraICState()); }
2035 
2036   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2037   DEFINE_CODE_STUB(StoreICTrampoline, TurboFanCodeStub);
2038 };
2039 
2040 class KeyedStoreICTrampolineStub : public PlatformCodeStub {
2041  public:
KeyedStoreICTrampolineStub(Isolate * isolate,const StoreICState & state)2042   KeyedStoreICTrampolineStub(Isolate* isolate, const StoreICState& state)
2043       : PlatformCodeStub(isolate) {
2044     minor_key_ = state.GetExtraICState();
2045   }
2046 
GetCodeKind()2047   Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2048 
GetExtraICState()2049   ExtraICState GetExtraICState() const final {
2050     return static_cast<ExtraICState>(minor_key_);
2051   }
2052 
2053  protected:
state()2054   StoreICState state() const { return StoreICState(GetExtraICState()); }
2055 
2056  private:
2057   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2058   DEFINE_PLATFORM_CODE_STUB(KeyedStoreICTrampoline, PlatformCodeStub);
2059 };
2060 
2061 class KeyedStoreICTrampolineTFStub : public StoreICTrampolineStub {
2062  public:
KeyedStoreICTrampolineTFStub(Isolate * isolate,const StoreICState & state)2063   KeyedStoreICTrampolineTFStub(Isolate* isolate, const StoreICState& state)
2064       : StoreICTrampolineStub(isolate, state) {}
2065 
2066   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2067 
GetCodeKind()2068   Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2069 
2070   DEFINE_CODE_STUB(KeyedStoreICTrampolineTF, StoreICTrampolineStub);
2071 };
2072 
2073 class CallICTrampolineStub : public PlatformCodeStub {
2074  public:
CallICTrampolineStub(Isolate * isolate,const CallICState & state)2075   CallICTrampolineStub(Isolate* isolate, const CallICState& state)
2076       : PlatformCodeStub(isolate) {
2077     minor_key_ = state.GetExtraICState();
2078   }
2079 
GetCodeKind()2080   Code::Kind GetCodeKind() const override { return Code::CALL_IC; }
2081 
GetExtraICState()2082   ExtraICState GetExtraICState() const final {
2083     return static_cast<ExtraICState>(minor_key_);
2084   }
2085 
2086  protected:
state()2087   CallICState state() const {
2088     return CallICState(static_cast<ExtraICState>(minor_key_));
2089   }
2090 
2091   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
2092   DEFINE_PLATFORM_CODE_STUB(CallICTrampoline, PlatformCodeStub);
2093 };
2094 
2095 class LoadICStub : public TurboFanCodeStub {
2096  public:
LoadICStub(Isolate * isolate)2097   explicit LoadICStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
2098 
2099   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2100 
GetCodeKind()2101   Code::Kind GetCodeKind() const override { return Code::LOAD_IC; }
2102 
2103   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2104   DEFINE_CODE_STUB(LoadIC, TurboFanCodeStub);
2105 };
2106 
2107 class LoadICProtoArrayStub : public TurboFanCodeStub {
2108  public:
LoadICProtoArrayStub(Isolate * isolate)2109   explicit LoadICProtoArrayStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
2110 
2111   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2112 
2113   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadICProtoArray);
2114   DEFINE_CODE_STUB(LoadICProtoArray, TurboFanCodeStub);
2115 };
2116 
2117 class LoadGlobalICStub : public TurboFanCodeStub {
2118  public:
LoadGlobalICStub(Isolate * isolate,const LoadGlobalICState & state)2119   explicit LoadGlobalICStub(Isolate* isolate, const LoadGlobalICState& state)
2120       : TurboFanCodeStub(isolate) {
2121     minor_key_ = state.GetExtraICState();
2122   }
2123 
2124   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2125 
GetCodeKind()2126   Code::Kind GetCodeKind() const override { return Code::LOAD_GLOBAL_IC; }
2127 
GetExtraICState()2128   ExtraICState GetExtraICState() const final {
2129     return static_cast<ExtraICState>(minor_key_);
2130   }
2131 
2132   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadGlobalWithVector);
2133   DEFINE_CODE_STUB(LoadGlobalIC, TurboFanCodeStub);
2134 };
2135 
2136 class KeyedLoadICTFStub : public LoadICStub {
2137  public:
KeyedLoadICTFStub(Isolate * isolate)2138   explicit KeyedLoadICTFStub(Isolate* isolate) : LoadICStub(isolate) {}
2139 
2140   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2141 
GetCodeKind()2142   Code::Kind GetCodeKind() const override { return Code::KEYED_LOAD_IC; }
2143 
2144   DEFINE_CODE_STUB(KeyedLoadICTF, LoadICStub);
2145 };
2146 
2147 class StoreICStub : public TurboFanCodeStub {
2148  public:
StoreICStub(Isolate * isolate,const StoreICState & state)2149   StoreICStub(Isolate* isolate, const StoreICState& state)
2150       : TurboFanCodeStub(isolate) {
2151     minor_key_ = state.GetExtraICState();
2152   }
2153 
2154   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2155 
GetCodeKind()2156   Code::Kind GetCodeKind() const override { return Code::STORE_IC; }
GetExtraICState()2157   ExtraICState GetExtraICState() const final {
2158     return static_cast<ExtraICState>(minor_key_);
2159   }
2160 
2161   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2162   DEFINE_CODE_STUB(StoreIC, TurboFanCodeStub);
2163 };
2164 
2165 class KeyedStoreICStub : public PlatformCodeStub {
2166  public:
KeyedStoreICStub(Isolate * isolate,const StoreICState & state)2167   KeyedStoreICStub(Isolate* isolate, const StoreICState& state)
2168       : PlatformCodeStub(isolate) {
2169     minor_key_ = state.GetExtraICState();
2170   }
2171 
2172   void GenerateForTrampoline(MacroAssembler* masm);
2173 
GetCodeKind()2174   Code::Kind GetCodeKind() const final { return Code::KEYED_STORE_IC; }
2175 
GetExtraICState()2176   ExtraICState GetExtraICState() const final {
2177     return static_cast<ExtraICState>(minor_key_);
2178   }
2179 
2180   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2181   DEFINE_PLATFORM_CODE_STUB(KeyedStoreIC, PlatformCodeStub);
2182 
2183  protected:
2184   void GenerateImpl(MacroAssembler* masm, bool in_frame);
2185 };
2186 
2187 class KeyedStoreICTFStub : public StoreICStub {
2188  public:
KeyedStoreICTFStub(Isolate * isolate,const StoreICState & state)2189   KeyedStoreICTFStub(Isolate* isolate, const StoreICState& state)
2190       : StoreICStub(isolate, state) {}
2191 
2192   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2193 
GetCodeKind()2194   Code::Kind GetCodeKind() const override { return Code::KEYED_STORE_IC; }
2195 
2196   DEFINE_CODE_STUB(KeyedStoreICTF, StoreICStub);
2197 };
2198 
2199 class DoubleToIStub : public PlatformCodeStub {
2200  public:
2201   DoubleToIStub(Isolate* isolate, Register source, Register destination,
2202                 int offset, bool is_truncating, bool skip_fastpath = false)
PlatformCodeStub(isolate)2203       : PlatformCodeStub(isolate) {
2204     minor_key_ = SourceRegisterBits::encode(source.code()) |
2205                  DestinationRegisterBits::encode(destination.code()) |
2206                  OffsetBits::encode(offset) |
2207                  IsTruncatingBits::encode(is_truncating) |
2208                  SkipFastPathBits::encode(skip_fastpath) |
2209                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
2210   }
2211 
SometimesSetsUpAFrame()2212   bool SometimesSetsUpAFrame() override { return false; }
2213 
2214  private:
source()2215   Register source() const {
2216     return Register::from_code(SourceRegisterBits::decode(minor_key_));
2217   }
destination()2218   Register destination() const {
2219     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
2220   }
is_truncating()2221   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
skip_fastpath()2222   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
offset()2223   int offset() const { return OffsetBits::decode(minor_key_); }
2224 
2225   static const int kBitsPerRegisterNumber = 6;
2226   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
2227   class SourceRegisterBits:
2228       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
2229   class DestinationRegisterBits:
2230       public BitField<int, kBitsPerRegisterNumber,
2231         kBitsPerRegisterNumber> {};  // NOLINT
2232   class IsTruncatingBits:
2233       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
2234   class OffsetBits:
2235       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
2236   class SkipFastPathBits:
2237       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
2238   class SSE3Bits:
2239       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
2240 
2241   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2242   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
2243 };
2244 
2245 class ScriptContextFieldStub : public TurboFanCodeStub {
2246  public:
ScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)2247   ScriptContextFieldStub(Isolate* isolate,
2248                          const ScriptContextTable::LookupResult* lookup_result)
2249       : TurboFanCodeStub(isolate) {
2250     DCHECK(Accepted(lookup_result));
2251     minor_key_ = ContextIndexBits::encode(lookup_result->context_index) |
2252                  SlotIndexBits::encode(lookup_result->slot_index);
2253   }
2254 
GetCodeKind()2255   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
2256 
context_index()2257   int context_index() const { return ContextIndexBits::decode(minor_key_); }
2258 
slot_index()2259   int slot_index() const { return SlotIndexBits::decode(minor_key_); }
2260 
Accepted(const ScriptContextTable::LookupResult * lookup_result)2261   static bool Accepted(const ScriptContextTable::LookupResult* lookup_result) {
2262     return ContextIndexBits::is_valid(lookup_result->context_index) &&
2263            SlotIndexBits::is_valid(lookup_result->slot_index);
2264   }
2265 
2266  private:
2267   static const int kContextIndexBits = 9;
2268   static const int kSlotIndexBits = 12;
2269   class ContextIndexBits : public BitField<int, 0, kContextIndexBits> {};
2270   class SlotIndexBits
2271       : public BitField<int, kContextIndexBits, kSlotIndexBits> {};
2272 
2273   DEFINE_CODE_STUB_BASE(ScriptContextFieldStub, TurboFanCodeStub);
2274 };
2275 
2276 
2277 class LoadScriptContextFieldStub : public ScriptContextFieldStub {
2278  public:
LoadScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)2279   LoadScriptContextFieldStub(
2280       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2281       : ScriptContextFieldStub(isolate, lookup_result) {}
2282 
GetExtraICState()2283   ExtraICState GetExtraICState() const override { return Code::LOAD_IC; }
2284 
2285  private:
2286   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2287   DEFINE_TURBOFAN_CODE_STUB(LoadScriptContextField, ScriptContextFieldStub);
2288 };
2289 
2290 
2291 class StoreScriptContextFieldStub : public ScriptContextFieldStub {
2292  public:
StoreScriptContextFieldStub(Isolate * isolate,const ScriptContextTable::LookupResult * lookup_result)2293   StoreScriptContextFieldStub(
2294       Isolate* isolate, const ScriptContextTable::LookupResult* lookup_result)
2295       : ScriptContextFieldStub(isolate, lookup_result) {}
2296 
GetExtraICState()2297   ExtraICState GetExtraICState() const override { return Code::STORE_IC; }
2298 
2299  private:
2300   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2301   DEFINE_TURBOFAN_CODE_STUB(StoreScriptContextField, ScriptContextFieldStub);
2302 };
2303 
2304 
2305 class LoadFastElementStub : public HandlerStub {
2306  public:
2307   LoadFastElementStub(Isolate* isolate, bool is_js_array,
2308                       ElementsKind elements_kind,
2309                       bool convert_hole_to_undefined = false)
HandlerStub(isolate)2310       : HandlerStub(isolate) {
2311     set_sub_minor_key(
2312         ElementsKindBits::encode(elements_kind) |
2313         IsJSArrayBits::encode(is_js_array) |
2314         CanConvertHoleToUndefined::encode(convert_hole_to_undefined));
2315   }
2316 
kind()2317   Code::Kind kind() const override { return Code::KEYED_LOAD_IC; }
2318 
is_js_array()2319   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
convert_hole_to_undefined()2320   bool convert_hole_to_undefined() const {
2321     return CanConvertHoleToUndefined::decode(sub_minor_key());
2322   }
2323 
elements_kind()2324   ElementsKind elements_kind() const {
2325     return ElementsKindBits::decode(sub_minor_key());
2326   }
2327 
2328  private:
2329   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2330   class IsJSArrayBits: public BitField<bool, 8, 1> {};
2331   class CanConvertHoleToUndefined : public BitField<bool, 9, 1> {};
2332 
2333   DEFINE_CALL_INTERFACE_DESCRIPTOR(LoadWithVector);
2334   DEFINE_HANDLER_CODE_STUB(LoadFastElement, HandlerStub);
2335 };
2336 
2337 class StoreFastElementStub : public TurboFanCodeStub {
2338  public:
StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)2339   StoreFastElementStub(Isolate* isolate, bool is_js_array,
2340                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
2341       : TurboFanCodeStub(isolate) {
2342     minor_key_ = CommonStoreModeBits::encode(mode) |
2343                  ElementsKindBits::encode(elements_kind) |
2344                  IsJSArrayBits::encode(is_js_array);
2345   }
2346 
2347   static void GenerateAheadOfTime(Isolate* isolate);
2348 
is_js_array()2349   bool is_js_array() const { return IsJSArrayBits::decode(minor_key_); }
2350 
elements_kind()2351   ElementsKind elements_kind() const {
2352     return ElementsKindBits::decode(minor_key_);
2353   }
2354 
store_mode()2355   KeyedAccessStoreMode store_mode() const {
2356     return CommonStoreModeBits::decode(minor_key_);
2357   }
2358 
GetCodeKind()2359   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()2360   ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
2361 
2362  private:
2363   class ElementsKindBits
2364       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
2365   class IsJSArrayBits : public BitField<bool, ElementsKindBits::kNext, 1> {};
2366 
2367   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2368   DEFINE_TURBOFAN_CODE_STUB(StoreFastElement, TurboFanCodeStub);
2369 };
2370 
2371 
2372 class TransitionElementsKindStub : public HydrogenCodeStub {
2373  public:
TransitionElementsKindStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind)2374   TransitionElementsKindStub(Isolate* isolate, ElementsKind from_kind,
2375                              ElementsKind to_kind)
2376       : HydrogenCodeStub(isolate) {
2377     set_sub_minor_key(FromKindBits::encode(from_kind) |
2378                       ToKindBits::encode(to_kind));
2379   }
2380 
from_kind()2381   ElementsKind from_kind() const {
2382     return FromKindBits::decode(sub_minor_key());
2383   }
2384 
to_kind()2385   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2386 
2387  private:
2388   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2389   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2390 
2391   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2392   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2393 };
2394 
2395 class AllocateHeapNumberStub : public TurboFanCodeStub {
2396  public:
AllocateHeapNumberStub(Isolate * isolate)2397   explicit AllocateHeapNumberStub(Isolate* isolate)
2398       : TurboFanCodeStub(isolate) {}
2399 
2400   void InitializeDescriptor(CodeStubDescriptor* descriptor) override;
2401   void GenerateAssembly(CodeStubAssembler* assembler) const override;
2402 
2403   DEFINE_CALL_INTERFACE_DESCRIPTOR(AllocateHeapNumber);
2404   DEFINE_CODE_STUB(AllocateHeapNumber, TurboFanCodeStub);
2405 };
2406 
2407 #define SIMD128_ALLOC_STUB(TYPE, Type, type, lane_count, lane_type)     \
2408   class Allocate##Type##Stub : public TurboFanCodeStub {                \
2409    public:                                                              \
2410     explicit Allocate##Type##Stub(Isolate* isolate)                     \
2411         : TurboFanCodeStub(isolate) {}                                  \
2412                                                                         \
2413     void InitializeDescriptor(CodeStubDescriptor* descriptor) override; \
2414     void GenerateAssembly(CodeStubAssembler* assembler) const override; \
2415                                                                         \
2416     DEFINE_CALL_INTERFACE_DESCRIPTOR(Allocate##Type);                   \
2417     DEFINE_CODE_STUB(Allocate##Type, TurboFanCodeStub);                 \
2418   };
SIMD128_TYPES(SIMD128_ALLOC_STUB)2419 SIMD128_TYPES(SIMD128_ALLOC_STUB)
2420 #undef SIMD128_ALLOC_STUB
2421 
2422 class CommonArrayConstructorStub : public TurboFanCodeStub {
2423  protected:
2424   CommonArrayConstructorStub(Isolate* isolate, ElementsKind kind,
2425                              AllocationSiteOverrideMode override_mode)
2426       : TurboFanCodeStub(isolate) {
2427     // It only makes sense to override local allocation site behavior
2428     // if there is a difference between the global allocation site policy
2429     // for an ElementsKind and the desired usage of the stub.
2430     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2431            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2432     set_sub_minor_key(ElementsKindBits::encode(kind) |
2433                       AllocationSiteOverrideModeBits::encode(override_mode));
2434   }
2435 
2436   void set_sub_minor_key(uint32_t key) { minor_key_ = key; }
2437 
2438   uint32_t sub_minor_key() const { return minor_key_; }
2439 
2440   CommonArrayConstructorStub(uint32_t key, Isolate* isolate)
2441       : TurboFanCodeStub(key, isolate) {}
2442 
2443  public:
2444   ElementsKind elements_kind() const {
2445     return ElementsKindBits::decode(sub_minor_key());
2446   }
2447 
2448   AllocationSiteOverrideMode override_mode() const {
2449     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2450   }
2451 
2452   static void GenerateStubsAheadOfTime(Isolate* isolate);
2453 
2454  private:
2455   // Ensure data fits within available bits.
2456   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2457 
2458   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2459   class AllocationSiteOverrideModeBits
2460       : public BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2461 };
2462 
2463 class ArrayNoArgumentConstructorStub : public CommonArrayConstructorStub {
2464  public:
2465   ArrayNoArgumentConstructorStub(
2466       Isolate* isolate, ElementsKind kind,
2467       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
CommonArrayConstructorStub(isolate,kind,override_mode)2468       : CommonArrayConstructorStub(isolate, kind, override_mode) {}
2469 
2470  private:
PrintName(std::ostream & os)2471   void PrintName(std::ostream& os) const override {  // NOLINT
2472     os << "ArrayNoArgumentConstructorStub";
2473   }
2474 
2475   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
2476   DEFINE_TURBOFAN_CODE_STUB(ArrayNoArgumentConstructor,
2477                             CommonArrayConstructorStub);
2478 };
2479 
2480 class InternalArrayNoArgumentConstructorStub
2481     : public CommonArrayConstructorStub {
2482  public:
InternalArrayNoArgumentConstructorStub(Isolate * isolate,ElementsKind kind)2483   InternalArrayNoArgumentConstructorStub(Isolate* isolate, ElementsKind kind)
2484       : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
2485 
2486  private:
PrintName(std::ostream & os)2487   void PrintName(std::ostream& os) const override {  // NOLINT
2488     os << "InternalArrayNoArgumentConstructorStub";
2489   }
2490 
2491   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayNoArgumentConstructor);
2492   DEFINE_TURBOFAN_CODE_STUB(InternalArrayNoArgumentConstructor,
2493                             CommonArrayConstructorStub);
2494 };
2495 
2496 class ArraySingleArgumentConstructorStub : public CommonArrayConstructorStub {
2497  public:
2498   ArraySingleArgumentConstructorStub(
2499       Isolate* isolate, ElementsKind kind,
2500       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
CommonArrayConstructorStub(isolate,kind,override_mode)2501       : CommonArrayConstructorStub(isolate, kind, override_mode) {}
2502 
2503  private:
PrintName(std::ostream & os)2504   void PrintName(std::ostream& os) const override {  // NOLINT
2505     os << "ArraySingleArgumentConstructorStub";
2506   }
2507 
2508   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
2509   DEFINE_TURBOFAN_CODE_STUB(ArraySingleArgumentConstructor,
2510                             CommonArrayConstructorStub);
2511 };
2512 
2513 class InternalArraySingleArgumentConstructorStub
2514     : public CommonArrayConstructorStub {
2515  public:
InternalArraySingleArgumentConstructorStub(Isolate * isolate,ElementsKind kind)2516   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2517                                              ElementsKind kind)
2518       : CommonArrayConstructorStub(isolate, kind, DONT_OVERRIDE) {}
2519 
2520  private:
PrintName(std::ostream & os)2521   void PrintName(std::ostream& os) const override {  // NOLINT
2522     os << "InternalArraySingleArgumentConstructorStub";
2523   }
2524 
2525   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArraySingleArgumentConstructor);
2526   DEFINE_TURBOFAN_CODE_STUB(InternalArraySingleArgumentConstructor,
2527                             CommonArrayConstructorStub);
2528 };
2529 
2530 class ArrayNArgumentsConstructorStub : public PlatformCodeStub {
2531  public:
ArrayNArgumentsConstructorStub(Isolate * isolate)2532   explicit ArrayNArgumentsConstructorStub(Isolate* isolate)
2533       : PlatformCodeStub(isolate) {}
2534 
GetCallInterfaceDescriptor()2535   CallInterfaceDescriptor GetCallInterfaceDescriptor() const override {
2536     return ArrayNArgumentsConstructorDescriptor(isolate());
2537   }
2538 
2539  private:
2540   DEFINE_PLATFORM_CODE_STUB(ArrayNArgumentsConstructor, PlatformCodeStub);
2541 };
2542 
2543 class StoreElementStub : public PlatformCodeStub {
2544  public:
StoreElementStub(Isolate * isolate,ElementsKind elements_kind,KeyedAccessStoreMode mode)2545   StoreElementStub(Isolate* isolate, ElementsKind elements_kind,
2546                    KeyedAccessStoreMode mode)
2547       : PlatformCodeStub(isolate) {
2548     // TODO(jkummerow): Rename this stub to StoreSlowElementStub,
2549     // drop elements_kind parameter.
2550     DCHECK_EQ(DICTIONARY_ELEMENTS, elements_kind);
2551     minor_key_ = ElementsKindBits::encode(elements_kind) |
2552                  CommonStoreModeBits::encode(mode);
2553   }
2554 
GetCodeKind()2555   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()2556   ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
2557 
2558  private:
elements_kind()2559   ElementsKind elements_kind() const {
2560     return ElementsKindBits::decode(minor_key_);
2561   }
2562 
2563   class ElementsKindBits
2564       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
2565 
2566   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreWithVector);
2567   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2568 };
2569 
2570 class ToBooleanICStub : public HydrogenCodeStub {
2571  public:
ToBooleanICStub(Isolate * isolate,ExtraICState state)2572   ToBooleanICStub(Isolate* isolate, ExtraICState state)
2573       : HydrogenCodeStub(isolate) {
2574     set_sub_minor_key(HintsBits::encode(static_cast<uint16_t>(state)));
2575   }
2576 
2577   bool UpdateStatus(Handle<Object> object);
hints()2578   ToBooleanHints hints() const {
2579     return ToBooleanHints(HintsBits::decode(sub_minor_key()));
2580   }
2581 
GetCodeKind()2582   Code::Kind GetCodeKind() const override { return Code::TO_BOOLEAN_IC; }
2583   void PrintState(std::ostream& os) const override;  // NOLINT
2584 
SometimesSetsUpAFrame()2585   bool SometimesSetsUpAFrame() override { return false; }
2586 
GetUninitialized(Isolate * isolate)2587   static Handle<Code> GetUninitialized(Isolate* isolate) {
2588     return ToBooleanICStub(isolate, UNINITIALIZED).GetCode();
2589   }
2590 
GetExtraICState()2591   ExtraICState GetExtraICState() const override { return hints(); }
2592 
GetICState()2593   InlineCacheState GetICState() const {
2594     if (hints() == ToBooleanHint::kNone) {
2595       return ::v8::internal::UNINITIALIZED;
2596     } else {
2597       return MONOMORPHIC;
2598     }
2599   }
2600 
2601  private:
ToBooleanICStub(Isolate * isolate,InitializationState init_state)2602   ToBooleanICStub(Isolate* isolate, InitializationState init_state)
2603       : HydrogenCodeStub(isolate, init_state) {}
2604 
2605   static const int kNumHints = 9;
2606   STATIC_ASSERT(static_cast<int>(ToBooleanHint::kAny) ==
2607                 ((1 << kNumHints) - 1));
2608   class HintsBits : public BitField<uint16_t, 0, kNumHints> {};
2609 
2610   DEFINE_CALL_INTERFACE_DESCRIPTOR(TypeConversion);
2611   DEFINE_HYDROGEN_CODE_STUB(ToBooleanIC, HydrogenCodeStub);
2612 };
2613 
2614 class ElementsTransitionAndStoreStub : public TurboFanCodeStub {
2615  public:
ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)2616   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2617                                  ElementsKind to_kind, bool is_jsarray,
2618                                  KeyedAccessStoreMode store_mode)
2619       : TurboFanCodeStub(isolate) {
2620     minor_key_ = CommonStoreModeBits::encode(store_mode) |
2621                  FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2622                  IsJSArrayBits::encode(is_jsarray);
2623   }
2624 
from_kind()2625   ElementsKind from_kind() const { return FromBits::decode(minor_key_); }
to_kind()2626   ElementsKind to_kind() const { return ToBits::decode(minor_key_); }
is_jsarray()2627   bool is_jsarray() const { return IsJSArrayBits::decode(minor_key_); }
store_mode()2628   KeyedAccessStoreMode store_mode() const {
2629     return CommonStoreModeBits::decode(minor_key_);
2630   }
2631 
GetCodeKind()2632   Code::Kind GetCodeKind() const override { return Code::HANDLER; }
GetExtraICState()2633   ExtraICState GetExtraICState() const override { return Code::KEYED_STORE_IC; }
2634 
2635  private:
2636   class FromBits
2637       : public BitField<ElementsKind, CommonStoreModeBits::kNext, 8> {};
2638   class ToBits : public BitField<ElementsKind, 11, 8> {};
2639   class IsJSArrayBits : public BitField<bool, 19, 1> {};
2640 
2641   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreTransition);
2642   DEFINE_TURBOFAN_CODE_STUB(ElementsTransitionAndStore, TurboFanCodeStub);
2643 };
2644 
2645 
2646 class StubFailureTrampolineStub : public PlatformCodeStub {
2647  public:
StubFailureTrampolineStub(Isolate * isolate,StubFunctionMode function_mode)2648   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2649       : PlatformCodeStub(isolate) {
2650     minor_key_ = FunctionModeField::encode(function_mode);
2651   }
2652 
2653   static void GenerateAheadOfTime(Isolate* isolate);
2654 
2655  private:
function_mode()2656   StubFunctionMode function_mode() const {
2657     return FunctionModeField::decode(minor_key_);
2658   }
2659 
2660   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2661 
2662   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2663   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2664 };
2665 
2666 
2667 class ProfileEntryHookStub : public PlatformCodeStub {
2668  public:
ProfileEntryHookStub(Isolate * isolate)2669   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2670 
2671   // The profile entry hook function is not allowed to cause a GC.
SometimesSetsUpAFrame()2672   bool SometimesSetsUpAFrame() override { return false; }
2673 
2674   // Generates a call to the entry hook if it's enabled.
2675   static void MaybeCallEntryHook(MacroAssembler* masm);
2676 
2677  private:
2678   static void EntryHookTrampoline(intptr_t function,
2679                                   intptr_t stack_pointer,
2680                                   Isolate* isolate);
2681 
2682   // ProfileEntryHookStub is called at the start of a function, so it has the
2683   // same register set.
2684   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2685   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2686 };
2687 
2688 
2689 class StoreBufferOverflowStub : public PlatformCodeStub {
2690  public:
StoreBufferOverflowStub(Isolate * isolate,SaveFPRegsMode save_fp)2691   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2692       : PlatformCodeStub(isolate) {
2693     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2694   }
2695 
2696   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
SometimesSetsUpAFrame()2697   bool SometimesSetsUpAFrame() override { return false; }
2698 
2699  private:
save_doubles()2700   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2701 
2702   class SaveDoublesBits : public BitField<bool, 0, 1> {};
2703 
2704   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2705   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2706 };
2707 
2708 class SubStringStub : public TurboFanCodeStub {
2709  public:
SubStringStub(Isolate * isolate)2710   explicit SubStringStub(Isolate* isolate) : TurboFanCodeStub(isolate) {}
2711 
2712   static compiler::Node* Generate(CodeStubAssembler* assembler,
2713                                   compiler::Node* string, compiler::Node* from,
2714                                   compiler::Node* to, compiler::Node* context);
2715 
GenerateAssembly(CodeStubAssembler * assembler)2716   void GenerateAssembly(CodeStubAssembler* assembler) const override {
2717     assembler->Return(Generate(assembler,
2718                                assembler->Parameter(Descriptor::kString),
2719                                assembler->Parameter(Descriptor::kFrom),
2720                                assembler->Parameter(Descriptor::kTo),
2721                                assembler->Parameter(Descriptor::kContext)));
2722   }
2723 
2724   DEFINE_CALL_INTERFACE_DESCRIPTOR(SubString);
2725   DEFINE_CODE_STUB(SubString, TurboFanCodeStub);
2726 };
2727 
2728 
2729 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2730 #undef DEFINE_PLATFORM_CODE_STUB
2731 #undef DEFINE_HANDLER_CODE_STUB
2732 #undef DEFINE_HYDROGEN_CODE_STUB
2733 #undef DEFINE_CODE_STUB
2734 #undef DEFINE_CODE_STUB_BASE
2735 
2736 }  // namespace internal
2737 }  // namespace v8
2738 
2739 #endif  // V8_CODE_STUBS_H_
2740