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