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