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