| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 namespace internal { | 37 namespace internal { |
| 38 | 38 |
| 39 | 39 |
| 40 void RelocInfo::apply(intptr_t delta) { | 40 void RelocInfo::apply(intptr_t delta) { |
| 41 UNIMPLEMENTED(); | 41 UNIMPLEMENTED(); |
| 42 } | 42 } |
| 43 | 43 |
| 44 | 44 |
| 45 void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { | 45 void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) { |
| 46 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 46 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 47 Assembler::set_target_address_at(pc_, target); | 47 Assembler::set_target_address_at(pc_, host_, target); |
| 48 if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { | 48 if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) { |
| 49 Object* target_code = Code::GetCodeFromTargetAddress(target); | 49 Object* target_code = Code::GetCodeFromTargetAddress(target); |
| 50 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 50 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
| 51 host(), this, HeapObject::cast(target_code)); | 51 host(), this, HeapObject::cast(target_code)); |
| 52 } | 52 } |
| 53 } | 53 } |
| 54 | 54 |
| 55 | 55 |
| 56 inline unsigned CPURegister::code() const { | 56 inline unsigned CPURegister::code() const { |
| 57 ASSERT(IsValid()); | 57 ASSERT(IsValid()); |
| (...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 | 547 |
| 548 | 548 |
| 549 Address Assembler::target_pointer_address_at(Address pc) { | 549 Address Assembler::target_pointer_address_at(Address pc) { |
| 550 Instruction* instr = reinterpret_cast<Instruction*>(pc); | 550 Instruction* instr = reinterpret_cast<Instruction*>(pc); |
| 551 ASSERT(instr->IsLdrLiteralX()); | 551 ASSERT(instr->IsLdrLiteralX()); |
| 552 return reinterpret_cast<Address>(instr->ImmPCOffsetTarget()); | 552 return reinterpret_cast<Address>(instr->ImmPCOffsetTarget()); |
| 553 } | 553 } |
| 554 | 554 |
| 555 | 555 |
| 556 // Read/Modify the code target address in the branch/call instruction at pc. | 556 // Read/Modify the code target address in the branch/call instruction at pc. |
| 557 Address Assembler::target_address_at(Address pc) { | 557 Address Assembler::target_address_at(Address pc, |
| 558 ConstantPoolArray* constant_pool) { |
| 558 return Memory::Address_at(target_pointer_address_at(pc)); | 559 return Memory::Address_at(target_pointer_address_at(pc)); |
| 559 } | 560 } |
| 560 | 561 |
| 561 | 562 |
| 563 Address Assembler::target_address_at(Address pc, Code* code) { |
| 564 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; |
| 565 return target_address_at(pc, constant_pool); |
| 566 } |
| 567 |
| 568 |
| 562 Address Assembler::target_address_from_return_address(Address pc) { | 569 Address Assembler::target_address_from_return_address(Address pc) { |
| 563 // Returns the address of the call target from the return address that will | 570 // Returns the address of the call target from the return address that will |
| 564 // be returned to after a call. | 571 // be returned to after a call. |
| 565 // Call sequence on A64 is: | 572 // Call sequence on A64 is: |
| 566 // ldr ip0, #... @ load from literal pool | 573 // ldr ip0, #... @ load from literal pool |
| 567 // blr ip0 | 574 // blr ip0 |
| 568 Address candidate = pc - 2 * kInstructionSize; | 575 Address candidate = pc - 2 * kInstructionSize; |
| 569 Instruction* instr = reinterpret_cast<Instruction*>(candidate); | 576 Instruction* instr = reinterpret_cast<Instruction*>(candidate); |
| 570 USE(instr); | 577 USE(instr); |
| 571 ASSERT(instr->IsLdrLiteralX()); | 578 ASSERT(instr->IsLdrLiteralX()); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 605 } else { | 612 } else { |
| 606 // Verify the instruction sequence. | 613 // Verify the instruction sequence. |
| 607 ASSERT(instr->IsLdrLiteralX()); | 614 ASSERT(instr->IsLdrLiteralX()); |
| 608 ASSERT(instr->following(1)->IsBranchAndLinkToRegister()); | 615 ASSERT(instr->following(1)->IsBranchAndLinkToRegister()); |
| 609 return pc + Assembler::kCallSizeWithRelocation; | 616 return pc + Assembler::kCallSizeWithRelocation; |
| 610 } | 617 } |
| 611 } | 618 } |
| 612 | 619 |
| 613 | 620 |
| 614 void Assembler::deserialization_set_special_target_at( | 621 void Assembler::deserialization_set_special_target_at( |
| 615 Address constant_pool_entry, Address target) { | 622 Address constant_pool_entry, Code* code, Address target) { |
| 616 Memory::Address_at(constant_pool_entry) = target; | 623 Memory::Address_at(constant_pool_entry) = target; |
| 617 } | 624 } |
| 618 | 625 |
| 619 | 626 |
| 620 void Assembler::set_target_address_at(Address pc, Address target) { | 627 void Assembler::set_target_address_at(Address pc, |
| 628 ConstantPoolArray* constant_pool, |
| 629 Address target) { |
| 621 Memory::Address_at(target_pointer_address_at(pc)) = target; | 630 Memory::Address_at(target_pointer_address_at(pc)) = target; |
| 622 // Intuitively, we would think it is necessary to always flush the | 631 // Intuitively, we would think it is necessary to always flush the |
| 623 // instruction cache after patching a target address in the code as follows: | 632 // instruction cache after patching a target address in the code as follows: |
| 624 // CPU::FlushICache(pc, sizeof(target)); | 633 // CPU::FlushICache(pc, sizeof(target)); |
| 625 // However, on ARM, an instruction is actually patched in the case of | 634 // However, on ARM, an instruction is actually patched in the case of |
| 626 // embedded constants of the form: | 635 // embedded constants of the form: |
| 627 // ldr ip, [pc, #...] | 636 // ldr ip, [pc, #...] |
| 628 // since the instruction accessing this address in the constant pool remains | 637 // since the instruction accessing this address in the constant pool remains |
| 629 // unchanged, a flush is not required. | 638 // unchanged, a flush is not required. |
| 630 } | 639 } |
| 631 | 640 |
| 632 | 641 |
| 642 void Assembler::set_target_address_at(Address pc, |
| 643 Code* code, |
| 644 Address target) { |
| 645 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; |
| 646 set_target_address_at(pc, constant_pool, target); |
| 647 } |
| 648 |
| 649 |
| 633 int RelocInfo::target_address_size() { | 650 int RelocInfo::target_address_size() { |
| 634 return kPointerSize; | 651 return kPointerSize; |
| 635 } | 652 } |
| 636 | 653 |
| 637 | 654 |
| 638 Address RelocInfo::target_address() { | 655 Address RelocInfo::target_address() { |
| 639 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 656 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
| 640 return Assembler::target_address_at(pc_); | 657 return Assembler::target_address_at(pc_, host_); |
| 641 } | 658 } |
| 642 | 659 |
| 643 | 660 |
| 644 Address RelocInfo::target_address_address() { | 661 Address RelocInfo::target_address_address() { |
| 645 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 662 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) |
| 646 || rmode_ == EMBEDDED_OBJECT | 663 || rmode_ == EMBEDDED_OBJECT |
| 647 || rmode_ == EXTERNAL_REFERENCE); | 664 || rmode_ == EXTERNAL_REFERENCE); |
| 648 return Assembler::target_pointer_address_at(pc_); | 665 return Assembler::target_pointer_address_at(pc_); |
| 649 } | 666 } |
| 650 | 667 |
| 651 | 668 |
| 652 Object* RelocInfo::target_object() { | 669 Object* RelocInfo::target_object() { |
| 653 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 670 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 654 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_)); | 671 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); |
| 655 } | 672 } |
| 656 | 673 |
| 657 | 674 |
| 658 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 675 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
| 659 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 676 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 660 return Handle<Object>(reinterpret_cast<Object**>( | 677 return Handle<Object>(reinterpret_cast<Object**>( |
| 661 Assembler::target_address_at(pc_))); | 678 Assembler::target_address_at(pc_, host_))); |
| 662 } | 679 } |
| 663 | 680 |
| 664 | 681 |
| 665 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { | 682 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { |
| 666 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 683 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
| 667 ASSERT(!target->IsConsString()); | 684 ASSERT(!target->IsConsString()); |
| 668 Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); | 685 Assembler::set_target_address_at(pc_, host_, |
| 686 reinterpret_cast<Address>(target)); |
| 669 if (mode == UPDATE_WRITE_BARRIER && | 687 if (mode == UPDATE_WRITE_BARRIER && |
| 670 host() != NULL && | 688 host() != NULL && |
| 671 target->IsHeapObject()) { | 689 target->IsHeapObject()) { |
| 672 host()->GetHeap()->incremental_marking()->RecordWrite( | 690 host()->GetHeap()->incremental_marking()->RecordWrite( |
| 673 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 691 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
| 674 } | 692 } |
| 675 } | 693 } |
| 676 | 694 |
| 677 | 695 |
| 678 Address RelocInfo::target_reference() { | 696 Address RelocInfo::target_reference() { |
| 679 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 697 ASSERT(rmode_ == EXTERNAL_REFERENCE); |
| 680 return Assembler::target_address_at(pc_); | 698 return Assembler::target_address_at(pc_, host_); |
| 681 } | 699 } |
| 682 | 700 |
| 683 | 701 |
| 684 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 702 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
| 685 ASSERT(IsRuntimeEntry(rmode_)); | 703 ASSERT(IsRuntimeEntry(rmode_)); |
| 686 return target_address(); | 704 return target_address(); |
| 687 } | 705 } |
| 688 | 706 |
| 689 | 707 |
| 690 void RelocInfo::set_target_runtime_entry(Address target, | 708 void RelocInfo::set_target_runtime_entry(Address target, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset; | 757 Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset; |
| 740 Memory::Address_at(stub_entry_address) = stub->instruction_start(); | 758 Memory::Address_at(stub_entry_address) = stub->instruction_start(); |
| 741 } | 759 } |
| 742 | 760 |
| 743 | 761 |
| 744 Address RelocInfo::call_address() { | 762 Address RelocInfo::call_address() { |
| 745 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 763 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 746 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 764 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 747 // For the above sequences the Relocinfo points to the load literal loading | 765 // For the above sequences the Relocinfo points to the load literal loading |
| 748 // the call address. | 766 // the call address. |
| 749 return Assembler::target_address_at(pc_); | 767 return Assembler::target_address_at(pc_, host_); |
| 750 } | 768 } |
| 751 | 769 |
| 752 | 770 |
| 753 void RelocInfo::set_call_address(Address target) { | 771 void RelocInfo::set_call_address(Address target) { |
| 754 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 772 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
| 755 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 773 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
| 756 Assembler::set_target_address_at(pc_, target); | 774 Assembler::set_target_address_at(pc_, host_, target); |
| 757 if (host() != NULL) { | 775 if (host() != NULL) { |
| 758 Object* target_code = Code::GetCodeFromTargetAddress(target); | 776 Object* target_code = Code::GetCodeFromTargetAddress(target); |
| 759 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 777 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
| 760 host(), this, HeapObject::cast(target_code)); | 778 host(), this, HeapObject::cast(target_code)); |
| 761 } | 779 } |
| 762 } | 780 } |
| 763 | 781 |
| 764 | 782 |
| 765 void RelocInfo::WipeOut() { | 783 void RelocInfo::WipeOut() { |
| 766 ASSERT(IsEmbeddedObject(rmode_) || | 784 ASSERT(IsEmbeddedObject(rmode_) || |
| 767 IsCodeTarget(rmode_) || | 785 IsCodeTarget(rmode_) || |
| 768 IsRuntimeEntry(rmode_) || | 786 IsRuntimeEntry(rmode_) || |
| 769 IsExternalReference(rmode_)); | 787 IsExternalReference(rmode_)); |
| 770 Assembler::set_target_address_at(pc_, NULL); | 788 Assembler::set_target_address_at(pc_, host_, NULL); |
| 771 } | 789 } |
| 772 | 790 |
| 773 | 791 |
| 774 bool RelocInfo::IsPatchedReturnSequence() { | 792 bool RelocInfo::IsPatchedReturnSequence() { |
| 775 // The sequence must be: | 793 // The sequence must be: |
| 776 // ldr ip0, [pc, #offset] | 794 // ldr ip0, [pc, #offset] |
| 777 // blr ip0 | 795 // blr ip0 |
| 778 // See a64/debug-a64.cc BreakLocationIterator::SetDebugBreakAtReturn(). | 796 // See a64/debug-a64.cc BreakLocationIterator::SetDebugBreakAtReturn(). |
| 779 Instruction* i1 = reinterpret_cast<Instruction*>(pc_); | 797 Instruction* i1 = reinterpret_cast<Instruction*>(pc_); |
| 780 Instruction* i2 = i1->following(); | 798 Instruction* i2 = i1->following(); |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 | 1209 |
| 1192 | 1210 |
| 1193 void Assembler::ClearRecordedAstId() { | 1211 void Assembler::ClearRecordedAstId() { |
| 1194 recorded_ast_id_ = TypeFeedbackId::None(); | 1212 recorded_ast_id_ = TypeFeedbackId::None(); |
| 1195 } | 1213 } |
| 1196 | 1214 |
| 1197 | 1215 |
| 1198 } } // namespace v8::internal | 1216 } } // namespace v8::internal |
| 1199 | 1217 |
| 1200 #endif // V8_A64_ASSEMBLER_A64_INL_H_ | 1218 #endif // V8_A64_ASSEMBLER_A64_INL_H_ |
| OLD | NEW |