Home | History | Annotate | Download | only in src
      1 // Copyright 2012 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #ifndef V8_CODE_STUBS_H_
     29 #define V8_CODE_STUBS_H_
     30 
     31 #include "allocation.h"
     32 #include "globals.h"
     33 #include "codegen.h"
     34 
     35 namespace v8 {
     36 namespace internal {
     37 
     38 // List of code stubs used on all platforms.
     39 #define CODE_STUB_LIST_ALL_PLATFORMS(V)  \
     40   V(CallFunction)                        \
     41   V(CallConstruct)                       \
     42   V(UnaryOp)                             \
     43   V(BinaryOp)                            \
     44   V(StringAdd)                           \
     45   V(SubString)                           \
     46   V(StringCompare)                       \
     47   V(Compare)                             \
     48   V(CompareIC)                           \
     49   V(MathPow)                             \
     50   V(RecordWrite)                         \
     51   V(StoreBufferOverflow)                 \
     52   V(RegExpExec)                          \
     53   V(TranscendentalCache)                 \
     54   V(Instanceof)                          \
     55   V(ConvertToDouble)                     \
     56   V(WriteInt32ToHeapNumber)              \
     57   V(StackCheck)                          \
     58   V(Interrupt)                           \
     59   V(FastNewClosure)                      \
     60   V(FastNewContext)                      \
     61   V(FastNewBlockContext)                 \
     62   V(FastCloneShallowArray)               \
     63   V(FastCloneShallowObject)              \
     64   V(ToBoolean)                           \
     65   V(ToNumber)                            \
     66   V(ArgumentsAccess)                     \
     67   V(RegExpConstructResult)               \
     68   V(NumberToString)                      \
     69   V(CEntry)                              \
     70   V(JSEntry)                             \
     71   V(KeyedLoadElement)                    \
     72   V(KeyedStoreElement)                   \
     73   V(DebuggerStatement)                   \
     74   V(StringDictionaryLookup)              \
     75   V(ElementsTransitionAndStore)          \
     76   V(StoreArrayLiteralElement)
     77 
     78 // List of code stubs only used on ARM platforms.
     79 #ifdef V8_TARGET_ARCH_ARM
     80 #define CODE_STUB_LIST_ARM(V)  \
     81   V(GetProperty)               \
     82   V(SetProperty)               \
     83   V(InvokeBuiltin)             \
     84   V(RegExpCEntry)              \
     85   V(DirectCEntry)
     86 #else
     87 #define CODE_STUB_LIST_ARM(V)
     88 #endif
     89 
     90 // List of code stubs only used on MIPS platforms.
     91 #ifdef V8_TARGET_ARCH_MIPS
     92 #define CODE_STUB_LIST_MIPS(V)  \
     93   V(RegExpCEntry)               \
     94   V(DirectCEntry)
     95 #else
     96 #define CODE_STUB_LIST_MIPS(V)
     97 #endif
     98 
     99 // Combined list of code stubs.
    100 #define CODE_STUB_LIST(V)            \
    101   CODE_STUB_LIST_ALL_PLATFORMS(V)    \
    102   CODE_STUB_LIST_ARM(V)              \
    103   CODE_STUB_LIST_MIPS(V)
    104 
    105 // Mode to overwrite BinaryExpression values.
    106 enum OverwriteMode { NO_OVERWRITE, OVERWRITE_LEFT, OVERWRITE_RIGHT };
    107 enum UnaryOverwriteMode { UNARY_OVERWRITE, UNARY_NO_OVERWRITE };
    108 
    109 
    110 // Stub is base classes of all stubs.
    111 class CodeStub BASE_EMBEDDED {
    112  public:
    113   enum Major {
    114 #define DEF_ENUM(name) name,
    115     CODE_STUB_LIST(DEF_ENUM)
    116 #undef DEF_ENUM
    117     NoCache,  // marker for stubs that do custom caching
    118     NUMBER_OF_IDS
    119   };
    120 
    121   // Retrieve the code for the stub. Generate the code if needed.
    122   Handle<Code> GetCode();
    123 
    124   static Major MajorKeyFromKey(uint32_t key) {
    125     return static_cast<Major>(MajorKeyBits::decode(key));
    126   }
    127   static int MinorKeyFromKey(uint32_t key) {
    128     return MinorKeyBits::decode(key);
    129   }
    130 
    131   // Gets the major key from a code object that is a code stub or binary op IC.
    132   static Major GetMajorKey(Code* code_stub) {
    133     return static_cast<Major>(code_stub->major_key());
    134   }
    135 
    136   static const char* MajorName(Major major_key, bool allow_unknown_keys);
    137 
    138   virtual ~CodeStub() {}
    139 
    140   bool CompilingCallsToThisStubIsGCSafe() {
    141     bool is_pregenerated = IsPregenerated();
    142     Code* code = NULL;
    143     CHECK(!is_pregenerated || FindCodeInCache(&code));
    144     return is_pregenerated;
    145   }
    146 
    147   // See comment above, where Instanceof is defined.
    148   virtual bool IsPregenerated() { return false; }
    149 
    150   static void GenerateStubsAheadOfTime();
    151   static void GenerateFPStubs();
    152 
    153   // Some stubs put untagged junk on the stack that cannot be scanned by the
    154   // GC.  This means that we must be statically sure that no GC can occur while
    155   // they are running.  If that is the case they should override this to return
    156   // true, which will cause an assertion if we try to call something that can
    157   // GC or if we try to put a stack frame on top of the junk, which would not
    158   // result in a traversable stack.
    159   virtual bool SometimesSetsUpAFrame() { return true; }
    160 
    161   // Lookup the code in the (possibly custom) cache.
    162   bool FindCodeInCache(Code** code_out);
    163 
    164  protected:
    165   static const int kMajorBits = 6;
    166   static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
    167 
    168  private:
    169   // Nonvirtual wrapper around the stub-specific Generate function.  Call
    170   // this function to set up the macro assembler and generate the code.
    171   void GenerateCode(MacroAssembler* masm);
    172 
    173   // Generates the assembler code for the stub.
    174   virtual void Generate(MacroAssembler* masm) = 0;
    175 
    176   // Perform bookkeeping required after code generation when stub code is
    177   // initially generated.
    178   void RecordCodeGeneration(Code* code, MacroAssembler* masm);
    179 
    180   // Finish the code object after it has been generated.
    181   virtual void FinishCode(Handle<Code> code) { }
    182 
    183   // Activate newly generated stub. Is called after
    184   // registering stub in the stub cache.
    185   virtual void Activate(Code* code) { }
    186 
    187   // Returns information for computing the number key.
    188   virtual Major MajorKey() = 0;
    189   virtual int MinorKey() = 0;
    190 
    191   // BinaryOpStub needs to override this.
    192   virtual int GetCodeKind();
    193 
    194   // BinaryOpStub needs to override this.
    195   virtual InlineCacheState GetICState() {
    196     return UNINITIALIZED;
    197   }
    198 
    199   // Add the code to a specialized cache, specific to an individual
    200   // stub type. Please note, this method must add the code object to a
    201   // roots object, otherwise we will remove the code during GC.
    202   virtual void AddToSpecialCache(Handle<Code> new_object) { }
    203 
    204   // Find code in a specialized cache, work is delegated to the specific stub.
    205   virtual bool FindCodeInSpecialCache(Code** code_out) { return false; }
    206 
    207   // If a stub uses a special cache override this.
    208   virtual bool UseSpecialCache() { return false; }
    209 
    210   // Returns a name for logging/debugging purposes.
    211   SmartArrayPointer<const char> GetName();
    212   virtual void PrintName(StringStream* stream);
    213 
    214   // Returns whether the code generated for this stub needs to be allocated as
    215   // a fixed (non-moveable) code object.
    216   virtual bool NeedsImmovableCode() { return false; }
    217 
    218   // Computes the key based on major and minor.
    219   uint32_t GetKey() {
    220     ASSERT(static_cast<int>(MajorKey()) < NUMBER_OF_IDS);
    221     return MinorKeyBits::encode(MinorKey()) |
    222            MajorKeyBits::encode(MajorKey());
    223   }
    224 
    225   class MajorKeyBits: public BitField<uint32_t, 0, kMajorBits> {};
    226   class MinorKeyBits: public BitField<uint32_t, kMajorBits, kMinorBits> {};
    227 
    228   friend class BreakPointIterator;
    229 };
    230 
    231 
    232 // Helper interface to prepare to/restore after making runtime calls.
    233 class RuntimeCallHelper {
    234  public:
    235   virtual ~RuntimeCallHelper() {}
    236 
    237   virtual void BeforeCall(MacroAssembler* masm) const = 0;
    238 
    239   virtual void AfterCall(MacroAssembler* masm) const = 0;
    240 
    241  protected:
    242   RuntimeCallHelper() {}
    243 
    244  private:
    245   DISALLOW_COPY_AND_ASSIGN(RuntimeCallHelper);
    246 };
    247 
    248 } }  // namespace v8::internal
    249 
    250 #if V8_TARGET_ARCH_IA32
    251 #include "ia32/code-stubs-ia32.h"
    252 #elif V8_TARGET_ARCH_X64
    253 #include "x64/code-stubs-x64.h"
    254 #elif V8_TARGET_ARCH_ARM
    255 #include "arm/code-stubs-arm.h"
    256 #elif V8_TARGET_ARCH_MIPS
    257 #include "mips/code-stubs-mips.h"
    258 #else
    259 #error Unsupported target architecture.
    260 #endif
    261 
    262 namespace v8 {
    263 namespace internal {
    264 
    265 
    266 // RuntimeCallHelper implementation used in stubs: enters/leaves a
    267 // newly created internal frame before/after the runtime call.
    268 class StubRuntimeCallHelper : public RuntimeCallHelper {
    269  public:
    270   StubRuntimeCallHelper() {}
    271 
    272   virtual void BeforeCall(MacroAssembler* masm) const;
    273 
    274   virtual void AfterCall(MacroAssembler* masm) const;
    275 };
    276 
    277 
    278 // Trivial RuntimeCallHelper implementation.
    279 class NopRuntimeCallHelper : public RuntimeCallHelper {
    280  public:
    281   NopRuntimeCallHelper() {}
    282 
    283   virtual void BeforeCall(MacroAssembler* masm) const {}
    284 
    285   virtual void AfterCall(MacroAssembler* masm) const {}
    286 };
    287 
    288 
    289 class StackCheckStub : public CodeStub {
    290  public:
    291   StackCheckStub() { }
    292 
    293   void Generate(MacroAssembler* masm);
    294 
    295  private:
    296   Major MajorKey() { return StackCheck; }
    297   int MinorKey() { return 0; }
    298 };
    299 
    300 
    301 class InterruptStub : public CodeStub {
    302  public:
    303   InterruptStub() { }
    304 
    305   void Generate(MacroAssembler* masm);
    306 
    307  private:
    308   Major MajorKey() { return Interrupt; }
    309   int MinorKey() { return 0; }
    310 };
    311 
    312 
    313 class ToNumberStub: public CodeStub {
    314  public:
    315   ToNumberStub() { }
    316 
    317   void Generate(MacroAssembler* masm);
    318 
    319  private:
    320   Major MajorKey() { return ToNumber; }
    321   int MinorKey() { return 0; }
    322 };
    323 
    324 
    325 class FastNewClosureStub : public CodeStub {
    326  public:
    327   explicit FastNewClosureStub(LanguageMode language_mode)
    328     : language_mode_(language_mode) { }
    329 
    330   void Generate(MacroAssembler* masm);
    331 
    332  private:
    333   Major MajorKey() { return FastNewClosure; }
    334   int MinorKey() { return language_mode_ == CLASSIC_MODE
    335         ? kNonStrictMode : kStrictMode; }
    336 
    337   LanguageMode language_mode_;
    338 };
    339 
    340 
    341 class FastNewContextStub : public CodeStub {
    342  public:
    343   static const int kMaximumSlots = 64;
    344 
    345   explicit FastNewContextStub(int slots) : slots_(slots) {
    346     ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
    347   }
    348 
    349   void Generate(MacroAssembler* masm);
    350 
    351  private:
    352   int slots_;
    353 
    354   Major MajorKey() { return FastNewContext; }
    355   int MinorKey() { return slots_; }
    356 };
    357 
    358 
    359 class FastNewBlockContextStub : public CodeStub {
    360  public:
    361   static const int kMaximumSlots = 64;
    362 
    363   explicit FastNewBlockContextStub(int slots) : slots_(slots) {
    364     ASSERT(slots_ > 0 && slots_ <= kMaximumSlots);
    365   }
    366 
    367   void Generate(MacroAssembler* masm);
    368 
    369  private:
    370   int slots_;
    371 
    372   Major MajorKey() { return FastNewBlockContext; }
    373   int MinorKey() { return slots_; }
    374 };
    375 
    376 
    377 class FastCloneShallowArrayStub : public CodeStub {
    378  public:
    379   // Maximum length of copied elements array.
    380   static const int kMaximumClonedLength = 8;
    381 
    382   enum Mode {
    383     CLONE_ELEMENTS,
    384     CLONE_DOUBLE_ELEMENTS,
    385     COPY_ON_WRITE_ELEMENTS,
    386     CLONE_ANY_ELEMENTS
    387   };
    388 
    389   FastCloneShallowArrayStub(Mode mode, int length)
    390       : mode_(mode),
    391         length_((mode == COPY_ON_WRITE_ELEMENTS) ? 0 : length) {
    392     ASSERT_GE(length_, 0);
    393     ASSERT_LE(length_, kMaximumClonedLength);
    394   }
    395 
    396   void Generate(MacroAssembler* masm);
    397 
    398  private:
    399   Mode mode_;
    400   int length_;
    401 
    402   Major MajorKey() { return FastCloneShallowArray; }
    403   int MinorKey() {
    404     ASSERT(mode_ == 0 || mode_ == 1 || mode_ == 2 || mode_ == 3);
    405     return length_ * 4 +  mode_;
    406   }
    407 };
    408 
    409 
    410 class FastCloneShallowObjectStub : public CodeStub {
    411  public:
    412   // Maximum number of properties in copied object.
    413   static const int kMaximumClonedProperties = 6;
    414 
    415   explicit FastCloneShallowObjectStub(int length) : length_(length) {
    416     ASSERT_GE(length_, 0);
    417     ASSERT_LE(length_, kMaximumClonedProperties);
    418   }
    419 
    420   void Generate(MacroAssembler* masm);
    421 
    422  private:
    423   int length_;
    424 
    425   Major MajorKey() { return FastCloneShallowObject; }
    426   int MinorKey() { return length_; }
    427 };
    428 
    429 
    430 class InstanceofStub: public CodeStub {
    431  public:
    432   enum Flags {
    433     kNoFlags = 0,
    434     kArgsInRegisters = 1 << 0,
    435     kCallSiteInlineCheck = 1 << 1,
    436     kReturnTrueFalseObject = 1 << 2
    437   };
    438 
    439   explicit InstanceofStub(Flags flags) : flags_(flags) { }
    440 
    441   static Register left();
    442   static Register right();
    443 
    444   void Generate(MacroAssembler* masm);
    445 
    446  private:
    447   Major MajorKey() { return Instanceof; }
    448   int MinorKey() { return static_cast<int>(flags_); }
    449 
    450   bool HasArgsInRegisters() const {
    451     return (flags_ & kArgsInRegisters) != 0;
    452   }
    453 
    454   bool HasCallSiteInlineCheck() const {
    455     return (flags_ & kCallSiteInlineCheck) != 0;
    456   }
    457 
    458   bool ReturnTrueFalseObject() const {
    459     return (flags_ & kReturnTrueFalseObject) != 0;
    460   }
    461 
    462   virtual void PrintName(StringStream* stream);
    463 
    464   Flags flags_;
    465 };
    466 
    467 
    468 class MathPowStub: public CodeStub {
    469  public:
    470   enum ExponentType { INTEGER, DOUBLE, TAGGED, ON_STACK};
    471 
    472   explicit MathPowStub(ExponentType exponent_type)
    473       : exponent_type_(exponent_type) { }
    474   virtual void Generate(MacroAssembler* masm);
    475 
    476  private:
    477   virtual CodeStub::Major MajorKey() { return MathPow; }
    478   virtual int MinorKey() { return exponent_type_; }
    479 
    480   ExponentType exponent_type_;
    481 };
    482 
    483 
    484 class ICCompareStub: public CodeStub {
    485  public:
    486   ICCompareStub(Token::Value op, CompareIC::State state)
    487       : op_(op), state_(state) {
    488     ASSERT(Token::IsCompareOp(op));
    489   }
    490 
    491   virtual void Generate(MacroAssembler* masm);
    492 
    493   void set_known_map(Handle<Map> map) { known_map_ = map; }
    494 
    495  private:
    496   class OpField: public BitField<int, 0, 3> { };
    497   class StateField: public BitField<int, 3, 5> { };
    498 
    499   virtual void FinishCode(Handle<Code> code) {
    500     code->set_compare_state(state_);
    501   }
    502 
    503   virtual CodeStub::Major MajorKey() { return CompareIC; }
    504   virtual int MinorKey();
    505 
    506   virtual int GetCodeKind() { return Code::COMPARE_IC; }
    507 
    508   void GenerateSmis(MacroAssembler* masm);
    509   void GenerateHeapNumbers(MacroAssembler* masm);
    510   void GenerateSymbols(MacroAssembler* masm);
    511   void GenerateStrings(MacroAssembler* masm);
    512   void GenerateObjects(MacroAssembler* masm);
    513   void GenerateMiss(MacroAssembler* masm);
    514   void GenerateKnownObjects(MacroAssembler* masm);
    515 
    516   bool strict() const { return op_ == Token::EQ_STRICT; }
    517   Condition GetCondition() const { return CompareIC::ComputeCondition(op_); }
    518 
    519   virtual void AddToSpecialCache(Handle<Code> new_object);
    520   virtual bool FindCodeInSpecialCache(Code** code_out);
    521   virtual bool UseSpecialCache() { return state_ == CompareIC::KNOWN_OBJECTS; }
    522 
    523   Token::Value op_;
    524   CompareIC::State state_;
    525   Handle<Map> known_map_;
    526 };
    527 
    528 
    529 // Flags that control the compare stub code generation.
    530 enum CompareFlags {
    531   NO_COMPARE_FLAGS = 0,
    532   NO_SMI_COMPARE_IN_STUB = 1 << 0,
    533   NO_NUMBER_COMPARE_IN_STUB = 1 << 1,
    534   CANT_BOTH_BE_NAN = 1 << 2
    535 };
    536 
    537 
    538 enum NaNInformation {
    539   kBothCouldBeNaN,
    540   kCantBothBeNaN
    541 };
    542 
    543 
    544 class CompareStub: public CodeStub {
    545  public:
    546   CompareStub(Condition cc,
    547               bool strict,
    548               CompareFlags flags,
    549               Register lhs,
    550               Register rhs) :
    551      cc_(cc),
    552       strict_(strict),
    553       never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
    554       include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
    555       include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
    556       lhs_(lhs),
    557       rhs_(rhs) { }
    558 
    559   CompareStub(Condition cc,
    560               bool strict,
    561               CompareFlags flags) :
    562       cc_(cc),
    563       strict_(strict),
    564       never_nan_nan_((flags & CANT_BOTH_BE_NAN) != 0),
    565       include_number_compare_((flags & NO_NUMBER_COMPARE_IN_STUB) == 0),
    566       include_smi_compare_((flags & NO_SMI_COMPARE_IN_STUB) == 0),
    567       lhs_(no_reg),
    568       rhs_(no_reg) { }
    569 
    570   void Generate(MacroAssembler* masm);
    571 
    572  private:
    573   Condition cc_;
    574   bool strict_;
    575   // Only used for 'equal' comparisons.  Tells the stub that we already know
    576   // that at least one side of the comparison is not NaN.  This allows the
    577   // stub to use object identity in the positive case.  We ignore it when
    578   // generating the minor key for other comparisons to avoid creating more
    579   // stubs.
    580   bool never_nan_nan_;
    581   // Do generate the number comparison code in the stub. Stubs without number
    582   // comparison code is used when the number comparison has been inlined, and
    583   // the stub will be called if one of the operands is not a number.
    584   bool include_number_compare_;
    585 
    586   // Generate the comparison code for two smi operands in the stub.
    587   bool include_smi_compare_;
    588 
    589   // Register holding the left hand side of the comparison if the stub gives
    590   // a choice, no_reg otherwise.
    591 
    592   Register lhs_;
    593   // Register holding the right hand side of the comparison if the stub gives
    594   // a choice, no_reg otherwise.
    595   Register rhs_;
    596 
    597   // Encoding of the minor key in 16 bits.
    598   class StrictField: public BitField<bool, 0, 1> {};
    599   class NeverNanNanField: public BitField<bool, 1, 1> {};
    600   class IncludeNumberCompareField: public BitField<bool, 2, 1> {};
    601   class IncludeSmiCompareField: public  BitField<bool, 3, 1> {};
    602   class RegisterField: public BitField<bool, 4, 1> {};
    603   class ConditionField: public BitField<int, 5, 11> {};
    604 
    605   Major MajorKey() { return Compare; }
    606 
    607   int MinorKey();
    608 
    609   virtual int GetCodeKind() { return Code::COMPARE_IC; }
    610   virtual void FinishCode(Handle<Code> code) {
    611     code->set_compare_state(CompareIC::GENERIC);
    612   }
    613 
    614   // Branch to the label if the given object isn't a symbol.
    615   void BranchIfNonSymbol(MacroAssembler* masm,
    616                          Label* label,
    617                          Register object,
    618                          Register scratch);
    619 
    620   // Unfortunately you have to run without snapshots to see most of these
    621   // names in the profile since most compare stubs end up in the snapshot.
    622   virtual void PrintName(StringStream* stream);
    623 };
    624 
    625 
    626 class CEntryStub : public CodeStub {
    627  public:
    628   explicit CEntryStub(int result_size,
    629                       SaveFPRegsMode save_doubles = kDontSaveFPRegs)
    630       : result_size_(result_size), save_doubles_(save_doubles) { }
    631 
    632   void Generate(MacroAssembler* masm);
    633 
    634   // The version of this stub that doesn't save doubles is generated ahead of
    635   // time, so it's OK to call it from other stubs that can't cope with GC during
    636   // their code generation.  On machines that always have gp registers (x64) we
    637   // can generate both variants ahead of time.
    638   virtual bool IsPregenerated();
    639   static void GenerateAheadOfTime();
    640 
    641  private:
    642   void GenerateCore(MacroAssembler* masm,
    643                     Label* throw_normal_exception,
    644                     Label* throw_termination_exception,
    645                     Label* throw_out_of_memory_exception,
    646                     bool do_gc,
    647                     bool always_allocate_scope);
    648 
    649   // Number of pointers/values returned.
    650   const int result_size_;
    651   SaveFPRegsMode save_doubles_;
    652 
    653   Major MajorKey() { return CEntry; }
    654   int MinorKey();
    655 
    656   bool NeedsImmovableCode();
    657 };
    658 
    659 
    660 class JSEntryStub : public CodeStub {
    661  public:
    662   JSEntryStub() { }
    663 
    664   void Generate(MacroAssembler* masm) { GenerateBody(masm, false); }
    665 
    666  protected:
    667   void GenerateBody(MacroAssembler* masm, bool is_construct);
    668 
    669  private:
    670   Major MajorKey() { return JSEntry; }
    671   int MinorKey() { return 0; }
    672 
    673   virtual void FinishCode(Handle<Code> code);
    674 
    675   int handler_offset_;
    676 };
    677 
    678 
    679 class JSConstructEntryStub : public JSEntryStub {
    680  public:
    681   JSConstructEntryStub() { }
    682 
    683   void Generate(MacroAssembler* masm) { GenerateBody(masm, true); }
    684 
    685  private:
    686   int MinorKey() { return 1; }
    687 
    688   virtual void PrintName(StringStream* stream) {
    689     stream->Add("JSConstructEntryStub");
    690   }
    691 };
    692 
    693 
    694 class ArgumentsAccessStub: public CodeStub {
    695  public:
    696   enum Type {
    697     READ_ELEMENT,
    698     NEW_NON_STRICT_FAST,
    699     NEW_NON_STRICT_SLOW,
    700     NEW_STRICT
    701   };
    702 
    703   explicit ArgumentsAccessStub(Type type) : type_(type) { }
    704 
    705  private:
    706   Type type_;
    707 
    708   Major MajorKey() { return ArgumentsAccess; }
    709   int MinorKey() { return type_; }
    710 
    711   void Generate(MacroAssembler* masm);
    712   void GenerateReadElement(MacroAssembler* masm);
    713   void GenerateNewStrict(MacroAssembler* masm);
    714   void GenerateNewNonStrictFast(MacroAssembler* masm);
    715   void GenerateNewNonStrictSlow(MacroAssembler* masm);
    716 
    717   virtual void PrintName(StringStream* stream);
    718 };
    719 
    720 
    721 class RegExpExecStub: public CodeStub {
    722  public:
    723   RegExpExecStub() { }
    724 
    725  private:
    726   Major MajorKey() { return RegExpExec; }
    727   int MinorKey() { return 0; }
    728 
    729   void Generate(MacroAssembler* masm);
    730 };
    731 
    732 
    733 class RegExpConstructResultStub: public CodeStub {
    734  public:
    735   RegExpConstructResultStub() { }
    736 
    737  private:
    738   Major MajorKey() { return RegExpConstructResult; }
    739   int MinorKey() { return 0; }
    740 
    741   void Generate(MacroAssembler* masm);
    742 };
    743 
    744 
    745 class CallFunctionStub: public CodeStub {
    746  public:
    747   CallFunctionStub(int argc, CallFunctionFlags flags)
    748       : argc_(argc), flags_(flags) { }
    749 
    750   void Generate(MacroAssembler* masm);
    751 
    752   virtual void FinishCode(Handle<Code> code) {
    753     code->set_has_function_cache(RecordCallTarget());
    754   }
    755 
    756   static int ExtractArgcFromMinorKey(int minor_key) {
    757     return ArgcBits::decode(minor_key);
    758   }
    759 
    760  private:
    761   int argc_;
    762   CallFunctionFlags flags_;
    763 
    764   virtual void PrintName(StringStream* stream);
    765 
    766   // Minor key encoding in 32 bits with Bitfield <Type, shift, size>.
    767   class FlagBits: public BitField<CallFunctionFlags, 0, 2> {};
    768   class ArgcBits: public BitField<unsigned, 2, 32 - 2> {};
    769 
    770   Major MajorKey() { return CallFunction; }
    771   int MinorKey() {
    772     // Encode the parameters in a unique 32 bit value.
    773     return FlagBits::encode(flags_) | ArgcBits::encode(argc_);
    774   }
    775 
    776   bool ReceiverMightBeImplicit() {
    777     return (flags_ & RECEIVER_MIGHT_BE_IMPLICIT) != 0;
    778   }
    779 
    780   bool RecordCallTarget() {
    781     return (flags_ & RECORD_CALL_TARGET) != 0;
    782   }
    783 };
    784 
    785 
    786 class CallConstructStub: public CodeStub {
    787  public:
    788   explicit CallConstructStub(CallFunctionFlags flags) : flags_(flags) {}
    789 
    790   void Generate(MacroAssembler* masm);
    791 
    792   virtual void FinishCode(Handle<Code> code) {
    793     code->set_has_function_cache(RecordCallTarget());
    794   }
    795 
    796  private:
    797   CallFunctionFlags flags_;
    798 
    799   virtual void PrintName(StringStream* stream);
    800 
    801   Major MajorKey() { return CallConstruct; }
    802   int MinorKey() { return flags_; }
    803 
    804   bool RecordCallTarget() {
    805     return (flags_ & RECORD_CALL_TARGET) != 0;
    806   }
    807 };
    808 
    809 
    810 enum StringIndexFlags {
    811   // Accepts smis or heap numbers.
    812   STRING_INDEX_IS_NUMBER,
    813 
    814   // Accepts smis or heap numbers that are valid array indices
    815   // (ECMA-262 15.4). Invalid indices are reported as being out of
    816   // range.
    817   STRING_INDEX_IS_ARRAY_INDEX
    818 };
    819 
    820 
    821 // Generates code implementing String.prototype.charCodeAt.
    822 //
    823 // Only supports the case when the receiver is a string and the index
    824 // is a number (smi or heap number) that is a valid index into the
    825 // string. Additional index constraints are specified by the
    826 // flags. Otherwise, bails out to the provided labels.
    827 //
    828 // Register usage: |object| may be changed to another string in a way
    829 // that doesn't affect charCodeAt/charAt semantics, |index| is
    830 // preserved, |scratch| and |result| are clobbered.
    831 class StringCharCodeAtGenerator {
    832  public:
    833   StringCharCodeAtGenerator(Register object,
    834                             Register index,
    835                             Register result,
    836                             Label* receiver_not_string,
    837                             Label* index_not_number,
    838                             Label* index_out_of_range,
    839                             StringIndexFlags index_flags)
    840       : object_(object),
    841         index_(index),
    842         result_(result),
    843         receiver_not_string_(receiver_not_string),
    844         index_not_number_(index_not_number),
    845         index_out_of_range_(index_out_of_range),
    846         index_flags_(index_flags) {
    847     ASSERT(!result_.is(object_));
    848     ASSERT(!result_.is(index_));
    849   }
    850 
    851   // Generates the fast case code. On the fallthrough path |result|
    852   // register contains the result.
    853   void GenerateFast(MacroAssembler* masm);
    854 
    855   // Generates the slow case code. Must not be naturally
    856   // reachable. Expected to be put after a ret instruction (e.g., in
    857   // deferred code). Always jumps back to the fast case.
    858   void GenerateSlow(MacroAssembler* masm,
    859                     const RuntimeCallHelper& call_helper);
    860 
    861  private:
    862   Register object_;
    863   Register index_;
    864   Register result_;
    865 
    866   Label* receiver_not_string_;
    867   Label* index_not_number_;
    868   Label* index_out_of_range_;
    869 
    870   StringIndexFlags index_flags_;
    871 
    872   Label call_runtime_;
    873   Label index_not_smi_;
    874   Label got_smi_index_;
    875   Label exit_;
    876 
    877   DISALLOW_COPY_AND_ASSIGN(StringCharCodeAtGenerator);
    878 };
    879 
    880 
    881 // Generates code for creating a one-char string from a char code.
    882 class StringCharFromCodeGenerator {
    883  public:
    884   StringCharFromCodeGenerator(Register code,
    885                               Register result)
    886       : code_(code),
    887         result_(result) {
    888     ASSERT(!code_.is(result_));
    889   }
    890 
    891   // Generates the fast case code. On the fallthrough path |result|
    892   // register contains the result.
    893   void GenerateFast(MacroAssembler* masm);
    894 
    895   // Generates the slow case code. Must not be naturally
    896   // reachable. Expected to be put after a ret instruction (e.g., in
    897   // deferred code). Always jumps back to the fast case.
    898   void GenerateSlow(MacroAssembler* masm,
    899                     const RuntimeCallHelper& call_helper);
    900 
    901  private:
    902   Register code_;
    903   Register result_;
    904 
    905   Label slow_case_;
    906   Label exit_;
    907 
    908   DISALLOW_COPY_AND_ASSIGN(StringCharFromCodeGenerator);
    909 };
    910 
    911 
    912 // Generates code implementing String.prototype.charAt.
    913 //
    914 // Only supports the case when the receiver is a string and the index
    915 // is a number (smi or heap number) that is a valid index into the
    916 // string. Additional index constraints are specified by the
    917 // flags. Otherwise, bails out to the provided labels.
    918 //
    919 // Register usage: |object| may be changed to another string in a way
    920 // that doesn't affect charCodeAt/charAt semantics, |index| is
    921 // preserved, |scratch1|, |scratch2|, and |result| are clobbered.
    922 class StringCharAtGenerator {
    923  public:
    924   StringCharAtGenerator(Register object,
    925                         Register index,
    926                         Register scratch,
    927                         Register result,
    928                         Label* receiver_not_string,
    929                         Label* index_not_number,
    930                         Label* index_out_of_range,
    931                         StringIndexFlags index_flags)
    932       : char_code_at_generator_(object,
    933                                 index,
    934                                 scratch,
    935                                 receiver_not_string,
    936                                 index_not_number,
    937                                 index_out_of_range,
    938                                 index_flags),
    939         char_from_code_generator_(scratch, result) {}
    940 
    941   // Generates the fast case code. On the fallthrough path |result|
    942   // register contains the result.
    943   void GenerateFast(MacroAssembler* masm);
    944 
    945   // Generates the slow case code. Must not be naturally
    946   // reachable. Expected to be put after a ret instruction (e.g., in
    947   // deferred code). Always jumps back to the fast case.
    948   void GenerateSlow(MacroAssembler* masm,
    949                     const RuntimeCallHelper& call_helper);
    950 
    951  private:
    952   StringCharCodeAtGenerator char_code_at_generator_;
    953   StringCharFromCodeGenerator char_from_code_generator_;
    954 
    955   DISALLOW_COPY_AND_ASSIGN(StringCharAtGenerator);
    956 };
    957 
    958 
    959 class AllowStubCallsScope {
    960  public:
    961   AllowStubCallsScope(MacroAssembler* masm, bool allow)
    962        : masm_(masm), previous_allow_(masm->allow_stub_calls()) {
    963     masm_->set_allow_stub_calls(allow);
    964   }
    965   ~AllowStubCallsScope() {
    966     masm_->set_allow_stub_calls(previous_allow_);
    967   }
    968 
    969  private:
    970   MacroAssembler* masm_;
    971   bool previous_allow_;
    972 
    973   DISALLOW_COPY_AND_ASSIGN(AllowStubCallsScope);
    974 };
    975 
    976 
    977 class KeyedLoadElementStub : public CodeStub {
    978  public:
    979   explicit KeyedLoadElementStub(ElementsKind elements_kind)
    980       : elements_kind_(elements_kind)
    981   { }
    982 
    983   Major MajorKey() { return KeyedLoadElement; }
    984   int MinorKey() { return elements_kind_; }
    985 
    986   void Generate(MacroAssembler* masm);
    987 
    988  private:
    989   ElementsKind elements_kind_;
    990 
    991   DISALLOW_COPY_AND_ASSIGN(KeyedLoadElementStub);
    992 };
    993 
    994 
    995 class KeyedStoreElementStub : public CodeStub {
    996  public:
    997   KeyedStoreElementStub(bool is_js_array,
    998                         ElementsKind elements_kind,
    999                         KeyedAccessGrowMode grow_mode)
   1000       : is_js_array_(is_js_array),
   1001         elements_kind_(elements_kind),
   1002         grow_mode_(grow_mode) { }
   1003 
   1004   Major MajorKey() { return KeyedStoreElement; }
   1005   int MinorKey() {
   1006     return ElementsKindBits::encode(elements_kind_) |
   1007         IsJSArrayBits::encode(is_js_array_) |
   1008         GrowModeBits::encode(grow_mode_);
   1009   }
   1010 
   1011   void Generate(MacroAssembler* masm);
   1012 
   1013  private:
   1014   class ElementsKindBits: public BitField<ElementsKind,    0, 8> {};
   1015   class GrowModeBits: public BitField<KeyedAccessGrowMode, 8, 1> {};
   1016   class IsJSArrayBits: public BitField<bool,               9, 1> {};
   1017 
   1018   bool is_js_array_;
   1019   ElementsKind elements_kind_;
   1020   KeyedAccessGrowMode grow_mode_;
   1021 
   1022   DISALLOW_COPY_AND_ASSIGN(KeyedStoreElementStub);
   1023 };
   1024 
   1025 
   1026 class ToBooleanStub: public CodeStub {
   1027  public:
   1028   enum Type {
   1029     UNDEFINED,
   1030     BOOLEAN,
   1031     NULL_TYPE,
   1032     SMI,
   1033     SPEC_OBJECT,
   1034     STRING,
   1035     HEAP_NUMBER,
   1036     NUMBER_OF_TYPES
   1037   };
   1038 
   1039   // At most 8 different types can be distinguished, because the Code object
   1040   // only has room for a single byte to hold a set of these types. :-P
   1041   STATIC_ASSERT(NUMBER_OF_TYPES <= 8);
   1042 
   1043   class Types {
   1044    public:
   1045     Types() {}
   1046     explicit Types(byte bits) : set_(bits) {}
   1047 
   1048     bool IsEmpty() const { return set_.IsEmpty(); }
   1049     bool Contains(Type type) const { return set_.Contains(type); }
   1050     void Add(Type type) { set_.Add(type); }
   1051     byte ToByte() const { return set_.ToIntegral(); }
   1052     void Print(StringStream* stream) const;
   1053     void TraceTransition(Types to) const;
   1054     bool Record(Handle<Object> object);
   1055     bool NeedsMap() const;
   1056     bool CanBeUndetectable() const;
   1057 
   1058    private:
   1059     EnumSet<Type, byte> set_;
   1060   };
   1061 
   1062   static Types no_types() { return Types(); }
   1063   static Types all_types() { return Types((1 << NUMBER_OF_TYPES) - 1); }
   1064 
   1065   explicit ToBooleanStub(Register tos, Types types = Types())
   1066       : tos_(tos), types_(types) { }
   1067 
   1068   void Generate(MacroAssembler* masm);
   1069   virtual int GetCodeKind() { return Code::TO_BOOLEAN_IC; }
   1070   virtual void PrintName(StringStream* stream);
   1071 
   1072   virtual bool SometimesSetsUpAFrame() { return false; }
   1073 
   1074  private:
   1075   Major MajorKey() { return ToBoolean; }
   1076   int MinorKey() { return (tos_.code() << NUMBER_OF_TYPES) | types_.ToByte(); }
   1077 
   1078   virtual void FinishCode(Handle<Code> code) {
   1079     code->set_to_boolean_state(types_.ToByte());
   1080   }
   1081 
   1082   void CheckOddball(MacroAssembler* masm,
   1083                     Type type,
   1084                     Heap::RootListIndex value,
   1085                     bool result);
   1086   void GenerateTypeTransition(MacroAssembler* masm);
   1087 
   1088   Register tos_;
   1089   Types types_;
   1090 };
   1091 
   1092 
   1093 class ElementsTransitionAndStoreStub : public CodeStub {
   1094  public:
   1095   ElementsTransitionAndStoreStub(ElementsKind from,
   1096                                  ElementsKind to,
   1097                                  bool is_jsarray,
   1098                                  StrictModeFlag strict_mode,
   1099                                  KeyedAccessGrowMode grow_mode)
   1100       : from_(from),
   1101         to_(to),
   1102         is_jsarray_(is_jsarray),
   1103         strict_mode_(strict_mode),
   1104         grow_mode_(grow_mode) {}
   1105 
   1106  private:
   1107   class FromBits:       public BitField<ElementsKind,      0, 8> {};
   1108   class ToBits:         public BitField<ElementsKind,      8, 8> {};
   1109   class IsJSArrayBits:  public BitField<bool,              16, 1> {};
   1110   class StrictModeBits: public BitField<StrictModeFlag,    17, 1> {};
   1111   class GrowModeBits: public BitField<KeyedAccessGrowMode, 18, 1> {};
   1112 
   1113   Major MajorKey() { return ElementsTransitionAndStore; }
   1114   int MinorKey() {
   1115     return FromBits::encode(from_) |
   1116         ToBits::encode(to_) |
   1117         IsJSArrayBits::encode(is_jsarray_) |
   1118         StrictModeBits::encode(strict_mode_) |
   1119         GrowModeBits::encode(grow_mode_);
   1120   }
   1121 
   1122   void Generate(MacroAssembler* masm);
   1123 
   1124   ElementsKind from_;
   1125   ElementsKind to_;
   1126   bool is_jsarray_;
   1127   StrictModeFlag strict_mode_;
   1128   KeyedAccessGrowMode grow_mode_;
   1129 
   1130   DISALLOW_COPY_AND_ASSIGN(ElementsTransitionAndStoreStub);
   1131 };
   1132 
   1133 
   1134 class StoreArrayLiteralElementStub : public CodeStub {
   1135  public:
   1136   explicit StoreArrayLiteralElementStub() {}
   1137 
   1138  private:
   1139   Major MajorKey() { return StoreArrayLiteralElement; }
   1140   int MinorKey() { return 0; }
   1141 
   1142   void Generate(MacroAssembler* masm);
   1143 
   1144   DISALLOW_COPY_AND_ASSIGN(StoreArrayLiteralElementStub);
   1145 };
   1146 
   1147 } }  // namespace v8::internal
   1148 
   1149 #endif  // V8_CODE_STUBS_H_
   1150