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