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/v8.h" 39 40 #include "src/allocation.h" 41 #include "src/builtins.h" 42 #include "src/gdb-jit.h" 43 #include "src/isolate.h" 44 #include "src/runtime.h" 45 #include "src/token.h" 46 47 namespace v8 { 48 49 class ApiFunction; 50 51 namespace internal { 52 53 class StatsCounter; 54 // ----------------------------------------------------------------------------- 55 // Platform independent assembler base class. 56 57 class AssemblerBase: public Malloced { 58 public: 59 AssemblerBase(Isolate* isolate, void* buffer, int buffer_size); 60 virtual ~AssemblerBase(); 61 62 Isolate* isolate() const { return isolate_; } 63 int jit_cookie() const { return jit_cookie_; } 64 65 bool emit_debug_code() const { return emit_debug_code_; } 66 void set_emit_debug_code(bool value) { emit_debug_code_ = value; } 67 68 bool serializer_enabled() const { return serializer_enabled_; } 69 void enable_serializer() { serializer_enabled_ = true; } 70 71 bool predictable_code_size() const { return predictable_code_size_; } 72 void set_predictable_code_size(bool value) { predictable_code_size_ = value; } 73 74 uint64_t enabled_cpu_features() const { return enabled_cpu_features_; } 75 void set_enabled_cpu_features(uint64_t features) { 76 enabled_cpu_features_ = features; 77 } 78 bool IsEnabled(CpuFeature f) { 79 return (enabled_cpu_features_ & (static_cast<uint64_t>(1) << f)) != 0; 80 } 81 82 // Overwrite a host NaN with a quiet target NaN. Used by mksnapshot for 83 // cross-snapshotting. 84 static void QuietNaN(HeapObject* nan) { } 85 86 int pc_offset() const { return static_cast<int>(pc_ - buffer_); } 87 88 // This function is called when code generation is aborted, so that 89 // the assembler could clean up internal data structures. 90 virtual void AbortedCodeGeneration() { } 91 92 static const int kMinimalBufferSize = 4*KB; 93 94 protected: 95 // The buffer into which code and relocation info are generated. It could 96 // either be owned by the assembler or be provided externally. 97 byte* buffer_; 98 int buffer_size_; 99 bool own_buffer_; 100 101 // The program counter, which points into the buffer above and moves forward. 102 byte* pc_; 103 104 private: 105 Isolate* isolate_; 106 int jit_cookie_; 107 uint64_t enabled_cpu_features_; 108 bool emit_debug_code_; 109 bool predictable_code_size_; 110 bool serializer_enabled_; 111 }; 112 113 114 // Avoids emitting debug code during the lifetime of this scope object. 115 class DontEmitDebugCodeScope BASE_EMBEDDED { 116 public: 117 explicit DontEmitDebugCodeScope(AssemblerBase* assembler) 118 : assembler_(assembler), old_value_(assembler->emit_debug_code()) { 119 assembler_->set_emit_debug_code(false); 120 } 121 ~DontEmitDebugCodeScope() { 122 assembler_->set_emit_debug_code(old_value_); 123 } 124 private: 125 AssemblerBase* assembler_; 126 bool old_value_; 127 }; 128 129 130 // Avoids using instructions that vary in size in unpredictable ways between the 131 // snapshot and the running VM. 132 class PredictableCodeSizeScope { 133 public: 134 PredictableCodeSizeScope(AssemblerBase* assembler, int expected_size); 135 ~PredictableCodeSizeScope(); 136 137 private: 138 AssemblerBase* assembler_; 139 int expected_size_; 140 int start_offset_; 141 bool old_value_; 142 }; 143 144 145 // Enable a specified feature within a scope. 146 class CpuFeatureScope BASE_EMBEDDED { 147 public: 148 #ifdef DEBUG 149 CpuFeatureScope(AssemblerBase* assembler, CpuFeature f); 150 ~CpuFeatureScope(); 151 152 private: 153 AssemblerBase* assembler_; 154 uint64_t old_enabled_; 155 #else 156 CpuFeatureScope(AssemblerBase* assembler, CpuFeature f) {} 157 #endif 158 }; 159 160 161 // CpuFeatures keeps track of which features are supported by the target CPU. 162 // Supported features must be enabled by a CpuFeatureScope before use. 163 // Example: 164 // if (assembler->IsSupported(SSE3)) { 165 // CpuFeatureScope fscope(assembler, SSE3); 166 // // Generate code containing SSE3 instructions. 167 // } else { 168 // // Generate alternative code. 169 // } 170 class CpuFeatures : public AllStatic { 171 public: 172 static void Probe(bool cross_compile) { 173 STATIC_ASSERT(NUMBER_OF_CPU_FEATURES <= kBitsPerInt); 174 if (initialized_) return; 175 initialized_ = true; 176 ProbeImpl(cross_compile); 177 } 178 179 static unsigned SupportedFeatures() { 180 Probe(false); 181 return supported_; 182 } 183 184 static bool IsSupported(CpuFeature f) { 185 return (supported_ & (1u << f)) != 0; 186 } 187 188 static inline bool SupportsCrankshaft(); 189 190 static inline unsigned cache_line_size() { 191 DCHECK(cache_line_size_ != 0); 192 return cache_line_size_; 193 } 194 195 static void PrintTarget(); 196 static void PrintFeatures(); 197 198 // Flush instruction cache. 199 static void FlushICache(void* start, size_t size); 200 201 private: 202 // Platform-dependent implementation. 203 static void ProbeImpl(bool cross_compile); 204 205 static unsigned supported_; 206 static unsigned cache_line_size_; 207 static bool initialized_; 208 friend class ExternalReference; 209 DISALLOW_COPY_AND_ASSIGN(CpuFeatures); 210 }; 211 212 213 // ----------------------------------------------------------------------------- 214 // Labels represent pc locations; they are typically jump or call targets. 215 // After declaration, a label can be freely used to denote known or (yet) 216 // unknown pc location. Assembler::bind() is used to bind a label to the 217 // current pc. A label can be bound only once. 218 219 class Label BASE_EMBEDDED { 220 public: 221 enum Distance { 222 kNear, kFar 223 }; 224 225 INLINE(Label()) { 226 Unuse(); 227 UnuseNear(); 228 } 229 230 INLINE(~Label()) { 231 DCHECK(!is_linked()); 232 DCHECK(!is_near_linked()); 233 } 234 235 INLINE(void Unuse()) { pos_ = 0; } 236 INLINE(void UnuseNear()) { near_link_pos_ = 0; } 237 238 INLINE(bool is_bound() const) { return pos_ < 0; } 239 INLINE(bool is_unused() const) { return pos_ == 0 && near_link_pos_ == 0; } 240 INLINE(bool is_linked() const) { return pos_ > 0; } 241 INLINE(bool is_near_linked() const) { return near_link_pos_ > 0; } 242 243 // Returns the position of bound or linked labels. Cannot be used 244 // for unused labels. 245 int pos() const; 246 int near_link_pos() const { return near_link_pos_ - 1; } 247 248 private: 249 // pos_ encodes both the binding state (via its sign) 250 // and the binding position (via its value) of a label. 251 // 252 // pos_ < 0 bound label, pos() returns the jump target position 253 // pos_ == 0 unused label 254 // pos_ > 0 linked label, pos() returns the last reference position 255 int pos_; 256 257 // Behaves like |pos_| in the "> 0" case, but for near jumps to this label. 258 int near_link_pos_; 259 260 void bind_to(int pos) { 261 pos_ = -pos - 1; 262 DCHECK(is_bound()); 263 } 264 void link_to(int pos, Distance distance = kFar) { 265 if (distance == kNear) { 266 near_link_pos_ = pos + 1; 267 DCHECK(is_near_linked()); 268 } else { 269 pos_ = pos + 1; 270 DCHECK(is_linked()); 271 } 272 } 273 274 friend class Assembler; 275 friend class Displacement; 276 friend class RegExpMacroAssemblerIrregexp; 277 278 #if V8_TARGET_ARCH_ARM64 279 // On ARM64, the Assembler keeps track of pointers to Labels to resolve 280 // branches to distant targets. Copying labels would confuse the Assembler. 281 DISALLOW_COPY_AND_ASSIGN(Label); // NOLINT 282 #endif 283 }; 284 285 286 enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs }; 287 288 // Specifies whether to perform icache flush operations on RelocInfo updates. 289 // If FLUSH_ICACHE_IF_NEEDED, the icache will always be flushed if an 290 // instruction was modified. If SKIP_ICACHE_FLUSH the flush will always be 291 // skipped (only use this if you will flush the icache manually before it is 292 // executed). 293 enum ICacheFlushMode { FLUSH_ICACHE_IF_NEEDED, SKIP_ICACHE_FLUSH }; 294 295 // ----------------------------------------------------------------------------- 296 // Relocation information 297 298 299 // Relocation information consists of the address (pc) of the datum 300 // to which the relocation information applies, the relocation mode 301 // (rmode), and an optional data field. The relocation mode may be 302 // "descriptive" and not indicate a need for relocation, but simply 303 // describe a property of the datum. Such rmodes are useful for GC 304 // and nice disassembly output. 305 306 class RelocInfo { 307 public: 308 // The constant kNoPosition is used with the collecting of source positions 309 // in the relocation information. Two types of source positions are collected 310 // "position" (RelocMode position) and "statement position" (RelocMode 311 // statement_position). The "position" is collected at places in the source 312 // code which are of interest when making stack traces to pin-point the source 313 // location of a stack frame as close as possible. The "statement position" is 314 // collected at the beginning at each statement, and is used to indicate 315 // possible break locations. kNoPosition is used to indicate an 316 // invalid/uninitialized position value. 317 static const int kNoPosition = -1; 318 319 // This string is used to add padding comments to the reloc info in cases 320 // where we are not sure to have enough space for patching in during 321 // lazy deoptimization. This is the case if we have indirect calls for which 322 // we do not normally record relocation info. 323 static const char* const kFillerCommentString; 324 325 // The minimum size of a comment is equal to three bytes for the extra tagged 326 // pc + the tag for the data, and kPointerSize for the actual pointer to the 327 // comment. 328 static const int kMinRelocCommentSize = 3 + kPointerSize; 329 330 // The maximum size for a call instruction including pc-jump. 331 static const int kMaxCallSize = 6; 332 333 // The maximum pc delta that will use the short encoding. 334 static const int kMaxSmallPCDelta; 335 336 enum Mode { 337 // Please note the order is important (see IsCodeTarget, IsGCRelocMode). 338 CODE_TARGET, // Code target which is not any of the above. 339 CODE_TARGET_WITH_ID, 340 CONSTRUCT_CALL, // code target that is a call to a JavaScript constructor. 341 DEBUG_BREAK, // Code target for the debugger statement. 342 EMBEDDED_OBJECT, 343 CELL, 344 345 // Everything after runtime_entry (inclusive) is not GC'ed. 346 RUNTIME_ENTRY, 347 JS_RETURN, // Marks start of the ExitJSFrame code. 348 COMMENT, 349 POSITION, // See comment for kNoPosition above. 350 STATEMENT_POSITION, // See comment for kNoPosition above. 351 DEBUG_BREAK_SLOT, // Additional code inserted for debug break slot. 352 EXTERNAL_REFERENCE, // The address of an external C++ function. 353 INTERNAL_REFERENCE, // An address inside the same function. 354 355 // Marks constant and veneer pools. Only used on ARM and ARM64. 356 // They use a custom noncompact encoding. 357 CONST_POOL, 358 VENEER_POOL, 359 360 // add more as needed 361 // Pseudo-types 362 NUMBER_OF_MODES, // There are at most 15 modes with noncompact encoding. 363 NONE32, // never recorded 32-bit value 364 NONE64, // never recorded 64-bit value 365 CODE_AGE_SEQUENCE, // Not stored in RelocInfo array, used explictly by 366 // code aging. 367 FIRST_REAL_RELOC_MODE = CODE_TARGET, 368 LAST_REAL_RELOC_MODE = VENEER_POOL, 369 FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE, 370 LAST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE, 371 LAST_CODE_ENUM = DEBUG_BREAK, 372 LAST_GCED_ENUM = CELL, 373 // Modes <= LAST_COMPACT_ENUM are guaranteed to have compact encoding. 374 LAST_COMPACT_ENUM = CODE_TARGET_WITH_ID, 375 LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE 376 }; 377 378 RelocInfo() {} 379 380 RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host) 381 : pc_(pc), rmode_(rmode), data_(data), host_(host) { 382 } 383 RelocInfo(byte* pc, double data64) 384 : pc_(pc), rmode_(NONE64), data64_(data64), host_(NULL) { 385 } 386 387 static inline bool IsRealRelocMode(Mode mode) { 388 return mode >= FIRST_REAL_RELOC_MODE && 389 mode <= LAST_REAL_RELOC_MODE; 390 } 391 static inline bool IsPseudoRelocMode(Mode mode) { 392 DCHECK(!IsRealRelocMode(mode)); 393 return mode >= FIRST_PSEUDO_RELOC_MODE && 394 mode <= LAST_PSEUDO_RELOC_MODE; 395 } 396 static inline bool IsConstructCall(Mode mode) { 397 return mode == CONSTRUCT_CALL; 398 } 399 static inline bool IsCodeTarget(Mode mode) { 400 return mode <= LAST_CODE_ENUM; 401 } 402 static inline bool IsEmbeddedObject(Mode mode) { 403 return mode == EMBEDDED_OBJECT; 404 } 405 static inline bool IsRuntimeEntry(Mode mode) { 406 return mode == RUNTIME_ENTRY; 407 } 408 // Is the relocation mode affected by GC? 409 static inline bool IsGCRelocMode(Mode mode) { 410 return mode <= LAST_GCED_ENUM; 411 } 412 static inline bool IsJSReturn(Mode mode) { 413 return mode == JS_RETURN; 414 } 415 static inline bool IsComment(Mode mode) { 416 return mode == COMMENT; 417 } 418 static inline bool IsConstPool(Mode mode) { 419 return mode == CONST_POOL; 420 } 421 static inline bool IsVeneerPool(Mode mode) { 422 return mode == VENEER_POOL; 423 } 424 static inline bool IsPosition(Mode mode) { 425 return mode == POSITION || mode == STATEMENT_POSITION; 426 } 427 static inline bool IsStatementPosition(Mode mode) { 428 return mode == STATEMENT_POSITION; 429 } 430 static inline bool IsExternalReference(Mode mode) { 431 return mode == EXTERNAL_REFERENCE; 432 } 433 static inline bool IsInternalReference(Mode mode) { 434 return mode == INTERNAL_REFERENCE; 435 } 436 static inline bool IsDebugBreakSlot(Mode mode) { 437 return mode == DEBUG_BREAK_SLOT; 438 } 439 static inline bool IsNone(Mode mode) { 440 return mode == NONE32 || mode == NONE64; 441 } 442 static inline bool IsCodeAgeSequence(Mode mode) { 443 return mode == CODE_AGE_SEQUENCE; 444 } 445 static inline int ModeMask(Mode mode) { return 1 << mode; } 446 447 // Returns true if the first RelocInfo has the same mode and raw data as the 448 // second one. 449 static inline bool IsEqual(RelocInfo first, RelocInfo second) { 450 return first.rmode() == second.rmode() && 451 (first.rmode() == RelocInfo::NONE64 ? 452 first.raw_data64() == second.raw_data64() : 453 first.data() == second.data()); 454 } 455 456 // Accessors 457 byte* pc() const { return pc_; } 458 void set_pc(byte* pc) { pc_ = pc; } 459 Mode rmode() const { return rmode_; } 460 intptr_t data() const { return data_; } 461 double data64() const { return data64_; } 462 uint64_t raw_data64() { return bit_cast<uint64_t>(data64_); } 463 Code* host() const { return host_; } 464 void set_host(Code* host) { host_ = host; } 465 466 // Apply a relocation by delta bytes 467 INLINE(void apply(intptr_t delta, 468 ICacheFlushMode icache_flush_mode = 469 FLUSH_ICACHE_IF_NEEDED)); 470 471 // Is the pointer this relocation info refers to coded like a plain pointer 472 // or is it strange in some way (e.g. relative or patched into a series of 473 // instructions). 474 bool IsCodedSpecially(); 475 476 // If true, the pointer this relocation info refers to is an entry in the 477 // constant pool, otherwise the pointer is embedded in the instruction stream. 478 bool IsInConstantPool(); 479 480 // Read/modify the code target in the branch/call instruction 481 // this relocation applies to; 482 // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) 483 INLINE(Address target_address()); 484 INLINE(void set_target_address(Address target, 485 WriteBarrierMode write_barrier_mode = 486 UPDATE_WRITE_BARRIER, 487 ICacheFlushMode icache_flush_mode = 488 FLUSH_ICACHE_IF_NEEDED)); 489 INLINE(Object* target_object()); 490 INLINE(Handle<Object> target_object_handle(Assembler* origin)); 491 INLINE(void set_target_object(Object* target, 492 WriteBarrierMode write_barrier_mode = 493 UPDATE_WRITE_BARRIER, 494 ICacheFlushMode icache_flush_mode = 495 FLUSH_ICACHE_IF_NEEDED)); 496 INLINE(Address target_runtime_entry(Assembler* origin)); 497 INLINE(void set_target_runtime_entry(Address target, 498 WriteBarrierMode write_barrier_mode = 499 UPDATE_WRITE_BARRIER, 500 ICacheFlushMode icache_flush_mode = 501 FLUSH_ICACHE_IF_NEEDED)); 502 INLINE(Cell* target_cell()); 503 INLINE(Handle<Cell> target_cell_handle()); 504 INLINE(void set_target_cell(Cell* cell, 505 WriteBarrierMode write_barrier_mode = 506 UPDATE_WRITE_BARRIER, 507 ICacheFlushMode icache_flush_mode = 508 FLUSH_ICACHE_IF_NEEDED)); 509 INLINE(Handle<Object> code_age_stub_handle(Assembler* origin)); 510 INLINE(Code* code_age_stub()); 511 INLINE(void set_code_age_stub(Code* stub, 512 ICacheFlushMode icache_flush_mode = 513 FLUSH_ICACHE_IF_NEEDED)); 514 515 // Returns the address of the constant pool entry where the target address 516 // is held. This should only be called if IsInConstantPool returns true. 517 INLINE(Address constant_pool_entry_address()); 518 519 // Read the address of the word containing the target_address in an 520 // instruction stream. What this means exactly is architecture-independent. 521 // The only architecture-independent user of this function is the serializer. 522 // The serializer uses it to find out how many raw bytes of instruction to 523 // output before the next target. Architecture-independent code shouldn't 524 // dereference the pointer it gets back from this. 525 INLINE(Address target_address_address()); 526 527 // This indicates how much space a target takes up when deserializing a code 528 // stream. For most architectures this is just the size of a pointer. For 529 // an instruction like movw/movt where the target bits are mixed into the 530 // instruction bits the size of the target will be zero, indicating that the 531 // serializer should not step forwards in memory after a target is resolved 532 // and written. In this case the target_address_address function above 533 // should return the end of the instructions to be patched, allowing the 534 // deserializer to deserialize the instructions as raw bytes and put them in 535 // place, ready to be patched with the target. 536 INLINE(int target_address_size()); 537 538 // Read/modify the reference in the instruction this relocation 539 // applies to; can only be called if rmode_ is external_reference 540 INLINE(Address target_reference()); 541 542 // Read/modify the address of a call instruction. This is used to relocate 543 // the break points where straight-line code is patched with a call 544 // instruction. 545 INLINE(Address call_address()); 546 INLINE(void set_call_address(Address target)); 547 INLINE(Object* call_object()); 548 INLINE(void set_call_object(Object* target)); 549 INLINE(Object** call_object_address()); 550 551 // Wipe out a relocation to a fixed value, used for making snapshots 552 // reproducible. 553 INLINE(void WipeOut()); 554 555 template<typename StaticVisitor> inline void Visit(Heap* heap); 556 inline void Visit(Isolate* isolate, ObjectVisitor* v); 557 558 // Patch the code with some other code. 559 void PatchCode(byte* instructions, int instruction_count); 560 561 // Patch the code with a call. 562 void PatchCodeWithCall(Address target, int guard_bytes); 563 564 // Check whether this return sequence has been patched 565 // with a call to the debugger. 566 INLINE(bool IsPatchedReturnSequence()); 567 568 // Check whether this debug break slot has been patched with a call to the 569 // debugger. 570 INLINE(bool IsPatchedDebugBreakSlotSequence()); 571 572 #ifdef DEBUG 573 // Check whether the given code contains relocation information that 574 // either is position-relative or movable by the garbage collector. 575 static bool RequiresRelocation(const CodeDesc& desc); 576 #endif 577 578 #ifdef ENABLE_DISASSEMBLER 579 // Printing 580 static const char* RelocModeName(Mode rmode); 581 void Print(Isolate* isolate, OStream& os); // NOLINT 582 #endif // ENABLE_DISASSEMBLER 583 #ifdef VERIFY_HEAP 584 void Verify(Isolate* isolate); 585 #endif 586 587 static const int kCodeTargetMask = (1 << (LAST_CODE_ENUM + 1)) - 1; 588 static const int kPositionMask = 1 << POSITION | 1 << STATEMENT_POSITION; 589 static const int kDataMask = 590 (1 << CODE_TARGET_WITH_ID) | kPositionMask | (1 << COMMENT); 591 static const int kApplyMask; // Modes affected by apply. Depends on arch. 592 593 private: 594 // On ARM, note that pc_ is the address of the constant pool entry 595 // to be relocated and not the address of the instruction 596 // referencing the constant pool entry (except when rmode_ == 597 // comment). 598 byte* pc_; 599 Mode rmode_; 600 union { 601 intptr_t data_; 602 double data64_; 603 }; 604 Code* host_; 605 // External-reference pointers are also split across instruction-pairs 606 // on some platforms, but are accessed via indirect pointers. This location 607 // provides a place for that pointer to exist naturally. Its address 608 // is returned by RelocInfo::target_reference_address(). 609 Address reconstructed_adr_ptr_; 610 friend class RelocIterator; 611 }; 612 613 614 // RelocInfoWriter serializes a stream of relocation info. It writes towards 615 // lower addresses. 616 class RelocInfoWriter BASE_EMBEDDED { 617 public: 618 RelocInfoWriter() : pos_(NULL), 619 last_pc_(NULL), 620 last_id_(0), 621 last_position_(0) {} 622 RelocInfoWriter(byte* pos, byte* pc) : pos_(pos), 623 last_pc_(pc), 624 last_id_(0), 625 last_position_(0) {} 626 627 byte* pos() const { return pos_; } 628 byte* last_pc() const { return last_pc_; } 629 630 void Write(const RelocInfo* rinfo); 631 632 // Update the state of the stream after reloc info buffer 633 // and/or code is moved while the stream is active. 634 void Reposition(byte* pos, byte* pc) { 635 pos_ = pos; 636 last_pc_ = pc; 637 } 638 639 // Max size (bytes) of a written RelocInfo. Longest encoding is 640 // ExtraTag, VariableLengthPCJump, ExtraTag, pc_delta, ExtraTag, data_delta. 641 // On ia32 and arm this is 1 + 4 + 1 + 1 + 1 + 4 = 12. 642 // On x64 this is 1 + 4 + 1 + 1 + 1 + 8 == 16; 643 // Here we use the maximum of the two. 644 static const int kMaxSize = 16; 645 646 private: 647 inline uint32_t WriteVariableLengthPCJump(uint32_t pc_delta); 648 inline void WriteTaggedPC(uint32_t pc_delta, int tag); 649 inline void WriteExtraTaggedPC(uint32_t pc_delta, int extra_tag); 650 inline void WriteExtraTaggedIntData(int data_delta, int top_tag); 651 inline void WriteExtraTaggedPoolData(int data, int pool_type); 652 inline void WriteExtraTaggedData(intptr_t data_delta, int top_tag); 653 inline void WriteTaggedData(intptr_t data_delta, int tag); 654 inline void WriteExtraTag(int extra_tag, int top_tag); 655 656 byte* pos_; 657 byte* last_pc_; 658 int last_id_; 659 int last_position_; 660 DISALLOW_COPY_AND_ASSIGN(RelocInfoWriter); 661 }; 662 663 664 // A RelocIterator iterates over relocation information. 665 // Typical use: 666 // 667 // for (RelocIterator it(code); !it.done(); it.next()) { 668 // // do something with it.rinfo() here 669 // } 670 // 671 // A mask can be specified to skip unwanted modes. 672 class RelocIterator: public Malloced { 673 public: 674 // Create a new iterator positioned at 675 // the beginning of the reloc info. 676 // Relocation information with mode k is included in the 677 // iteration iff bit k of mode_mask is set. 678 explicit RelocIterator(Code* code, int mode_mask = -1); 679 explicit RelocIterator(const CodeDesc& desc, int mode_mask = -1); 680 681 // Iteration 682 bool done() const { return done_; } 683 void next(); 684 685 // Return pointer valid until next next(). 686 RelocInfo* rinfo() { 687 DCHECK(!done()); 688 return &rinfo_; 689 } 690 691 private: 692 // Advance* moves the position before/after reading. 693 // *Read* reads from current byte(s) into rinfo_. 694 // *Get* just reads and returns info on current byte. 695 void Advance(int bytes = 1) { pos_ -= bytes; } 696 int AdvanceGetTag(); 697 int GetExtraTag(); 698 int GetTopTag(); 699 void ReadTaggedPC(); 700 void AdvanceReadPC(); 701 void AdvanceReadId(); 702 void AdvanceReadPoolData(); 703 void AdvanceReadPosition(); 704 void AdvanceReadData(); 705 void AdvanceReadVariableLengthPCJump(); 706 int GetLocatableTypeTag(); 707 void ReadTaggedId(); 708 void ReadTaggedPosition(); 709 710 // If the given mode is wanted, set it in rinfo_ and return true. 711 // Else return false. Used for efficiently skipping unwanted modes. 712 bool SetMode(RelocInfo::Mode mode) { 713 return (mode_mask_ & (1 << mode)) ? (rinfo_.rmode_ = mode, true) : false; 714 } 715 716 byte* pos_; 717 byte* end_; 718 byte* code_age_sequence_; 719 RelocInfo rinfo_; 720 bool done_; 721 int mode_mask_; 722 int last_id_; 723 int last_position_; 724 DISALLOW_COPY_AND_ASSIGN(RelocIterator); 725 }; 726 727 728 //------------------------------------------------------------------------------ 729 // External function 730 731 //---------------------------------------------------------------------------- 732 class IC_Utility; 733 class SCTableReference; 734 class Debug_Address; 735 736 737 // An ExternalReference represents a C++ address used in the generated 738 // code. All references to C++ functions and variables must be encapsulated in 739 // an ExternalReference instance. This is done in order to track the origin of 740 // all external references in the code so that they can be bound to the correct 741 // addresses when deserializing a heap. 742 class ExternalReference BASE_EMBEDDED { 743 public: 744 // Used in the simulator to support different native api calls. 745 enum Type { 746 // Builtin call. 747 // Object* f(v8::internal::Arguments). 748 BUILTIN_CALL, // default 749 750 // Builtin that takes float arguments and returns an int. 751 // int f(double, double). 752 BUILTIN_COMPARE_CALL, 753 754 // Builtin call that returns floating point. 755 // double f(double, double). 756 BUILTIN_FP_FP_CALL, 757 758 // Builtin call that returns floating point. 759 // double f(double). 760 BUILTIN_FP_CALL, 761 762 // Builtin call that returns floating point. 763 // double f(double, int). 764 BUILTIN_FP_INT_CALL, 765 766 // Direct call to API function callback. 767 // void f(v8::FunctionCallbackInfo&) 768 DIRECT_API_CALL, 769 770 // Call to function callback via InvokeFunctionCallback. 771 // void f(v8::FunctionCallbackInfo&, v8::FunctionCallback) 772 PROFILING_API_CALL, 773 774 // Direct call to accessor getter callback. 775 // void f(Local<Name> property, PropertyCallbackInfo& info) 776 DIRECT_GETTER_CALL, 777 778 // Call to accessor getter callback via InvokeAccessorGetterCallback. 779 // void f(Local<Name> property, PropertyCallbackInfo& info, 780 // AccessorNameGetterCallback callback) 781 PROFILING_GETTER_CALL 782 }; 783 784 static void SetUp(); 785 static void InitializeMathExpData(); 786 static void TearDownMathExpData(); 787 788 typedef void* ExternalReferenceRedirector(void* original, Type type); 789 790 ExternalReference() : address_(NULL) {} 791 792 ExternalReference(Builtins::CFunctionId id, Isolate* isolate); 793 794 ExternalReference(ApiFunction* ptr, Type type, Isolate* isolate); 795 796 ExternalReference(Builtins::Name name, Isolate* isolate); 797 798 ExternalReference(Runtime::FunctionId id, Isolate* isolate); 799 800 ExternalReference(const Runtime::Function* f, Isolate* isolate); 801 802 ExternalReference(const IC_Utility& ic_utility, Isolate* isolate); 803 804 explicit ExternalReference(StatsCounter* counter); 805 806 ExternalReference(Isolate::AddressId id, Isolate* isolate); 807 808 explicit ExternalReference(const SCTableReference& table_ref); 809 810 // Isolate as an external reference. 811 static ExternalReference isolate_address(Isolate* isolate); 812 813 // One-of-a-kind references. These references are not part of a general 814 // pattern. This means that they have to be added to the 815 // ExternalReferenceTable in serialize.cc manually. 816 817 static ExternalReference incremental_marking_record_write_function( 818 Isolate* isolate); 819 static ExternalReference store_buffer_overflow_function( 820 Isolate* isolate); 821 static ExternalReference flush_icache_function(Isolate* isolate); 822 static ExternalReference delete_handle_scope_extensions(Isolate* isolate); 823 824 static ExternalReference get_date_field_function(Isolate* isolate); 825 static ExternalReference date_cache_stamp(Isolate* isolate); 826 827 static ExternalReference get_make_code_young_function(Isolate* isolate); 828 static ExternalReference get_mark_code_as_executed_function(Isolate* isolate); 829 830 // Deoptimization support. 831 static ExternalReference new_deoptimizer_function(Isolate* isolate); 832 static ExternalReference compute_output_frames_function(Isolate* isolate); 833 834 // Log support. 835 static ExternalReference log_enter_external_function(Isolate* isolate); 836 static ExternalReference log_leave_external_function(Isolate* isolate); 837 838 // Static data in the keyed lookup cache. 839 static ExternalReference keyed_lookup_cache_keys(Isolate* isolate); 840 static ExternalReference keyed_lookup_cache_field_offsets(Isolate* isolate); 841 842 // Static variable Heap::roots_array_start() 843 static ExternalReference roots_array_start(Isolate* isolate); 844 845 // Static variable Heap::allocation_sites_list_address() 846 static ExternalReference allocation_sites_list_address(Isolate* isolate); 847 848 // Static variable StackGuard::address_of_jslimit() 849 static ExternalReference address_of_stack_limit(Isolate* isolate); 850 851 // Static variable StackGuard::address_of_real_jslimit() 852 static ExternalReference address_of_real_stack_limit(Isolate* isolate); 853 854 // Static variable RegExpStack::limit_address() 855 static ExternalReference address_of_regexp_stack_limit(Isolate* isolate); 856 857 // Static variables for RegExp. 858 static ExternalReference address_of_static_offsets_vector(Isolate* isolate); 859 static ExternalReference address_of_regexp_stack_memory_address( 860 Isolate* isolate); 861 static ExternalReference address_of_regexp_stack_memory_size( 862 Isolate* isolate); 863 864 // Static variable Heap::NewSpaceStart() 865 static ExternalReference new_space_start(Isolate* isolate); 866 static ExternalReference new_space_mask(Isolate* isolate); 867 868 // Write barrier. 869 static ExternalReference store_buffer_top(Isolate* isolate); 870 871 // Used for fast allocation in generated code. 872 static ExternalReference new_space_allocation_top_address(Isolate* isolate); 873 static ExternalReference new_space_allocation_limit_address(Isolate* isolate); 874 static ExternalReference old_pointer_space_allocation_top_address( 875 Isolate* isolate); 876 static ExternalReference old_pointer_space_allocation_limit_address( 877 Isolate* isolate); 878 static ExternalReference old_data_space_allocation_top_address( 879 Isolate* isolate); 880 static ExternalReference old_data_space_allocation_limit_address( 881 Isolate* isolate); 882 883 static ExternalReference mod_two_doubles_operation(Isolate* isolate); 884 static ExternalReference power_double_double_function(Isolate* isolate); 885 static ExternalReference power_double_int_function(Isolate* isolate); 886 887 static ExternalReference handle_scope_next_address(Isolate* isolate); 888 static ExternalReference handle_scope_limit_address(Isolate* isolate); 889 static ExternalReference handle_scope_level_address(Isolate* isolate); 890 891 static ExternalReference scheduled_exception_address(Isolate* isolate); 892 static ExternalReference address_of_pending_message_obj(Isolate* isolate); 893 static ExternalReference address_of_has_pending_message(Isolate* isolate); 894 static ExternalReference address_of_pending_message_script(Isolate* isolate); 895 896 // Static variables containing common double constants. 897 static ExternalReference address_of_min_int(); 898 static ExternalReference address_of_one_half(); 899 static ExternalReference address_of_minus_one_half(); 900 static ExternalReference address_of_negative_infinity(); 901 static ExternalReference address_of_canonical_non_hole_nan(); 902 static ExternalReference address_of_the_hole_nan(); 903 static ExternalReference address_of_uint32_bias(); 904 905 static ExternalReference math_log_double_function(Isolate* isolate); 906 907 static ExternalReference math_exp_constants(int constant_index); 908 static ExternalReference math_exp_log_table(); 909 910 static ExternalReference page_flags(Page* page); 911 912 static ExternalReference ForDeoptEntry(Address entry); 913 914 static ExternalReference cpu_features(); 915 916 static ExternalReference debug_is_active_address(Isolate* isolate); 917 static ExternalReference debug_after_break_target_address(Isolate* isolate); 918 static ExternalReference debug_restarter_frame_function_pointer_address( 919 Isolate* isolate); 920 921 static ExternalReference is_profiling_address(Isolate* isolate); 922 static ExternalReference invoke_function_callback(Isolate* isolate); 923 static ExternalReference invoke_accessor_getter_callback(Isolate* isolate); 924 925 Address address() const { return reinterpret_cast<Address>(address_); } 926 927 // Function Debug::Break() 928 static ExternalReference debug_break(Isolate* isolate); 929 930 // Used to check if single stepping is enabled in generated code. 931 static ExternalReference debug_step_in_fp_address(Isolate* isolate); 932 933 #ifndef V8_INTERPRETED_REGEXP 934 // C functions called from RegExp generated code. 935 936 // Function NativeRegExpMacroAssembler::CaseInsensitiveCompareUC16() 937 static ExternalReference re_case_insensitive_compare_uc16(Isolate* isolate); 938 939 // Function RegExpMacroAssembler*::CheckStackGuardState() 940 static ExternalReference re_check_stack_guard_state(Isolate* isolate); 941 942 // Function NativeRegExpMacroAssembler::GrowStack() 943 static ExternalReference re_grow_stack(Isolate* isolate); 944 945 // byte NativeRegExpMacroAssembler::word_character_bitmap 946 static ExternalReference re_word_character_map(); 947 948 #endif 949 950 // This lets you register a function that rewrites all external references. 951 // Used by the ARM simulator to catch calls to external references. 952 static void set_redirector(Isolate* isolate, 953 ExternalReferenceRedirector* redirector) { 954 // We can't stack them. 955 DCHECK(isolate->external_reference_redirector() == NULL); 956 isolate->set_external_reference_redirector( 957 reinterpret_cast<ExternalReferenceRedirectorPointer*>(redirector)); 958 } 959 960 static ExternalReference stress_deopt_count(Isolate* isolate); 961 962 bool operator==(const ExternalReference& other) const { 963 return address_ == other.address_; 964 } 965 966 bool operator!=(const ExternalReference& other) const { 967 return !(*this == other); 968 } 969 970 private: 971 explicit ExternalReference(void* address) 972 : address_(address) {} 973 974 static void* Redirect(Isolate* isolate, 975 Address address_arg, 976 Type type = ExternalReference::BUILTIN_CALL) { 977 ExternalReferenceRedirector* redirector = 978 reinterpret_cast<ExternalReferenceRedirector*>( 979 isolate->external_reference_redirector()); 980 void* address = reinterpret_cast<void*>(address_arg); 981 void* answer = (redirector == NULL) ? 982 address : 983 (*redirector)(address, type); 984 return answer; 985 } 986 987 void* address_; 988 }; 989 990 991 // ----------------------------------------------------------------------------- 992 // Position recording support 993 994 struct PositionState { 995 PositionState() : current_position(RelocInfo::kNoPosition), 996 written_position(RelocInfo::kNoPosition), 997 current_statement_position(RelocInfo::kNoPosition), 998 written_statement_position(RelocInfo::kNoPosition) {} 999 1000 int current_position; 1001 int written_position; 1002 1003 int current_statement_position; 1004 int written_statement_position; 1005 }; 1006 1007 1008 class PositionsRecorder BASE_EMBEDDED { 1009 public: 1010 explicit PositionsRecorder(Assembler* assembler) 1011 : assembler_(assembler) { 1012 jit_handler_data_ = NULL; 1013 } 1014 1015 void AttachJITHandlerData(void* user_data) { 1016 jit_handler_data_ = user_data; 1017 } 1018 1019 void* DetachJITHandlerData() { 1020 void* old_data = jit_handler_data_; 1021 jit_handler_data_ = NULL; 1022 return old_data; 1023 } 1024 // Set current position to pos. 1025 void RecordPosition(int pos); 1026 1027 // Set current statement position to pos. 1028 void RecordStatementPosition(int pos); 1029 1030 // Write recorded positions to relocation information. 1031 bool WriteRecordedPositions(); 1032 1033 int current_position() const { return state_.current_position; } 1034 1035 int current_statement_position() const { 1036 return state_.current_statement_position; 1037 } 1038 1039 private: 1040 Assembler* assembler_; 1041 PositionState state_; 1042 1043 // Currently jit_handler_data_ is used to store JITHandler-specific data 1044 // over the lifetime of a PositionsRecorder 1045 void* jit_handler_data_; 1046 friend class PreservePositionScope; 1047 1048 DISALLOW_COPY_AND_ASSIGN(PositionsRecorder); 1049 }; 1050 1051 1052 class PreservePositionScope BASE_EMBEDDED { 1053 public: 1054 explicit PreservePositionScope(PositionsRecorder* positions_recorder) 1055 : positions_recorder_(positions_recorder), 1056 saved_state_(positions_recorder->state_) {} 1057 1058 ~PreservePositionScope() { 1059 positions_recorder_->state_ = saved_state_; 1060 } 1061 1062 private: 1063 PositionsRecorder* positions_recorder_; 1064 const PositionState saved_state_; 1065 1066 DISALLOW_COPY_AND_ASSIGN(PreservePositionScope); 1067 }; 1068 1069 1070 // ----------------------------------------------------------------------------- 1071 // Utility functions 1072 1073 inline int NumberOfBitsSet(uint32_t x) { 1074 unsigned int num_bits_set; 1075 for (num_bits_set = 0; x; x >>= 1) { 1076 num_bits_set += x & 1; 1077 } 1078 return num_bits_set; 1079 } 1080 1081 bool EvalComparison(Token::Value op, double op1, double op2); 1082 1083 // Computes pow(x, y) with the special cases in the spec for Math.pow. 1084 double power_helper(double x, double y); 1085 double power_double_int(double x, int y); 1086 double power_double_double(double x, double y); 1087 1088 // Helper class for generating code or data associated with the code 1089 // right after a call instruction. As an example this can be used to 1090 // generate safepoint data after calls for crankshaft. 1091 class CallWrapper { 1092 public: 1093 CallWrapper() { } 1094 virtual ~CallWrapper() { } 1095 // Called just before emitting a call. Argument is the size of the generated 1096 // call code. 1097 virtual void BeforeCall(int call_size) const = 0; 1098 // Called just after emitting a call, i.e., at the return site for the call. 1099 virtual void AfterCall() const = 0; 1100 }; 1101 1102 class NullCallWrapper : public CallWrapper { 1103 public: 1104 NullCallWrapper() { } 1105 virtual ~NullCallWrapper() { } 1106 virtual void BeforeCall(int call_size) const { } 1107 virtual void AfterCall() const { } 1108 }; 1109 1110 1111 } } // namespace v8::internal 1112 1113 #endif // V8_ASSEMBLER_H_ 1114