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