• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_CODE_STUBS_H_
6 #define V8_CODE_STUBS_H_
7 
8 #include "src/allocation.h"
9 #include "src/assembler.h"
10 #include "src/codegen.h"
11 #include "src/globals.h"
12 #include "src/ic/ic-state.h"
13 #include "src/interface-descriptors.h"
14 #include "src/macro-assembler.h"
15 #include "src/ostreams.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 // List of code stubs used on all platforms.
21 #define CODE_STUB_LIST_ALL_PLATFORMS(V)     \
22   /* PlatformCodeStubs */                   \
23   V(ArgumentsAccess)                        \
24   V(ArrayConstructor)                       \
25   V(BinaryOpICWithAllocationSite)           \
26   V(CallApiFunction)                        \
27   V(CallApiGetter)                          \
28   V(CallConstruct)                          \
29   V(CallFunction)                           \
30   V(CallIC)                                 \
31   V(CallIC_Array)                           \
32   V(CEntry)                                 \
33   V(CompareIC)                              \
34   V(DoubleToI)                              \
35   V(FunctionPrototype)                      \
36   V(Instanceof)                             \
37   V(InternalArrayConstructor)               \
38   V(JSEntry)                                \
39   V(KeyedLoadICTrampoline)                  \
40   V(LoadICTrampoline)                       \
41   V(LoadIndexedInterceptor)                 \
42   V(MathPow)                                \
43   V(ProfileEntryHook)                       \
44   V(RecordWrite)                            \
45   V(RegExpExec)                             \
46   V(StoreArrayLiteralElement)               \
47   V(StoreBufferOverflow)                    \
48   V(StoreElement)                           \
49   V(StringCompare)                          \
50   V(StubFailureTrampoline)                  \
51   V(SubString)                              \
52   /* HydrogenCodeStubs */                   \
53   V(ArrayNArgumentsConstructor)             \
54   V(ArrayNoArgumentConstructor)             \
55   V(ArraySingleArgumentConstructor)         \
56   V(BinaryOpIC)                             \
57   V(BinaryOpWithAllocationSite)             \
58   V(CompareNilIC)                           \
59   V(CreateAllocationSite)                   \
60   V(ElementsTransitionAndStore)             \
61   V(FastCloneShallowArray)                  \
62   V(FastCloneShallowObject)                 \
63   V(FastNewClosure)                         \
64   V(FastNewContext)                         \
65   V(InternalArrayNArgumentsConstructor)     \
66   V(InternalArrayNoArgumentConstructor)     \
67   V(InternalArraySingleArgumentConstructor) \
68   V(KeyedLoadGeneric)                       \
69   V(LoadDictionaryElement)                  \
70   V(LoadFastElement)                        \
71   V(MegamorphicLoad)                        \
72   V(NameDictionaryLookup)                   \
73   V(NumberToString)                         \
74   V(RegExpConstructResult)                  \
75   V(StoreFastElement)                       \
76   V(StringAdd)                              \
77   V(ToBoolean)                              \
78   V(ToNumber)                               \
79   V(TransitionElementsKind)                 \
80   V(VectorKeyedLoad)                        \
81   V(VectorLoad)                             \
82   /* IC Handler stubs */                    \
83   V(LoadConstant)                           \
84   V(LoadField)                              \
85   V(KeyedLoadSloppyArguments)               \
86   V(StoreField)                             \
87   V(StoreGlobal)                            \
88   V(StringLength)
89 
90 // List of code stubs only used on ARM 32 bits platforms.
91 #if V8_TARGET_ARCH_ARM
92 #define CODE_STUB_LIST_ARM(V) \
93   V(DirectCEntry)             \
94   V(WriteInt32ToHeapNumber)
95 
96 #else
97 #define CODE_STUB_LIST_ARM(V)
98 #endif
99 
100 // List of code stubs only used on ARM 64 bits platforms.
101 #if V8_TARGET_ARCH_ARM64
102 #define CODE_STUB_LIST_ARM64(V) \
103   V(DirectCEntry)               \
104   V(RestoreRegistersState)      \
105   V(StoreRegistersState)
106 
107 #else
108 #define CODE_STUB_LIST_ARM64(V)
109 #endif
110 
111 // List of code stubs only used on MIPS platforms.
112 #if V8_TARGET_ARCH_MIPS
113 #define CODE_STUB_LIST_MIPS(V)  \
114   V(DirectCEntry)               \
115   V(RestoreRegistersState)      \
116   V(StoreRegistersState)        \
117   V(WriteInt32ToHeapNumber)
118 #elif V8_TARGET_ARCH_MIPS64
119 #define CODE_STUB_LIST_MIPS(V)  \
120   V(DirectCEntry)               \
121   V(RestoreRegistersState)      \
122   V(StoreRegistersState)        \
123   V(WriteInt32ToHeapNumber)
124 #else
125 #define CODE_STUB_LIST_MIPS(V)
126 #endif
127 
128 // Combined list of code stubs.
129 #define CODE_STUB_LIST(V)            \
130   CODE_STUB_LIST_ALL_PLATFORMS(V)    \
131   CODE_STUB_LIST_ARM(V)              \
132   CODE_STUB_LIST_ARM64(V)           \
133   CODE_STUB_LIST_MIPS(V)
134 
135 // Stub is base classes of all stubs.
136 class CodeStub BASE_EMBEDDED {
137  public:
138   enum Major {
139 #define DEF_ENUM(name) name,
140     CODE_STUB_LIST(DEF_ENUM)
141 #undef DEF_ENUM
142     NoCache,  // marker for stubs that do custom caching
143     NUMBER_OF_IDS
144   };
145 
146   // Retrieve the code for the stub. Generate the code if needed.
147   Handle<Code> GetCode();
148 
149   // Retrieve the code for the stub, make and return a copy of the code.
150   Handle<Code> GetCodeCopy(const Code::FindAndReplacePattern& pattern);
151 
MajorKeyFromKey(uint32_t key)152   static Major MajorKeyFromKey(uint32_t key) {
153     return static_cast<Major>(MajorKeyBits::decode(key));
154   }
MinorKeyFromKey(uint32_t key)155   static uint32_t MinorKeyFromKey(uint32_t key) {
156     return MinorKeyBits::decode(key);
157   }
158 
159   // Gets the major key from a code object that is a code stub or binary op IC.
GetMajorKey(Code * code_stub)160   static Major GetMajorKey(Code* code_stub) {
161     return MajorKeyFromKey(code_stub->stub_key());
162   }
163 
NoCacheKey()164   static uint32_t NoCacheKey() { return MajorKeyBits::encode(NoCache); }
165 
166   static const char* MajorName(Major major_key, bool allow_unknown_keys);
167 
CodeStub(Isolate * isolate)168   explicit CodeStub(Isolate* isolate) : minor_key_(0), isolate_(isolate) {}
~CodeStub()169   virtual ~CodeStub() {}
170 
171   static void GenerateStubsAheadOfTime(Isolate* isolate);
172   static void GenerateFPStubs(Isolate* isolate);
173 
174   // Some stubs put untagged junk on the stack that cannot be scanned by the
175   // GC.  This means that we must be statically sure that no GC can occur while
176   // they are running.  If that is the case they should override this to return
177   // true, which will cause an assertion if we try to call something that can
178   // GC or if we try to put a stack frame on top of the junk, which would not
179   // result in a traversable stack.
SometimesSetsUpAFrame()180   virtual bool SometimesSetsUpAFrame() { return true; }
181 
182   // Lookup the code in the (possibly custom) cache.
183   bool FindCodeInCache(Code** code_out);
184 
185   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() = 0;
186 
InitializeDescriptor(CodeStubDescriptor * descriptor)187   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) {}
188 
189   static void InitializeDescriptor(Isolate* isolate, uint32_t key,
190                                    CodeStubDescriptor* desc);
191 
192   static MaybeHandle<Code> GetCode(Isolate* isolate, uint32_t key);
193 
194   // Returns information for computing the number key.
195   virtual Major MajorKey() const = 0;
MinorKey()196   uint32_t MinorKey() const { return minor_key_; }
197 
GetICState()198   virtual InlineCacheState GetICState() const { return UNINITIALIZED; }
GetExtraICState()199   virtual ExtraICState GetExtraICState() const { return kNoExtraICState; }
GetStubType()200   virtual Code::StubType GetStubType() {
201     return Code::NORMAL;
202   }
203 
204   friend OStream& operator<<(OStream& os, const CodeStub& s) {
205     s.PrintName(os);
206     return os;
207   }
208 
isolate()209   Isolate* isolate() const { return isolate_; }
210 
211  protected:
CodeStub(uint32_t key,Isolate * isolate)212   CodeStub(uint32_t key, Isolate* isolate)
213       : minor_key_(MinorKeyFromKey(key)), isolate_(isolate) {}
214 
215   // Generates the assembler code for the stub.
216   virtual Handle<Code> GenerateCode() = 0;
217 
218   // Returns whether the code generated for this stub needs to be allocated as
219   // a fixed (non-moveable) code object.
NeedsImmovableCode()220   virtual bool NeedsImmovableCode() { return false; }
221 
222   virtual void PrintName(OStream& os) const;        // NOLINT
223   virtual void PrintBaseName(OStream& os) const;    // NOLINT
PrintState(OStream & os)224   virtual void PrintState(OStream& os) const { ; }  // NOLINT
225 
226   // Computes the key based on major and minor.
GetKey()227   uint32_t GetKey() {
228     DCHECK(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
229     return MinorKeyBits::encode(MinorKey()) | MajorKeyBits::encode(MajorKey());
230   }
231 
232   uint32_t minor_key_;
233 
234  private:
235   // Perform bookkeeping required after code generation when stub code is
236   // initially generated.
237   void RecordCodeGeneration(Handle<Code> code);
238 
239   // Finish the code object after it has been generated.
FinishCode(Handle<Code> code)240   virtual void FinishCode(Handle<Code> code) { }
241 
242   // Activate newly generated stub. Is called after
243   // registering stub in the stub cache.
Activate(Code * code)244   virtual void Activate(Code* code) { }
245 
246   // BinaryOpStub needs to override this.
247   virtual Code::Kind GetCodeKind() const;
248 
249   // Add the code to a specialized cache, specific to an individual
250   // stub type. Please note, this method must add the code object to a
251   // roots object, otherwise we will remove the code during GC.
AddToSpecialCache(Handle<Code> new_object)252   virtual void AddToSpecialCache(Handle<Code> new_object) { }
253 
254   // Find code in a specialized cache, work is delegated to the specific stub.
FindCodeInSpecialCache(Code ** code_out)255   virtual bool FindCodeInSpecialCache(Code** code_out) {
256     return false;
257   }
258 
259   // If a stub uses a special cache override this.
UseSpecialCache()260   virtual bool UseSpecialCache() { return false; }
261 
262   // We use this dispatch to statically instantiate the correct code stub for
263   // the given stub key and call the passed function with that code stub.
264   typedef void (*DispatchedCall)(CodeStub* stub, void** value_out);
265   static void Dispatch(Isolate* isolate, uint32_t key, void** value_out,
266                        DispatchedCall call);
267 
268   static void GetCodeDispatchCall(CodeStub* stub, void** value_out);
269 
270   STATIC_ASSERT(NUMBER_OF_IDS < (1 << kStubMajorKeyBits));
271   class MajorKeyBits: public BitField<uint32_t, 0, kStubMajorKeyBits> {};
272   class MinorKeyBits: public BitField<uint32_t,
273       kStubMajorKeyBits, kStubMinorKeyBits> {};  // NOLINT
274 
275   friend class BreakPointIterator;
276 
277   Isolate* isolate_;
278 };
279 
280 
281 #define DEFINE_CODE_STUB_BASE(NAME, SUPER)                      \
282  public:                                                        \
283   NAME(uint32_t key, Isolate* isolate) : SUPER(key, isolate) {} \
284                                                                 \
285  private:                                                       \
286   DISALLOW_COPY_AND_ASSIGN(NAME)
287 
288 
289 #define DEFINE_CODE_STUB(NAME, SUPER)              \
290  protected:                                        \
291   virtual inline Major MajorKey() const OVERRIDE { \
292     return NAME;                                   \
293   };                                               \
294   DEFINE_CODE_STUB_BASE(NAME##Stub, SUPER)
295 
296 
297 #define DEFINE_PLATFORM_CODE_STUB(NAME, SUPER)          \
298  private:                                               \
299   virtual void Generate(MacroAssembler* masm) OVERRIDE; \
300   DEFINE_CODE_STUB(NAME, SUPER)
301 
302 
303 #define DEFINE_HYDROGEN_CODE_STUB(NAME, SUPER)                                \
304  public:                                                                      \
305   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE; \
306   virtual Handle<Code> GenerateCode() OVERRIDE;                               \
307   DEFINE_CODE_STUB(NAME, SUPER)
308 
309 #define DEFINE_HANDLER_CODE_STUB(NAME, SUPER)   \
310  public:                                        \
311   virtual Handle<Code> GenerateCode() OVERRIDE; \
312   DEFINE_CODE_STUB(NAME, SUPER)
313 
314 #define DEFINE_CALL_INTERFACE_DESCRIPTOR(NAME)                            \
315  public:                                                                  \
316   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
317     return NAME##Descriptor(isolate());                                   \
318   }
319 
320 // There are some code stubs we just can't describe right now with a
321 // CallInterfaceDescriptor. Isolate behavior for those cases with this macro.
322 // An attempt to retrieve a descriptor will fail.
323 #define DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR()                           \
324  public:                                                                  \
325   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE { \
326     UNREACHABLE();                                                        \
327     return CallInterfaceDescriptor();                                     \
328   }
329 
330 
331 class PlatformCodeStub : public CodeStub {
332  public:
333   // Retrieve the code for the stub. Generate the code if needed.
334   virtual Handle<Code> GenerateCode() OVERRIDE;
335 
GetCodeKind()336   virtual Code::Kind GetCodeKind() const { return Code::STUB; }
337 
338  protected:
PlatformCodeStub(Isolate * isolate)339   explicit PlatformCodeStub(Isolate* isolate) : CodeStub(isolate) {}
340 
341   // Generates the assembler code for the stub.
342   virtual void Generate(MacroAssembler* masm) = 0;
343 
344   DEFINE_CODE_STUB_BASE(PlatformCodeStub, CodeStub);
345 };
346 
347 
348 enum StubFunctionMode { NOT_JS_FUNCTION_STUB_MODE, JS_FUNCTION_STUB_MODE };
349 enum HandlerArgumentsMode { DONT_PASS_ARGUMENTS, PASS_ARGUMENTS };
350 
351 
352 class CodeStubDescriptor {
353  public:
354   explicit CodeStubDescriptor(CodeStub* stub);
355 
356   CodeStubDescriptor(Isolate* isolate, uint32_t stub_key);
357 
358   void Initialize(Address deoptimization_handler = NULL,
359                   int hint_stack_parameter_count = -1,
360                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE);
361   void Initialize(Register stack_parameter_count,
362                   Address deoptimization_handler = NULL,
363                   int hint_stack_parameter_count = -1,
364                   StubFunctionMode function_mode = NOT_JS_FUNCTION_STUB_MODE,
365                   HandlerArgumentsMode handler_mode = DONT_PASS_ARGUMENTS);
366 
SetMissHandler(ExternalReference handler)367   void SetMissHandler(ExternalReference handler) {
368     miss_handler_ = handler;
369     has_miss_handler_ = true;
370     // Our miss handler infrastructure doesn't currently support
371     // variable stack parameter counts.
372     DCHECK(!stack_parameter_count_.is_valid());
373   }
374 
set_call_descriptor(CallInterfaceDescriptor d)375   void set_call_descriptor(CallInterfaceDescriptor d) { call_descriptor_ = d; }
call_descriptor()376   CallInterfaceDescriptor call_descriptor() const { return call_descriptor_; }
377 
GetEnvironmentParameterCount()378   int GetEnvironmentParameterCount() const {
379     return call_descriptor().GetEnvironmentParameterCount();
380   }
381 
GetEnvironmentParameterRepresentation(int index)382   Representation GetEnvironmentParameterRepresentation(int index) const {
383     return call_descriptor().GetEnvironmentParameterRepresentation(index);
384   }
385 
miss_handler()386   ExternalReference miss_handler() const {
387     DCHECK(has_miss_handler_);
388     return miss_handler_;
389   }
390 
has_miss_handler()391   bool has_miss_handler() const {
392     return has_miss_handler_;
393   }
394 
IsEnvironmentParameterCountRegister(int index)395   bool IsEnvironmentParameterCountRegister(int index) const {
396     return call_descriptor().GetEnvironmentParameterRegister(index).is(
397         stack_parameter_count_);
398   }
399 
GetHandlerParameterCount()400   int GetHandlerParameterCount() const {
401     int params = call_descriptor().GetEnvironmentParameterCount();
402     if (handler_arguments_mode_ == PASS_ARGUMENTS) {
403       params += 1;
404     }
405     return params;
406   }
407 
hint_stack_parameter_count()408   int hint_stack_parameter_count() const { return hint_stack_parameter_count_; }
stack_parameter_count()409   Register stack_parameter_count() const { return stack_parameter_count_; }
function_mode()410   StubFunctionMode function_mode() const { return function_mode_; }
deoptimization_handler()411   Address deoptimization_handler() const { return deoptimization_handler_; }
412 
413  private:
414   CallInterfaceDescriptor call_descriptor_;
415   Register stack_parameter_count_;
416   // If hint_stack_parameter_count_ > 0, the code stub can optimize the
417   // return sequence. Default value is -1, which means it is ignored.
418   int hint_stack_parameter_count_;
419   StubFunctionMode function_mode_;
420 
421   Address deoptimization_handler_;
422   HandlerArgumentsMode handler_arguments_mode_;
423 
424   ExternalReference miss_handler_;
425   bool has_miss_handler_;
426 };
427 
428 
429 class HydrogenCodeStub : public CodeStub {
430  public:
431   enum InitializationState {
432     UNINITIALIZED,
433     INITIALIZED
434   };
435 
GetCodeKind()436   virtual Code::Kind GetCodeKind() const { return Code::STUB; }
437 
438   template<class SubClass>
GetUninitialized(Isolate * isolate)439   static Handle<Code> GetUninitialized(Isolate* isolate) {
440     SubClass::GenerateAheadOfTime(isolate);
441     return SubClass().GetCode(isolate);
442   }
443 
444   // Retrieve the code for the stub. Generate the code if needed.
445   virtual Handle<Code> GenerateCode() = 0;
446 
IsUninitialized()447   bool IsUninitialized() const { return IsMissBits::decode(minor_key_); }
448 
449   Handle<Code> GenerateLightweightMissCode(ExternalReference miss);
450 
451   template<class StateType>
452   void TraceTransition(StateType from, StateType to);
453 
454  protected:
455   explicit HydrogenCodeStub(Isolate* isolate,
456                             InitializationState state = INITIALIZED)
CodeStub(isolate)457       : CodeStub(isolate) {
458     minor_key_ = IsMissBits::encode(state == UNINITIALIZED);
459   }
460 
set_sub_minor_key(uint32_t key)461   void set_sub_minor_key(uint32_t key) {
462     minor_key_ = SubMinorKeyBits::update(minor_key_, key);
463   }
464 
sub_minor_key()465   uint32_t sub_minor_key() const { return SubMinorKeyBits::decode(minor_key_); }
466 
467   static const int kSubMinorKeyBits = kStubMinorKeyBits - 1;
468 
469  private:
470   class IsMissBits : public BitField<bool, kSubMinorKeyBits, 1> {};
471   class SubMinorKeyBits : public BitField<int, 0, kSubMinorKeyBits> {};
472 
473   void GenerateLightweightMiss(MacroAssembler* masm, ExternalReference miss);
474 
475   DEFINE_CODE_STUB_BASE(HydrogenCodeStub, CodeStub);
476 };
477 
478 
479 // Helper interface to prepare to/restore after making runtime calls.
480 class RuntimeCallHelper {
481  public:
~RuntimeCallHelper()482   virtual ~RuntimeCallHelper() {}
483 
484   virtual void BeforeCall(MacroAssembler* masm) const = 0;
485 
486   virtual void AfterCall(MacroAssembler* masm) const = 0;
487 
488  protected:
RuntimeCallHelper()489   RuntimeCallHelper() {}
490 
491  private:
492   DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
493 };
494 
495 
496 } }  // namespace v8::internal
497 
498 #if V8_TARGET_ARCH_IA32
499 #include "src/ia32/code-stubs-ia32.h"
500 #elif V8_TARGET_ARCH_X64
501 #include "src/x64/code-stubs-x64.h"
502 #elif V8_TARGET_ARCH_ARM64
503 #include "src/arm64/code-stubs-arm64.h"
504 #elif V8_TARGET_ARCH_ARM
505 #include "src/arm/code-stubs-arm.h"
506 #elif V8_TARGET_ARCH_MIPS
507 #include "src/mips/code-stubs-mips.h"
508 #elif V8_TARGET_ARCH_MIPS64
509 #include "src/mips64/code-stubs-mips64.h"
510 #elif V8_TARGET_ARCH_X87
511 #include "src/x87/code-stubs-x87.h"
512 #else
513 #error Unsupported target architecture.
514 #endif
515 
516 namespace v8 {
517 namespace internal {
518 
519 
520 // RuntimeCallHelper implementation used in stubs: enters/leaves a
521 // newly created internal frame before/after the runtime call.
522 class StubRuntimeCallHelper : public RuntimeCallHelper {
523  public:
StubRuntimeCallHelper()524   StubRuntimeCallHelper() {}
525 
526   virtual void BeforeCall(MacroAssembler* masm) const;
527 
528   virtual void AfterCall(MacroAssembler* masm) const;
529 };
530 
531 
532 // Trivial RuntimeCallHelper implementation.
533 class NopRuntimeCallHelper : public RuntimeCallHelper {
534  public:
NopRuntimeCallHelper()535   NopRuntimeCallHelper() {}
536 
BeforeCall(MacroAssembler * masm)537   virtual void BeforeCall(MacroAssembler* masm) const {}
538 
AfterCall(MacroAssembler * masm)539   virtual void AfterCall(MacroAssembler* masm) const {}
540 };
541 
542 
543 class ToNumberStub: public HydrogenCodeStub {
544  public:
ToNumberStub(Isolate * isolate)545   explicit ToNumberStub(Isolate* isolate) : HydrogenCodeStub(isolate) { }
546 
547   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToNumber);
548   DEFINE_HYDROGEN_CODE_STUB(ToNumber, HydrogenCodeStub);
549 };
550 
551 
552 class NumberToStringStub FINAL : public HydrogenCodeStub {
553  public:
NumberToStringStub(Isolate * isolate)554   explicit NumberToStringStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
555 
556   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
557   static const int kNumber = 0;
558 
559   DEFINE_CALL_INTERFACE_DESCRIPTOR(NumberToString);
560   DEFINE_HYDROGEN_CODE_STUB(NumberToString, HydrogenCodeStub);
561 };
562 
563 
564 class FastNewClosureStub : public HydrogenCodeStub {
565  public:
FastNewClosureStub(Isolate * isolate,StrictMode strict_mode,FunctionKind kind)566   FastNewClosureStub(Isolate* isolate, StrictMode strict_mode,
567                      FunctionKind kind)
568       : HydrogenCodeStub(isolate) {
569     DCHECK(IsValidFunctionKind(kind));
570     set_sub_minor_key(StrictModeBits::encode(strict_mode) |
571                       FunctionKindBits::encode(kind));
572   }
573 
strict_mode()574   StrictMode strict_mode() const {
575     return StrictModeBits::decode(sub_minor_key());
576   }
577 
kind()578   FunctionKind kind() const {
579     return FunctionKindBits::decode(sub_minor_key());
580   }
is_arrow()581   bool is_arrow() const { return IsArrowFunction(kind()); }
is_generator()582   bool is_generator() const { return IsGeneratorFunction(kind()); }
is_concise_method()583   bool is_concise_method() const { return IsConciseMethod(kind()); }
584 
585  private:
586   class StrictModeBits : public BitField<StrictMode, 0, 1> {};
587   class FunctionKindBits : public BitField<FunctionKind, 1, 3> {};
588 
589   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewClosure);
590   DEFINE_HYDROGEN_CODE_STUB(FastNewClosure, HydrogenCodeStub);
591 };
592 
593 
594 class FastNewContextStub FINAL : public HydrogenCodeStub {
595  public:
596   static const int kMaximumSlots = 64;
597 
FastNewContextStub(Isolate * isolate,int slots)598   FastNewContextStub(Isolate* isolate, int slots) : HydrogenCodeStub(isolate) {
599     DCHECK(slots > 0 && slots <= kMaximumSlots);
600     set_sub_minor_key(SlotsBits::encode(slots));
601   }
602 
slots()603   int slots() const { return SlotsBits::decode(sub_minor_key()); }
604 
605   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
606   static const int kFunction = 0;
607 
608  private:
609   class SlotsBits : public BitField<int, 0, 8> {};
610 
611   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastNewContext);
612   DEFINE_HYDROGEN_CODE_STUB(FastNewContext, HydrogenCodeStub);
613 };
614 
615 
616 class FastCloneShallowArrayStub : public HydrogenCodeStub {
617  public:
FastCloneShallowArrayStub(Isolate * isolate,AllocationSiteMode allocation_site_mode)618   FastCloneShallowArrayStub(Isolate* isolate,
619                             AllocationSiteMode allocation_site_mode)
620       : HydrogenCodeStub(isolate) {
621     set_sub_minor_key(AllocationSiteModeBits::encode(allocation_site_mode));
622   }
623 
allocation_site_mode()624   AllocationSiteMode allocation_site_mode() const {
625     return AllocationSiteModeBits::decode(sub_minor_key());
626   }
627 
628  private:
629   class AllocationSiteModeBits: public BitField<AllocationSiteMode, 0, 1> {};
630 
631   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowArray);
632   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowArray, HydrogenCodeStub);
633 };
634 
635 
636 class FastCloneShallowObjectStub : public HydrogenCodeStub {
637  public:
638   // Maximum number of properties in copied object.
639   static const int kMaximumClonedProperties = 6;
640 
FastCloneShallowObjectStub(Isolate * isolate,int length)641   FastCloneShallowObjectStub(Isolate* isolate, int length)
642       : HydrogenCodeStub(isolate) {
643     DCHECK_GE(length, 0);
644     DCHECK_LE(length, kMaximumClonedProperties);
645     set_sub_minor_key(LengthBits::encode(length));
646   }
647 
length()648   int length() const { return LengthBits::decode(sub_minor_key()); }
649 
650  private:
651   class LengthBits : public BitField<int, 0, 4> {};
652 
653   DEFINE_CALL_INTERFACE_DESCRIPTOR(FastCloneShallowObject);
654   DEFINE_HYDROGEN_CODE_STUB(FastCloneShallowObject, HydrogenCodeStub);
655 };
656 
657 
658 class CreateAllocationSiteStub : public HydrogenCodeStub {
659  public:
CreateAllocationSiteStub(Isolate * isolate)660   explicit CreateAllocationSiteStub(Isolate* isolate)
661       : HydrogenCodeStub(isolate) { }
662 
663   static void GenerateAheadOfTime(Isolate* isolate);
664 
665   DEFINE_CALL_INTERFACE_DESCRIPTOR(CreateAllocationSite);
666   DEFINE_HYDROGEN_CODE_STUB(CreateAllocationSite, HydrogenCodeStub);
667 };
668 
669 
670 class InstanceofStub: public PlatformCodeStub {
671  public:
672   enum Flags {
673     kNoFlags = 0,
674     kArgsInRegisters = 1 << 0,
675     kCallSiteInlineCheck = 1 << 1,
676     kReturnTrueFalseObject = 1 << 2
677   };
678 
InstanceofStub(Isolate * isolate,Flags flags)679   InstanceofStub(Isolate* isolate, Flags flags) : PlatformCodeStub(isolate) {
680     minor_key_ = FlagBits::encode(flags);
681   }
682 
left()683   static Register left() { return InstanceofDescriptor::left(); }
right()684   static Register right() { return InstanceofDescriptor::right(); }
685 
GetCallInterfaceDescriptor()686   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
687     if (HasArgsInRegisters()) {
688       return InstanceofDescriptor(isolate());
689     }
690     return ContextOnlyDescriptor(isolate());
691   }
692 
693  private:
flags()694   Flags flags() const { return FlagBits::decode(minor_key_); }
695 
HasArgsInRegisters()696   bool HasArgsInRegisters() const { return (flags() & kArgsInRegisters) != 0; }
697 
HasCallSiteInlineCheck()698   bool HasCallSiteInlineCheck() const {
699     return (flags() & kCallSiteInlineCheck) != 0;
700   }
701 
ReturnTrueFalseObject()702   bool ReturnTrueFalseObject() const {
703     return (flags() & kReturnTrueFalseObject) != 0;
704   }
705 
706   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
707 
708   class FlagBits : public BitField<Flags, 0, 3> {};
709 
710   DEFINE_PLATFORM_CODE_STUB(Instanceof, PlatformCodeStub);
711 };
712 
713 
714 enum AllocationSiteOverrideMode {
715   DONT_OVERRIDE,
716   DISABLE_ALLOCATION_SITES,
717   LAST_ALLOCATION_SITE_OVERRIDE_MODE = DISABLE_ALLOCATION_SITES
718 };
719 
720 
721 class ArrayConstructorStub: public PlatformCodeStub {
722  public:
723   enum ArgumentCountKey { ANY, NONE, ONE, MORE_THAN_ONE };
724 
725   ArrayConstructorStub(Isolate* isolate, int argument_count);
726 
727   explicit ArrayConstructorStub(Isolate* isolate);
728 
729  private:
argument_count()730   ArgumentCountKey argument_count() const {
731     return ArgumentCountBits::decode(minor_key_);
732   }
733 
734   void GenerateDispatchToArrayStub(MacroAssembler* masm,
735                                    AllocationSiteOverrideMode mode);
736 
737   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
738 
739   class ArgumentCountBits : public BitField<ArgumentCountKey, 0, 2> {};
740 
741   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
742   DEFINE_PLATFORM_CODE_STUB(ArrayConstructor, PlatformCodeStub);
743 };
744 
745 
746 class InternalArrayConstructorStub: public PlatformCodeStub {
747  public:
748   explicit InternalArrayConstructorStub(Isolate* isolate);
749 
750  private:
751   void GenerateCase(MacroAssembler* masm, ElementsKind kind);
752 
753   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
754   DEFINE_PLATFORM_CODE_STUB(InternalArrayConstructor, PlatformCodeStub);
755 };
756 
757 
758 class MathPowStub: public PlatformCodeStub {
759  public:
760   enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK };
761 
MathPowStub(Isolate * isolate,ExponentType exponent_type)762   MathPowStub(Isolate* isolate, ExponentType exponent_type)
763       : PlatformCodeStub(isolate) {
764     minor_key_ = ExponentTypeBits::encode(exponent_type);
765   }
766 
GetCallInterfaceDescriptor()767   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
768     if (exponent_type() == TAGGED) {
769       return MathPowTaggedDescriptor(isolate());
770     } else if (exponent_type() == INTEGER) {
771       return MathPowIntegerDescriptor(isolate());
772     }
773     // A CallInterfaceDescriptor doesn't specify double registers (yet).
774     return ContextOnlyDescriptor(isolate());
775   }
776 
777  private:
exponent_type()778   ExponentType exponent_type() const {
779     return ExponentTypeBits::decode(minor_key_);
780   }
781 
782   class ExponentTypeBits : public BitField<ExponentType, 0, 2> {};
783 
784   DEFINE_PLATFORM_CODE_STUB(MathPow, PlatformCodeStub);
785 };
786 
787 
788 class CallICStub: public PlatformCodeStub {
789  public:
CallICStub(Isolate * isolate,const CallICState & state)790   CallICStub(Isolate* isolate, const CallICState& state)
791       : PlatformCodeStub(isolate) {
792     minor_key_ = state.GetExtraICState();
793   }
794 
ExtractArgcFromMinorKey(int minor_key)795   static int ExtractArgcFromMinorKey(int minor_key) {
796     CallICState state(static_cast<ExtraICState>(minor_key));
797     return state.arg_count();
798   }
799 
GetCodeKind()800   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::CALL_IC; }
801 
GetICState()802   virtual InlineCacheState GetICState() const OVERRIDE { return DEFAULT; }
803 
GetExtraICState()804   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
805     return static_cast<ExtraICState>(minor_key_);
806   }
807 
808  protected:
CallAsMethod()809   bool CallAsMethod() const {
810     return state().call_type() == CallICState::METHOD;
811   }
812 
arg_count()813   int arg_count() const { return state().arg_count(); }
814 
state()815   CallICState state() const {
816     return CallICState(static_cast<ExtraICState>(minor_key_));
817   }
818 
819   // Code generation helpers.
820   void GenerateMiss(MacroAssembler* masm);
821 
822  private:
823   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
824 
825   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunctionWithFeedback);
826   DEFINE_PLATFORM_CODE_STUB(CallIC, PlatformCodeStub);
827 };
828 
829 
830 class CallIC_ArrayStub: public CallICStub {
831  public:
CallIC_ArrayStub(Isolate * isolate,const CallICState & state_in)832   CallIC_ArrayStub(Isolate* isolate, const CallICState& state_in)
833       : CallICStub(isolate, state_in) {}
834 
GetICState()835   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
836     return MONOMORPHIC;
837   }
838 
839  private:
840   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
841 
842   DEFINE_PLATFORM_CODE_STUB(CallIC_Array, CallICStub);
843 };
844 
845 
846 // TODO(verwaest): Translate to hydrogen code stub.
847 class FunctionPrototypeStub : public PlatformCodeStub {
848  public:
FunctionPrototypeStub(Isolate * isolate)849   explicit FunctionPrototypeStub(Isolate* isolate)
850       : PlatformCodeStub(isolate) {}
851 
GetCodeKind()852   virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
853 
854   // TODO(mvstanton): only the receiver register is accessed. When this is
855   // translated to a hydrogen code stub, a new CallInterfaceDescriptor
856   // should be created that just uses that register for more efficient code.
857   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
858   DEFINE_PLATFORM_CODE_STUB(FunctionPrototype, PlatformCodeStub);
859 };
860 
861 
862 // TODO(mvstanton): Translate to hydrogen code stub.
863 class LoadIndexedInterceptorStub : public PlatformCodeStub {
864  public:
LoadIndexedInterceptorStub(Isolate * isolate)865   explicit LoadIndexedInterceptorStub(Isolate* isolate)
866       : PlatformCodeStub(isolate) {}
867 
GetCodeKind()868   virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
GetStubType()869   virtual Code::StubType GetStubType() { return Code::FAST; }
870 
871   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
872   DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
873 };
874 
875 
876 class HandlerStub : public HydrogenCodeStub {
877  public:
GetCodeKind()878   virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
GetExtraICState()879   virtual ExtraICState GetExtraICState() const { return kind(); }
GetICState()880   virtual InlineCacheState GetICState() const { return MONOMORPHIC; }
881 
882   virtual void InitializeDescriptor(CodeStubDescriptor* descriptor) OVERRIDE;
883 
884   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE;
885 
886  protected:
HandlerStub(Isolate * isolate)887   explicit HandlerStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
888 
889   virtual Code::Kind kind() const = 0;
890 
891   DEFINE_CODE_STUB_BASE(HandlerStub, HydrogenCodeStub);
892 };
893 
894 
895 class LoadFieldStub: public HandlerStub {
896  public:
LoadFieldStub(Isolate * isolate,FieldIndex index)897   LoadFieldStub(Isolate* isolate, FieldIndex index) : HandlerStub(isolate) {
898     int property_index_key = index.GetFieldAccessStubKey();
899     set_sub_minor_key(LoadFieldByIndexBits::encode(property_index_key));
900   }
901 
index()902   FieldIndex index() const {
903     int property_index_key = LoadFieldByIndexBits::decode(sub_minor_key());
904     return FieldIndex::FromFieldAccessStubKey(property_index_key);
905   }
906 
907  protected:
kind()908   virtual Code::Kind kind() const { return Code::LOAD_IC; }
GetStubType()909   virtual Code::StubType GetStubType() { return Code::FAST; }
910 
911  private:
912   class LoadFieldByIndexBits : public BitField<int, 0, 13> {};
913 
914   DEFINE_HANDLER_CODE_STUB(LoadField, HandlerStub);
915 };
916 
917 
918 class KeyedLoadSloppyArgumentsStub : public HandlerStub {
919  public:
KeyedLoadSloppyArgumentsStub(Isolate * isolate)920   explicit KeyedLoadSloppyArgumentsStub(Isolate* isolate)
921       : HandlerStub(isolate) {}
922 
923  protected:
kind()924   virtual Code::Kind kind() const { return Code::KEYED_LOAD_IC; }
GetStubType()925   virtual Code::StubType GetStubType() { return Code::FAST; }
926 
927  private:
928   DEFINE_HANDLER_CODE_STUB(KeyedLoadSloppyArguments, HandlerStub);
929 };
930 
931 
932 class LoadConstantStub : public HandlerStub {
933  public:
LoadConstantStub(Isolate * isolate,int constant_index)934   LoadConstantStub(Isolate* isolate, int constant_index)
935       : HandlerStub(isolate) {
936     set_sub_minor_key(ConstantIndexBits::encode(constant_index));
937   }
938 
constant_index()939   int constant_index() const {
940     return ConstantIndexBits::decode(sub_minor_key());
941   }
942 
943  protected:
kind()944   virtual Code::Kind kind() const { return Code::LOAD_IC; }
GetStubType()945   virtual Code::StubType GetStubType() { return Code::FAST; }
946 
947  private:
948   class ConstantIndexBits : public BitField<int, 0, kSubMinorKeyBits> {};
949 
950   DEFINE_HANDLER_CODE_STUB(LoadConstant, HandlerStub);
951 };
952 
953 
954 class StringLengthStub: public HandlerStub {
955  public:
StringLengthStub(Isolate * isolate)956   explicit StringLengthStub(Isolate* isolate) : HandlerStub(isolate) {}
957 
958  protected:
kind()959   virtual Code::Kind kind() const { return Code::LOAD_IC; }
GetStubType()960   virtual Code::StubType GetStubType() { return Code::FAST; }
961 
962   DEFINE_HANDLER_CODE_STUB(StringLength, HandlerStub);
963 };
964 
965 
966 class StoreFieldStub : public HandlerStub {
967  public:
StoreFieldStub(Isolate * isolate,FieldIndex index,Representation representation)968   StoreFieldStub(Isolate* isolate, FieldIndex index,
969                  Representation representation)
970       : HandlerStub(isolate) {
971     int property_index_key = index.GetFieldAccessStubKey();
972     uint8_t repr = PropertyDetails::EncodeRepresentation(representation);
973     set_sub_minor_key(StoreFieldByIndexBits::encode(property_index_key) |
974                       RepresentationBits::encode(repr));
975   }
976 
index()977   FieldIndex index() const {
978     int property_index_key = StoreFieldByIndexBits::decode(sub_minor_key());
979     return FieldIndex::FromFieldAccessStubKey(property_index_key);
980   }
981 
representation()982   Representation representation() {
983     uint8_t repr = RepresentationBits::decode(sub_minor_key());
984     return PropertyDetails::DecodeRepresentation(repr);
985   }
986 
987  protected:
kind()988   virtual Code::Kind kind() const { return Code::STORE_IC; }
GetStubType()989   virtual Code::StubType GetStubType() { return Code::FAST; }
990 
991  private:
992   class StoreFieldByIndexBits : public BitField<int, 0, 13> {};
993   class RepresentationBits : public BitField<uint8_t, 13, 4> {};
994 
995   DEFINE_HANDLER_CODE_STUB(StoreField, HandlerStub);
996 };
997 
998 
999 class StoreGlobalStub : public HandlerStub {
1000  public:
StoreGlobalStub(Isolate * isolate,bool is_constant,bool check_global)1001   StoreGlobalStub(Isolate* isolate, bool is_constant, bool check_global)
1002       : HandlerStub(isolate) {
1003     set_sub_minor_key(IsConstantBits::encode(is_constant) |
1004                       CheckGlobalBits::encode(check_global));
1005   }
1006 
global_placeholder(Isolate * isolate)1007   static Handle<HeapObject> global_placeholder(Isolate* isolate) {
1008     return isolate->factory()->uninitialized_value();
1009   }
1010 
GetCodeCopyFromTemplate(Handle<GlobalObject> global,Handle<PropertyCell> cell)1011   Handle<Code> GetCodeCopyFromTemplate(Handle<GlobalObject> global,
1012                                        Handle<PropertyCell> cell) {
1013     if (check_global()) {
1014       Code::FindAndReplacePattern pattern;
1015       pattern.Add(Handle<Map>(global_placeholder(isolate())->map()), global);
1016       pattern.Add(isolate()->factory()->meta_map(), Handle<Map>(global->map()));
1017       pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1018       return CodeStub::GetCodeCopy(pattern);
1019     } else {
1020       Code::FindAndReplacePattern pattern;
1021       pattern.Add(isolate()->factory()->global_property_cell_map(), cell);
1022       return CodeStub::GetCodeCopy(pattern);
1023     }
1024   }
1025 
kind()1026   virtual Code::Kind kind() const { return Code::STORE_IC; }
1027 
is_constant()1028   bool is_constant() const { return IsConstantBits::decode(sub_minor_key()); }
1029 
check_global()1030   bool check_global() const { return CheckGlobalBits::decode(sub_minor_key()); }
1031 
set_is_constant(bool value)1032   void set_is_constant(bool value) {
1033     set_sub_minor_key(IsConstantBits::update(sub_minor_key(), value));
1034   }
1035 
representation()1036   Representation representation() {
1037     return Representation::FromKind(
1038         RepresentationBits::decode(sub_minor_key()));
1039   }
1040 
set_representation(Representation r)1041   void set_representation(Representation r) {
1042     set_sub_minor_key(RepresentationBits::update(sub_minor_key(), r.kind()));
1043   }
1044 
1045  private:
1046   class IsConstantBits: public BitField<bool, 0, 1> {};
1047   class RepresentationBits: public BitField<Representation::Kind, 1, 8> {};
1048   class CheckGlobalBits: public BitField<bool, 9, 1> {};
1049 
1050   DEFINE_HANDLER_CODE_STUB(StoreGlobal, HandlerStub);
1051 };
1052 
1053 
1054 class CallApiFunctionStub : public PlatformCodeStub {
1055  public:
CallApiFunctionStub(Isolate * isolate,bool is_store,bool call_data_undefined,int argc)1056   CallApiFunctionStub(Isolate* isolate,
1057                       bool is_store,
1058                       bool call_data_undefined,
1059                       int argc) : PlatformCodeStub(isolate) {
1060     minor_key_ = IsStoreBits::encode(is_store) |
1061                  CallDataUndefinedBits::encode(call_data_undefined) |
1062                  ArgumentBits::encode(argc);
1063     DCHECK(!is_store || argc == 1);
1064   }
1065 
1066  private:
is_store()1067   bool is_store() const { return IsStoreBits::decode(minor_key_); }
call_data_undefined()1068   bool call_data_undefined() const {
1069     return CallDataUndefinedBits::decode(minor_key_);
1070   }
argc()1071   int argc() const { return ArgumentBits::decode(minor_key_); }
1072 
1073   class IsStoreBits: public BitField<bool, 0, 1> {};
1074   class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
1075   class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
1076   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1077 
1078   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiFunction);
1079   DEFINE_PLATFORM_CODE_STUB(CallApiFunction, PlatformCodeStub);
1080 };
1081 
1082 
1083 class CallApiGetterStub : public PlatformCodeStub {
1084  public:
CallApiGetterStub(Isolate * isolate)1085   explicit CallApiGetterStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
1086 
1087   DEFINE_CALL_INTERFACE_DESCRIPTOR(ApiGetter);
1088   DEFINE_PLATFORM_CODE_STUB(CallApiGetter, PlatformCodeStub);
1089 };
1090 
1091 
1092 class BinaryOpICStub : public HydrogenCodeStub {
1093  public:
1094   BinaryOpICStub(Isolate* isolate, Token::Value op,
1095                  OverwriteMode mode = NO_OVERWRITE)
HydrogenCodeStub(isolate,UNINITIALIZED)1096       : HydrogenCodeStub(isolate, UNINITIALIZED) {
1097     BinaryOpICState state(isolate, op, mode);
1098     set_sub_minor_key(state.GetExtraICState());
1099   }
1100 
BinaryOpICStub(Isolate * isolate,const BinaryOpICState & state)1101   BinaryOpICStub(Isolate* isolate, const BinaryOpICState& state)
1102       : HydrogenCodeStub(isolate) {
1103     set_sub_minor_key(state.GetExtraICState());
1104   }
1105 
1106   static void GenerateAheadOfTime(Isolate* isolate);
1107 
GetCodeKind()1108   virtual Code::Kind GetCodeKind() const OVERRIDE {
1109     return Code::BINARY_OP_IC;
1110   }
1111 
GetICState()1112   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1113     return state().GetICState();
1114   }
1115 
GetExtraICState()1116   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1117     return static_cast<ExtraICState>(sub_minor_key());
1118   }
1119 
state()1120   BinaryOpICState state() const {
1121     return BinaryOpICState(isolate(), GetExtraICState());
1122   }
1123 
1124   virtual void PrintState(OStream& os) const FINAL OVERRIDE;  // NOLINT
1125 
1126   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1127   static const int kLeft = 0;
1128   static const int kRight = 1;
1129 
1130  private:
1131   static void GenerateAheadOfTime(Isolate* isolate,
1132                                   const BinaryOpICState& state);
1133 
1134   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1135   DEFINE_HYDROGEN_CODE_STUB(BinaryOpIC, HydrogenCodeStub);
1136 };
1137 
1138 
1139 // TODO(bmeurer): Merge this into the BinaryOpICStub once we have proper tail
1140 // call support for stubs in Hydrogen.
1141 class BinaryOpICWithAllocationSiteStub FINAL : public PlatformCodeStub {
1142  public:
BinaryOpICWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1143   BinaryOpICWithAllocationSiteStub(Isolate* isolate,
1144                                    const BinaryOpICState& state)
1145       : PlatformCodeStub(isolate) {
1146     minor_key_ = state.GetExtraICState();
1147   }
1148 
1149   static void GenerateAheadOfTime(Isolate* isolate);
1150 
GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site)1151   Handle<Code> GetCodeCopyFromTemplate(Handle<AllocationSite> allocation_site) {
1152     Code::FindAndReplacePattern pattern;
1153     pattern.Add(isolate()->factory()->undefined_map(), allocation_site);
1154     return CodeStub::GetCodeCopy(pattern);
1155   }
1156 
GetCodeKind()1157   virtual Code::Kind GetCodeKind() const OVERRIDE {
1158     return Code::BINARY_OP_IC;
1159   }
1160 
GetICState()1161   virtual InlineCacheState GetICState() const OVERRIDE {
1162     return state().GetICState();
1163   }
1164 
GetExtraICState()1165   virtual ExtraICState GetExtraICState() const OVERRIDE {
1166     return static_cast<ExtraICState>(minor_key_);
1167   }
1168 
1169   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
1170 
1171  private:
state()1172   BinaryOpICState state() const {
1173     return BinaryOpICState(isolate(), static_cast<ExtraICState>(minor_key_));
1174   }
1175 
1176   static void GenerateAheadOfTime(Isolate* isolate,
1177                                   const BinaryOpICState& state);
1178 
1179   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1180   DEFINE_PLATFORM_CODE_STUB(BinaryOpICWithAllocationSite, PlatformCodeStub);
1181 };
1182 
1183 
1184 class BinaryOpWithAllocationSiteStub FINAL : public BinaryOpICStub {
1185  public:
BinaryOpWithAllocationSiteStub(Isolate * isolate,Token::Value op,OverwriteMode mode)1186   BinaryOpWithAllocationSiteStub(Isolate* isolate,
1187                                  Token::Value op,
1188                                  OverwriteMode mode)
1189       : BinaryOpICStub(isolate, op, mode) {}
1190 
BinaryOpWithAllocationSiteStub(Isolate * isolate,const BinaryOpICState & state)1191   BinaryOpWithAllocationSiteStub(Isolate* isolate, const BinaryOpICState& state)
1192       : BinaryOpICStub(isolate, state) {}
1193 
GetCodeKind()1194   virtual Code::Kind GetCodeKind() const FINAL OVERRIDE {
1195     return Code::STUB;
1196   }
1197 
1198   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1199   static const int kAllocationSite = 0;
1200   static const int kLeft = 1;
1201   static const int kRight = 2;
1202 
1203   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOpWithAllocationSite);
1204   DEFINE_HYDROGEN_CODE_STUB(BinaryOpWithAllocationSite, BinaryOpICStub);
1205 };
1206 
1207 
1208 enum StringAddFlags {
1209   // Omit both parameter checks.
1210   STRING_ADD_CHECK_NONE = 0,
1211   // Check left parameter.
1212   STRING_ADD_CHECK_LEFT = 1 << 0,
1213   // Check right parameter.
1214   STRING_ADD_CHECK_RIGHT = 1 << 1,
1215   // Check both parameters.
1216   STRING_ADD_CHECK_BOTH = STRING_ADD_CHECK_LEFT | STRING_ADD_CHECK_RIGHT
1217 };
1218 
1219 
1220 class StringAddStub FINAL : public HydrogenCodeStub {
1221  public:
StringAddStub(Isolate * isolate,StringAddFlags flags,PretenureFlag pretenure_flag)1222   StringAddStub(Isolate* isolate, StringAddFlags flags,
1223                 PretenureFlag pretenure_flag)
1224       : HydrogenCodeStub(isolate) {
1225     set_sub_minor_key(StringAddFlagsBits::encode(flags) |
1226                       PretenureFlagBits::encode(pretenure_flag));
1227   }
1228 
flags()1229   StringAddFlags flags() const {
1230     return StringAddFlagsBits::decode(sub_minor_key());
1231   }
1232 
pretenure_flag()1233   PretenureFlag pretenure_flag() const {
1234     return PretenureFlagBits::decode(sub_minor_key());
1235   }
1236 
1237   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1238   static const int kLeft = 0;
1239   static const int kRight = 1;
1240 
1241  private:
1242   class StringAddFlagsBits: public BitField<StringAddFlags, 0, 2> {};
1243   class PretenureFlagBits: public BitField<PretenureFlag, 2, 1> {};
1244 
1245   virtual void PrintBaseName(OStream& os) const OVERRIDE;  // NOLINT
1246 
1247   DEFINE_CALL_INTERFACE_DESCRIPTOR(StringAdd);
1248   DEFINE_HYDROGEN_CODE_STUB(StringAdd, HydrogenCodeStub);
1249 };
1250 
1251 
1252 class CompareICStub : public PlatformCodeStub {
1253  public:
CompareICStub(Isolate * isolate,Token::Value op,CompareICState::State left,CompareICState::State right,CompareICState::State state)1254   CompareICStub(Isolate* isolate, Token::Value op, CompareICState::State left,
1255                 CompareICState::State right, CompareICState::State state)
1256       : PlatformCodeStub(isolate) {
1257     DCHECK(Token::IsCompareOp(op));
1258     minor_key_ = OpBits::encode(op - Token::EQ) | LeftStateBits::encode(left) |
1259                  RightStateBits::encode(right) | StateBits::encode(state);
1260   }
1261 
set_known_map(Handle<Map> map)1262   void set_known_map(Handle<Map> map) { known_map_ = map; }
1263 
1264   virtual InlineCacheState GetICState() const;
1265 
op()1266   Token::Value op() const {
1267     return static_cast<Token::Value>(Token::EQ + OpBits::decode(minor_key_));
1268   }
1269 
left()1270   CompareICState::State left() const {
1271     return LeftStateBits::decode(minor_key_);
1272   }
right()1273   CompareICState::State right() const {
1274     return RightStateBits::decode(minor_key_);
1275   }
state()1276   CompareICState::State state() const { return StateBits::decode(minor_key_); }
1277 
1278  private:
GetCodeKind()1279   virtual Code::Kind GetCodeKind() const { return Code::COMPARE_IC; }
1280 
1281   void GenerateSmis(MacroAssembler* masm);
1282   void GenerateNumbers(MacroAssembler* masm);
1283   void GenerateInternalizedStrings(MacroAssembler* masm);
1284   void GenerateStrings(MacroAssembler* masm);
1285   void GenerateUniqueNames(MacroAssembler* masm);
1286   void GenerateObjects(MacroAssembler* masm);
1287   void GenerateMiss(MacroAssembler* masm);
1288   void GenerateKnownObjects(MacroAssembler* masm);
1289   void GenerateGeneric(MacroAssembler* masm);
1290 
strict()1291   bool strict() const { return op() == Token::EQ_STRICT; }
1292   Condition GetCondition() const;
1293 
1294   virtual void AddToSpecialCache(Handle<Code> new_object);
1295   virtual bool FindCodeInSpecialCache(Code** code_out);
UseSpecialCache()1296   virtual bool UseSpecialCache() {
1297     return state() == CompareICState::KNOWN_OBJECT;
1298   }
1299 
1300   class OpBits : public BitField<int, 0, 3> {};
1301   class LeftStateBits : public BitField<CompareICState::State, 3, 4> {};
1302   class RightStateBits : public BitField<CompareICState::State, 7, 4> {};
1303   class StateBits : public BitField<CompareICState::State, 11, 4> {};
1304 
1305   Handle<Map> known_map_;
1306 
1307   DEFINE_CALL_INTERFACE_DESCRIPTOR(BinaryOp);
1308   DEFINE_PLATFORM_CODE_STUB(CompareIC, PlatformCodeStub);
1309 };
1310 
1311 
1312 class CompareNilICStub : public HydrogenCodeStub  {
1313  public:
1314   Type* GetType(Zone* zone, Handle<Map> map = Handle<Map>());
1315   Type* GetInputType(Zone* zone, Handle<Map> map);
1316 
CompareNilICStub(Isolate * isolate,NilValue nil)1317   CompareNilICStub(Isolate* isolate, NilValue nil) : HydrogenCodeStub(isolate) {
1318     set_sub_minor_key(NilValueBits::encode(nil));
1319   }
1320 
1321   CompareNilICStub(Isolate* isolate, ExtraICState ic_state,
1322                    InitializationState init_state = INITIALIZED)
HydrogenCodeStub(isolate,init_state)1323       : HydrogenCodeStub(isolate, init_state) {
1324     set_sub_minor_key(ic_state);
1325   }
1326 
GetUninitialized(Isolate * isolate,NilValue nil)1327   static Handle<Code> GetUninitialized(Isolate* isolate,
1328                                        NilValue nil) {
1329     return CompareNilICStub(isolate, nil, UNINITIALIZED).GetCode();
1330   }
1331 
GetICState()1332   virtual InlineCacheState GetICState() const {
1333     State state = this->state();
1334     if (state.Contains(GENERIC)) {
1335       return MEGAMORPHIC;
1336     } else if (state.Contains(MONOMORPHIC_MAP)) {
1337       return MONOMORPHIC;
1338     } else {
1339       return PREMONOMORPHIC;
1340     }
1341   }
1342 
GetCodeKind()1343   virtual Code::Kind GetCodeKind() const { return Code::COMPARE_NIL_IC; }
1344 
GetExtraICState()1345   virtual ExtraICState GetExtraICState() const { return sub_minor_key(); }
1346 
1347   void UpdateStatus(Handle<Object> object);
1348 
IsMonomorphic()1349   bool IsMonomorphic() const { return state().Contains(MONOMORPHIC_MAP); }
1350 
nil_value()1351   NilValue nil_value() const { return NilValueBits::decode(sub_minor_key()); }
1352 
ClearState()1353   void ClearState() {
1354     set_sub_minor_key(TypesBits::update(sub_minor_key(), 0));
1355   }
1356 
1357   virtual void PrintState(OStream& os) const OVERRIDE;     // NOLINT
1358   virtual void PrintBaseName(OStream& os) const OVERRIDE;  // NOLINT
1359 
1360  private:
CompareNilICStub(Isolate * isolate,NilValue nil,InitializationState init_state)1361   CompareNilICStub(Isolate* isolate, NilValue nil,
1362                    InitializationState init_state)
1363       : HydrogenCodeStub(isolate, init_state) {
1364     set_sub_minor_key(NilValueBits::encode(nil));
1365   }
1366 
1367   enum CompareNilType {
1368     UNDEFINED,
1369     NULL_TYPE,
1370     MONOMORPHIC_MAP,
1371     GENERIC,
1372     NUMBER_OF_TYPES
1373   };
1374 
1375   // At most 6 different types can be distinguished, because the Code object
1376   // only has room for a single byte to hold a set and there are two more
1377   // boolean flags we need to store. :-P
1378   STATIC_ASSERT(NUMBER_OF_TYPES <= 6);
1379 
1380   class State : public EnumSet<CompareNilType, byte> {
1381    public:
State()1382     State() : EnumSet<CompareNilType, byte>(0) { }
State(byte bits)1383     explicit State(byte bits) : EnumSet<CompareNilType, byte>(bits) { }
1384   };
1385   friend OStream& operator<<(OStream& os, const State& s);
1386 
state()1387   State state() const { return State(TypesBits::decode(sub_minor_key())); }
1388 
1389   class NilValueBits : public BitField<NilValue, 0, 1> {};
1390   class TypesBits : public BitField<byte, 1, NUMBER_OF_TYPES> {};
1391 
1392   friend class CompareNilIC;
1393 
1394   DEFINE_CALL_INTERFACE_DESCRIPTOR(CompareNil);
1395   DEFINE_HYDROGEN_CODE_STUB(CompareNilIC, HydrogenCodeStub);
1396 };
1397 
1398 
1399 OStream& operator<<(OStream& os, const CompareNilICStub::State& s);
1400 
1401 
1402 class CEntryStub : public PlatformCodeStub {
1403  public:
1404   CEntryStub(Isolate* isolate, int result_size,
1405              SaveFPRegsMode save_doubles = kDontSaveFPRegs)
PlatformCodeStub(isolate)1406       : PlatformCodeStub(isolate) {
1407     minor_key_ = SaveDoublesBits::encode(save_doubles == kSaveFPRegs);
1408     DCHECK(result_size == 1 || result_size == 2);
1409 #ifdef _WIN64
1410     minor_key_ = ResultSizeBits::update(minor_key_, result_size);
1411 #endif  // _WIN64
1412   }
1413 
1414   // The version of this stub that doesn't save doubles is generated ahead of
1415   // time, so it's OK to call it from other stubs that can't cope with GC during
1416   // their code generation.  On machines that always have gp registers (x64) we
1417   // can generate both variants ahead of time.
1418   static void GenerateAheadOfTime(Isolate* isolate);
1419 
1420  private:
save_doubles()1421   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
1422 #ifdef _WIN64
result_size()1423   int result_size() const { return ResultSizeBits::decode(minor_key_); }
1424 #endif  // _WIN64
1425 
1426   bool NeedsImmovableCode();
1427 
1428   class SaveDoublesBits : public BitField<bool, 0, 1> {};
1429   class ResultSizeBits : public BitField<int, 1, 3> {};
1430 
1431   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1432   DEFINE_PLATFORM_CODE_STUB(CEntry, PlatformCodeStub);
1433 };
1434 
1435 
1436 class JSEntryStub : public PlatformCodeStub {
1437  public:
JSEntryStub(Isolate * isolate,StackFrame::Type type)1438   JSEntryStub(Isolate* isolate, StackFrame::Type type)
1439       : PlatformCodeStub(isolate) {
1440     DCHECK(type == StackFrame::ENTRY || type == StackFrame::ENTRY_CONSTRUCT);
1441     minor_key_ = StackFrameTypeBits::encode(type);
1442   }
1443 
1444  private:
1445   virtual void FinishCode(Handle<Code> code);
1446 
PrintName(OStream & os)1447   virtual void PrintName(OStream& os) const OVERRIDE {  // NOLINT
1448     os << (type() == StackFrame::ENTRY ? "JSEntryStub"
1449                                        : "JSConstructEntryStub");
1450   }
1451 
type()1452   StackFrame::Type type() const {
1453     return StackFrameTypeBits::decode(minor_key_);
1454   }
1455 
1456   class StackFrameTypeBits : public BitField<StackFrame::Type, 0, 5> {};
1457 
1458   int handler_offset_;
1459 
1460   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1461   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
1462 };
1463 
1464 
1465 class ArgumentsAccessStub: public PlatformCodeStub {
1466  public:
1467   enum Type {
1468     READ_ELEMENT,
1469     NEW_SLOPPY_FAST,
1470     NEW_SLOPPY_SLOW,
1471     NEW_STRICT
1472   };
1473 
ArgumentsAccessStub(Isolate * isolate,Type type)1474   ArgumentsAccessStub(Isolate* isolate, Type type) : PlatformCodeStub(isolate) {
1475     minor_key_ = TypeBits::encode(type);
1476   }
1477 
GetCallInterfaceDescriptor()1478   virtual CallInterfaceDescriptor GetCallInterfaceDescriptor() OVERRIDE {
1479     if (type() == READ_ELEMENT) {
1480       return ArgumentsAccessReadDescriptor(isolate());
1481     }
1482     return ContextOnlyDescriptor(isolate());
1483   }
1484 
1485  private:
type()1486   Type type() const { return TypeBits::decode(minor_key_); }
1487 
1488   void GenerateReadElement(MacroAssembler* masm);
1489   void GenerateNewStrict(MacroAssembler* masm);
1490   void GenerateNewSloppyFast(MacroAssembler* masm);
1491   void GenerateNewSloppySlow(MacroAssembler* masm);
1492 
1493   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
1494 
1495   class TypeBits : public BitField<Type, 0, 2> {};
1496 
1497   DEFINE_PLATFORM_CODE_STUB(ArgumentsAccess, PlatformCodeStub);
1498 };
1499 
1500 
1501 class RegExpExecStub: public PlatformCodeStub {
1502  public:
RegExpExecStub(Isolate * isolate)1503   explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
1504 
1505   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
1506   DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
1507 };
1508 
1509 
1510 class RegExpConstructResultStub FINAL : public HydrogenCodeStub {
1511  public:
RegExpConstructResultStub(Isolate * isolate)1512   explicit RegExpConstructResultStub(Isolate* isolate)
1513       : HydrogenCodeStub(isolate) { }
1514 
1515   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
1516   static const int kLength = 0;
1517   static const int kIndex = 1;
1518   static const int kInput = 2;
1519 
1520   DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpConstructResult);
1521   DEFINE_HYDROGEN_CODE_STUB(RegExpConstructResult, HydrogenCodeStub);
1522 };
1523 
1524 
1525 class CallFunctionStub: public PlatformCodeStub {
1526  public:
CallFunctionStub(Isolate * isolate,int argc,CallFunctionFlags flags)1527   CallFunctionStub(Isolate* isolate, int argc, CallFunctionFlags flags)
1528       : PlatformCodeStub(isolate) {
1529     DCHECK(argc >= 0 && argc <= Code::kMaxArguments);
1530     minor_key_ = ArgcBits::encode(argc) | FlagBits::encode(flags);
1531   }
1532 
ExtractArgcFromMinorKey(int minor_key)1533   static int ExtractArgcFromMinorKey(int minor_key) {
1534     return ArgcBits::decode(minor_key);
1535   }
1536 
1537  private:
argc()1538   int argc() const { return ArgcBits::decode(minor_key_); }
flags()1539   int flags() const { return FlagBits::decode(minor_key_); }
1540 
CallAsMethod()1541   bool CallAsMethod() const {
1542     return flags() == CALL_AS_METHOD || flags() == WRAP_AND_CALL;
1543   }
1544 
NeedsChecks()1545   bool NeedsChecks() const { return flags() != WRAP_AND_CALL; }
1546 
1547   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
1548 
1549   // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
1550   class FlagBits : public BitField<CallFunctionFlags, 0, 2> {};
1551   class ArgcBits : public BitField<unsigned, 2, Code::kArgumentsBits> {};
1552   STATIC_ASSERT(Code::kArgumentsBits + 2 <= kStubMinorKeyBits);
1553 
1554   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction);
1555   DEFINE_PLATFORM_CODE_STUB(CallFunction, PlatformCodeStub);
1556 };
1557 
1558 
1559 class CallConstructStub: public PlatformCodeStub {
1560  public:
CallConstructStub(Isolate * isolate,CallConstructorFlags flags)1561   CallConstructStub(Isolate* isolate, CallConstructorFlags flags)
1562       : PlatformCodeStub(isolate) {
1563     minor_key_ = FlagBits::encode(flags);
1564   }
1565 
FinishCode(Handle<Code> code)1566   virtual void FinishCode(Handle<Code> code) {
1567     code->set_has_function_cache(RecordCallTarget());
1568   }
1569 
1570  private:
flags()1571   CallConstructorFlags flags() const { return FlagBits::decode(minor_key_); }
1572 
RecordCallTarget()1573   bool RecordCallTarget() const {
1574     return (flags() & RECORD_CONSTRUCTOR_TARGET) != 0;
1575   }
1576 
1577   virtual void PrintName(OStream& os) const OVERRIDE;  // NOLINT
1578 
1579   class FlagBits : public BitField<CallConstructorFlags, 0, 1> {};
1580 
1581   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallConstruct);
1582   DEFINE_PLATFORM_CODE_STUB(CallConstruct, PlatformCodeStub);
1583 };
1584 
1585 
1586 enum StringIndexFlags {
1587   // Accepts smis or heap numbers.
1588   STRING_INDEX_IS_NUMBER,
1589 
1590   // Accepts smis or heap numbers that are valid array indices
1591   // (ECMA-262 15.4). Invalid indices are reported as being out of
1592   // range.
1593   STRING_INDEX_IS_ARRAY_INDEX
1594 };
1595 
1596 
1597 // Generates code implementing String.prototype.charCodeAt.
1598 //
1599 // Only supports the case when the receiver is a string and the index
1600 // is a number (smi or heap number) that is a valid index into the
1601 // string. Additional index constraints are specified by the
1602 // flags. Otherwise, bails out to the provided labels.
1603 //
1604 // Register usage: |object| may be changed to another string in a way
1605 // that doesn't affect charCodeAt/charAt semantics, |index| is
1606 // preserved, |scratch| and |result| are clobbered.
1607 class StringCharCodeAtGenerator {
1608  public:
StringCharCodeAtGenerator(Register object,Register index,Register result,Label * receiver_not_string,Label * index_not_number,Label * index_out_of_range,StringIndexFlags index_flags)1609   StringCharCodeAtGenerator(Register object,
1610                             Register index,
1611                             Register result,
1612                             Label* receiver_not_string,
1613                             Label* index_not_number,
1614                             Label* index_out_of_range,
1615                             StringIndexFlags index_flags)
1616       : object_(object),
1617         index_(index),
1618         result_(result),
1619         receiver_not_string_(receiver_not_string),
1620         index_not_number_(index_not_number),
1621         index_out_of_range_(index_out_of_range),
1622         index_flags_(index_flags) {
1623     DCHECK(!result_.is(object_));
1624     DCHECK(!result_.is(index_));
1625   }
1626 
1627   // Generates the fast case code. On the fallthrough path |result|
1628   // register contains the result.
1629   void GenerateFast(MacroAssembler* masm);
1630 
1631   // Generates the slow case code. Must not be naturally
1632   // reachable. Expected to be put after a ret instruction (e.g., in
1633   // deferred code). Always jumps back to the fast case.
1634   void GenerateSlow(MacroAssembler* masm,
1635                     const RuntimeCallHelper& call_helper);
1636 
1637   // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1638   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1639     masm->bind(&index_not_smi_);
1640     masm->bind(&call_runtime_);
1641     masm->jmp(bailout);
1642   }
1643 
1644  private:
1645   Register object_;
1646   Register index_;
1647   Register result_;
1648 
1649   Label* receiver_not_string_;
1650   Label* index_not_number_;
1651   Label* index_out_of_range_;
1652 
1653   StringIndexFlags index_flags_;
1654 
1655   Label call_runtime_;
1656   Label index_not_smi_;
1657   Label got_smi_index_;
1658   Label exit_;
1659 
1660   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
1661 };
1662 
1663 
1664 // Generates code for creating a one-char string from a char code.
1665 class StringCharFromCodeGenerator {
1666  public:
StringCharFromCodeGenerator(Register code,Register result)1667   StringCharFromCodeGenerator(Register code,
1668                               Register result)
1669       : code_(code),
1670         result_(result) {
1671     DCHECK(!code_.is(result_));
1672   }
1673 
1674   // Generates the fast case code. On the fallthrough path |result|
1675   // register contains the result.
1676   void GenerateFast(MacroAssembler* masm);
1677 
1678   // Generates the slow case code. Must not be naturally
1679   // reachable. Expected to be put after a ret instruction (e.g., in
1680   // deferred code). Always jumps back to the fast case.
1681   void GenerateSlow(MacroAssembler* masm,
1682                     const RuntimeCallHelper& call_helper);
1683 
1684   // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1685   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1686     masm->bind(&slow_case_);
1687     masm->jmp(bailout);
1688   }
1689 
1690  private:
1691   Register code_;
1692   Register result_;
1693 
1694   Label slow_case_;
1695   Label exit_;
1696 
1697   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
1698 };
1699 
1700 
1701 // Generates code implementing String.prototype.charAt.
1702 //
1703 // Only supports the case when the receiver is a string and the index
1704 // is a number (smi or heap number) that is a valid index into the
1705 // string. Additional index constraints are specified by the
1706 // flags. Otherwise, bails out to the provided labels.
1707 //
1708 // Register usage: |object| may be changed to another string in a way
1709 // that doesn't affect charCodeAt/charAt semantics, |index| is
1710 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
1711 class StringCharAtGenerator {
1712  public:
StringCharAtGenerator(Register object,Register index,Register scratch,Register result,Label * receiver_not_string,Label * index_not_number,Label * index_out_of_range,StringIndexFlags index_flags)1713   StringCharAtGenerator(Register object,
1714                         Register index,
1715                         Register scratch,
1716                         Register result,
1717                         Label* receiver_not_string,
1718                         Label* index_not_number,
1719                         Label* index_out_of_range,
1720                         StringIndexFlags index_flags)
1721       : char_code_at_generator_(object,
1722                                 index,
1723                                 scratch,
1724                                 receiver_not_string,
1725                                 index_not_number,
1726                                 index_out_of_range,
1727                                 index_flags),
1728         char_from_code_generator_(scratch, result) {}
1729 
1730   // Generates the fast case code. On the fallthrough path |result|
1731   // register contains the result.
GenerateFast(MacroAssembler * masm)1732   void GenerateFast(MacroAssembler* masm) {
1733     char_code_at_generator_.GenerateFast(masm);
1734     char_from_code_generator_.GenerateFast(masm);
1735   }
1736 
1737   // Generates the slow case code. Must not be naturally
1738   // reachable. Expected to be put after a ret instruction (e.g., in
1739   // deferred code). Always jumps back to the fast case.
GenerateSlow(MacroAssembler * masm,const RuntimeCallHelper & call_helper)1740   void GenerateSlow(MacroAssembler* masm,
1741                     const RuntimeCallHelper& call_helper) {
1742     char_code_at_generator_.GenerateSlow(masm, call_helper);
1743     char_from_code_generator_.GenerateSlow(masm, call_helper);
1744   }
1745 
1746   // Skip handling slow case and directly jump to bailout.
SkipSlow(MacroAssembler * masm,Label * bailout)1747   void SkipSlow(MacroAssembler* masm, Label* bailout) {
1748     char_code_at_generator_.SkipSlow(masm, bailout);
1749     char_from_code_generator_.SkipSlow(masm, bailout);
1750   }
1751 
1752  private:
1753   StringCharCodeAtGenerator char_code_at_generator_;
1754   StringCharFromCodeGenerator char_from_code_generator_;
1755 
1756   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
1757 };
1758 
1759 
1760 class LoadDictionaryElementStub : public HydrogenCodeStub {
1761  public:
LoadDictionaryElementStub(Isolate * isolate)1762   explicit LoadDictionaryElementStub(Isolate* isolate)
1763       : HydrogenCodeStub(isolate) {}
1764 
1765   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1766   DEFINE_HYDROGEN_CODE_STUB(LoadDictionaryElement, HydrogenCodeStub);
1767 };
1768 
1769 
1770 class KeyedLoadGenericStub : public HydrogenCodeStub {
1771  public:
KeyedLoadGenericStub(Isolate * isolate)1772   explicit KeyedLoadGenericStub(Isolate* isolate) : HydrogenCodeStub(isolate) {}
1773 
GetCodeKind()1774   virtual Code::Kind GetCodeKind() const { return Code::KEYED_LOAD_IC; }
GetICState()1775   virtual InlineCacheState GetICState() const { return GENERIC; }
1776 
1777   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1778   DEFINE_HYDROGEN_CODE_STUB(KeyedLoadGeneric, HydrogenCodeStub);
1779 };
1780 
1781 
1782 class LoadICTrampolineStub : public PlatformCodeStub {
1783  public:
LoadICTrampolineStub(Isolate * isolate,const LoadICState & state)1784   LoadICTrampolineStub(Isolate* isolate, const LoadICState& state)
1785       : PlatformCodeStub(isolate) {
1786     minor_key_ = state.GetExtraICState();
1787   }
1788 
GetCodeKind()1789   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1790 
GetICState()1791   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1792     return GENERIC;
1793   }
1794 
GetExtraICState()1795   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1796     return static_cast<ExtraICState>(minor_key_);
1797   }
1798 
1799  private:
state()1800   LoadICState state() const {
1801     return LoadICState(static_cast<ExtraICState>(minor_key_));
1802   }
1803 
1804   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadICTrampoline);
1805   DEFINE_PLATFORM_CODE_STUB(LoadICTrampoline, PlatformCodeStub);
1806 };
1807 
1808 
1809 class KeyedLoadICTrampolineStub : public LoadICTrampolineStub {
1810  public:
KeyedLoadICTrampolineStub(Isolate * isolate)1811   explicit KeyedLoadICTrampolineStub(Isolate* isolate)
1812       : LoadICTrampolineStub(isolate, LoadICState(0)) {}
1813 
GetCodeKind()1814   virtual Code::Kind GetCodeKind() const OVERRIDE {
1815     return Code::KEYED_LOAD_IC;
1816   }
1817 
1818   DEFINE_PLATFORM_CODE_STUB(KeyedLoadICTrampoline, LoadICTrampolineStub);
1819 };
1820 
1821 
1822 class MegamorphicLoadStub : public HydrogenCodeStub {
1823  public:
MegamorphicLoadStub(Isolate * isolate,const LoadICState & state)1824   MegamorphicLoadStub(Isolate* isolate, const LoadICState& state)
1825       : HydrogenCodeStub(isolate) {
1826     set_sub_minor_key(state.GetExtraICState());
1827   }
1828 
GetCodeKind()1829   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1830 
GetICState()1831   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1832     return MEGAMORPHIC;
1833   }
1834 
GetExtraICState()1835   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1836     return static_cast<ExtraICState>(sub_minor_key());
1837   }
1838 
1839   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1840   DEFINE_HYDROGEN_CODE_STUB(MegamorphicLoad, HydrogenCodeStub);
1841 };
1842 
1843 
1844 class VectorLoadStub : public HydrogenCodeStub {
1845  public:
VectorLoadStub(Isolate * isolate,const LoadICState & state)1846   explicit VectorLoadStub(Isolate* isolate, const LoadICState& state)
1847       : HydrogenCodeStub(isolate) {
1848     set_sub_minor_key(state.GetExtraICState());
1849   }
1850 
GetCodeKind()1851   virtual Code::Kind GetCodeKind() const OVERRIDE { return Code::LOAD_IC; }
1852 
GetICState()1853   virtual InlineCacheState GetICState() const FINAL OVERRIDE {
1854     return GENERIC;
1855   }
1856 
GetExtraICState()1857   virtual ExtraICState GetExtraICState() const FINAL OVERRIDE {
1858     return static_cast<ExtraICState>(sub_minor_key());
1859   }
1860 
1861  private:
state()1862   LoadICState state() const { return LoadICState(GetExtraICState()); }
1863 
1864   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1865   DEFINE_HYDROGEN_CODE_STUB(VectorLoad, HydrogenCodeStub);
1866 };
1867 
1868 
1869 class VectorKeyedLoadStub : public VectorLoadStub {
1870  public:
VectorKeyedLoadStub(Isolate * isolate)1871   explicit VectorKeyedLoadStub(Isolate* isolate)
1872       : VectorLoadStub(isolate, LoadICState(0)) {}
1873 
GetCodeKind()1874   virtual Code::Kind GetCodeKind() const OVERRIDE {
1875     return Code::KEYED_LOAD_IC;
1876   }
1877 
1878   DEFINE_CALL_INTERFACE_DESCRIPTOR(VectorLoadIC);
1879   DEFINE_HYDROGEN_CODE_STUB(VectorKeyedLoad, VectorLoadStub);
1880 };
1881 
1882 
1883 class DoubleToIStub : public PlatformCodeStub {
1884  public:
1885   DoubleToIStub(Isolate* isolate, Register source, Register destination,
1886                 int offset, bool is_truncating, bool skip_fastpath = false)
PlatformCodeStub(isolate)1887       : PlatformCodeStub(isolate) {
1888     minor_key_ = SourceRegisterBits::encode(source.code()) |
1889                  DestinationRegisterBits::encode(destination.code()) |
1890                  OffsetBits::encode(offset) |
1891                  IsTruncatingBits::encode(is_truncating) |
1892                  SkipFastPathBits::encode(skip_fastpath) |
1893                  SSE3Bits::encode(CpuFeatures::IsSupported(SSE3) ? 1 : 0);
1894   }
1895 
SometimesSetsUpAFrame()1896   virtual bool SometimesSetsUpAFrame() { return false; }
1897 
1898  private:
source()1899   Register source() const {
1900     return Register::from_code(SourceRegisterBits::decode(minor_key_));
1901   }
destination()1902   Register destination() const {
1903     return Register::from_code(DestinationRegisterBits::decode(minor_key_));
1904   }
is_truncating()1905   bool is_truncating() const { return IsTruncatingBits::decode(minor_key_); }
skip_fastpath()1906   bool skip_fastpath() const { return SkipFastPathBits::decode(minor_key_); }
offset()1907   int offset() const { return OffsetBits::decode(minor_key_); }
1908 
1909   static const int kBitsPerRegisterNumber = 6;
1910   STATIC_ASSERT((1L << kBitsPerRegisterNumber) >= Register::kNumRegisters);
1911   class SourceRegisterBits:
1912       public BitField<int, 0, kBitsPerRegisterNumber> {};  // NOLINT
1913   class DestinationRegisterBits:
1914       public BitField<int, kBitsPerRegisterNumber,
1915         kBitsPerRegisterNumber> {};  // NOLINT
1916   class IsTruncatingBits:
1917       public BitField<bool, 2 * kBitsPerRegisterNumber, 1> {};  // NOLINT
1918   class OffsetBits:
1919       public BitField<int, 2 * kBitsPerRegisterNumber + 1, 3> {};  // NOLINT
1920   class SkipFastPathBits:
1921       public BitField<int, 2 * kBitsPerRegisterNumber + 4, 1> {};  // NOLINT
1922   class SSE3Bits:
1923       public BitField<int, 2 * kBitsPerRegisterNumber + 5, 1> {};  // NOLINT
1924 
1925   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
1926   DEFINE_PLATFORM_CODE_STUB(DoubleToI, PlatformCodeStub);
1927 };
1928 
1929 
1930 class LoadFastElementStub : public HydrogenCodeStub {
1931  public:
LoadFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind)1932   LoadFastElementStub(Isolate* isolate, bool is_js_array,
1933                       ElementsKind elements_kind)
1934       : HydrogenCodeStub(isolate) {
1935     set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1936                       IsJSArrayBits::encode(is_js_array));
1937   }
1938 
is_js_array()1939   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1940 
elements_kind()1941   ElementsKind elements_kind() const {
1942     return ElementsKindBits::decode(sub_minor_key());
1943   }
1944 
1945  private:
1946   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
1947   class IsJSArrayBits: public BitField<bool, 8, 1> {};
1948 
1949   DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
1950   DEFINE_HYDROGEN_CODE_STUB(LoadFastElement, HydrogenCodeStub);
1951 };
1952 
1953 
1954 class StoreFastElementStub : public HydrogenCodeStub {
1955  public:
StoreFastElementStub(Isolate * isolate,bool is_js_array,ElementsKind elements_kind,KeyedAccessStoreMode mode)1956   StoreFastElementStub(Isolate* isolate, bool is_js_array,
1957                        ElementsKind elements_kind, KeyedAccessStoreMode mode)
1958       : HydrogenCodeStub(isolate) {
1959     set_sub_minor_key(ElementsKindBits::encode(elements_kind) |
1960                       IsJSArrayBits::encode(is_js_array) |
1961                       StoreModeBits::encode(mode));
1962   }
1963 
is_js_array()1964   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
1965 
elements_kind()1966   ElementsKind elements_kind() const {
1967     return ElementsKindBits::decode(sub_minor_key());
1968   }
1969 
store_mode()1970   KeyedAccessStoreMode store_mode() const {
1971     return StoreModeBits::decode(sub_minor_key());
1972   }
1973 
1974  private:
1975   class ElementsKindBits: public BitField<ElementsKind,      0, 8> {};
1976   class StoreModeBits: public BitField<KeyedAccessStoreMode, 8, 4> {};
1977   class IsJSArrayBits: public BitField<bool,                12, 1> {};
1978 
1979   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
1980   DEFINE_HYDROGEN_CODE_STUB(StoreFastElement, HydrogenCodeStub);
1981 };
1982 
1983 
1984 class TransitionElementsKindStub : public HydrogenCodeStub {
1985  public:
TransitionElementsKindStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_js_array)1986   TransitionElementsKindStub(Isolate* isolate,
1987                              ElementsKind from_kind,
1988                              ElementsKind to_kind,
1989                              bool is_js_array) : HydrogenCodeStub(isolate) {
1990     set_sub_minor_key(FromKindBits::encode(from_kind) |
1991                       ToKindBits::encode(to_kind) |
1992                       IsJSArrayBits::encode(is_js_array));
1993   }
1994 
from_kind()1995   ElementsKind from_kind() const {
1996     return FromKindBits::decode(sub_minor_key());
1997   }
1998 
to_kind()1999   ElementsKind to_kind() const { return ToKindBits::decode(sub_minor_key()); }
2000 
is_js_array()2001   bool is_js_array() const { return IsJSArrayBits::decode(sub_minor_key()); }
2002 
2003  private:
2004   class FromKindBits: public BitField<ElementsKind, 8, 8> {};
2005   class ToKindBits: public BitField<ElementsKind, 0, 8> {};
2006   class IsJSArrayBits: public BitField<bool, 16, 1> {};
2007 
2008   DEFINE_CALL_INTERFACE_DESCRIPTOR(TransitionElementsKind);
2009   DEFINE_HYDROGEN_CODE_STUB(TransitionElementsKind, HydrogenCodeStub);
2010 };
2011 
2012 
2013 class ArrayConstructorStubBase : public HydrogenCodeStub {
2014  public:
ArrayConstructorStubBase(Isolate * isolate,ElementsKind kind,AllocationSiteOverrideMode override_mode)2015   ArrayConstructorStubBase(Isolate* isolate,
2016                            ElementsKind kind,
2017                            AllocationSiteOverrideMode override_mode)
2018       : HydrogenCodeStub(isolate) {
2019     // It only makes sense to override local allocation site behavior
2020     // if there is a difference between the global allocation site policy
2021     // for an ElementsKind and the desired usage of the stub.
2022     DCHECK(override_mode != DISABLE_ALLOCATION_SITES ||
2023            AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE);
2024     set_sub_minor_key(ElementsKindBits::encode(kind) |
2025                       AllocationSiteOverrideModeBits::encode(override_mode));
2026   }
2027 
elements_kind()2028   ElementsKind elements_kind() const {
2029     return ElementsKindBits::decode(sub_minor_key());
2030   }
2031 
override_mode()2032   AllocationSiteOverrideMode override_mode() const {
2033     return AllocationSiteOverrideModeBits::decode(sub_minor_key());
2034   }
2035 
2036   static void GenerateStubsAheadOfTime(Isolate* isolate);
2037 
2038   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2039   static const int kConstructor = 0;
2040   static const int kAllocationSite = 1;
2041 
2042  protected:
2043   OStream& BasePrintName(OStream& os, const char* name) const;  // NOLINT
2044 
2045  private:
2046   // Ensure data fits within available bits.
2047   STATIC_ASSERT(LAST_ALLOCATION_SITE_OVERRIDE_MODE == 1);
2048 
2049   class ElementsKindBits: public BitField<ElementsKind, 0, 8> {};
2050   class AllocationSiteOverrideModeBits: public
2051       BitField<AllocationSiteOverrideMode, 8, 1> {};  // NOLINT
2052 
2053   DEFINE_CODE_STUB_BASE(ArrayConstructorStubBase, HydrogenCodeStub);
2054 };
2055 
2056 
2057 class ArrayNoArgumentConstructorStub : public ArrayConstructorStubBase {
2058  public:
2059   ArrayNoArgumentConstructorStub(
2060       Isolate* isolate,
2061       ElementsKind kind,
2062       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
ArrayConstructorStubBase(isolate,kind,override_mode)2063       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2064   }
2065 
2066  private:
PrintName(OStream & os)2067   virtual void PrintName(OStream& os) const OVERRIDE {  // NOLINT
2068     BasePrintName(os, "ArrayNoArgumentConstructorStub");
2069   }
2070 
2071   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructorConstantArgCount);
2072   DEFINE_HYDROGEN_CODE_STUB(ArrayNoArgumentConstructor,
2073                             ArrayConstructorStubBase);
2074 };
2075 
2076 
2077 class ArraySingleArgumentConstructorStub : public ArrayConstructorStubBase {
2078  public:
2079   ArraySingleArgumentConstructorStub(
2080       Isolate* isolate,
2081       ElementsKind kind,
2082       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
ArrayConstructorStubBase(isolate,kind,override_mode)2083       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2084   }
2085 
2086  private:
PrintName(OStream & os)2087   virtual void PrintName(OStream& os) const {  // NOLINT
2088     BasePrintName(os, "ArraySingleArgumentConstructorStub");
2089   }
2090 
2091   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2092   DEFINE_HYDROGEN_CODE_STUB(ArraySingleArgumentConstructor,
2093                             ArrayConstructorStubBase);
2094 };
2095 
2096 
2097 class ArrayNArgumentsConstructorStub : public ArrayConstructorStubBase {
2098  public:
2099   ArrayNArgumentsConstructorStub(
2100       Isolate* isolate,
2101       ElementsKind kind,
2102       AllocationSiteOverrideMode override_mode = DONT_OVERRIDE)
ArrayConstructorStubBase(isolate,kind,override_mode)2103       : ArrayConstructorStubBase(isolate, kind, override_mode) {
2104   }
2105 
2106  private:
PrintName(OStream & os)2107   virtual void PrintName(OStream& os) const {  // NOLINT
2108     BasePrintName(os, "ArrayNArgumentsConstructorStub");
2109   }
2110 
2111   DEFINE_CALL_INTERFACE_DESCRIPTOR(ArrayConstructor);
2112   DEFINE_HYDROGEN_CODE_STUB(ArrayNArgumentsConstructor,
2113                             ArrayConstructorStubBase);
2114 };
2115 
2116 
2117 class InternalArrayConstructorStubBase : public HydrogenCodeStub {
2118  public:
InternalArrayConstructorStubBase(Isolate * isolate,ElementsKind kind)2119   InternalArrayConstructorStubBase(Isolate* isolate, ElementsKind kind)
2120       : HydrogenCodeStub(isolate) {
2121     set_sub_minor_key(ElementsKindBits::encode(kind));
2122   }
2123 
2124   static void GenerateStubsAheadOfTime(Isolate* isolate);
2125 
2126   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2127   static const int kConstructor = 0;
2128 
elements_kind()2129   ElementsKind elements_kind() const {
2130     return ElementsKindBits::decode(sub_minor_key());
2131   }
2132 
2133  private:
2134   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2135 
2136   DEFINE_CODE_STUB_BASE(InternalArrayConstructorStubBase, HydrogenCodeStub);
2137 };
2138 
2139 
2140 class InternalArrayNoArgumentConstructorStub : public
2141     InternalArrayConstructorStubBase {
2142  public:
InternalArrayNoArgumentConstructorStub(Isolate * isolate,ElementsKind kind)2143   InternalArrayNoArgumentConstructorStub(Isolate* isolate,
2144                                          ElementsKind kind)
2145       : InternalArrayConstructorStubBase(isolate, kind) { }
2146 
2147   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructorConstantArgCount);
2148   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNoArgumentConstructor,
2149                             InternalArrayConstructorStubBase);
2150 };
2151 
2152 
2153 class InternalArraySingleArgumentConstructorStub : public
2154     InternalArrayConstructorStubBase {
2155  public:
InternalArraySingleArgumentConstructorStub(Isolate * isolate,ElementsKind kind)2156   InternalArraySingleArgumentConstructorStub(Isolate* isolate,
2157                                              ElementsKind kind)
2158       : InternalArrayConstructorStubBase(isolate, kind) { }
2159 
2160   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2161   DEFINE_HYDROGEN_CODE_STUB(InternalArraySingleArgumentConstructor,
2162                             InternalArrayConstructorStubBase);
2163 };
2164 
2165 
2166 class InternalArrayNArgumentsConstructorStub : public
2167     InternalArrayConstructorStubBase {
2168  public:
InternalArrayNArgumentsConstructorStub(Isolate * isolate,ElementsKind kind)2169   InternalArrayNArgumentsConstructorStub(Isolate* isolate, ElementsKind kind)
2170       : InternalArrayConstructorStubBase(isolate, kind) { }
2171 
2172   DEFINE_CALL_INTERFACE_DESCRIPTOR(InternalArrayConstructor);
2173   DEFINE_HYDROGEN_CODE_STUB(InternalArrayNArgumentsConstructor,
2174                             InternalArrayConstructorStubBase);
2175 };
2176 
2177 
2178 class StoreElementStub : public PlatformCodeStub {
2179  public:
StoreElementStub(Isolate * isolate,ElementsKind elements_kind)2180   StoreElementStub(Isolate* isolate, ElementsKind elements_kind)
2181       : PlatformCodeStub(isolate) {
2182     minor_key_ = ElementsKindBits::encode(elements_kind);
2183   }
2184 
2185  private:
elements_kind()2186   ElementsKind elements_kind() const {
2187     return ElementsKindBits::decode(minor_key_);
2188   }
2189 
2190   class ElementsKindBits : public BitField<ElementsKind, 0, 8> {};
2191 
2192   DEFINE_CALL_INTERFACE_DESCRIPTOR(Store);
2193   DEFINE_PLATFORM_CODE_STUB(StoreElement, PlatformCodeStub);
2194 };
2195 
2196 
2197 class ToBooleanStub: public HydrogenCodeStub {
2198  public:
2199   enum Type {
2200     UNDEFINED,
2201     BOOLEAN,
2202     NULL_TYPE,
2203     SMI,
2204     SPEC_OBJECT,
2205     STRING,
2206     SYMBOL,
2207     HEAP_NUMBER,
2208     NUMBER_OF_TYPES
2209   };
2210 
2211   enum ResultMode {
2212     RESULT_AS_SMI,             // For Smi(1) on truthy value, Smi(0) otherwise.
2213     RESULT_AS_ODDBALL,         // For {true} on truthy value, {false} otherwise.
2214     RESULT_AS_INVERSE_ODDBALL  // For {false} on truthy value, {true} otherwise.
2215   };
2216 
2217   // At most 8 different types can be distinguished, because the Code object
2218   // only has room for a single byte to hold a set of these types. :-P
2219   STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
2220 
2221   class Types : public EnumSet<Type, byte> {
2222    public:
Types()2223     Types() : EnumSet<Type, byte>(0) {}
Types(byte bits)2224     explicit Types(byte bits) : EnumSet<Type, byte>(bits) {}
2225 
ToByte()2226     byte ToByte() const { return ToIntegral(); }
2227     bool UpdateStatus(Handle<Object> object);
2228     bool NeedsMap() const;
2229     bool CanBeUndetectable() const;
IsGeneric()2230     bool IsGeneric() const { return ToIntegral() == Generic().ToIntegral(); }
2231 
Generic()2232     static Types Generic() { return Types((1 << NUMBER_OF_TYPES) - 1); }
2233   };
2234 
2235   ToBooleanStub(Isolate* isolate, ResultMode mode, Types types = Types())
HydrogenCodeStub(isolate)2236       : HydrogenCodeStub(isolate) {
2237     set_sub_minor_key(TypesBits::encode(types.ToByte()) |
2238                       ResultModeBits::encode(mode));
2239   }
2240 
ToBooleanStub(Isolate * isolate,ExtraICState state)2241   ToBooleanStub(Isolate* isolate, ExtraICState state)
2242       : HydrogenCodeStub(isolate) {
2243     set_sub_minor_key(TypesBits::encode(static_cast<byte>(state)) |
2244                       ResultModeBits::encode(RESULT_AS_SMI));
2245   }
2246 
2247   bool UpdateStatus(Handle<Object> object);
types()2248   Types types() const { return Types(TypesBits::decode(sub_minor_key())); }
mode()2249   ResultMode mode() const { return ResultModeBits::decode(sub_minor_key()); }
2250 
GetCodeKind()2251   virtual Code::Kind GetCodeKind() const { return Code::TO_BOOLEAN_IC; }
2252   virtual void PrintState(OStream& os) const OVERRIDE;  // NOLINT
2253 
SometimesSetsUpAFrame()2254   virtual bool SometimesSetsUpAFrame() { return false; }
2255 
GetUninitialized(Isolate * isolate)2256   static Handle<Code> GetUninitialized(Isolate* isolate) {
2257     return ToBooleanStub(isolate, UNINITIALIZED).GetCode();
2258   }
2259 
GetExtraICState()2260   virtual ExtraICState GetExtraICState() const { return types().ToIntegral(); }
2261 
GetICState()2262   virtual InlineCacheState GetICState() const {
2263     if (types().IsEmpty()) {
2264       return ::v8::internal::UNINITIALIZED;
2265     } else {
2266       return MONOMORPHIC;
2267     }
2268   }
2269 
2270  private:
ToBooleanStub(Isolate * isolate,InitializationState init_state)2271   ToBooleanStub(Isolate* isolate, InitializationState init_state)
2272       : HydrogenCodeStub(isolate, init_state) {
2273     set_sub_minor_key(ResultModeBits::encode(RESULT_AS_SMI));
2274   }
2275 
2276   class TypesBits : public BitField<byte, 0, NUMBER_OF_TYPES> {};
2277   class ResultModeBits : public BitField<ResultMode, NUMBER_OF_TYPES, 2> {};
2278 
2279   DEFINE_CALL_INTERFACE_DESCRIPTOR(ToBoolean);
2280   DEFINE_HYDROGEN_CODE_STUB(ToBoolean, HydrogenCodeStub);
2281 };
2282 
2283 
2284 OStream& operator<<(OStream& os, const ToBooleanStub::Types& t);
2285 
2286 
2287 class ElementsTransitionAndStoreStub : public HydrogenCodeStub {
2288  public:
ElementsTransitionAndStoreStub(Isolate * isolate,ElementsKind from_kind,ElementsKind to_kind,bool is_jsarray,KeyedAccessStoreMode store_mode)2289   ElementsTransitionAndStoreStub(Isolate* isolate, ElementsKind from_kind,
2290                                  ElementsKind to_kind, bool is_jsarray,
2291                                  KeyedAccessStoreMode store_mode)
2292       : HydrogenCodeStub(isolate) {
2293     set_sub_minor_key(FromBits::encode(from_kind) | ToBits::encode(to_kind) |
2294                       IsJSArrayBits::encode(is_jsarray) |
2295                       StoreModeBits::encode(store_mode));
2296   }
2297 
from_kind()2298   ElementsKind from_kind() const { return FromBits::decode(sub_minor_key()); }
to_kind()2299   ElementsKind to_kind() const { return ToBits::decode(sub_minor_key()); }
is_jsarray()2300   bool is_jsarray() const { return IsJSArrayBits::decode(sub_minor_key()); }
store_mode()2301   KeyedAccessStoreMode store_mode() const {
2302     return StoreModeBits::decode(sub_minor_key());
2303   }
2304 
2305   // Parameters accessed via CodeStubGraphBuilder::GetParameter()
2306   enum ParameterIndices {
2307     kValueIndex,
2308     kMapIndex,
2309     kKeyIndex,
2310     kObjectIndex,
2311     kParameterCount
2312   };
2313 
ValueRegister()2314   static const Register ValueRegister() {
2315     return ElementTransitionAndStoreDescriptor::ValueRegister();
2316   }
MapRegister()2317   static const Register MapRegister() {
2318     return ElementTransitionAndStoreDescriptor::MapRegister();
2319   }
KeyRegister()2320   static const Register KeyRegister() {
2321     return ElementTransitionAndStoreDescriptor::NameRegister();
2322   }
ObjectRegister()2323   static const Register ObjectRegister() {
2324     return ElementTransitionAndStoreDescriptor::ReceiverRegister();
2325   }
2326 
2327  private:
2328   class FromBits : public BitField<ElementsKind, 0, 8> {};
2329   class ToBits : public BitField<ElementsKind, 8, 8> {};
2330   class IsJSArrayBits : public BitField<bool, 16, 1> {};
2331   class StoreModeBits : public BitField<KeyedAccessStoreMode, 17, 4> {};
2332 
2333   DEFINE_CALL_INTERFACE_DESCRIPTOR(ElementTransitionAndStore);
2334   DEFINE_HYDROGEN_CODE_STUB(ElementsTransitionAndStore, HydrogenCodeStub);
2335 };
2336 
2337 
2338 class StoreArrayLiteralElementStub : public PlatformCodeStub {
2339  public:
StoreArrayLiteralElementStub(Isolate * isolate)2340   explicit StoreArrayLiteralElementStub(Isolate* isolate)
2341       : PlatformCodeStub(isolate) { }
2342 
2343   DEFINE_CALL_INTERFACE_DESCRIPTOR(StoreArrayLiteralElement);
2344   DEFINE_PLATFORM_CODE_STUB(StoreArrayLiteralElement, PlatformCodeStub);
2345 };
2346 
2347 
2348 class StubFailureTrampolineStub : public PlatformCodeStub {
2349  public:
StubFailureTrampolineStub(Isolate * isolate,StubFunctionMode function_mode)2350   StubFailureTrampolineStub(Isolate* isolate, StubFunctionMode function_mode)
2351       : PlatformCodeStub(isolate) {
2352     minor_key_ = FunctionModeField::encode(function_mode);
2353   }
2354 
2355   static void GenerateAheadOfTime(Isolate* isolate);
2356 
2357  private:
function_mode()2358   StubFunctionMode function_mode() const {
2359     return FunctionModeField::decode(minor_key_);
2360   }
2361 
2362   class FunctionModeField : public BitField<StubFunctionMode, 0, 1> {};
2363 
2364   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2365   DEFINE_PLATFORM_CODE_STUB(StubFailureTrampoline, PlatformCodeStub);
2366 };
2367 
2368 
2369 class ProfileEntryHookStub : public PlatformCodeStub {
2370  public:
ProfileEntryHookStub(Isolate * isolate)2371   explicit ProfileEntryHookStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2372 
2373   // The profile entry hook function is not allowed to cause a GC.
SometimesSetsUpAFrame()2374   virtual bool SometimesSetsUpAFrame() { return false; }
2375 
2376   // Generates a call to the entry hook if it's enabled.
2377   static void MaybeCallEntryHook(MacroAssembler* masm);
2378 
2379  private:
2380   static void EntryHookTrampoline(intptr_t function,
2381                                   intptr_t stack_pointer,
2382                                   Isolate* isolate);
2383 
2384   // ProfileEntryHookStub is called at the start of a function, so it has the
2385   // same register set.
2386   DEFINE_CALL_INTERFACE_DESCRIPTOR(CallFunction)
2387   DEFINE_PLATFORM_CODE_STUB(ProfileEntryHook, PlatformCodeStub);
2388 };
2389 
2390 
2391 class StoreBufferOverflowStub : public PlatformCodeStub {
2392  public:
StoreBufferOverflowStub(Isolate * isolate,SaveFPRegsMode save_fp)2393   StoreBufferOverflowStub(Isolate* isolate, SaveFPRegsMode save_fp)
2394       : PlatformCodeStub(isolate) {
2395     minor_key_ = SaveDoublesBits::encode(save_fp == kSaveFPRegs);
2396   }
2397 
2398   static void GenerateFixedRegStubsAheadOfTime(Isolate* isolate);
SometimesSetsUpAFrame()2399   virtual bool SometimesSetsUpAFrame() { return false; }
2400 
2401  private:
save_doubles()2402   bool save_doubles() const { return SaveDoublesBits::decode(minor_key_); }
2403 
2404   class SaveDoublesBits : public BitField<bool, 0, 1> {};
2405 
2406   DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
2407   DEFINE_PLATFORM_CODE_STUB(StoreBufferOverflow, PlatformCodeStub);
2408 };
2409 
2410 
2411 class SubStringStub : public PlatformCodeStub {
2412  public:
SubStringStub(Isolate * isolate)2413   explicit SubStringStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2414 
2415   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2416   DEFINE_PLATFORM_CODE_STUB(SubString, PlatformCodeStub);
2417 };
2418 
2419 
2420 class StringCompareStub : public PlatformCodeStub {
2421  public:
StringCompareStub(Isolate * isolate)2422   explicit StringCompareStub(Isolate* isolate) : PlatformCodeStub(isolate) {}
2423 
2424   DEFINE_CALL_INTERFACE_DESCRIPTOR(ContextOnly);
2425   DEFINE_PLATFORM_CODE_STUB(StringCompare, PlatformCodeStub);
2426 };
2427 
2428 
2429 #undef DEFINE_CALL_INTERFACE_DESCRIPTOR
2430 #undef DEFINE_PLATFORM_CODE_STUB
2431 #undef DEFINE_HANDLER_CODE_STUB
2432 #undef DEFINE_HYDROGEN_CODE_STUB
2433 #undef DEFINE_CODE_STUB
2434 #undef DEFINE_CODE_STUB_BASE
2435 } }  // namespace v8::internal
2436 
2437 #endif  // V8_CODE_STUBS_H_
2438