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 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
551 | 551 |
552 | 552 |
553 Address Assembler::target_pointer_address_at(Address pc) { | 553 Address Assembler::target_pointer_address_at(Address pc) { |
554 Instruction* instr = reinterpret_cast<Instruction*>(pc); | 554 Instruction* instr = reinterpret_cast<Instruction*>(pc); |
555 ASSERT(instr->IsLdrLiteralX()); | 555 ASSERT(instr->IsLdrLiteralX()); |
556 return reinterpret_cast<Address>(instr->ImmPCOffsetTarget()); | 556 return reinterpret_cast<Address>(instr->ImmPCOffsetTarget()); |
557 } | 557 } |
558 | 558 |
559 | 559 |
560 // Read/Modify the code target address in the branch/call instruction at pc. | 560 // Read/Modify the code target address in the branch/call instruction at pc. |
561 Address Assembler::target_address_at(Address pc) { | 561 Address Assembler::target_address_at(Address pc, |
| 562 ConstantPoolArray* constant_pool) { |
562 return Memory::Address_at(target_pointer_address_at(pc)); | 563 return Memory::Address_at(target_pointer_address_at(pc)); |
563 } | 564 } |
564 | 565 |
565 | 566 |
| 567 Address Assembler::target_address_at(Address pc, Code* code) { |
| 568 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; |
| 569 return target_address_at(pc, constant_pool); |
| 570 } |
| 571 |
| 572 |
566 Address Assembler::target_address_from_return_address(Address pc) { | 573 Address Assembler::target_address_from_return_address(Address pc) { |
567 // Returns the address of the call target from the return address that will | 574 // Returns the address of the call target from the return address that will |
568 // be returned to after a call. | 575 // be returned to after a call. |
569 // Call sequence on A64 is: | 576 // Call sequence on A64 is: |
570 // ldr ip0, #... @ load from literal pool | 577 // ldr ip0, #... @ load from literal pool |
571 // blr ip0 | 578 // blr ip0 |
572 Address candidate = pc - 2 * kInstructionSize; | 579 Address candidate = pc - 2 * kInstructionSize; |
573 Instruction* instr = reinterpret_cast<Instruction*>(candidate); | 580 Instruction* instr = reinterpret_cast<Instruction*>(candidate); |
574 USE(instr); | 581 USE(instr); |
575 ASSERT(instr->IsLdrLiteralX()); | 582 ASSERT(instr->IsLdrLiteralX()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 } else { | 616 } else { |
610 // Verify the instruction sequence. | 617 // Verify the instruction sequence. |
611 ASSERT(instr->IsLdrLiteralX()); | 618 ASSERT(instr->IsLdrLiteralX()); |
612 ASSERT(instr->following(1)->IsBranchAndLinkToRegister()); | 619 ASSERT(instr->following(1)->IsBranchAndLinkToRegister()); |
613 return pc + Assembler::kCallSizeWithRelocation; | 620 return pc + Assembler::kCallSizeWithRelocation; |
614 } | 621 } |
615 } | 622 } |
616 | 623 |
617 | 624 |
618 void Assembler::deserialization_set_special_target_at( | 625 void Assembler::deserialization_set_special_target_at( |
619 Address constant_pool_entry, Address target) { | 626 Address constant_pool_entry, Code* code, Address target) { |
620 Memory::Address_at(constant_pool_entry) = target; | 627 Memory::Address_at(constant_pool_entry) = target; |
621 } | 628 } |
622 | 629 |
623 | 630 |
624 void Assembler::set_target_address_at(Address pc, Address target) { | 631 void Assembler::set_target_address_at(Address pc, |
| 632 ConstantPoolArray* constant_pool, |
| 633 Address target) { |
625 Memory::Address_at(target_pointer_address_at(pc)) = target; | 634 Memory::Address_at(target_pointer_address_at(pc)) = target; |
626 // Intuitively, we would think it is necessary to always flush the | 635 // Intuitively, we would think it is necessary to always flush the |
627 // instruction cache after patching a target address in the code as follows: | 636 // instruction cache after patching a target address in the code as follows: |
628 // CPU::FlushICache(pc, sizeof(target)); | 637 // CPU::FlushICache(pc, sizeof(target)); |
629 // However, on ARM, an instruction is actually patched in the case of | 638 // However, on ARM, an instruction is actually patched in the case of |
630 // embedded constants of the form: | 639 // embedded constants of the form: |
631 // ldr ip, [pc, #...] | 640 // ldr ip, [pc, #...] |
632 // since the instruction accessing this address in the constant pool remains | 641 // since the instruction accessing this address in the constant pool remains |
633 // unchanged, a flush is not required. | 642 // unchanged, a flush is not required. |
634 } | 643 } |
635 | 644 |
636 | 645 |
| 646 void Assembler::set_target_address_at(Address pc, |
| 647 Code* code, |
| 648 Address target) { |
| 649 ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL; |
| 650 set_target_address_at(pc, constant_pool, target); |
| 651 } |
| 652 |
| 653 |
637 int RelocInfo::target_address_size() { | 654 int RelocInfo::target_address_size() { |
638 return kPointerSize; | 655 return kPointerSize; |
639 } | 656 } |
640 | 657 |
641 | 658 |
642 Address RelocInfo::target_address() { | 659 Address RelocInfo::target_address() { |
643 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); | 660 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)); |
644 return Assembler::target_address_at(pc_); | 661 return Assembler::target_address_at(pc_, host_); |
645 } | 662 } |
646 | 663 |
647 | 664 |
648 Address RelocInfo::target_address_address() { | 665 Address RelocInfo::target_address_address() { |
649 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) | 666 ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_) |
650 || rmode_ == EMBEDDED_OBJECT | 667 || rmode_ == EMBEDDED_OBJECT |
651 || rmode_ == EXTERNAL_REFERENCE); | 668 || rmode_ == EXTERNAL_REFERENCE); |
652 return Assembler::target_pointer_address_at(pc_); | 669 return Assembler::target_pointer_address_at(pc_); |
653 } | 670 } |
654 | 671 |
655 | 672 |
656 Address RelocInfo::constant_pool_entry_address() { | 673 Address RelocInfo::constant_pool_entry_address() { |
657 ASSERT(IsInConstantPool()); | 674 ASSERT(IsInConstantPool()); |
658 return Assembler::target_pointer_address_at(pc_); | 675 return Assembler::target_pointer_address_at(pc_); |
659 } | 676 } |
660 | 677 |
661 | 678 |
662 Object* RelocInfo::target_object() { | 679 Object* RelocInfo::target_object() { |
663 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 680 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
664 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_)); | 681 return reinterpret_cast<Object*>(Assembler::target_address_at(pc_, host_)); |
665 } | 682 } |
666 | 683 |
667 | 684 |
668 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { | 685 Handle<Object> RelocInfo::target_object_handle(Assembler* origin) { |
669 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 686 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
670 return Handle<Object>(reinterpret_cast<Object**>( | 687 return Handle<Object>(reinterpret_cast<Object**>( |
671 Assembler::target_address_at(pc_))); | 688 Assembler::target_address_at(pc_, host_))); |
672 } | 689 } |
673 | 690 |
674 | 691 |
675 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { | 692 void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) { |
676 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); | 693 ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT); |
677 ASSERT(!target->IsConsString()); | 694 ASSERT(!target->IsConsString()); |
678 Assembler::set_target_address_at(pc_, reinterpret_cast<Address>(target)); | 695 Assembler::set_target_address_at(pc_, host_, |
| 696 reinterpret_cast<Address>(target)); |
679 if (mode == UPDATE_WRITE_BARRIER && | 697 if (mode == UPDATE_WRITE_BARRIER && |
680 host() != NULL && | 698 host() != NULL && |
681 target->IsHeapObject()) { | 699 target->IsHeapObject()) { |
682 host()->GetHeap()->incremental_marking()->RecordWrite( | 700 host()->GetHeap()->incremental_marking()->RecordWrite( |
683 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); | 701 host(), &Memory::Object_at(pc_), HeapObject::cast(target)); |
684 } | 702 } |
685 } | 703 } |
686 | 704 |
687 | 705 |
688 Address RelocInfo::target_reference() { | 706 Address RelocInfo::target_reference() { |
689 ASSERT(rmode_ == EXTERNAL_REFERENCE); | 707 ASSERT(rmode_ == EXTERNAL_REFERENCE); |
690 return Assembler::target_address_at(pc_); | 708 return Assembler::target_address_at(pc_, host_); |
691 } | 709 } |
692 | 710 |
693 | 711 |
694 Address RelocInfo::target_runtime_entry(Assembler* origin) { | 712 Address RelocInfo::target_runtime_entry(Assembler* origin) { |
695 ASSERT(IsRuntimeEntry(rmode_)); | 713 ASSERT(IsRuntimeEntry(rmode_)); |
696 return target_address(); | 714 return target_address(); |
697 } | 715 } |
698 | 716 |
699 | 717 |
700 void RelocInfo::set_target_runtime_entry(Address target, | 718 void RelocInfo::set_target_runtime_entry(Address target, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
749 Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset; | 767 Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset; |
750 Memory::Address_at(stub_entry_address) = stub->instruction_start(); | 768 Memory::Address_at(stub_entry_address) = stub->instruction_start(); |
751 } | 769 } |
752 | 770 |
753 | 771 |
754 Address RelocInfo::call_address() { | 772 Address RelocInfo::call_address() { |
755 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 773 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
756 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 774 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
757 // For the above sequences the Relocinfo points to the load literal loading | 775 // For the above sequences the Relocinfo points to the load literal loading |
758 // the call address. | 776 // the call address. |
759 return Assembler::target_address_at(pc_); | 777 return Assembler::target_address_at(pc_, host_); |
760 } | 778 } |
761 | 779 |
762 | 780 |
763 void RelocInfo::set_call_address(Address target) { | 781 void RelocInfo::set_call_address(Address target) { |
764 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 782 ASSERT((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || |
765 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 783 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); |
766 Assembler::set_target_address_at(pc_, target); | 784 Assembler::set_target_address_at(pc_, host_, target); |
767 if (host() != NULL) { | 785 if (host() != NULL) { |
768 Object* target_code = Code::GetCodeFromTargetAddress(target); | 786 Object* target_code = Code::GetCodeFromTargetAddress(target); |
769 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 787 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
770 host(), this, HeapObject::cast(target_code)); | 788 host(), this, HeapObject::cast(target_code)); |
771 } | 789 } |
772 } | 790 } |
773 | 791 |
774 | 792 |
775 void RelocInfo::WipeOut() { | 793 void RelocInfo::WipeOut() { |
776 ASSERT(IsEmbeddedObject(rmode_) || | 794 ASSERT(IsEmbeddedObject(rmode_) || |
777 IsCodeTarget(rmode_) || | 795 IsCodeTarget(rmode_) || |
778 IsRuntimeEntry(rmode_) || | 796 IsRuntimeEntry(rmode_) || |
779 IsExternalReference(rmode_)); | 797 IsExternalReference(rmode_)); |
780 Assembler::set_target_address_at(pc_, NULL); | 798 Assembler::set_target_address_at(pc_, host_, NULL); |
781 } | 799 } |
782 | 800 |
783 | 801 |
784 bool RelocInfo::IsPatchedReturnSequence() { | 802 bool RelocInfo::IsPatchedReturnSequence() { |
785 // The sequence must be: | 803 // The sequence must be: |
786 // ldr ip0, [pc, #offset] | 804 // ldr ip0, [pc, #offset] |
787 // blr ip0 | 805 // blr ip0 |
788 // See a64/debug-a64.cc BreakLocationIterator::SetDebugBreakAtReturn(). | 806 // See a64/debug-a64.cc BreakLocationIterator::SetDebugBreakAtReturn(). |
789 Instruction* i1 = reinterpret_cast<Instruction*>(pc_); | 807 Instruction* i1 = reinterpret_cast<Instruction*>(pc_); |
790 Instruction* i2 = i1->following(); | 808 Instruction* i2 = i1->following(); |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1204 | 1222 |
1205 | 1223 |
1206 void Assembler::ClearRecordedAstId() { | 1224 void Assembler::ClearRecordedAstId() { |
1207 recorded_ast_id_ = TypeFeedbackId::None(); | 1225 recorded_ast_id_ = TypeFeedbackId::None(); |
1208 } | 1226 } |
1209 | 1227 |
1210 | 1228 |
1211 } } // namespace v8::internal | 1229 } } // namespace v8::internal |
1212 | 1230 |
1213 #endif // V8_A64_ASSEMBLER_A64_INL_H_ | 1231 #endif // V8_A64_ASSEMBLER_A64_INL_H_ |
OLD | NEW |