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