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