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