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