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 "src/allocation.h"
     39 #include "src/builtins/builtins.h"
     40 #include "src/deoptimize-reason.h"
     41 #include "src/globals.h"
     42 #include "src/isolate.h"
     43 #include "src/label.h"
     44 #include "src/log.h"
     45 #include "src/register-configuration.h"
     46 #include "src/runtime/runtime.h"
     47 
     48 namespace v8 {
     49 
     50 // Forward declarations.
     51 class ApiFunction;
     52 
     53 namespace internal {
     54 
     55 // Forward declarations.
     56 class SourcePosition;
     57 class StatsCounter;
     58 
     59 // -----------------------------------------------------------------------------
     60 // Platform independent assembler base class.
     61 
     62 enum class CodeObjectRequired { kNo, kYes };
     63 
     64 
     65 class AssemblerBase: public Malloced {
     66  public:
     67   AssemblerBase(Isolate* isolate, void* buffer, int buffer_size);
     68   virtual ~AssemblerBase();
     69 
     70   Isolate* isolate() const { return isolate_; }
     71   int jit_cookie() const { return jit_cookie_; }
     72 
     73   bool emit_debug_code() const { return emit_debug_code_; }
     74   void set_emit_debug_code(bool value) { emit_debug_code_ = value; }
     75 
     76   bool serializer_enabled() const { return serializer_enabled_; }
     77   void enable_serializer() { serializer_enabled_ = true; }
     78 
     79   bool predictable_code_size() const { return predictable_code_size_; }
     80   void set_predictable_code_size(bool value) { predictable_code_size_ = value; }
     81 
     82   uint64_t enabled_cpu_features() const { return enabled_cpu_features_; }
     83   void set_enabled_cpu_features(uint64_t features) {
     84     enabled_cpu_features_ = features;
     85   }
     86   // Features are usually enabled by CpuFeatureScope, which also asserts that
     87   // the features are supported before they are enabled.
     88   bool IsEnabled(CpuFeature f) {
     89     return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0;
     90   }
     91   void EnableCpuFeature(CpuFeature f) {
     92     enabled_cpu_features_ |= (static_cast<uint64_t>(1) << f);
     93   }
     94 
     95   bool is_constant_pool_available() const {
     96     if (FLAG_enable_embedded_constant_pool) {
     97       return constant_pool_available_;
     98     } else {
     99       // Embedded constant pool not supported on this architecture.
    100       UNREACHABLE();
    101       return false;
    102     }
    103   }
    104 
    105   // Overwrite a host NaN with a quiet target NaN.  Used by mksnapshot for
    106   // cross-snapshotting.
    107   static void QuietNaN(HeapObject* nan) { }
    108 
    109   int pc_offset() const { return static_cast<int>(pc_ - buffer_); }
    110 
    111   // This function is called when code generation is aborted, so that
    112   // the assembler could clean up internal data structures.
    113   virtual void AbortedCodeGeneration() { }
    114 
    115   // Debugging
    116   void Print();
    117 
    118   static const int kMinimalBufferSize = 4*KB;
    119 
    120   static void FlushICache(Isolate* isolate, void* start, size_t size);
    121 
    122  protected:
    123   // The buffer into which code and relocation info are generated. It could
    124   // either be owned by the assembler or be provided externally.
    125   byte* buffer_;
    126   int buffer_size_;
    127   bool own_buffer_;
    128 
    129   void set_constant_pool_available(bool available) {
    130     if (FLAG_enable_embedded_constant_pool) {
    131       constant_pool_available_ = available;
    132     } else {
    133       // Embedded constant pool not supported on this architecture.
    134       UNREACHABLE();
    135     }
    136   }
    137 
    138   // The program counter, which points into the buffer above and moves forward.
    139   byte* pc_;
    140 
    141  private:
    142   Isolate* isolate_;
    143   int jit_cookie_;
    144   uint64_t enabled_cpu_features_;
    145   bool emit_debug_code_;
    146   bool predictable_code_size_;
    147   bool serializer_enabled_;
    148 
    149   // Indicates whether the constant pool can be accessed, which is only possible
    150   // if the pp register points to the current code object's constant pool.
    151   bool constant_pool_available_;
    152 
    153   // Constant pool.
    154   friend class FrameAndConstantPoolScope;
    155   friend class ConstantPoolUnavailableScope;
    156 };
    157 
    158 
    159 // Avoids emitting debug code during the lifetime of this scope object.
    160 class DontEmitDebugCodeScope BASE_EMBEDDED {
    161  public:
    162   explicit DontEmitDebugCodeScope(AssemblerBase* assembler)
    163       : assembler_(assembler), old_value_(assembler->emit_debug_code()) {
    164     assembler_->set_emit_debug_code(false);
    165   }
    166   ~DontEmitDebugCodeScope() {
    167     assembler_->set_emit_debug_code(old_value_);
    168   }
    169  private:
    170   AssemblerBase* assembler_;
    171   bool old_value_;
    172 };
    173 
    174 
    175 // Avoids using instructions that vary in size in unpredictable ways between the
    176 // snapshot and the running VM.
    177 class PredictableCodeSizeScope {
    178  public:
    179   explicit PredictableCodeSizeScope(AssemblerBase* assembler);
    180   PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size);
    181   ~PredictableCodeSizeScope();
    182   void ExpectSize(int expected_size) { expected_size_ = expected_size; }
    183 
    184  private:
    185   AssemblerBase* assembler_;
    186   int expected_size_;
    187   int start_offset_;
    188   bool old_value_;
    189 };
    190 
    191 
    192 // Enable a specified feature within a scope.
    193 class CpuFeatureScope BASE_EMBEDDED {
    194  public:
    195   enum CheckPolicy {
    196     kCheckSupported,
    197     kDontCheckSupported,
    198   };
    199 
    200 #ifdef DEBUG
    201   CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
    202                   CheckPolicy check = kCheckSupported);
    203   ~CpuFeatureScope();
    204 
    205  private:
    206   AssemblerBase* assembler_;
    207   uint64_t old_enabled_;
    208 #else
    209   CpuFeatureScope(AssemblerBase* assembler, CpuFeature f,
    210                   CheckPolicy check = kCheckSupported) {}
    211 #endif
    212 };
    213 
    214 
    215 // CpuFeatures keeps track of which features are supported by the target CPU.
    216 // Supported features must be enabled by a CpuFeatureScope before use.
    217 // Example:
    218 //   if (assembler->IsSupported(SSE3)) {
    219 //     CpuFeatureScope fscope(assembler, SSE3);
    220 //     // Generate code containing SSE3 instructions.
    221 //   } else {
    222 //     // Generate alternative code.
    223 //   }
    224 class CpuFeatures : public AllStatic {
    225  public:
    226   static void Probe(bool cross_compile) {
    227     STATIC_ASSERT(NUMBER_OF_CPU_FEATURES <= kBitsPerInt);
    228     if (initialized_) return;
    229     initialized_ = true;
    230     ProbeImpl(cross_compile);
    231   }
    232 
    233   static unsigned SupportedFeatures() {
    234     Probe(false);
    235     return supported_;
    236   }
    237 
    238   static bool IsSupported(CpuFeature f) {
    239     return (supported_ & (1u << f)) != 0;
    240   }
    241 
    242   static inline bool SupportsCrankshaft();
    243 
    244   static inline bool SupportsSimd128();
    245 
    246   static inline unsigned icache_line_size() {
    247     DCHECK(icache_line_size_ != 0);
    248     return icache_line_size_;
    249   }
    250 
    251   static inline unsigned dcache_line_size() {
    252     DCHECK(dcache_line_size_ != 0);
    253     return dcache_line_size_;
    254   }
    255 
    256   static void PrintTarget();
    257   static void PrintFeatures();
    258 
    259  private:
    260   friend class ExternalReference;
    261   friend class AssemblerBase;
    262   // Flush instruction cache.
    263   static void FlushICache(void* start, size_t size);
    264 
    265   // Platform-dependent implementation.
    266   static void ProbeImpl(bool cross_compile);
    267 
    268   static unsigned supported_;
    269   static unsigned icache_line_size_;
    270   static unsigned dcache_line_size_;
    271   static bool initialized_;
    272   DISALLOW_COPY_AND_ASSIGN(CpuFeatures);
    273 };
    274 
    275 
    276 enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };
    277 
    278 enum ArgvMode { kArgvOnStack, kArgvInRegister };
    279 
    280 // Specifies whether to perform icache flush operations on RelocInfo updates.
    281 // If FLUSH_ICACHE_IF_NEEDED, the icache will always be flushed if an
    282 // instruction was modified. If SKIP_ICACHE_FLUSH the flush will always be
    283 // skipped (only use this if you will flush the icache manually before it is
    284 // executed).
    285 enum ICacheFlushMode { FLUSH_ICACHE_IF_NEEDED, SKIP_ICACHE_FLUSH };
    286 
    287 // -----------------------------------------------------------------------------
    288 // Relocation information
    289 
    290 
    291 // Relocation information consists of the address (pc) of the datum
    292 // to which the relocation information applies, the relocation mode
    293 // (rmode), and an optional data field. The relocation mode may be
    294 // "descriptive" and not indicate a need for relocation, but simply
    295 // describe a property of the datum. Such rmodes are useful for GC
    296 // and nice disassembly output.
    297 
    298 class RelocInfo {
    299  public:
    300   // This string is used to add padding comments to the reloc info in cases
    301   // where we are not sure to have enough space for patching in during
    302   // lazy deoptimization. This is the case if we have indirect calls for which
    303   // we do not normally record relocation info.
    304   static const char* const kFillerCommentString;
    305 
    306   // The minimum size of a comment is equal to two bytes for the extra tagged
    307   // pc and kPointerSize for the actual pointer to the comment.
    308   static const int kMinRelocCommentSize = 2 + kPointerSize;
    309 
    310   // The maximum size for a call instruction including pc-jump.
    311   static const int kMaxCallSize = 6;
    312 
    313   // The maximum pc delta that will use the short encoding.
    314   static const int kMaxSmallPCDelta;
    315 
    316   enum Mode {
    317     // Please note the order is important (see IsCodeTarget, IsGCRelocMode).
    318     CODE_TARGET,  // Code target which is not any of the above.
    319     CODE_TARGET_WITH_ID,
    320     EMBEDDED_OBJECT,
    321     // To relocate pointers into the wasm memory embedded in wasm code
    322     WASM_MEMORY_REFERENCE,
    323     WASM_GLOBAL_REFERENCE,
    324     WASM_MEMORY_SIZE_REFERENCE,
    325     WASM_FUNCTION_TABLE_SIZE_REFERENCE,
    326     WASM_PROTECTED_INSTRUCTION_LANDING,
    327     CELL,
    328 
    329     // Everything after runtime_entry (inclusive) is not GC'ed.
    330     RUNTIME_ENTRY,
    331     COMMENT,
    332 
    333     // Additional code inserted for debug break slot.
    334     DEBUG_BREAK_SLOT_AT_POSITION,
    335     DEBUG_BREAK_SLOT_AT_RETURN,
    336     DEBUG_BREAK_SLOT_AT_CALL,
    337     DEBUG_BREAK_SLOT_AT_TAIL_CALL,
    338 
    339     EXTERNAL_REFERENCE,  // The address of an external C++ function.
    340     INTERNAL_REFERENCE,  // An address inside the same function.
    341 
    342     // Encoded internal reference, used only on MIPS, MIPS64 and PPC.
    343     INTERNAL_REFERENCE_ENCODED,
    344 
    345     // Marks constant and veneer pools. Only used on ARM and ARM64.
    346     // They use a custom noncompact encoding.
    347     CONST_POOL,
    348     VENEER_POOL,
    349 
    350     DEOPT_SCRIPT_OFFSET,
    351     DEOPT_INLINING_ID,  // Deoptimization source position.
    352     DEOPT_REASON,       // Deoptimization reason index.
    353     DEOPT_ID,           // Deoptimization inlining id.
    354 
    355     // This is not an actual reloc mode, but used to encode a long pc jump that
    356     // cannot be encoded as part of another record.
    357     PC_JUMP,
    358 
    359     // Pseudo-types
    360     NUMBER_OF_MODES,
    361     NONE32,             // never recorded 32-bit value
    362     NONE64,             // never recorded 64-bit value
    363     CODE_AGE_SEQUENCE,  // Not stored in RelocInfo array, used explictly by
    364                         // code aging.
    365 
    366     FIRST_REAL_RELOC_MODE = CODE_TARGET,
    367     LAST_REAL_RELOC_MODE = VENEER_POOL,
    368     LAST_CODE_ENUM = CODE_TARGET_WITH_ID,
    369     LAST_GCED_ENUM = WASM_FUNCTION_TABLE_SIZE_REFERENCE,
    370     FIRST_SHAREABLE_RELOC_MODE = CELL,
    371   };
    372 
    373   STATIC_ASSERT(NUMBER_OF_MODES <= kBitsPerInt);
    374 
    375   explicit RelocInfo(Isolate* isolate) : isolate_(isolate) {
    376     DCHECK_NOT_NULL(isolate);
    377   }
    378 
    379   RelocInfo(Isolate* isolate, byte* pc, Mode rmode, intptr_t data, Code* host)
    380       : isolate_(isolate), pc_(pc), rmode_(rmode), data_(data), host_(host) {
    381     DCHECK_NOT_NULL(isolate);
    382   }
    383 
    384   static inline bool IsRealRelocMode(Mode mode) {
    385     return mode >= FIRST_REAL_RELOC_MODE && mode <= LAST_REAL_RELOC_MODE;
    386   }
    387   static inline bool IsCodeTarget(Mode mode) {
    388     return mode <= LAST_CODE_ENUM;
    389   }
    390   static inline bool IsEmbeddedObject(Mode mode) {
    391     return mode == EMBEDDED_OBJECT;
    392   }
    393   static inline bool IsCell(Mode mode) { return mode == CELL; }
    394   static inline bool IsRuntimeEntry(Mode mode) {
    395     return mode == RUNTIME_ENTRY;
    396   }
    397   // Is the relocation mode affected by GC?
    398   static inline bool IsGCRelocMode(Mode mode) {
    399     return mode <= LAST_GCED_ENUM;
    400   }
    401   static inline bool IsComment(Mode mode) {
    402     return mode == COMMENT;
    403   }
    404   static inline bool IsConstPool(Mode mode) {
    405     return mode == CONST_POOL;
    406   }
    407   static inline bool IsVeneerPool(Mode mode) {
    408     return mode == VENEER_POOL;
    409   }
    410   static inline bool IsDeoptPosition(Mode mode) {
    411     return mode == DEOPT_SCRIPT_OFFSET || mode == DEOPT_INLINING_ID;
    412   }
    413   static inline bool IsDeoptReason(Mode mode) {
    414     return mode == DEOPT_REASON;
    415   }
    416   static inline bool IsDeoptId(Mode mode) {
    417     return mode == DEOPT_ID;
    418   }
    419   static inline bool IsExternalReference(Mode mode) {
    420     return mode == EXTERNAL_REFERENCE;
    421   }
    422   static inline bool IsInternalReference(Mode mode) {
    423     return mode == INTERNAL_REFERENCE;
    424   }
    425   static inline bool IsInternalReferenceEncoded(Mode mode) {
    426     return mode == INTERNAL_REFERENCE_ENCODED;
    427   }
    428   static inline bool IsDebugBreakSlot(Mode mode) {
    429     return IsDebugBreakSlotAtPosition(mode) || IsDebugBreakSlotAtReturn(mode) ||
    430            IsDebugBreakSlotAtCall(mode) || IsDebugBreakSlotAtTailCall(mode);
    431   }
    432   static inline bool IsDebugBreakSlotAtPosition(Mode mode) {
    433     return mode == DEBUG_BREAK_SLOT_AT_POSITION;
    434   }
    435   static inline bool IsDebugBreakSlotAtReturn(Mode mode) {
    436     return mode == DEBUG_BREAK_SLOT_AT_RETURN;
    437   }
    438   static inline bool IsDebugBreakSlotAtCall(Mode mode) {
    439     return mode == DEBUG_BREAK_SLOT_AT_CALL;
    440   }
    441   static inline bool IsDebugBreakSlotAtTailCall(Mode mode) {
    442     return mode == DEBUG_BREAK_SLOT_AT_TAIL_CALL;
    443   }
    444   static inline bool IsNone(Mode mode) {
    445     return mode == NONE32 || mode == NONE64;
    446   }
    447   static inline bool IsCodeAgeSequence(Mode mode) {
    448     return mode == CODE_AGE_SEQUENCE;
    449   }
    450   static inline bool IsWasmMemoryReference(Mode mode) {
    451     return mode == WASM_MEMORY_REFERENCE;
    452   }
    453   static inline bool IsWasmMemorySizeReference(Mode mode) {
    454     return mode == WASM_MEMORY_SIZE_REFERENCE;
    455   }
    456   static inline bool IsWasmGlobalReference(Mode mode) {
    457     return mode == WASM_GLOBAL_REFERENCE;
    458   }
    459   static inline bool IsWasmFunctionTableSizeReference(Mode mode) {
    460     return mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
    461   }
    462   static inline bool IsWasmReference(Mode mode) {
    463     return mode == WASM_MEMORY_REFERENCE || mode == WASM_GLOBAL_REFERENCE ||
    464            mode == WASM_MEMORY_SIZE_REFERENCE ||
    465            mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
    466   }
    467   static inline bool IsWasmSizeReference(Mode mode) {
    468     return mode == WASM_MEMORY_SIZE_REFERENCE ||
    469            mode == WASM_FUNCTION_TABLE_SIZE_REFERENCE;
    470   }
    471   static inline bool IsWasmPtrReference(Mode mode) {
    472     return mode == WASM_MEMORY_REFERENCE || mode == WASM_GLOBAL_REFERENCE;
    473   }
    474   static inline bool IsWasmProtectedLanding(Mode mode) {
    475     return mode == WASM_PROTECTED_INSTRUCTION_LANDING;
    476   }
    477 
    478   static inline int ModeMask(Mode mode) { return 1 << mode; }
    479 
    480   // Accessors
    481   Isolate* isolate() const { return isolate_; }
    482   byte* pc() const { return pc_; }
    483   void set_pc(byte* pc) { pc_ = pc; }
    484   Mode rmode() const {  return rmode_; }
    485   intptr_t data() const { return data_; }
    486   Code* host() const { return host_; }
    487   void set_host(Code* host) { host_ = host; }
    488 
    489   // Apply a relocation by delta bytes. When the code object is moved, PC
    490   // relative addresses have to be updated as well as absolute addresses
    491   // inside the code (internal references).
    492   // Do not forget to flush the icache afterwards!
    493   INLINE(void apply(intptr_t delta));
    494 
    495   // Is the pointer this relocation info refers to coded like a plain pointer
    496   // or is it strange in some way (e.g. relative or patched into a series of
    497   // instructions).
    498   bool IsCodedSpecially();
    499 
    500   // If true, the pointer this relocation info refers to is an entry in the
    501   // constant pool, otherwise the pointer is embedded in the instruction stream.
    502   bool IsInConstantPool();
    503 
    504   Address wasm_memory_reference();
    505   Address wasm_global_reference();
    506   uint32_t wasm_function_table_size_reference();
    507   uint32_t wasm_memory_size_reference();
    508   void update_wasm_memory_reference(
    509       Address old_base, Address new_base,
    510       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
    511   void update_wasm_memory_size(
    512       uint32_t old_size, uint32_t new_size,
    513       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
    514   void update_wasm_global_reference(
    515       Address old_base, Address new_base,
    516       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
    517   void update_wasm_function_table_size_reference(
    518       uint32_t old_base, uint32_t new_base,
    519       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
    520   void set_target_address(
    521       Address target,
    522       WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
    523       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED);
    524 
    525   // this relocation applies to;
    526   // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
    527   INLINE(Address target_address());
    528   INLINE(Object* target_object());
    529   INLINE(Handle<Object> target_object_handle(Assembler* origin));
    530   INLINE(void set_target_object(
    531       Object* target,
    532       WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
    533       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
    534   INLINE(Address target_runtime_entry(Assembler* origin));
    535   INLINE(void set_target_runtime_entry(
    536       Address target,
    537       WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
    538       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
    539   INLINE(Cell* target_cell());
    540   INLINE(Handle<Cell> target_cell_handle());
    541   INLINE(void set_target_cell(
    542       Cell* cell, WriteBarrierMode write_barrier_mode = UPDATE_WRITE_BARRIER,
    543       ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
    544   INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
    545   INLINE(Code* code_age_stub());
    546   INLINE(void set_code_age_stub(
    547       Code* stub, ICacheFlushMode icache_flush_mode = FLUSH_ICACHE_IF_NEEDED));
    548 
    549   // Returns the address of the constant pool entry where the target address
    550   // is held.  This should only be called if IsInConstantPool returns true.
    551   INLINE(Address constant_pool_entry_address());
    552 
    553   // Read the address of the word containing the target_address in an
    554   // instruction stream.  What this means exactly is architecture-independent.
    555   // The only architecture-independent user of this function is the serializer.
    556   // The serializer uses it to find out how many raw bytes of instruction to
    557   // output before the next target.  Architecture-independent code shouldn't
    558   // dereference the pointer it gets back from this.
    559   INLINE(Address target_address_address());
    560 
    561   // This indicates how much space a target takes up when deserializing a code
    562   // stream.  For most architectures this is just the size of a pointer.  For
    563   // an instruction like movw/movt where the target bits are mixed into the
    564   // instruction bits the size of the target will be zero, indicating that the
    565   // serializer should not step forwards in memory after a target is resolved
    566   // and written.  In this case the target_address_address function above
    567   // should return the end of the instructions to be patched, allowing the
    568   // deserializer to deserialize the instructions as raw bytes and put them in
    569   // place, ready to be patched with the target.
    570   INLINE(int target_address_size());
    571 
    572   // Read the reference in the instruction this relocation
    573   // applies to; can only be called if rmode_ is EXTERNAL_REFERENCE.
    574   INLINE(Address target_external_reference());
    575 
    576   // Read the reference in the instruction this relocation
    577   // applies to; can only be called if rmode_ is INTERNAL_REFERENCE.
    578   INLINE(Address target_internal_reference());
    579 
    580   // Return the reference address this relocation applies to;
    581   // can only be called if rmode_ is INTERNAL_REFERENCE.
    582   INLINE(Address target_internal_reference_address());
    583 
    584   // Read/modify the address of a call instruction. This is used to relocate
    585   // the break points where straight-line code is patched with a call
    586   // instruction.
    587   INLINE(Address debug_call_address());
    588   INLINE(void set_debug_call_address(Address target));
    589 
    590   // Wipe out a relocation to a fixed value, used for making snapshots
    591   // reproducible.
    592   INLINE(void WipeOut());
    593 
    594   template<typename StaticVisitor> inline void Visit(Heap* heap);
    595 
    596   template <typename ObjectVisitor>
    597   inline void Visit(Isolate* isolate, ObjectVisitor* v);
    598 
    599   // Check whether this debug break slot has been patched with a call to the
    600   // debugger.
    601   bool IsPatchedDebugBreakSlotSequence();
    602 
    603 #ifdef DEBUG
    604   // Check whether the given code contains relocation information that
    605   // either is position-relative or movable by the garbage collector.
    606   static bool RequiresRelocation(const CodeDesc& desc);
    607 #endif
    608 
    609 #ifdef ENABLE_DISASSEMBLER
    610   // Printing
    611   static const char* RelocModeName(Mode rmode);
    612   void Print(Isolate* isolate, std::ostream& os);  // NOLINT
    613 #endif  // ENABLE_DISASSEMBLER
    614 #ifdef VERIFY_HEAP
    615   void Verify(Isolate* isolate);
    616 #endif
    617 
    618   static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1;
    619   static const int kDataMask = (1 << CODE_TARGET_WITH_ID) | (1 << COMMENT);
    620   static const int kDebugBreakSlotMask = 1 << DEBUG_BREAK_SLOT_AT_POSITION |
    621                                          1 << DEBUG_BREAK_SLOT_AT_RETURN |
    622                                          1 << DEBUG_BREAK_SLOT_AT_CALL;
    623   static const int kApplyMask;  // Modes affected by apply.  Depends on arch.
    624 
    625  private:
    626   void unchecked_update_wasm_memory_reference(Address address,
    627                                               ICacheFlushMode flush_mode);
    628   void unchecked_update_wasm_size(uint32_t size, ICacheFlushMode flush_mode);
    629 
    630   Isolate* isolate_;
    631   // On ARM, note that pc_ is the address of the constant pool entry
    632   // to be relocated and not the address of the instruction
    633   // referencing the constant pool entry (except when rmode_ ==
    634   // comment).
    635   byte* pc_;
    636   Mode rmode_;
    637   intptr_t data_;
    638   Code* host_;
    639   friend class RelocIterator;
    640 };
    641 
    642 
    643 // RelocInfoWriter serializes a stream of relocation info. It writes towards
    644 // lower addresses.
    645 class RelocInfoWriter BASE_EMBEDDED {
    646  public:
    647   RelocInfoWriter() : pos_(NULL), last_pc_(NULL), last_id_(0) {}
    648   RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), last_pc_(pc), last_id_(0) {}
    649 
    650   byte* pos() const { return pos_; }
    651   byte* last_pc() const { return last_pc_; }
    652 
    653   void Write(const RelocInfo* rinfo);
    654 
    655   // Update the state of the stream after reloc info buffer
    656   // and/or code is moved while the stream is active.
    657   void Reposition(byte* pos, byte* pc) {
    658     pos_ = pos;
    659     last_pc_ = pc;
    660   }
    661 
    662   // Max size (bytes) of a written RelocInfo. Longest encoding is
    663   // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, data_delta.
    664   // On ia32 and arm this is 1 + 4 + 1 + 1 + 4 = 11.
    665   // On x64 this is 1 + 4 + 1 + 1 + 8 == 15;
    666   // Here we use the maximum of the two.
    667   static const int kMaxSize = 15;
    668 
    669  private:
    670   inline uint32_t WriteLongPCJump(uint32_t pc_delta);
    671 
    672   inline void WriteShortTaggedPC(uint32_t pc_delta, int tag);
    673   inline void WriteShortTaggedData(intptr_t data_delta, int tag);
    674 
    675   inline void WriteMode(RelocInfo::Mode rmode);
    676   inline void WriteModeAndPC(uint32_t pc_delta, RelocInfo::Mode rmode);
    677   inline void WriteIntData(int data_delta);
    678   inline void WriteData(intptr_t data_delta);
    679 
    680   byte* pos_;
    681   byte* last_pc_;
    682   int last_id_;
    683   RelocInfo::Mode last_mode_;
    684 
    685   DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter);
    686 };
    687 
    688 
    689 // A RelocIterator iterates over relocation information.
    690 // Typical use:
    691 //
    692 //   for (RelocIterator it(code); !it.done(); it.next()) {
    693 //     // do something with it.rinfo() here
    694 //   }
    695 //
    696 // A mask can be specified to skip unwanted modes.
    697 class RelocIterator: public Malloced {
    698  public:
    699   // Create a new iterator positioned at
    700   // the beginning of the reloc info.
    701   // Relocation information with mode k is included in the
    702   // iteration iff bit k of mode_mask is set.
    703   explicit RelocIterator(Code* code, int mode_mask = -1);
    704   explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1);
    705 
    706   // Iteration
    707   bool done() const { return done_; }
    708   void next();
    709 
    710   // Return pointer valid until next next().
    711   RelocInfo* rinfo() {
    712     DCHECK(!done());
    713     return &rinfo_;
    714   }
    715 
    716  private:
    717   // Advance* moves the position before/after reading.
    718   // *Read* reads from current byte(s) into rinfo_.
    719   // *Get* just reads and returns info on current byte.
    720   void Advance(int bytes = 1) { pos_ -= bytes; }
    721   int AdvanceGetTag();
    722   RelocInfo::Mode GetMode();
    723 
    724   void AdvanceReadLongPCJump();
    725 
    726   int GetShortDataTypeTag();
    727   void ReadShortTaggedPC();
    728   void ReadShortTaggedId();
    729   void ReadShortTaggedData();
    730 
    731   void AdvanceReadPC();
    732   void AdvanceReadId();
    733   void AdvanceReadInt();
    734   void AdvanceReadData();
    735 
    736   // If the given mode is wanted, set it in rinfo_ and return true.
    737   // Else return false. Used for efficiently skipping unwanted modes.
    738   bool SetMode(RelocInfo::Mode mode) {
    739     return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false;
    740   }
    741 
    742   byte* pos_;
    743   byte* end_;
    744   byte* code_age_sequence_;
    745   RelocInfo rinfo_;
    746   bool done_;
    747   int mode_mask_;
    748   int last_id_;
    749   DISALLOW_COPY_AND_ASSIGN(RelocIterator);
    750 };
    751 
    752 
    753 //------------------------------------------------------------------------------
    754 // External function
    755 
    756 //----------------------------------------------------------------------------
    757 class SCTableReference;
    758 class Debug_Address;
    759 
    760 
    761 // An ExternalReference represents a C++ address used in the generated
    762 // code. All references to C++ functions and variables must be encapsulated in
    763 // an ExternalReference instance. This is done in order to track the origin of
    764 // all external references in the code so that they can be bound to the correct
    765 // addresses when deserializing a heap.
    766 class ExternalReference BASE_EMBEDDED {
    767  public:
    768   // Used in the simulator to support different native api calls.
    769   enum Type {
    770     // Builtin call.
    771     // Object* f(v8::internal::Arguments).
    772     BUILTIN_CALL,  // default
    773 
    774     // Builtin call returning object pair.
    775     // ObjectPair f(v8::internal::Arguments).
    776     BUILTIN_CALL_PAIR,
    777 
    778     // Builtin call that returns .
    779     // ObjectTriple f(v8::internal::Arguments).
    780     BUILTIN_CALL_TRIPLE,
    781 
    782     // Builtin that takes float arguments and returns an int.
    783     // int f(double, double).
    784     BUILTIN_COMPARE_CALL,
    785 
    786     // Builtin call that returns floating point.
    787     // double f(double, double).
    788     BUILTIN_FP_FP_CALL,
    789 
    790     // Builtin call that returns floating point.
    791     // double f(double).
    792     BUILTIN_FP_CALL,
    793 
    794     // Builtin call that returns floating point.
    795     // double f(double, int).
    796     BUILTIN_FP_INT_CALL,
    797 
    798     // Direct call to API function callback.
    799     // void f(v8::FunctionCallbackInfo&)
    800     DIRECT_API_CALL,
    801 
    802     // Call to function callback via InvokeFunctionCallback.
    803     // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback)
    804     PROFILING_API_CALL,
    805 
    806     // Direct call to accessor getter callback.
    807     // void f(Local<Name> property, PropertyCallbackInfo& info)
    808     DIRECT_GETTER_CALL,
    809 
    810     // Call to accessor getter callback via InvokeAccessorGetterCallback.
    811     // void f(Local<Name> property, PropertyCallbackInfo& info,
    812     //     AccessorNameGetterCallback callback)
    813     PROFILING_GETTER_CALL
    814   };
    815 
    816   static void SetUp();
    817 
    818   typedef void* ExternalReferenceRedirector(Isolate* isolate, void* original,
    819                                             Type type);
    820 
    821   ExternalReference() : address_(NULL) {}
    822 
    823   ExternalReference(Address address, Isolate* isolate);
    824 
    825   ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate);
    826 
    827   ExternalReference(Builtins::Name name, Isolate* isolate);
    828 
    829   ExternalReference(Runtime::FunctionId id, Isolate* isolate);
    830 
    831   ExternalReference(const Runtime::Function* f, Isolate* isolate);
    832 
    833   explicit ExternalReference(StatsCounter* counter);
    834 
    835   ExternalReference(Isolate::AddressId id, Isolate* isolate);
    836 
    837   explicit ExternalReference(const SCTableReference& table_ref);
    838 
    839   // Isolate as an external reference.
    840   static ExternalReference isolate_address(Isolate* isolate);
    841 
    842   // One-of-a-kind references. These references are not part of a general
    843   // pattern. This means that they have to be added to the
    844   // ExternalReferenceTable in serialize.cc manually.
    845 
    846   static ExternalReference interpreter_dispatch_table_address(Isolate* isolate);
    847   static ExternalReference interpreter_dispatch_counters(Isolate* isolate);
    848 
    849   static ExternalReference incremental_marking_record_write_function(
    850       Isolate* isolate);
    851   static ExternalReference incremental_marking_record_write_code_entry_function(
    852       Isolate* isolate);
    853   static ExternalReference store_buffer_overflow_function(
    854       Isolate* isolate);
    855   static ExternalReference delete_handle_scope_extensions(Isolate* isolate);
    856 
    857   static ExternalReference get_date_field_function(Isolate* isolate);
    858   static ExternalReference date_cache_stamp(Isolate* isolate);
    859 
    860   static ExternalReference get_make_code_young_function(Isolate* isolate);
    861   static ExternalReference get_mark_code_as_executed_function(Isolate* isolate);
    862 
    863   // Deoptimization support.
    864   static ExternalReference new_deoptimizer_function(Isolate* isolate);
    865   static ExternalReference compute_output_frames_function(Isolate* isolate);
    866 
    867   static ExternalReference wasm_f32_trunc(Isolate* isolate);
    868   static ExternalReference wasm_f32_floor(Isolate* isolate);
    869   static ExternalReference wasm_f32_ceil(Isolate* isolate);
    870   static ExternalReference wasm_f32_nearest_int(Isolate* isolate);
    871   static ExternalReference wasm_f64_trunc(Isolate* isolate);
    872   static ExternalReference wasm_f64_floor(Isolate* isolate);
    873   static ExternalReference wasm_f64_ceil(Isolate* isolate);
    874   static ExternalReference wasm_f64_nearest_int(Isolate* isolate);
    875   static ExternalReference wasm_int64_to_float32(Isolate* isolate);
    876   static ExternalReference wasm_uint64_to_float32(Isolate* isolate);
    877   static ExternalReference wasm_int64_to_float64(Isolate* isolate);
    878   static ExternalReference wasm_uint64_to_float64(Isolate* isolate);
    879   static ExternalReference wasm_float32_to_int64(Isolate* isolate);
    880   static ExternalReference wasm_float32_to_uint64(Isolate* isolate);
    881   static ExternalReference wasm_float64_to_int64(Isolate* isolate);
    882   static ExternalReference wasm_float64_to_uint64(Isolate* isolate);
    883   static ExternalReference wasm_int64_div(Isolate* isolate);
    884   static ExternalReference wasm_int64_mod(Isolate* isolate);
    885   static ExternalReference wasm_uint64_div(Isolate* isolate);
    886   static ExternalReference wasm_uint64_mod(Isolate* isolate);
    887   static ExternalReference wasm_word32_ctz(Isolate* isolate);
    888   static ExternalReference wasm_word64_ctz(Isolate* isolate);
    889   static ExternalReference wasm_word32_popcnt(Isolate* isolate);
    890   static ExternalReference wasm_word64_popcnt(Isolate* isolate);
    891   static ExternalReference wasm_float64_pow(Isolate* isolate);
    892 
    893   static ExternalReference f64_acos_wrapper_function(Isolate* isolate);
    894   static ExternalReference f64_asin_wrapper_function(Isolate* isolate);
    895   static ExternalReference f64_mod_wrapper_function(Isolate* isolate);
    896 
    897   // Trap callback function for cctest/wasm/wasm-run-utils.h
    898   static ExternalReference wasm_call_trap_callback_for_testing(
    899       Isolate* isolate);
    900 
    901   // Log support.
    902   static ExternalReference log_enter_external_function(Isolate* isolate);
    903   static ExternalReference log_leave_external_function(Isolate* isolate);
    904 
    905   // Static variable Heap::roots_array_start()
    906   static ExternalReference roots_array_start(Isolate* isolate);
    907 
    908   // Static variable Heap::allocation_sites_list_address()
    909   static ExternalReference allocation_sites_list_address(Isolate* isolate);
    910 
    911   // Static variable StackGuard::address_of_jslimit()
    912   V8_EXPORT_PRIVATE static ExternalReference address_of_stack_limit(
    913       Isolate* isolate);
    914 
    915   // Static variable StackGuard::address_of_real_jslimit()
    916   static ExternalReference address_of_real_stack_limit(Isolate* isolate);
    917 
    918   // Static variable RegExpStack::limit_address()
    919   static ExternalReference address_of_regexp_stack_limit(Isolate* isolate);
    920 
    921   // Static variables for RegExp.
    922   static ExternalReference address_of_static_offsets_vector(Isolate* isolate);
    923   static ExternalReference address_of_regexp_stack_memory_address(
    924       Isolate* isolate);
    925   static ExternalReference address_of_regexp_stack_memory_size(
    926       Isolate* isolate);
    927 
    928   // Write barrier.
    929   static ExternalReference store_buffer_top(Isolate* isolate);
    930 
    931   // Used for fast allocation in generated code.
    932   static ExternalReference new_space_allocation_top_address(Isolate* isolate);
    933   static ExternalReference new_space_allocation_limit_address(Isolate* isolate);
    934   static ExternalReference old_space_allocation_top_address(Isolate* isolate);
    935   static ExternalReference old_space_allocation_limit_address(Isolate* isolate);
    936 
    937   static ExternalReference mod_two_doubles_operation(Isolate* isolate);
    938   static ExternalReference power_double_double_function(Isolate* isolate);
    939 
    940   static ExternalReference handle_scope_next_address(Isolate* isolate);
    941   static ExternalReference handle_scope_limit_address(Isolate* isolate);
    942   static ExternalReference handle_scope_level_address(Isolate* isolate);
    943 
    944   static ExternalReference scheduled_exception_address(Isolate* isolate);
    945   static ExternalReference address_of_pending_message_obj(Isolate* isolate);
    946 
    947   // Static variables containing common double constants.
    948   static ExternalReference address_of_min_int();
    949   static ExternalReference address_of_one_half();
    950   static ExternalReference address_of_minus_one_half();
    951   static ExternalReference address_of_negative_infinity();
    952   static ExternalReference address_of_the_hole_nan();
    953   static ExternalReference address_of_uint32_bias();
    954 
    955   // Static variables containing simd constants.
    956   static ExternalReference address_of_float_abs_constant();
    957   static ExternalReference address_of_float_neg_constant();
    958   static ExternalReference address_of_double_abs_constant();
    959   static ExternalReference address_of_double_neg_constant();
    960 
    961   // IEEE 754 functions.
    962   static ExternalReference ieee754_acos_function(Isolate* isolate);
    963   static ExternalReference ieee754_acosh_function(Isolate* isolate);
    964   static ExternalReference ieee754_asin_function(Isolate* isolate);
    965   static ExternalReference ieee754_asinh_function(Isolate* isolate);
    966   static ExternalReference ieee754_atan_function(Isolate* isolate);
    967   static ExternalReference ieee754_atanh_function(Isolate* isolate);
    968   static ExternalReference ieee754_atan2_function(Isolate* isolate);
    969   static ExternalReference ieee754_cbrt_function(Isolate* isolate);
    970   static ExternalReference ieee754_cos_function(Isolate* isolate);
    971   static ExternalReference ieee754_cosh_function(Isolate* isolate);
    972   static ExternalReference ieee754_exp_function(Isolate* isolate);
    973   static ExternalReference ieee754_expm1_function(Isolate* isolate);
    974   static ExternalReference ieee754_log_function(Isolate* isolate);
    975   static ExternalReference ieee754_log1p_function(Isolate* isolate);
    976   static ExternalReference ieee754_log10_function(Isolate* isolate);
    977   static ExternalReference ieee754_log2_function(Isolate* isolate);
    978   static ExternalReference ieee754_sin_function(Isolate* isolate);
    979   static ExternalReference ieee754_sinh_function(Isolate* isolate);
    980   static ExternalReference ieee754_tan_function(Isolate* isolate);
    981   static ExternalReference ieee754_tanh_function(Isolate* isolate);
    982 
    983   static ExternalReference libc_memchr_function(Isolate* isolate);
    984 
    985   static ExternalReference page_flags(Page* page);
    986 
    987   static ExternalReference ForDeoptEntry(Address entry);
    988 
    989   static ExternalReference cpu_features();
    990 
    991   static ExternalReference is_tail_call_elimination_enabled_address(
    992       Isolate* isolate);
    993 
    994   static ExternalReference debug_is_active_address(Isolate* isolate);
    995   static ExternalReference debug_hook_on_function_call_address(
    996       Isolate* isolate);
    997   static ExternalReference debug_after_break_target_address(Isolate* isolate);
    998 
    999   static ExternalReference is_profiling_address(Isolate* isolate);
   1000   static ExternalReference invoke_function_callback(Isolate* isolate);
   1001   static ExternalReference invoke_accessor_getter_callback(Isolate* isolate);
   1002 
   1003   static ExternalReference promise_hook_or_debug_is_active_address(
   1004       Isolate* isolate);
   1005 
   1006   V8_EXPORT_PRIVATE static ExternalReference runtime_function_table_address(
   1007       Isolate* isolate);
   1008 
   1009   Address address() const { return reinterpret_cast<Address>(address_); }
   1010 
   1011   // Used to read out the last step action of the debugger.
   1012   static ExternalReference debug_last_step_action_address(Isolate* isolate);
   1013 
   1014   // Used to check for suspended generator, used for stepping across await call.
   1015   static ExternalReference debug_suspended_generator_address(Isolate* isolate);
   1016 
   1017   // Used to store the frame pointer to drop to when restarting a frame.
   1018   static ExternalReference debug_restart_fp_address(Isolate* isolate);
   1019 
   1020 #ifndef V8_INTERPRETED_REGEXP
   1021   // C functions called from RegExp generated code.
   1022 
   1023   // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16()
   1024   static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate);
   1025 
   1026   // Function RegExpMacroAssembler*::CheckStackGuardState()
   1027   static ExternalReference re_check_stack_guard_state(Isolate* isolate);
   1028 
   1029   // Function NativeRegExpMacroAssembler::GrowStack()
   1030   static ExternalReference re_grow_stack(Isolate* isolate);
   1031 
   1032   // byte NativeRegExpMacroAssembler::word_character_bitmap
   1033   static ExternalReference re_word_character_map();
   1034 
   1035 #endif
   1036 
   1037   // This lets you register a function that rewrites all external references.
   1038   // Used by the ARM simulator to catch calls to external references.
   1039   static void set_redirector(Isolate* isolate,
   1040                              ExternalReferenceRedirector* redirector) {
   1041     // We can't stack them.
   1042     DCHECK(isolate->external_reference_redirector() == NULL);
   1043     isolate->set_external_reference_redirector(
   1044         reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector));
   1045   }
   1046 
   1047   static ExternalReference stress_deopt_count(Isolate* isolate);
   1048 
   1049   static ExternalReference fixed_typed_array_base_data_offset();
   1050 
   1051  private:
   1052   explicit ExternalReference(void* address)
   1053       : address_(address) {}
   1054 
   1055   static void* Redirect(Isolate* isolate,
   1056                         Address address_arg,
   1057                         Type type = ExternalReference::BUILTIN_CALL) {
   1058     ExternalReferenceRedirector* redirector =
   1059         reinterpret_cast<ExternalReferenceRedirector*>(
   1060             isolate->external_reference_redirector());
   1061     void* address = reinterpret_cast<void*>(address_arg);
   1062     void* answer =
   1063         (redirector == NULL) ? address : (*redirector)(isolate, address, type);
   1064     return answer;
   1065   }
   1066 
   1067   void* address_;
   1068 };
   1069 
   1070 V8_EXPORT_PRIVATE bool operator==(ExternalReference, ExternalReference);
   1071 bool operator!=(ExternalReference, ExternalReference);
   1072 
   1073 size_t hash_value(ExternalReference);
   1074 
   1075 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, ExternalReference);
   1076 
   1077 // -----------------------------------------------------------------------------
   1078 // Utility functions
   1079 void* libc_memchr(void* string, int character, size_t search_length);
   1080 
   1081 inline int NumberOfBitsSet(uint32_t x) {
   1082   unsigned int num_bits_set;
   1083   for (num_bits_set = 0; x; x >>= 1) {
   1084     num_bits_set += x & 1;
   1085   }
   1086   return num_bits_set;
   1087 }
   1088 
   1089 // Computes pow(x, y) with the special cases in the spec for Math.pow.
   1090 double power_helper(Isolate* isolate, double x, double y);
   1091 double power_double_int(double x, int y);
   1092 double power_double_double(double x, double y);
   1093 
   1094 // Helper class for generating code or data associated with the code
   1095 // right after a call instruction. As an example this can be used to
   1096 // generate safepoint data after calls for crankshaft.
   1097 class CallWrapper {
   1098  public:
   1099   CallWrapper() { }
   1100   virtual ~CallWrapper() { }
   1101   // Called just before emitting a call. Argument is the size of the generated
   1102   // call code.
   1103   virtual void BeforeCall(int call_size) const = 0;
   1104   // Called just after emitting a call, i.e., at the return site for the call.
   1105   virtual void AfterCall() const = 0;
   1106   // Return whether call needs to check for debug stepping.
   1107   virtual bool NeedsDebugHookCheck() const { return false; }
   1108 };
   1109 
   1110 
   1111 class NullCallWrapper : public CallWrapper {
   1112  public:
   1113   NullCallWrapper() { }
   1114   virtual ~NullCallWrapper() { }
   1115   virtual void BeforeCall(int call_size) const { }
   1116   virtual void AfterCall() const { }
   1117 };
   1118 
   1119 
   1120 class CheckDebugStepCallWrapper : public CallWrapper {
   1121  public:
   1122   CheckDebugStepCallWrapper() {}
   1123   virtual ~CheckDebugStepCallWrapper() {}
   1124   virtual void BeforeCall(int call_size) const {}
   1125   virtual void AfterCall() const {}
   1126   virtual bool NeedsDebugHookCheck() const { return true; }
   1127 };
   1128 
   1129 
   1130 // -----------------------------------------------------------------------------
   1131 // Constant pool support
   1132 
   1133 class ConstantPoolEntry {
   1134  public:
   1135   ConstantPoolEntry() {}
   1136   ConstantPoolEntry(int position, intptr_t value, bool sharing_ok)
   1137       : position_(position),
   1138         merged_index_(sharing_ok ? SHARING_ALLOWED : SHARING_PROHIBITED),
   1139         value_(value) {}
   1140   ConstantPoolEntry(int position, double value)
   1141       : position_(position), merged_index_(SHARING_ALLOWED), value64_(value) {}
   1142 
   1143   int position() const { return position_; }
   1144   bool sharing_ok() const { return merged_index_ != SHARING_PROHIBITED; }
   1145   bool is_merged() const { return merged_index_ >= 0; }
   1146   int merged_index(void) const {
   1147     DCHECK(is_merged());
   1148     return merged_index_;
   1149   }
   1150   void set_merged_index(int index) {
   1151     merged_index_ = index;
   1152     DCHECK(is_merged());
   1153   }
   1154   int offset(void) const {
   1155     DCHECK(merged_index_ >= 0);
   1156     return merged_index_;
   1157   }
   1158   void set_offset(int offset) {
   1159     DCHECK(offset >= 0);
   1160     merged_index_ = offset;
   1161   }
   1162   intptr_t value() const { return value_; }
   1163   uint64_t value64() const { return bit_cast<uint64_t>(value64_); }
   1164 
   1165   enum Type { INTPTR, DOUBLE, NUMBER_OF_TYPES };
   1166 
   1167   static int size(Type type) {
   1168     return (type == INTPTR) ? kPointerSize : kDoubleSize;
   1169   }
   1170 
   1171   enum Access { REGULAR, OVERFLOWED };
   1172 
   1173  private:
   1174   int position_;
   1175   int merged_index_;
   1176   union {
   1177     intptr_t value_;
   1178     double value64_;
   1179   };
   1180   enum { SHARING_PROHIBITED = -2, SHARING_ALLOWED = -1 };
   1181 };
   1182 
   1183 
   1184 // -----------------------------------------------------------------------------
   1185 // Embedded constant pool support
   1186 
   1187 class ConstantPoolBuilder BASE_EMBEDDED {
   1188  public:
   1189   ConstantPoolBuilder(int ptr_reach_bits, int double_reach_bits);
   1190 
   1191   // Add pointer-sized constant to the embedded constant pool
   1192   ConstantPoolEntry::Access AddEntry(int position, intptr_t value,
   1193                                      bool sharing_ok) {
   1194     ConstantPoolEntry entry(position, value, sharing_ok);
   1195     return AddEntry(entry, ConstantPoolEntry::INTPTR);
   1196   }
   1197 
   1198   // Add double constant to the embedded constant pool
   1199   ConstantPoolEntry::Access AddEntry(int position, double value) {
   1200     ConstantPoolEntry entry(position, value);
   1201     return AddEntry(entry, ConstantPoolEntry::DOUBLE);
   1202   }
   1203 
   1204   // Previews the access type required for the next new entry to be added.
   1205   ConstantPoolEntry::Access NextAccess(ConstantPoolEntry::Type type) const;
   1206 
   1207   bool IsEmpty() {
   1208     return info_[ConstantPoolEntry::INTPTR].entries.empty() &&
   1209            info_[ConstantPoolEntry::INTPTR].shared_entries.empty() &&
   1210            info_[ConstantPoolEntry::DOUBLE].entries.empty() &&
   1211            info_[ConstantPoolEntry::DOUBLE].shared_entries.empty();
   1212   }
   1213 
   1214   // Emit the constant pool.  Invoke only after all entries have been
   1215   // added and all instructions have been emitted.
   1216   // Returns position of the emitted pool (zero implies no constant pool).
   1217   int Emit(Assembler* assm);
   1218 
   1219   // Returns the label associated with the start of the constant pool.
   1220   // Linking to this label in the function prologue may provide an
   1221   // efficient means of constant pool pointer register initialization
   1222   // on some architectures.
   1223   inline Label* EmittedPosition() { return &emitted_label_; }
   1224 
   1225  private:
   1226   ConstantPoolEntry::Access AddEntry(ConstantPoolEntry& entry,
   1227                                      ConstantPoolEntry::Type type);
   1228   void EmitSharedEntries(Assembler* assm, ConstantPoolEntry::Type type);
   1229   void EmitGroup(Assembler* assm, ConstantPoolEntry::Access access,
   1230                  ConstantPoolEntry::Type type);
   1231 
   1232   struct PerTypeEntryInfo {
   1233     PerTypeEntryInfo() : regular_count(0), overflow_start(-1) {}
   1234     bool overflow() const {
   1235       return (overflow_start >= 0 &&
   1236               overflow_start < static_cast<int>(entries.size()));
   1237     }
   1238     int regular_reach_bits;
   1239     int regular_count;
   1240     int overflow_start;
   1241     std::vector<ConstantPoolEntry> entries;
   1242     std::vector<ConstantPoolEntry> shared_entries;
   1243   };
   1244 
   1245   Label emitted_label_;  // Records pc_offset of emitted pool
   1246   PerTypeEntryInfo info_[ConstantPoolEntry::NUMBER_OF_TYPES];
   1247 };
   1248 
   1249 }  // namespace internal
   1250 }  // namespace v8
   1251 #endif  // V8_ASSEMBLER_H_
   1252