Changeset 44711 in webkit for trunk/JavaScriptCore/assembler/CodeLocation.h
- Timestamp:
- Jun 15, 2009, 10:35:32 PM (16 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/assembler/CodeLocation.h
r44705 r44711 1 1 /* 2 * Copyright (C) 200 8Apple Inc. All rights reserved.2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 24 24 */ 25 25 26 #ifndef AbstractMacroAssembler_h27 #define AbstractMacroAssembler_h26 #ifndef CodeLocation_h 27 #define CodeLocation_h 28 28 29 29 #include <wtf/Platform.h> 30 30 31 31 #include <MacroAssemblerCodeRef.h> 32 #include <wtf/Noncopyable.h>33 #include <wtf/UnusedParam.h>34 32 35 33 #if ENABLE(ASSEMBLER) 36 34 37 // FIXME: keep transitioning this out into MacroAssemblerX86_64.38 #if PLATFORM(X86_64)39 #define REPTACH_OFFSET_CALL_R11 340 #endif41 42 35 namespace JSC { 43 36 44 template <class AssemblerType> 45 class AbstractMacroAssembler { 37 class CodeLocationInstruction; 38 class CodeLocationLabel; 39 class CodeLocationJump; 40 class CodeLocationCall; 41 class CodeLocationNearCall; 42 class CodeLocationDataLabel32; 43 class CodeLocationDataLabelPtr; 44 45 // The CodeLocation* types are all pretty much do-nothing wrappers around 46 // CodePtr (or MacroAssemblerCodePtr, to give it its full name). These 47 // classes only exist to provide type-safety when linking and patching code. 48 // 49 // The one new piece of functionallity introduced by these classes is the 50 // ability to create (or put another way, to re-discover) another CodeLocation 51 // at an offset from one you already know. When patching code to optimize it 52 // we often want to patch a number of instructions that are short, fixed 53 // offsets apart. To reduce memory overhead we will only retain a pointer to 54 // one of the instructions, and we will use the *AtOffset methods provided by 55 // CodeLocationCommon to find the other points in the code to modify. 56 class CodeLocationCommon : public MacroAssemblerCodePtr { 46 57 public: 47 typedef MacroAssemblerCodePtr CodePtr; 48 typedef MacroAssemblerCodeRef CodeRef; 58 CodeLocationInstruction instructionAtOffset(int offset); 59 CodeLocationLabel labelAtOffset(int offset); 60 CodeLocationJump jumpAtOffset(int offset); 61 CodeLocationCall callAtOffset(int offset); 62 CodeLocationNearCall nearCallAtOffset(int offset); 63 CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset); 64 CodeLocationDataLabel32 dataLabel32AtOffset(int offset); 49 65 50 class Jump; 51 class PatchBuffer; 52 class RepatchBuffer; 53 class CodeLocationInstruction; 54 class CodeLocationLabel; 55 class CodeLocationJump; 56 class CodeLocationCall; 57 class CodeLocationNearCall; 58 class CodeLocationDataLabel32; 59 class CodeLocationDataLabelPtr; 60 61 typedef typename AssemblerType::RegisterID RegisterID; 62 typedef typename AssemblerType::FPRegisterID FPRegisterID; 63 typedef typename AssemblerType::JmpSrc JmpSrc; 64 typedef typename AssemblerType::JmpDst JmpDst; 65 66 67 // Section 1: MacroAssembler operand types 68 // 69 // The following types are used as operands to MacroAssembler operations, 70 // describing immediate and memory operands to the instructions to be planted. 71 72 73 enum Scale { 74 TimesOne, 75 TimesTwo, 76 TimesFour, 77 TimesEight, 78 }; 79 80 // Address: 81 // 82 // Describes a simple base-offset address. 83 struct Address { 84 explicit Address(RegisterID base, int32_t offset = 0) 85 : base(base) 86 , offset(offset) 87 { 88 } 89 90 RegisterID base; 91 int32_t offset; 92 }; 93 94 // ImplicitAddress: 95 // 96 // This class is used for explicit 'load' and 'store' operations 97 // (as opposed to situations in which a memory operand is provided 98 // to a generic operation, such as an integer arithmetic instruction). 99 // 100 // In the case of a load (or store) operation we want to permit 101 // addresses to be implicitly constructed, e.g. the two calls: 102 // 103 // load32(Address(addrReg), destReg); 104 // load32(addrReg, destReg); 105 // 106 // Are equivalent, and the explicit wrapping of the Address in the former 107 // is unnecessary. 108 struct ImplicitAddress { 109 ImplicitAddress(RegisterID base) 110 : base(base) 111 , offset(0) 112 { 113 } 114 115 ImplicitAddress(Address address) 116 : base(address.base) 117 , offset(address.offset) 118 { 119 } 120 121 RegisterID base; 122 int32_t offset; 123 }; 124 125 // BaseIndex: 126 // 127 // Describes a complex addressing mode. 128 struct BaseIndex { 129 BaseIndex(RegisterID base, RegisterID index, Scale scale, int32_t offset = 0) 130 : base(base) 131 , index(index) 132 , scale(scale) 133 , offset(offset) 134 { 135 } 136 137 RegisterID base; 138 RegisterID index; 139 Scale scale; 140 int32_t offset; 141 }; 142 143 // AbsoluteAddress: 144 // 145 // Describes an memory operand given by a pointer. For regular load & store 146 // operations an unwrapped void* will be used, rather than using this. 147 struct AbsoluteAddress { 148 explicit AbsoluteAddress(void* ptr) 149 : m_ptr(ptr) 150 { 151 } 152 153 void* m_ptr; 154 }; 155 156 // ImmPtr: 157 // 158 // A pointer sized immediate operand to an instruction - this is wrapped 159 // in a class requiring explicit construction in order to differentiate 160 // from pointers used as absolute addresses to memory operations 161 struct ImmPtr { 162 explicit ImmPtr(void* value) 163 : m_value(value) 164 { 165 } 166 167 intptr_t asIntptr() 168 { 169 return reinterpret_cast<intptr_t>(m_value); 170 } 171 172 void* m_value; 173 }; 174 175 // Imm32: 176 // 177 // A 32bit immediate operand to an instruction - this is wrapped in a 178 // class requiring explicit construction in order to prevent RegisterIDs 179 // (which are implemented as an enum) from accidentally being passed as 180 // immediate values. 181 struct Imm32 { 182 explicit Imm32(int32_t value) 183 : m_value(value) 184 #if PLATFORM(ARM_V7) 185 , m_isPointer(false) 186 #endif 187 { 188 } 189 190 #if !PLATFORM(X86_64) 191 explicit Imm32(ImmPtr ptr) 192 : m_value(ptr.asIntptr()) 193 #if PLATFORM(ARM_V7) 194 , m_isPointer(true) 195 #endif 196 { 197 } 198 #endif 199 200 int32_t m_value; 201 #if PLATFORM(ARM_V7) 202 // We rely on being able to regenerate code to recover exception handling 203 // information. Since ARMv7 supports 16-bit immediates there is a danger 204 // that if pointer values change the layout of the generated code will change. 205 // To avoid this problem, always generate pointers (and thus Imm32s constructed 206 // from ImmPtrs) with a code sequence that is able to represent any pointer 207 // value - don't use a more compact form in these cases. 208 bool m_isPointer; 209 #endif 210 }; 211 212 213 // Section 2: MacroAssembler code buffer handles 214 // 215 // The following types are used to reference items in the code buffer 216 // during JIT code generation. For example, the type Jump is used to 217 // track the location of a jump instruction so that it may later be 218 // linked to a label marking its destination. 219 220 221 // Label: 222 // 223 // A Label records a point in the generated instruction stream, typically such that 224 // it may be used as a destination for a jump. 225 class Label { 226 template<class TemplateAssemblerType> 227 friend class AbstractMacroAssembler; 228 friend class Jump; 229 friend class MacroAssemblerCodeRef; 230 friend class PatchBuffer; 231 232 public: 233 Label() 234 { 235 } 236 237 Label(AbstractMacroAssembler<AssemblerType>* masm) 238 : m_label(masm->m_assembler.label()) 239 { 240 } 241 242 bool isUsed() const { return m_label.isUsed(); } 243 void used() { m_label.used(); } 244 private: 245 JmpDst m_label; 246 }; 247 248 // DataLabelPtr: 249 // 250 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be 251 // patched after the code has been generated. 252 class DataLabelPtr { 253 template<class TemplateAssemblerType> 254 friend class AbstractMacroAssembler; 255 friend class PatchBuffer; 256 public: 257 DataLabelPtr() 258 { 259 } 260 261 DataLabelPtr(AbstractMacroAssembler<AssemblerType>* masm) 262 : m_label(masm->m_assembler.label()) 263 { 264 } 265 266 private: 267 JmpDst m_label; 268 }; 269 270 // DataLabel32: 271 // 272 // A DataLabelPtr is used to refer to a location in the code containing a pointer to be 273 // patched after the code has been generated. 274 class DataLabel32 { 275 template<class TemplateAssemblerType> 276 friend class AbstractMacroAssembler; 277 friend class PatchBuffer; 278 public: 279 DataLabel32() 280 { 281 } 282 283 DataLabel32(AbstractMacroAssembler<AssemblerType>* masm) 284 : m_label(masm->m_assembler.label()) 285 { 286 } 287 288 private: 289 JmpDst m_label; 290 }; 291 292 // Call: 293 // 294 // A Call object is a reference to a call instruction that has been planted 295 // into the code buffer - it is typically used to link the call, setting the 296 // relative offset such that when executed it will call to the desired 297 // destination. 298 class Call { 299 template<class TemplateAssemblerType> 300 friend class AbstractMacroAssembler; 301 friend class PatchBuffer; 302 public: 303 enum Flags { 304 None = 0x0, 305 Linkable = 0x1, 306 Near = 0x2, 307 LinkableNear = 0x3, 308 }; 309 310 Call() 311 : m_flags(None) 312 { 313 } 314 315 Call(JmpSrc jmp, Flags flags) 316 : m_jmp(jmp) 317 , m_flags(flags) 318 { 319 } 320 321 bool isFlagSet(Flags flag) 322 { 323 return m_flags & flag; 324 } 325 326 static Call fromTailJump(Jump jump) 327 { 328 return Call(jump.m_jmp, Linkable); 329 } 330 331 private: 332 JmpSrc m_jmp; 333 Flags m_flags; 334 }; 335 336 // Jump: 337 // 338 // A jump object is a reference to a jump instruction that has been planted 339 // into the code buffer - it is typically used to link the jump, setting the 340 // relative offset such that when executed it will jump to the desired 341 // destination. 342 class Jump { 343 template<class TemplateAssemblerType> 344 friend class AbstractMacroAssembler; 345 friend class Call; 346 friend class PatchBuffer; 347 public: 348 Jump() 349 { 350 } 351 352 Jump(JmpSrc jmp) 353 : m_jmp(jmp) 354 { 355 } 356 357 void link(AbstractMacroAssembler<AssemblerType>* masm) 358 { 359 masm->m_assembler.linkJump(m_jmp, masm->m_assembler.label()); 360 } 361 362 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) 363 { 364 masm->m_assembler.linkJump(m_jmp, label.m_label); 365 } 366 367 private: 368 JmpSrc m_jmp; 369 }; 370 371 // JumpList: 372 // 373 // A JumpList is a set of Jump objects. 374 // All jumps in the set will be linked to the same destination. 375 class JumpList { 376 friend class PatchBuffer; 377 378 public: 379 void link(AbstractMacroAssembler<AssemblerType>* masm) 380 { 381 size_t size = m_jumps.size(); 382 for (size_t i = 0; i < size; ++i) 383 m_jumps[i].link(masm); 384 m_jumps.clear(); 385 } 386 387 void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) 388 { 389 size_t size = m_jumps.size(); 390 for (size_t i = 0; i < size; ++i) 391 m_jumps[i].linkTo(label, masm); 392 m_jumps.clear(); 393 } 394 395 void append(Jump jump) 396 { 397 m_jumps.append(jump); 398 } 399 400 void append(JumpList& other) 401 { 402 m_jumps.append(other.m_jumps.begin(), other.m_jumps.size()); 403 } 404 405 bool empty() 406 { 407 return !m_jumps.size(); 408 } 409 410 private: 411 Vector<Jump, 16> m_jumps; 412 }; 413 414 415 // Section 3: MacroAssembler JIT instruction stream handles. 416 // 417 // The MacroAssembler supported facilities to modify a JIT generated 418 // instruction stream after it has been generated (relinking calls and 419 // jumps, and repatching data values). The following types are used 420 // to store handles into the underlying instruction stream, the type 421 // providing semantic information as to what it is that is in the 422 // instruction stream at this point, and thus what operations may be 423 // performed on it. 424 425 426 // CodeLocationCommon: 427 // 428 // Base type for other CodeLocation* types. A postion in the JIT genertaed 429 // instruction stream, without any semantic information. 430 class CodeLocationCommon { 431 friend class RepatchBuffer; 432 433 public: 434 CodeLocationCommon() 435 { 436 } 437 438 // In order to avoid the need to store multiple handles into the 439 // instructions stream, where the code generation is deterministic 440 // and the labels will always be a fixed distance apart, these 441 // methods may be used to recover a handle that has nopw been 442 // retained, based on a known fixed relative offset from one that has. 443 CodeLocationInstruction instructionAtOffset(int offset); 444 CodeLocationLabel labelAtOffset(int offset); 445 CodeLocationJump jumpAtOffset(int offset); 446 CodeLocationCall callAtOffset(int offset); 447 CodeLocationNearCall nearCallAtOffset(int offset); 448 CodeLocationDataLabelPtr dataLabelPtrAtOffset(int offset); 449 CodeLocationDataLabel32 dataLabel32AtOffset(int offset); 450 451 protected: 452 explicit CodeLocationCommon(CodePtr location) 453 : m_location(location) 454 { 455 } 456 457 void* dataLocation() { return m_location.dataLocation(); } 458 void* executableAddress() { return m_location.executableAddress(); } 459 460 void reset() 461 { 462 m_location = CodePtr(); 463 } 464 465 private: 466 CodePtr m_location; 467 }; 468 469 // CodeLocationInstruction: 470 // 471 // An arbitrary instruction in the JIT code. 472 class CodeLocationInstruction : public CodeLocationCommon { 473 public: 474 CodeLocationInstruction() 475 { 476 } 477 478 explicit CodeLocationInstruction(void* location) 479 : CodeLocationCommon(CodePtr(location)) 480 { 481 } 482 }; 483 484 // CodeLocationLabel: 485 // 486 // A point in the JIT code maked with a label. 487 class CodeLocationLabel : public CodeLocationCommon { 488 friend class CodeLocationCommon; 489 friend class CodeLocationJump; 490 friend class CodeLocationCall; 491 friend class CodeLocationNearCall; 492 friend class PatchBuffer; 493 friend class RepatchBuffer; 494 495 public: 496 CodeLocationLabel() 497 { 498 } 499 500 void* addressForSwitch() { return this->executableAddress(); } 501 void* addressForExceptionHandler() { return this->executableAddress(); } 502 void* addressForJSR() { return this->executableAddress(); } 503 504 bool operator!() 505 { 506 return !this->executableAddress(); 507 } 508 509 void reset() 510 { 511 CodeLocationCommon::reset(); 512 } 513 514 private: 515 explicit CodeLocationLabel(CodePtr location) 516 : CodeLocationCommon(location) 517 { 518 } 519 520 explicit CodeLocationLabel(void* location) 521 : CodeLocationCommon(CodePtr(location)) 522 { 523 } 524 525 void* getJumpDestination() { return this->executableAddress(); } 526 }; 527 528 // CodeLocationJump: 529 // 530 // A point in the JIT code at which there is a jump instruction. 531 class CodeLocationJump : public CodeLocationCommon { 532 friend class CodeLocationCommon; 533 friend class PatchBuffer; 534 public: 535 CodeLocationJump() 536 { 537 } 538 539 explicit CodeLocationJump(void* location) 540 : CodeLocationCommon(CodePtr(location)) 541 { 542 } 543 }; 544 545 // CodeLocationCall: 546 // 547 // A point in the JIT code at which there is a call instruction. 548 class CodeLocationCall : public CodeLocationCommon { 549 public: 550 CodeLocationCall() 551 { 552 } 553 554 explicit CodeLocationCall(CodePtr location) 555 : CodeLocationCommon(location) 556 { 557 } 558 559 explicit CodeLocationCall(void* location) 560 : CodeLocationCommon(CodePtr(location)) 561 { 562 } 563 564 // This methods returns the value that will be set as the return address 565 // within a function that has been called from this call instruction. 566 void* calleeReturnAddressValue() 567 { 568 return this->executableAddress(); 569 } 570 571 }; 572 573 // CodeLocationNearCall: 574 // 575 // A point in the JIT code at which there is a call instruction with near linkage. 576 class CodeLocationNearCall : public CodeLocationCommon { 577 public: 578 CodeLocationNearCall() 579 { 580 } 581 582 explicit CodeLocationNearCall(CodePtr location) 583 : CodeLocationCommon(location) 584 { 585 } 586 587 explicit CodeLocationNearCall(void* location) 588 : CodeLocationCommon(CodePtr(location)) 589 { 590 } 591 592 // This methods returns the value that will be set as the return address 593 // within a function that has been called from this call instruction. 594 void* calleeReturnAddressValue() 595 { 596 return this->executableAddress(); 597 } 598 }; 599 600 // CodeLocationDataLabel32: 601 // 602 // A point in the JIT code at which there is an int32_t immediate that may be repatched. 603 class CodeLocationDataLabel32 : public CodeLocationCommon { 604 public: 605 CodeLocationDataLabel32() 606 { 607 } 608 609 explicit CodeLocationDataLabel32(void* location) 610 : CodeLocationCommon(CodePtr(location)) 611 { 612 } 613 }; 614 615 // CodeLocationDataLabelPtr: 616 // 617 // A point in the JIT code at which there is a void* immediate that may be repatched. 618 class CodeLocationDataLabelPtr : public CodeLocationCommon { 619 public: 620 CodeLocationDataLabelPtr() 621 { 622 } 623 624 explicit CodeLocationDataLabelPtr(void* location) 625 : CodeLocationCommon(CodePtr(location)) 626 { 627 } 628 }; 629 630 631 // Section 4: PatchBuffer - utility to finalize code generation. 632 633 static CodePtr trampolineAt(CodeRef ref, Label label) 66 protected: 67 CodeLocationCommon() 634 68 { 635 return CodePtr(AssemblerType::getRelocatedAddress(ref.m_code.dataLocation(), label.m_label));636 69 } 637 70 638 // PatchBuffer: 639 // 640 // This class assists in linking code generated by the macro assembler, once code generation 641 // has been completed, and the code has been copied to is final location in memory. At this 642 // time pointers to labels within the code may be resolved, and relative offsets to external 643 // addresses may be fixed. 644 // 645 // Specifically: 646 // * Jump objects may be linked to external targets, 647 // * The address of Jump objects may taken, such that it can later be relinked. 648 // * The return address of a Jump object representing a call may be acquired. 649 // * The address of a Label pointing into the code may be resolved. 650 // * The value referenced by a DataLabel may be fixed. 651 // 652 // FIXME: distinguish between Calls & Jumps (make a specific call to obtain the return 653 // address of calls, as opposed to a point that can be used to later relink a Jump - 654 // possibly wrap the later up in an object that can do just that). 655 class PatchBuffer : public Noncopyable { 656 public: 657 // Note: Initialization sequence is significant, since executablePool is a PassRefPtr. 658 // First, executablePool is copied into m_executablePool, then the initialization of 659 // m_code uses m_executablePool, *not* executablePool, since this is no longer valid. 660 PatchBuffer(AbstractMacroAssembler<AssemblerType>* masm, PassRefPtr<ExecutablePool> executablePool) 661 : m_executablePool(executablePool) 662 , m_code(masm->m_assembler.executableCopy(m_executablePool.get())) 663 , m_size(masm->m_assembler.size()) 664 #ifndef NDEBUG 665 , m_completed(false) 666 #endif 667 { 668 } 669 670 ~PatchBuffer() 671 { 672 ASSERT(m_completed); 673 } 674 675 // These methods are used to link or set values at code generation time. 676 677 void link(Call call, FunctionPtr function) 678 { 679 ASSERT(call.isFlagSet(Call::Linkable)); 680 #if PLATFORM(X86_64) 681 if (!call.isFlagSet(Call::Near)) { 682 char* callLocation = reinterpret_cast<char*>(AssemblerType::getRelocatedAddress(code(), call.m_jmp)) - REPTACH_OFFSET_CALL_R11; 683 AssemblerType::patchPointerForCall(callLocation, function.value()); 684 } else 685 #endif 686 AssemblerType::linkCall(code(), call.m_jmp, function.value()); 687 } 688 689 void link(Jump jump, CodeLocationLabel label) 690 { 691 AssemblerType::linkJump(code(), jump.m_jmp, label.dataLocation()); 692 } 693 694 void link(JumpList list, CodeLocationLabel label) 695 { 696 for (unsigned i = 0; i < list.m_jumps.size(); ++i) 697 AssemblerType::linkJump(code(), list.m_jumps[i].m_jmp, label.dataLocation()); 698 } 699 700 void patch(DataLabelPtr label, void* value) 701 { 702 AssemblerType::patchPointer(code(), label.m_label, value); 703 } 704 705 void patch(DataLabelPtr label, CodeLocationLabel value) 706 { 707 AssemblerType::patchPointer(code(), label.m_label, value.getJumpDestination()); 708 } 709 710 // These methods are used to obtain handles to allow the code to be relinked / repatched later. 711 712 CodeLocationCall locationOf(Call call) 713 { 714 ASSERT(call.isFlagSet(Call::Linkable)); 715 ASSERT(!call.isFlagSet(Call::Near)); 716 return CodeLocationCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp)); 717 } 718 719 CodeLocationNearCall locationOfNearCall(Call call) 720 { 721 ASSERT(call.isFlagSet(Call::Linkable)); 722 ASSERT(call.isFlagSet(Call::Near)); 723 return CodeLocationNearCall(AssemblerType::getRelocatedAddress(code(), call.m_jmp)); 724 } 725 726 CodeLocationLabel locationOf(Label label) 727 { 728 return CodeLocationLabel(AssemblerType::getRelocatedAddress(code(), label.m_label)); 729 } 730 731 CodeLocationDataLabelPtr locationOf(DataLabelPtr label) 732 { 733 return CodeLocationDataLabelPtr(AssemblerType::getRelocatedAddress(code(), label.m_label)); 734 } 735 736 CodeLocationDataLabel32 locationOf(DataLabel32 label) 737 { 738 return CodeLocationDataLabel32(AssemblerType::getRelocatedAddress(code(), label.m_label)); 739 } 740 741 // This method obtains the return address of the call, given as an offset from 742 // the start of the code. 743 unsigned returnAddressOffset(Call call) 744 { 745 return AssemblerType::getCallReturnOffset(call.m_jmp); 746 } 747 748 // Upon completion of all patching either 'finalizeCode()' or 'finalizeCodeAddendum()' should be called 749 // once to complete generation of the code. 'finalizeCode()' is suited to situations 750 // where the executable pool must also be retained, the lighter-weight 'finalizeCodeAddendum()' is 751 // suited to adding to an existing allocation. 752 CodeRef finalizeCode() 753 { 754 performFinalization(); 755 756 return CodeRef(m_code, m_executablePool, m_size); 757 } 758 CodeLocationLabel finalizeCodeAddendum() 759 { 760 performFinalization(); 761 762 return CodeLocationLabel(code()); 763 } 764 765 private: 766 // Keep this private! - the underlying code should only be obtained externally via 767 // finalizeCode() or finalizeCodeAddendum(). 768 void* code() 769 { 770 return m_code; 771 } 772 773 void performFinalization() 774 { 775 #ifndef NDEBUG 776 ASSERT(!m_completed); 777 m_completed = true; 778 #endif 779 780 ExecutableAllocator::makeExecutable(code(), m_size); 781 } 782 783 RefPtr<ExecutablePool> m_executablePool; 784 void* m_code; 785 size_t m_size; 786 #ifndef NDEBUG 787 bool m_completed; 788 #endif 789 }; 790 791 class RepatchBuffer { 792 public: 793 RepatchBuffer() 794 { 795 } 796 797 void relink(CodeLocationJump jump, CodeLocationLabel destination) 798 { 799 AssemblerType::relinkJump(jump.dataLocation(), destination.dataLocation()); 800 } 801 802 void relink(CodeLocationCall call, CodeLocationLabel destination) 803 { 804 #if PLATFORM(X86_64) 805 repatch(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11), destination.executableAddress()); 806 #else 807 AssemblerType::relinkCall(call.dataLocation(), destination.executableAddress()); 808 #endif 809 } 810 811 void relink(CodeLocationCall call, FunctionPtr destination) 812 { 813 #if PLATFORM(X86_64) 814 repatch(call.dataLabelPtrAtOffset(-REPTACH_OFFSET_CALL_R11), destination.executableAddress()); 815 #else 816 AssemblerType::relinkCall(call.dataLocation(), destination.executableAddress()); 817 #endif 818 } 819 820 void relink(CodeLocationNearCall nearCall, CodePtr destination) 821 { 822 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); 823 } 824 825 void relink(CodeLocationNearCall nearCall, CodeLocationLabel destination) 826 { 827 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); 828 } 829 830 void relink(CodeLocationNearCall nearCall, FunctionPtr destination) 831 { 832 AssemblerType::relinkCall(nearCall.dataLocation(), destination.executableAddress()); 833 } 834 835 void repatch(CodeLocationDataLabel32 dataLabel32, int32_t value) 836 { 837 AssemblerType::repatchInt32(dataLabel32.dataLocation(), value); 838 } 839 840 void repatch(CodeLocationDataLabelPtr dataLabelPtr, void* value) 841 { 842 AssemblerType::repatchPointer(dataLabelPtr.dataLocation(), value); 843 } 844 845 void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label) 846 { 847 relink(CodeLocationCall(CodePtr(returnAddress)), label); 848 } 849 850 void relinkCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction) 851 { 852 relinkCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction)); 853 } 854 855 void relinkCallerToFunction(ReturnAddressPtr returnAddress, FunctionPtr function) 856 { 857 relink(CodeLocationCall(CodePtr(returnAddress)), function); 858 } 859 860 void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodeLocationLabel label) 861 { 862 relink(CodeLocationNearCall(CodePtr(returnAddress)), label); 863 } 864 865 void relinkNearCallerToTrampoline(ReturnAddressPtr returnAddress, CodePtr newCalleeFunction) 866 { 867 relinkNearCallerToTrampoline(returnAddress, CodeLocationLabel(newCalleeFunction)); 868 } 869 870 void repatchLoadPtrToLEA(CodeLocationInstruction instruction) 871 { 872 AssemblerType::repatchLoadPtrToLEA(instruction.dataLocation()); 873 } 874 }; 875 876 877 // Section 5: Misc admin methods 878 879 size_t size() 71 CodeLocationCommon(MacroAssemblerCodePtr location) 72 : MacroAssemblerCodePtr(location) 880 73 { 881 return m_assembler.size();882 74 } 883 884 Label label()885 {886 return Label(this);887 }888 889 Label align()890 {891 m_assembler.align(16);892 return Label(this);893 }894 895 ptrdiff_t differenceBetween(Label from, Jump to)896 {897 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);898 }899 900 ptrdiff_t differenceBetween(Label from, Call to)901 {902 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);903 }904 905 ptrdiff_t differenceBetween(Label from, Label to)906 {907 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);908 }909 910 ptrdiff_t differenceBetween(Label from, DataLabelPtr to)911 {912 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);913 }914 915 ptrdiff_t differenceBetween(Label from, DataLabel32 to)916 {917 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);918 }919 920 ptrdiff_t differenceBetween(DataLabelPtr from, Jump to)921 {922 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);923 }924 925 ptrdiff_t differenceBetween(DataLabelPtr from, DataLabelPtr to)926 {927 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label);928 }929 930 ptrdiff_t differenceBetween(DataLabelPtr from, Call to)931 {932 return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_jmp);933 }934 935 protected:936 AssemblerType m_assembler;937 75 }; 938 76 77 class CodeLocationInstruction : public CodeLocationCommon { 78 public: 79 CodeLocationInstruction() {} 80 explicit CodeLocationInstruction(MacroAssemblerCodePtr location) 81 : CodeLocationCommon(location) {} 82 explicit CodeLocationInstruction(void* location) 83 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 84 }; 939 85 940 template <class AssemblerType> 941 typename AbstractMacroAssembler<AssemblerType>::CodeLocationInstruction AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::instructionAtOffset(int offset) 86 class CodeLocationLabel : public CodeLocationCommon { 87 public: 88 CodeLocationLabel() {} 89 explicit CodeLocationLabel(MacroAssemblerCodePtr location) 90 : CodeLocationCommon(location) {} 91 explicit CodeLocationLabel(void* location) 92 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 93 }; 94 95 class CodeLocationJump : public CodeLocationCommon { 96 public: 97 CodeLocationJump() {} 98 explicit CodeLocationJump(MacroAssemblerCodePtr location) 99 : CodeLocationCommon(location) {} 100 explicit CodeLocationJump(void* location) 101 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 102 }; 103 104 class CodeLocationCall : public CodeLocationCommon { 105 public: 106 CodeLocationCall() {} 107 explicit CodeLocationCall(MacroAssemblerCodePtr location) 108 : CodeLocationCommon(location) {} 109 explicit CodeLocationCall(void* location) 110 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 111 }; 112 113 class CodeLocationNearCall : public CodeLocationCommon { 114 public: 115 CodeLocationNearCall() {} 116 explicit CodeLocationNearCall(MacroAssemblerCodePtr location) 117 : CodeLocationCommon(location) {} 118 explicit CodeLocationNearCall(void* location) 119 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 120 }; 121 122 class CodeLocationDataLabel32 : public CodeLocationCommon { 123 public: 124 CodeLocationDataLabel32() {} 125 explicit CodeLocationDataLabel32(MacroAssemblerCodePtr location) 126 : CodeLocationCommon(location) {} 127 explicit CodeLocationDataLabel32(void* location) 128 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 129 }; 130 131 class CodeLocationDataLabelPtr : public CodeLocationCommon { 132 public: 133 CodeLocationDataLabelPtr() {} 134 explicit CodeLocationDataLabelPtr(MacroAssemblerCodePtr location) 135 : CodeLocationCommon(location) {} 136 explicit CodeLocationDataLabelPtr(void* location) 137 : CodeLocationCommon(MacroAssemblerCodePtr(location)) {} 138 }; 139 140 inline CodeLocationInstruction CodeLocationCommon::instructionAtOffset(int offset) 942 141 { 943 return typename AbstractMacroAssembler::CodeLocationInstruction(reinterpret_cast<char*>(dataLocation()) + offset); 142 ASSERT_VALID_CODE_OFFSET(offset); 143 return CodeLocationInstruction(reinterpret_cast<char*>(dataLocation()) + offset); 944 144 } 945 145 946 template <class AssemblerType> 947 typename AbstractMacroAssembler<AssemblerType>::CodeLocationLabel AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::labelAtOffset(int offset) 146 inline CodeLocationLabel CodeLocationCommon::labelAtOffset(int offset) 948 147 { 949 return typename AbstractMacroAssembler::CodeLocationLabel(reinterpret_cast<char*>(dataLocation()) + offset); 148 ASSERT_VALID_CODE_OFFSET(offset); 149 return CodeLocationLabel(reinterpret_cast<char*>(dataLocation()) + offset); 950 150 } 951 151 952 template <class AssemblerType> 953 typename AbstractMacroAssembler<AssemblerType>::CodeLocationJump AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::jumpAtOffset(int offset) 152 inline CodeLocationJump CodeLocationCommon::jumpAtOffset(int offset) 954 153 { 955 return typename AbstractMacroAssembler::CodeLocationJump(reinterpret_cast<char*>(dataLocation()) + offset); 154 ASSERT_VALID_CODE_OFFSET(offset); 155 return CodeLocationJump(reinterpret_cast<char*>(dataLocation()) + offset); 956 156 } 957 157 958 template <class AssemblerType> 959 typename AbstractMacroAssembler<AssemblerType>::CodeLocationCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::callAtOffset(int offset) 158 inline CodeLocationCall CodeLocationCommon::callAtOffset(int offset) 960 159 { 961 return typename AbstractMacroAssembler::CodeLocationCall(reinterpret_cast<char*>(dataLocation()) + offset); 160 ASSERT_VALID_CODE_OFFSET(offset); 161 return CodeLocationCall(reinterpret_cast<char*>(dataLocation()) + offset); 962 162 } 963 163 964 template <class AssemblerType> 965 typename AbstractMacroAssembler<AssemblerType>::CodeLocationNearCall AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::nearCallAtOffset(int offset) 164 inline CodeLocationNearCall CodeLocationCommon::nearCallAtOffset(int offset) 966 165 { 967 return typename AbstractMacroAssembler::CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset); 166 ASSERT_VALID_CODE_OFFSET(offset); 167 return CodeLocationNearCall(reinterpret_cast<char*>(dataLocation()) + offset); 968 168 } 969 169 970 template <class AssemblerType> 971 typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabelPtr AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabelPtrAtOffset(int offset) 170 inline CodeLocationDataLabelPtr CodeLocationCommon::dataLabelPtrAtOffset(int offset) 972 171 { 973 return typename AbstractMacroAssembler::CodeLocationDataLabelPtr(reinterpret_cast<char*>(dataLocation()) + offset); 172 ASSERT_VALID_CODE_OFFSET(offset); 173 return CodeLocationDataLabelPtr(reinterpret_cast<char*>(dataLocation()) + offset); 974 174 } 975 175 976 template <class AssemblerType> 977 typename AbstractMacroAssembler<AssemblerType>::CodeLocationDataLabel32 AbstractMacroAssembler<AssemblerType>::CodeLocationCommon::dataLabel32AtOffset(int offset) 176 inline CodeLocationDataLabel32 CodeLocationCommon::dataLabel32AtOffset(int offset) 978 177 { 979 return typename AbstractMacroAssembler::CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset); 178 ASSERT_VALID_CODE_OFFSET(offset); 179 return CodeLocationDataLabel32(reinterpret_cast<char*>(dataLocation()) + offset); 980 180 } 981 181 … … 984 184 #endif // ENABLE(ASSEMBLER) 985 185 986 #endif // AbstractMacroAssembler_h186 #endif // CodeLocation_h
Note:
See TracChangeset
for help on using the changeset viewer.