Home | History | Annotate | Download | only in src
      1 // Copyright (c) 1994-2006 Sun Microsystems Inc.
      2 // All Rights Reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 // - Redistributions of source code must retain the above copyright notice,
      9 // this list of conditions and the following disclaimer.
     10 //
     11 // - Redistribution in binary form must reproduce the above copyright
     12 // notice, this list of conditions and the following disclaimer in the
     13 // documentation and/or other materials provided with the distribution.
     14 //
     15 // - Neither the name of Sun Microsystems or the names of contributors may
     16 // be used to endorse or promote products derived from this software without
     17 // specific prior written permission.
     18 //
     19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
     20 // IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     21 // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     23 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     24 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     26 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
     27 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
     28 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     29 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30 
     31 // The original source code covered by the above license above has been
     32 // modified significantly by Google Inc.
     33 // Copyright 2012 the V8 project authors. All rights reserved.
     34 
     35 #ifndef V8_ASSEMBLER_H_
     36 #define V8_ASSEMBLER_H_
     37 
     38 #include "v8.h"
     39 
     40 #include "allocation.h"
     41 #include "builtins.h"
     42 #include "gdb-jit.h"
     43 #include "isolate.h"
     44 #include "runtime.h"
     45 #include "token.h"
     46 
     47 namespace v8 {
     48 
     49 class ApiFunction;
     50 
     51 namespace internal {
     52 
     53 class StatsCounter;
     54 // -----------------------------------------------------------------------------
     55 // Platform independent assembler base class.
     56 
     57 class AssemblerBase: public Malloced {
     58  public:
     59   AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
     60   virtual ~AssemblerBase();
     61 
     62   Isolate* isolate() const { return isolate_; }
     63   int jit_cookie() const { return jit_cookie_; }
     64 
     65   bool emit_debug_code() const { return emit_debug_code_; }
     66   void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
     67 
     68   bool predictable_code_size() const { return predictable_code_size_; }
     69   void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
     70 
     71   uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
     72   void set_enabled_cpu_features(uint64_t features) {
     73     enabled_cpu_features_ = features;
     74   }
     75   bool IsEnabled(CpuFeature f) {
     76     return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
     77   }
     78 
     79   // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
     80   // cross-snapshotting.
     81   static void QuietNaN(HeapObject* nan) { }
     82 
     83   int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
     84 
     85   static const int kMinimalBufferSize = 4*KB;
     86 
     87  protected:
     88   // The buffer into which code and relocation info are generated. It could
     89   // either be owned by the assembler or be provided externally.
     90   byte* buffer_;
     91   int buffer_size_;
     92   bool own_buffer_;
     93 
     94   // The program counter, which points into the buffer above and moves forward.
     95   byte* pc_;
     96 
     97  private:
     98   Isolate* isolate_;
     99   int jit_cookie_;
    100   uint64_t enabled_cpu_features_;
    101   bool emit_debug_code_;
    102   bool predictable_code_size_;
    103 };
    104 
    105 
    106 // Avoids using instructions that vary in size in unpredictable ways between the
    107 // snapshot and the running VM.
    108 class PredictableCodeSizeScope {
    109  public:
    110   PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
    111   ~PredictableCodeSizeScope();
    112 
    113  private:
    114   AssemblerBase* assembler_;
    115   int expected_size_;
    116   int start_offset_;
    117   bool old_value_;
    118 };
    119 
    120 
    121 // Enable a specified feature within a scope.
    122 class CpuFeatureScope BASE_EMBEDDED {
    123  public:
    124 #ifdef DEBUG
    125   CpuFeatureScope(AssemblerBase* assembler, CpuFeature f);
    126   ~CpuFeatureScope();
    127 
    128  private:
    129   AssemblerBase* assembler_;
    130   uint64_t old_enabled_;
    131 #else
    132   CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {}
    133 #endif
    134 };
    135 
    136 
    137 // Enable a unsupported feature within a scope for cross-compiling for a
    138 // different CPU.
    139 class PlatformFeatureScope BASE_EMBEDDED {
    140  public:
    141   explicit PlatformFeatureScope(CpuFeature f);
    142   ~PlatformFeatureScope();
    143 
    144  private:
    145   uint64_t old_cross_compile_;
    146 };
    147 
    148 
    149 // -----------------------------------------------------------------------------
    150 // Labels represent pc locations; they are typically jump or call targets.
    151 // After declaration, a label can be freely used to denote known or (yet)
    152 // unknown pc location. Assembler::bind() is used to bind a label to the
    153 // current pc. A label can be bound only once.
    154 
    155 class Label BASE_EMBEDDED {
    156  public:
    157   enum Distance {
    158     kNear, kFar
    159   };
    160 
    161   INLINE(Label()) {
    162     Unuse();
    163     UnuseNear();
    164   }
    165 
    166   INLINE(~Label()) {
    167     ASSERT(!is_linked());
    168     ASSERT(!is_near_linked());
    169   }
    170 
    171   INLINE(void Unuse()) { pos_ = 0; }
    172   INLINE(void UnuseNear()) { near_link_pos_ = 0; }
    173 
    174   INLINE(bool is_bound() const) { return pos_ <  0; }
    175   INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; }
    176   INLINE(bool is_linked() const) { return pos_ >  0; }
    177   INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; }
    178 
    179   // Returns the position of bound or linked labels. Cannot be used
    180   // for unused labels.
    181   int pos() const;
    182   int near_link_pos() const { return near_link_pos_ - 1; }
    183 
    184  private:
    185   // pos_ encodes both the binding state (via its sign)
    186   // and the binding position (via its value) of a label.
    187   //
    188   // pos_ <  0  bound label, pos() returns the jump target position
    189   // pos_ == 0  unused label
    190   // pos_ >  0  linked label, pos() returns the last reference position
    191   int pos_;
    192 
    193   // Behaves like |pos_| in the "> 0" case, but for near jumps to this label.
    194   int near_link_pos_;
    195 
    196   void bind_to(int pos)  {
    197     pos_ = -pos - 1;
    198     ASSERT(is_bound());
    199   }
    200   void link_to(int pos, Distance distance = kFar) {
    201     if (distance == kNear) {
    202       near_link_pos_ = pos + 1;
    203       ASSERT(is_near_linked());
    204     } else {
    205       pos_ = pos + 1;
    206       ASSERT(is_linked());
    207     }
    208   }
    209 
    210   friend class Assembler;
    211   friend class Displacement;
    212   friend class RegExpMacroAssemblerIrregexp;
    213 };
    214 
    215 
    216 enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
    217 
    218 
    219 // -----------------------------------------------------------------------------
    220 // Relocation information
    221 
    222 
    223 // Relocation information consists of the address (pc) of the datum
    224 // to which the relocation information applies, the relocation mode
    225 // (rmode), and an optional data field. The relocation mode may be
    226 // "descriptive" and not indicate a need for relocation, but simply
    227 // describe a property of the datum. Such rmodes are useful for GC
    228 // and nice disassembly output.
    229 
    230 class RelocInfo BASE_EMBEDDED {
    231  public:
    232   // The constant kNoPosition is used with the collecting of source positions
    233   // in the relocation information. Two types of source positions are collected
    234   // "position" (RelocMode position) and "statement position" (RelocMode
    235   // statement_position). The "position" is collected at places in the source
    236   // code which are of interest when making stack traces to pin-point the source
    237   // location of a stack frame as close as possible. The "statement position" is
    238   // collected at the beginning at each statement, and is used to indicate
    239   // possible break locations. kNoPosition is used to indicate an
    240   // invalid/uninitialized position value.
    241   static const int kNoPosition = -1;
    242 
    243   // This string is used to add padding comments to the reloc info in cases
    244   // where we are not sure to have enough space for patching in during
    245   // lazy deoptimization. This is the case if we have indirect calls for which
    246   // we do not normally record relocation info.
    247   static const char* const kFillerCommentString;
    248 
    249   // The minimum size of a comment is equal to three bytes for the extra tagged
    250   // pc + the tag for the data, and kPointerSize for the actual pointer to the
    251   // comment.
    252   static const int kMinRelocCommentSize = 3 + kPointerSize;
    253 
    254   // The maximum size for a call instruction including pc-jump.
    255   static const int kMaxCallSize = 6;
    256 
    257   // The maximum pc delta that will use the short encoding.
    258   static const int kMaxSmallPCDelta;
    259 
    260   enum Mode {
    261     // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
    262     CODE_TARGET,  // Code target which is not any of the above.
    263     CODE_TARGET_WITH_ID,
    264     CONSTRUCT_CALL,  // code target that is a call to a JavaScript constructor.
    265     CODE_TARGET_CONTEXT,  // Code target used for contextual loads and stores.
    266     DEBUG_BREAK,  // Code target for the debugger statement.
    267     EMBEDDED_OBJECT,
    268     CELL,
    269 
    270     // Everything after runtime_entry (inclusive) is not GC'ed.
    271     RUNTIME_ENTRY,
    272     JS_RETURN,  // Marks start of the ExitJSFrame code.
    273     COMMENT,
    274     POSITION,  // See comment for kNoPosition above.
    275     STATEMENT_POSITION,  // See comment for kNoPosition above.
    276     DEBUG_BREAK_SLOT,  // Additional code inserted for debug break slot.
    277     EXTERNAL_REFERENCE,  // The address of an external C++ function.
    278     INTERNAL_REFERENCE,  // An address inside the same function.
    279 
    280     // Marks a constant pool. Only used on ARM.
    281     // It uses a custom noncompact encoding.
    282     CONST_POOL,
    283 
    284     // add more as needed
    285     // Pseudo-types
    286     NUMBER_OF_MODES,  // There are at most 15 modes with noncompact encoding.
    287     NONE32,  // never recorded 32-bit value
    288     NONE64,  // never recorded 64-bit value
    289     CODE_AGE_SEQUENCE,  // Not stored in RelocInfo array, used explictly by
    290                         // code aging.
    291     FIRST_REAL_RELOC_MODE = CODE_TARGET,
    292     LAST_REAL_RELOC_MODE = CONST_POOL,
    293     FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
    294     LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
    295     LAST_CODE_ENUM = DEBUG_BREAK,
    296     LAST_GCED_ENUM = CELL,
    297     // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding.
    298     LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID,
    299     LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
    300   };
    301 
    302 
    303   RelocInfo() {}
    304 
    305   RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host)
    306       : pc_(pc), rmode_(rmode), data_(data), host_(host) {
    307   }
    308   RelocInfo(byte* pc, double data64)
    309       : pc_(pc), rmode_(NONE64), data64_(data64), host_(NULL) {
    310   }
    311 
    312   static inline bool IsRealRelocMode(Mode mode) {
    313     return mode >= FIRST_REAL_RELOC_MODE &&
    314         mode <= LAST_REAL_RELOC_MODE;
    315   }
    316   static inline bool IsPseudoRelocMode(Mode mode) {
    317     ASSERT(!IsRealRelocMode(mode));
    318     return mode >= FIRST_PSEUDO_RELOC_MODE &&
    319         mode <= LAST_PSEUDO_RELOC_MODE;
    320   }
    321   static inline bool IsConstructCall(Mode mode) {
    322     return mode == CONSTRUCT_CALL;
    323   }
    324   static inline bool IsCodeTarget(Mode mode) {
    325     return mode <= LAST_CODE_ENUM;
    326   }
    327   static inline bool IsEmbeddedObject(Mode mode) {
    328     return mode == EMBEDDED_OBJECT;
    329   }
    330   static inline bool IsRuntimeEntry(Mode mode) {
    331     return mode == RUNTIME_ENTRY;
    332   }
    333   // Is the relocation mode affected by GC?
    334   static inline bool IsGCRelocMode(Mode mode) {
    335     return mode <= LAST_GCED_ENUM;
    336   }
    337   static inline bool IsJSReturn(Mode mode) {
    338     return mode == JS_RETURN;
    339   }
    340   static inline bool IsComment(Mode mode) {
    341     return mode == COMMENT;
    342   }
    343   static inline bool IsConstPool(Mode mode) {
    344     return mode == CONST_POOL;
    345   }
    346   static inline bool IsPosition(Mode mode) {
    347     return mode == POSITION || mode == STATEMENT_POSITION;
    348   }
    349   static inline bool IsStatementPosition(Mode mode) {
    350     return mode == STATEMENT_POSITION;
    351   }
    352   static inline bool IsExternalReference(Mode mode) {
    353     return mode == EXTERNAL_REFERENCE;
    354   }
    355   static inline bool IsInternalReference(Mode mode) {
    356     return mode == INTERNAL_REFERENCE;
    357   }
    358   static inline bool IsDebugBreakSlot(Mode mode) {
    359     return mode == DEBUG_BREAK_SLOT;
    360   }
    361   static inline bool IsNone(Mode mode) {
    362     return mode == NONE32 || mode == NONE64;
    363   }
    364   static inline bool IsCodeAgeSequence(Mode mode) {
    365     return mode == CODE_AGE_SEQUENCE;
    366   }
    367   static inline int ModeMask(Mode mode) { return 1 << mode; }
    368 
    369   // Accessors
    370   byte* pc() const { return pc_; }
    371   void set_pc(byte* pc) { pc_ = pc; }
    372   Mode rmode() const {  return rmode_; }
    373   intptr_t data() const { return data_; }
    374   double data64() const { return data64_; }
    375   uint64_t raw_data64() {
    376     return BitCast<uint64_t>(data64_);
    377   }
    378   Code* host() const { return host_; }
    379 
    380   // Apply a relocation by delta bytes
    381   INLINE(void apply(intptr_t delta));
    382 
    383   // Is the pointer this relocation info refers to coded like a plain pointer
    384   // or is it strange in some way (e.g. relative or patched into a series of
    385   // instructions).
    386   bool IsCodedSpecially();
    387 
    388   // Read/modify the code target in the branch/call instruction
    389   // this relocation applies to;
    390   // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
    391   INLINE(Address target_address());
    392   INLINE(void set_target_address(Address target,
    393                                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
    394   INLINE(Object* target_object());
    395   INLINE(Handle<Object> target_object_handle(Assembler* origin));
    396   INLINE(void set_target_object(Object* target,
    397                                 WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
    398   INLINE(Address target_runtime_entry(Assembler* origin));
    399   INLINE(void set_target_runtime_entry(Address target,
    400                                        WriteBarrierMode mode =
    401                                            UPDATE_WRITE_BARRIER));
    402   INLINE(Cell* target_cell());
    403   INLINE(Handle<Cell> target_cell_handle());
    404   INLINE(void set_target_cell(Cell* cell,
    405                               WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
    406   INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
    407   INLINE(Code* code_age_stub());
    408   INLINE(void set_code_age_stub(Code* stub));
    409 
    410   // Read the address of the word containing the target_address in an
    411   // instruction stream.  What this means exactly is architecture-independent.
    412   // The only architecture-independent user of this function is the serializer.
    413   // The serializer uses it to find out how many raw bytes of instruction to
    414   // output before the next target.  Architecture-independent code shouldn't
    415   // dereference the pointer it gets back from this.
    416   INLINE(Address target_address_address());
    417   // This indicates how much space a target takes up when deserializing a code
    418   // stream.  For most architectures this is just the size of a pointer.  For
    419   // an instruction like movw/movt where the target bits are mixed into the
    420   // instruction bits the size of the target will be zero, indicating that the
    421   // serializer should not step forwards in memory after a target is resolved
    422   // and written.  In this case the target_address_address function above
    423   // should return the end of the instructions to be patched, allowing the
    424   // deserializer to deserialize the instructions as raw bytes and put them in
    425   // place, ready to be patched with the target.
    426   INLINE(int target_address_size());
    427 
    428   // Read/modify the reference in the instruction this relocation
    429   // applies to; can only be called if rmode_ is external_reference
    430   INLINE(Address target_reference());
    431 
    432   // Read/modify the address of a call instruction. This is used to relocate
    433   // the break points where straight-line code is patched with a call
    434   // instruction.
    435   INLINE(Address call_address());
    436   INLINE(void set_call_address(Address target));
    437   INLINE(Object* call_object());
    438   INLINE(void set_call_object(Object* target));
    439   INLINE(Object** call_object_address());
    440 
    441   // Wipe out a relocation to a fixed value, used for making snapshots
    442   // reproducible.
    443   INLINE(void WipeOut());
    444 
    445   template<typename StaticVisitor> inline void Visit(Heap* heap);
    446   inline void Visit(Isolate* isolate, ObjectVisitor* v);
    447 
    448   // Patch the code with some other code.
    449   void PatchCode(byte* instructions, int instruction_count);
    450 
    451   // Patch the code with a call.
    452   void PatchCodeWithCall(Address target, int guard_bytes);
    453 
    454   // Check whether this return sequence has been patched
    455   // with a call to the debugger.
    456   INLINE(bool IsPatchedReturnSequence());
    457 
    458   // Check whether this debug break slot has been patched with a call to the
    459   // debugger.
    460   INLINE(bool IsPatchedDebugBreakSlotSequence());
    461 
    462 #ifdef DEBUG
    463   // Check whether the given code contains relocation information that
    464   // either is position-relative or movable by the garbage collector.
    465   static bool RequiresRelocation(const CodeDesc& desc);
    466 #endif
    467 
    468 #ifdef ENABLE_DISASSEMBLER
    469   // Printing
    470   static const char* RelocModeName(Mode rmode);
    471   void Print(Isolate* isolate, FILE* out);
    472 #endif  // ENABLE_DISASSEMBLER
    473 #ifdef VERIFY_HEAP
    474   void Verify();
    475 #endif
    476 
    477   static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
    478   static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION;
    479   static const int kDataMask =
    480       (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT);
    481   static const int kApplyMask;  // Modes affected by apply. Depends on arch.
    482 
    483  private:
    484   // On ARM, note that pc_ is the address of the constant pool entry
    485   // to be relocated and not the address of the instruction
    486   // referencing the constant pool entry (except when rmode_ ==
    487   // comment).
    488   byte* pc_;
    489   Mode rmode_;
    490   union {
    491     intptr_t data_;
    492     double data64_;
    493   };
    494   Code* host_;
    495   // External-reference pointers are also split across instruction-pairs
    496   // on some platforms, but are accessed via indirect pointers. This location
    497   // provides a place for that pointer to exist naturally. Its address
    498   // is returned by RelocInfo::target_reference_address().
    499   Address reconstructed_adr_ptr_;
    500   friend class RelocIterator;
    501 };
    502 
    503 
    504 // RelocInfoWriter serializes a stream of relocation info. It writes towards
    505 // lower addresses.
    506 class RelocInfoWriter BASE_EMBEDDED {
    507  public:
    508   RelocInfoWriter() : pos_(NULL),
    509                       last_pc_(NULL),
    510                       last_id_(0),
    511                       last_position_(0) {}
    512   RelocInfoWriter(byte* pos, byte* pc) : pos_(pos),
    513                                          last_pc_(pc),
    514                                          last_id_(0),
    515                                          last_position_(0) {}
    516 
    517   byte* pos() const { return pos_; }
    518   byte* last_pc() const { return last_pc_; }
    519 
    520   void Write(const RelocInfo* rinfo);
    521 
    522   // Update the state of the stream after reloc info buffer
    523   // and/or code is moved while the stream is active.
    524   void Reposition(byte* pos, byte* pc) {
    525     pos_ = pos;
    526     last_pc_ = pc;
    527   }
    528 
    529   // Max size (bytes) of a written RelocInfo. Longest encoding is
    530   // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta.
    531   // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12.
    532   // On x64 this is 1 + 4 + 1 + 1 + 1 + 8 == 16;
    533   // Here we use the maximum of the two.
    534   static const int kMaxSize = 16;
    535 
    536  private:
    537   inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta);
    538   inline void WriteTaggedPC(uint32_t pc_delta, int tag);
    539   inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag);
    540   inline void WriteExtraTaggedIntData(int data_delta, int top_tag);
    541   inline void WriteExtraTaggedConstPoolData(int data);
    542   inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag);
    543   inline void WriteTaggedData(intptr_t data_delta, int tag);
    544   inline void WriteExtraTag(int extra_tag, int top_tag);
    545 
    546   byte* pos_;
    547   byte* last_pc_;
    548   int last_id_;
    549   int last_position_;
    550   DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
    551 };
    552 
    553 
    554 // A RelocIterator iterates over relocation information.
    555 // Typical use:
    556 //
    557 //   for (RelocIterator it(code); !it.done(); it.next()) {
    558 //     // do something with it.rinfo() here
    559 //   }
    560 //
    561 // A mask can be specified to skip unwanted modes.
    562 class RelocIterator: public Malloced {
    563  public:
    564   // Create a new iterator positioned at
    565   // the beginning of the reloc info.
    566   // Relocation information with mode k is included in the
    567   // iteration iff bit k of mode_mask is set.
    568   explicit RelocIterator(Code* code, int mode_mask = -1);
    569   explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
    570 
    571   // Iteration
    572   bool done() const { return done_; }
    573   void next();
    574 
    575   // Return pointer valid until next next().
    576   RelocInfo* rinfo() {
    577     ASSERT(!done());
    578     return &rinfo_;
    579   }
    580 
    581  private:
    582   // Advance* moves the position before/after reading.
    583   // *Read* reads from current byte(s) into rinfo_.
    584   // *Get* just reads and returns info on current byte.
    585   void Advance(int bytes = 1) { pos_ -= bytes; }
    586   int AdvanceGetTag();
    587   int GetExtraTag();
    588   int GetTopTag();
    589   void ReadTaggedPC();
    590   void AdvanceReadPC();
    591   void AdvanceReadId();
    592   void AdvanceReadConstPoolData();
    593   void AdvanceReadPosition();
    594   void AdvanceReadData();
    595   void AdvanceReadVariableLengthPCJump();
    596   int GetLocatableTypeTag();
    597   void ReadTaggedId();
    598   void ReadTaggedPosition();
    599 
    600   // If the given mode is wanted, set it in rinfo_ and return true.
    601   // Else return false. Used for efficiently skipping unwanted modes.
    602   bool SetMode(RelocInfo::Mode mode) {
    603     return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
    604   }
    605 
    606   byte* pos_;
    607   byte* end_;
    608   byte* code_age_sequence_;
    609   RelocInfo rinfo_;
    610   bool done_;
    611   int mode_mask_;
    612   int last_id_;
    613   int last_position_;
    614   DISALLOW_COPY_AND_ASSIGN(RelocIterator);
    615 };
    616 
    617 
    618 //------------------------------------------------------------------------------
    619 // External function
    620 
    621 //----------------------------------------------------------------------------
    622 class IC_Utility;
    623 class SCTableReference;
    624 #ifdef ENABLE_DEBUGGER_SUPPORT
    625 class Debug_Address;
    626 #endif
    627 
    628 
    629 // An ExternalReference represents a C++ address used in the generated
    630 // code. All references to C++ functions and variables must be encapsulated in
    631 // an ExternalReference instance. This is done in order to track the origin of
    632 // all external references in the code so that they can be bound to the correct
    633 // addresses when deserializing a heap.
    634 class ExternalReference BASE_EMBEDDED {
    635  public:
    636   // Used in the simulator to support different native api calls.
    637   enum Type {
    638     // Builtin call.
    639     // MaybeObject* f(v8::internal::Arguments).
    640     BUILTIN_CALL,  // default
    641 
    642     // Builtin that takes float arguments and returns an int.
    643     // int f(double, double).
    644     BUILTIN_COMPARE_CALL,
    645 
    646     // Builtin call that returns floating point.
    647     // double f(double, double).
    648     BUILTIN_FP_FP_CALL,
    649 
    650     // Builtin call that returns floating point.
    651     // double f(double).
    652     BUILTIN_FP_CALL,
    653 
    654     // Builtin call that returns floating point.
    655     // double f(double, int).
    656     BUILTIN_FP_INT_CALL,
    657 
    658     // Direct call to API function callback.
    659     // void f(v8::FunctionCallbackInfo&)
    660     DIRECT_API_CALL,
    661 
    662     // Call to function callback via InvokeFunctionCallback.
    663     // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
    664     PROFILING_API_CALL,
    665 
    666     // Direct call to accessor getter callback.
    667     // void f(Local<String> property, PropertyCallbackInfo& info)
    668     DIRECT_GETTER_CALL,
    669 
    670     // Call to accessor getter callback via InvokeAccessorGetterCallback.
    671     // void f(Local<String> property, PropertyCallbackInfo& info,
    672     //     AccessorGetterCallback callback)
    673     PROFILING_GETTER_CALL
    674   };
    675 
    676   static void SetUp();
    677   static void InitializeMathExpData();
    678   static void TearDownMathExpData();
    679 
    680   typedef void* ExternalReferenceRedirector(void* original, Type type);
    681 
    682   ExternalReference() : address_(NULL) {}
    683 
    684   ExternalReference(Builtins::CFunctionId id, Isolate* isolate);
    685 
    686   ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
    687 
    688   ExternalReference(Builtins::Name name, Isolate* isolate);
    689 
    690   ExternalReference(Runtime::FunctionId id, Isolate* isolate);
    691 
    692   ExternalReference(const Runtime::Function* f, Isolate* isolate);
    693 
    694   ExternalReference(const IC_Utility& ic_utility, Isolate* isolate);
    695 
    696 #ifdef ENABLE_DEBUGGER_SUPPORT
    697   ExternalReference(const Debug_Address& debug_address, Isolate* isolate);
    698 #endif
    699 
    700   explicit ExternalReference(StatsCounter* counter);
    701 
    702   ExternalReference(Isolate::AddressId id, Isolate* isolate);
    703 
    704   explicit ExternalReference(const SCTableReference& table_ref);
    705 
    706   // Isolate as an external reference.
    707   static ExternalReference isolate_address(Isolate* isolate);
    708 
    709   // One-of-a-kind references. These references are not part of a general
    710   // pattern. This means that they have to be added to the
    711   // ExternalReferenceTable in serialize.cc manually.
    712 
    713   static ExternalReference incremental_marking_record_write_function(
    714       Isolate* isolate);
    715   static ExternalReference incremental_evacuation_record_write_function(
    716       Isolate* isolate);
    717   static ExternalReference store_buffer_overflow_function(
    718       Isolate* isolate);
    719   static ExternalReference flush_icache_function(Isolate* isolate);
    720   static ExternalReference perform_gc_function(Isolate* isolate);
    721   static ExternalReference transcendental_cache_array_address(Isolate* isolate);
    722   static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
    723 
    724   static ExternalReference get_date_field_function(Isolate* isolate);
    725   static ExternalReference date_cache_stamp(Isolate* isolate);
    726 
    727   static ExternalReference get_make_code_young_function(Isolate* isolate);
    728   static ExternalReference get_mark_code_as_executed_function(Isolate* isolate);
    729 
    730   // Deoptimization support.
    731   static ExternalReference new_deoptimizer_function(Isolate* isolate);
    732   static ExternalReference compute_output_frames_function(Isolate* isolate);
    733 
    734   // Log support.
    735   static ExternalReference log_enter_external_function(Isolate* isolate);
    736   static ExternalReference log_leave_external_function(Isolate* isolate);
    737 
    738   // Static data in the keyed lookup cache.
    739   static ExternalReference keyed_lookup_cache_keys(Isolate* isolate);
    740   static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate);
    741 
    742   // Static variable Heap::roots_array_start()
    743   static ExternalReference roots_array_start(Isolate* isolate);
    744 
    745   // Static variable Heap::allocation_sites_list_address()
    746   static ExternalReference allocation_sites_list_address(Isolate* isolate);
    747 
    748   // Static variable StackGuard::address_of_jslimit()
    749   static ExternalReference address_of_stack_limit(Isolate* isolate);
    750 
    751   // Static variable StackGuard::address_of_real_jslimit()
    752   static ExternalReference address_of_real_stack_limit(Isolate* isolate);
    753 
    754   // Static variable RegExpStack::limit_address()
    755   static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
    756 
    757   // Static variables for RegExp.
    758   static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
    759   static ExternalReference address_of_regexp_stack_memory_address(
    760       Isolate* isolate);
    761   static ExternalReference address_of_regexp_stack_memory_size(
    762       Isolate* isolate);
    763 
    764   // Static variable Heap::NewSpaceStart()
    765   static ExternalReference new_space_start(Isolate* isolate);
    766   static ExternalReference new_space_mask(Isolate* isolate);
    767   static ExternalReference heap_always_allocate_scope_depth(Isolate* isolate);
    768   static ExternalReference new_space_mark_bits(Isolate* isolate);
    769 
    770   // Write barrier.
    771   static ExternalReference store_buffer_top(Isolate* isolate);
    772 
    773   // Used for fast allocation in generated code.
    774   static ExternalReference new_space_allocation_top_address(Isolate* isolate);
    775   static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
    776   static ExternalReference old_pointer_space_allocation_top_address(
    777       Isolate* isolate);
    778   static ExternalReference old_pointer_space_allocation_limit_address(
    779       Isolate* isolate);
    780   static ExternalReference old_data_space_allocation_top_address(
    781       Isolate* isolate);
    782   static ExternalReference old_data_space_allocation_limit_address(
    783       Isolate* isolate);
    784   static ExternalReference new_space_high_promotion_mode_active_address(
    785       Isolate* isolate);
    786 
    787   static ExternalReference double_fp_operation(Token::Value operation,
    788                                                Isolate* isolate);
    789   static ExternalReference compare_doubles(Isolate* isolate);
    790   static ExternalReference power_double_double_function(Isolate* isolate);
    791   static ExternalReference power_double_int_function(Isolate* isolate);
    792 
    793   static ExternalReference handle_scope_next_address(Isolate* isolate);
    794   static ExternalReference handle_scope_limit_address(Isolate* isolate);
    795   static ExternalReference handle_scope_level_address(Isolate* isolate);
    796 
    797   static ExternalReference scheduled_exception_address(Isolate* isolate);
    798   static ExternalReference address_of_pending_message_obj(Isolate* isolate);
    799   static ExternalReference address_of_has_pending_message(Isolate* isolate);
    800   static ExternalReference address_of_pending_message_script(Isolate* isolate);
    801 
    802   // Static variables containing common double constants.
    803   static ExternalReference address_of_min_int();
    804   static ExternalReference address_of_one_half();
    805   static ExternalReference address_of_minus_one_half();
    806   static ExternalReference address_of_minus_zero();
    807   static ExternalReference address_of_zero();
    808   static ExternalReference address_of_uint8_max_value();
    809   static ExternalReference address_of_negative_infinity();
    810   static ExternalReference address_of_canonical_non_hole_nan();
    811   static ExternalReference address_of_the_hole_nan();
    812   static ExternalReference address_of_uint32_bias();
    813 
    814   static ExternalReference math_sin_double_function(Isolate* isolate);
    815   static ExternalReference math_cos_double_function(Isolate* isolate);
    816   static ExternalReference math_tan_double_function(Isolate* isolate);
    817   static ExternalReference math_log_double_function(Isolate* isolate);
    818 
    819   static ExternalReference math_exp_constants(int constant_index);
    820   static ExternalReference math_exp_log_table();
    821 
    822   static ExternalReference page_flags(Page* page);
    823 
    824   static ExternalReference ForDeoptEntry(Address entry);
    825 
    826   static ExternalReference cpu_features();
    827 
    828   Address address() const { return reinterpret_cast<Address>(address_); }
    829 
    830 #ifdef ENABLE_DEBUGGER_SUPPORT
    831   // Function Debug::Break()
    832   static ExternalReference debug_break(Isolate* isolate);
    833 
    834   // Used to check if single stepping is enabled in generated code.
    835   static ExternalReference debug_step_in_fp_address(Isolate* isolate);
    836 #endif
    837 
    838 #ifndef V8_INTERPRETED_REGEXP
    839   // C functions called from RegExp generated code.
    840 
    841   // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
    842   static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
    843 
    844   // Function RegExpMacroAssembler*::CheckStackGuardState()
    845   static ExternalReference re_check_stack_guard_state(Isolate* isolate);
    846 
    847   // Function NativeRegExpMacroAssembler::GrowStack()
    848   static ExternalReference re_grow_stack(Isolate* isolate);
    849 
    850   // byte NativeRegExpMacroAssembler::word_character_bitmap
    851   static ExternalReference re_word_character_map();
    852 
    853 #endif
    854 
    855   // This lets you register a function that rewrites all external references.
    856   // Used by the ARM simulator to catch calls to external references.
    857   static void set_redirector(Isolate* isolate,
    858                              ExternalReferenceRedirector* redirector) {
    859     // We can't stack them.
    860     ASSERT(isolate->external_reference_redirector() == NULL);
    861     isolate->set_external_reference_redirector(
    862         reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
    863   }
    864 
    865   static ExternalReference stress_deopt_count(Isolate* isolate);
    866 
    867   bool operator==(const ExternalReference& other) const {
    868     return address_ == other.address_;
    869   }
    870 
    871   bool operator!=(const ExternalReference& other) const {
    872     return !(*this == other);
    873   }
    874 
    875  private:
    876   explicit ExternalReference(void* address)
    877       : address_(address) {}
    878 
    879   static void* Redirect(Isolate* isolate,
    880                         void* address,
    881                         Type type = ExternalReference::BUILTIN_CALL) {
    882     ExternalReferenceRedirector* redirector =
    883         reinterpret_cast<ExternalReferenceRedirector*>(
    884             isolate->external_reference_redirector());
    885     if (redirector == NULL) return address;
    886     void* answer = (*redirector)(address, type);
    887     return answer;
    888   }
    889 
    890   static void* Redirect(Isolate* isolate,
    891                         Address address_arg,
    892                         Type type = ExternalReference::BUILTIN_CALL) {
    893     ExternalReferenceRedirector* redirector =
    894         reinterpret_cast<ExternalReferenceRedirector*>(
    895             isolate->external_reference_redirector());
    896     void* address = reinterpret_cast<void*>(address_arg);
    897     void* answer = (redirector == NULL) ?
    898                    address :
    899                    (*redirector)(address, type);
    900     return answer;
    901   }
    902 
    903   void* address_;
    904 };
    905 
    906 
    907 // -----------------------------------------------------------------------------
    908 // Position recording support
    909 
    910 struct PositionState {
    911   PositionState() : current_position(RelocInfo::kNoPosition),
    912                     written_position(RelocInfo::kNoPosition),
    913                     current_statement_position(RelocInfo::kNoPosition),
    914                     written_statement_position(RelocInfo::kNoPosition) {}
    915 
    916   int current_position;
    917   int written_position;
    918 
    919   int current_statement_position;
    920   int written_statement_position;
    921 };
    922 
    923 
    924 class PositionsRecorder BASE_EMBEDDED {
    925  public:
    926   explicit PositionsRecorder(Assembler* assembler)
    927       : assembler_(assembler) {
    928 #ifdef ENABLE_GDB_JIT_INTERFACE
    929     gdbjit_lineinfo_ = NULL;
    930 #endif
    931     jit_handler_data_ = NULL;
    932   }
    933 
    934 #ifdef ENABLE_GDB_JIT_INTERFACE
    935   ~PositionsRecorder() {
    936     delete gdbjit_lineinfo_;
    937   }
    938 
    939   void StartGDBJITLineInfoRecording() {
    940     if (FLAG_gdbjit) {
    941       gdbjit_lineinfo_ = new GDBJITLineInfo();
    942     }
    943   }
    944 
    945   GDBJITLineInfo* DetachGDBJITLineInfo() {
    946     GDBJITLineInfo* lineinfo = gdbjit_lineinfo_;
    947     gdbjit_lineinfo_ = NULL;  // To prevent deallocation in destructor.
    948     return lineinfo;
    949   }
    950 #endif
    951   void AttachJITHandlerData(void* user_data) {
    952     jit_handler_data_ = user_data;
    953   }
    954 
    955   void* DetachJITHandlerData() {
    956     void* old_data = jit_handler_data_;
    957     jit_handler_data_ = NULL;
    958     return old_data;
    959   }
    960   // Set current position to pos.
    961   void RecordPosition(int pos);
    962 
    963   // Set current statement position to pos.
    964   void RecordStatementPosition(int pos);
    965 
    966   // Write recorded positions to relocation information.
    967   bool WriteRecordedPositions();
    968 
    969   int current_position() const { return state_.current_position; }
    970 
    971   int current_statement_position() const {
    972     return state_.current_statement_position;
    973   }
    974 
    975  private:
    976   Assembler* assembler_;
    977   PositionState state_;
    978 #ifdef ENABLE_GDB_JIT_INTERFACE
    979   GDBJITLineInfo* gdbjit_lineinfo_;
    980 #endif
    981 
    982   // Currently jit_handler_data_ is used to store JITHandler-specific data
    983   // over the lifetime of a PositionsRecorder
    984   void* jit_handler_data_;
    985   friend class PreservePositionScope;
    986 
    987   DISALLOW_COPY_AND_ASSIGN(PositionsRecorder);
    988 };
    989 
    990 
    991 class PreservePositionScope BASE_EMBEDDED {
    992  public:
    993   explicit PreservePositionScope(PositionsRecorder* positions_recorder)
    994       : positions_recorder_(positions_recorder),
    995         saved_state_(positions_recorder->state_) {}
    996 
    997   ~PreservePositionScope() {
    998     positions_recorder_->state_ = saved_state_;
    999   }
   1000 
   1001  private:
   1002   PositionsRecorder* positions_recorder_;
   1003   const PositionState saved_state_;
   1004 
   1005   DISALLOW_COPY_AND_ASSIGN(PreservePositionScope);
   1006 };
   1007 
   1008 
   1009 // -----------------------------------------------------------------------------
   1010 // Utility functions
   1011 
   1012 inline bool is_intn(int x, int n)  {
   1013   return -(1 << (n-1)) <= x && x < (1 << (n-1));
   1014 }
   1015 
   1016 inline bool is_int8(int x)  { return is_intn(x, 8); }
   1017 inline bool is_int16(int x)  { return is_intn(x, 16); }
   1018 inline bool is_int18(int x)  { return is_intn(x, 18); }
   1019 inline bool is_int24(int x)  { return is_intn(x, 24); }
   1020 
   1021 inline bool is_uintn(int x, int n) {
   1022   return (x & -(1 << n)) == 0;
   1023 }
   1024 
   1025 inline bool is_uint2(int x)  { return is_uintn(x, 2); }
   1026 inline bool is_uint3(int x)  { return is_uintn(x, 3); }
   1027 inline bool is_uint4(int x)  { return is_uintn(x, 4); }
   1028 inline bool is_uint5(int x)  { return is_uintn(x, 5); }
   1029 inline bool is_uint6(int x)  { return is_uintn(x, 6); }
   1030 inline bool is_uint8(int x)  { return is_uintn(x, 8); }
   1031 inline bool is_uint10(int x)  { return is_uintn(x, 10); }
   1032 inline bool is_uint12(int x)  { return is_uintn(x, 12); }
   1033 inline bool is_uint16(int x)  { return is_uintn(x, 16); }
   1034 inline bool is_uint24(int x)  { return is_uintn(x, 24); }
   1035 inline bool is_uint26(int x)  { return is_uintn(x, 26); }
   1036 inline bool is_uint28(int x)  { return is_uintn(x, 28); }
   1037 
   1038 inline int NumberOfBitsSet(uint32_t x) {
   1039   unsigned int num_bits_set;
   1040   for (num_bits_set = 0; x; x >>= 1) {
   1041     num_bits_set += x & 1;
   1042   }
   1043   return num_bits_set;
   1044 }
   1045 
   1046 bool EvalComparison(Token::Value op, double op1, double op2);
   1047 
   1048 // Computes pow(x, y) with the special cases in the spec for Math.pow.
   1049 double power_helper(double x, double y);
   1050 double power_double_int(double x, int y);
   1051 double power_double_double(double x, double y);
   1052 
   1053 // Helper class for generating code or data associated with the code
   1054 // right after a call instruction. As an example this can be used to
   1055 // generate safepoint data after calls for crankshaft.
   1056 class CallWrapper {
   1057  public:
   1058   CallWrapper() { }
   1059   virtual ~CallWrapper() { }
   1060   // Called just before emitting a call. Argument is the size of the generated
   1061   // call code.
   1062   virtual void BeforeCall(int call_size) const = 0;
   1063   // Called just after emitting a call, i.e., at the return site for the call.
   1064   virtual void AfterCall() const = 0;
   1065 };
   1066 
   1067 class NullCallWrapper : public CallWrapper {
   1068  public:
   1069   NullCallWrapper() { }
   1070   virtual ~NullCallWrapper() { }
   1071   virtual void BeforeCall(int call_size) const { }
   1072   virtual void AfterCall() const { }
   1073 };
   1074 
   1075 } }  // namespace v8::internal
   1076 
   1077 #endif  // V8_ASSEMBLER_H_
   1078