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

Generated by: LCOV version 1.10