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