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 |