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