LCOV - code coverage report
Current view: top level - src - assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 59 67 88.1 %
Date: 2017-04-26 Functions: 19 29 65.5 %

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

Generated by: LCOV version 1.10