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