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