OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_ARM64_ASSEMBLER_ARM64_INL_H_ | 5 #ifndef V8_ARM64_ASSEMBLER_ARM64_INL_H_ |
6 #define V8_ARM64_ASSEMBLER_ARM64_INL_H_ | 6 #define V8_ARM64_ASSEMBLER_ARM64_INL_H_ |
7 | 7 |
8 #include "src/arm64/assembler-arm64.h" | 8 #include "src/arm64/assembler-arm64.h" |
9 #include "src/assembler.h" | 9 #include "src/assembler.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
11 | 11 |
12 | 12 |
13 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 bool CpuFeatures::SupportsCrankshaft() { return true; } | 17 bool CpuFeatures::SupportsCrankshaft() { return true; } |
18 | 18 |
19 | 19 |
20 void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) { | 20 void RelocInfo::apply(intptr_t delta) { |
21 // On arm64 only internal references need extra work. | 21 // On arm64 only internal references need extra work. |
22 DCHECK(RelocInfo::IsInternalReference(rmode_)); | 22 DCHECK(RelocInfo::IsInternalReference(rmode_)); |
23 | 23 |
24 // Absolute code pointer inside code object moves with the code object. | 24 // Absolute code pointer inside code object moves with the code object. |
25 intptr_t* p = reinterpret_cast<intptr_t*>(pc_); | 25 intptr_t* p = reinterpret_cast<intptr_t*>(pc_); |
26 *p += delta; // Relocate entry. | 26 *p += delta; // Relocate entry. |
27 } | 27 } |
28 | 28 |
29 | 29 |
30 void RelocInfo::set_target_address(Address target, | 30 void RelocInfo::set_target_address(Address target, |
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 // ldr ip0, #... @ load from literal pool | 604 // ldr ip0, #... @ load from literal pool |
605 // blr ip0 | 605 // blr ip0 |
606 Address candidate = pc - 2 * kInstructionSize; | 606 Address candidate = pc - 2 * kInstructionSize; |
607 Instruction* instr = reinterpret_cast<Instruction*>(candidate); | 607 Instruction* instr = reinterpret_cast<Instruction*>(candidate); |
608 USE(instr); | 608 USE(instr); |
609 DCHECK(instr->IsLdrLiteralX()); | 609 DCHECK(instr->IsLdrLiteralX()); |
610 return candidate; | 610 return candidate; |
611 } | 611 } |
612 | 612 |
613 | 613 |
614 Address Assembler::break_address_from_return_address(Address pc) { | |
615 return pc - Assembler::kPatchDebugBreakSlotReturnOffset; | |
616 } | |
617 | |
618 | |
619 Address Assembler::return_address_from_call_start(Address pc) { | 614 Address Assembler::return_address_from_call_start(Address pc) { |
620 // The call, generated by MacroAssembler::Call, is one of two possible | 615 // The call, generated by MacroAssembler::Call, is one of two possible |
621 // sequences: | 616 // sequences: |
622 // | 617 // |
623 // Without relocation: | 618 // Without relocation: |
624 // movz temp, #(target & 0x000000000000ffff) | 619 // movz temp, #(target & 0x000000000000ffff) |
625 // movk temp, #(target & 0x00000000ffff0000) | 620 // movk temp, #(target & 0x00000000ffff0000) |
626 // movk temp, #(target & 0x0000ffff00000000) | 621 // movk temp, #(target & 0x0000ffff00000000) |
627 // blr temp | 622 // blr temp |
628 // | 623 // |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 ICacheFlushMode icache_flush_mode) { | 813 ICacheFlushMode icache_flush_mode) { |
819 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); | 814 DCHECK(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); |
820 DCHECK(!Code::IsYoungSequence(stub->GetIsolate(), pc_)); | 815 DCHECK(!Code::IsYoungSequence(stub->GetIsolate(), pc_)); |
821 // Overwrite the stub entry point in the code age sequence. This is loaded as | 816 // Overwrite the stub entry point in the code age sequence. This is loaded as |
822 // a literal so there is no need to call FlushICache here. | 817 // a literal so there is no need to call FlushICache here. |
823 Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset; | 818 Address stub_entry_address = pc_ + kCodeAgeStubEntryOffset; |
824 Memory::Address_at(stub_entry_address) = stub->instruction_start(); | 819 Memory::Address_at(stub_entry_address) = stub->instruction_start(); |
825 } | 820 } |
826 | 821 |
827 | 822 |
828 Address RelocInfo::call_address() { | 823 Address RelocInfo::debug_call_address() { |
829 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 824 DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()); |
830 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | |
831 // For the above sequences the Relocinfo points to the load literal loading | 825 // For the above sequences the Relocinfo points to the load literal loading |
832 // the call address. | 826 // the call address. |
| 827 STATIC_ASSERT(Assembler::kPatchDebugBreakSlotAddressOffset == 0); |
833 return Assembler::target_address_at(pc_, host_); | 828 return Assembler::target_address_at(pc_, host_); |
834 } | 829 } |
835 | 830 |
836 | 831 |
837 void RelocInfo::set_call_address(Address target) { | 832 void RelocInfo::set_debug_call_address(Address target) { |
838 DCHECK((IsJSReturn(rmode()) && IsPatchedReturnSequence()) || | 833 DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence()); |
839 (IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence())); | 834 STATIC_ASSERT(Assembler::kPatchDebugBreakSlotAddressOffset == 0); |
840 Assembler::set_target_address_at(pc_, host_, target); | 835 Assembler::set_target_address_at(pc_, host_, target); |
841 if (host() != NULL) { | 836 if (host() != NULL) { |
842 Object* target_code = Code::GetCodeFromTargetAddress(target); | 837 Object* target_code = Code::GetCodeFromTargetAddress(target); |
843 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( | 838 host()->GetHeap()->incremental_marking()->RecordWriteIntoCode( |
844 host(), this, HeapObject::cast(target_code)); | 839 host(), this, HeapObject::cast(target_code)); |
845 } | 840 } |
846 } | 841 } |
847 | 842 |
848 | 843 |
849 void RelocInfo::WipeOut() { | 844 void RelocInfo::WipeOut() { |
850 DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) || | 845 DCHECK(IsEmbeddedObject(rmode_) || IsCodeTarget(rmode_) || |
851 IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) || | 846 IsRuntimeEntry(rmode_) || IsExternalReference(rmode_) || |
852 IsInternalReference(rmode_)); | 847 IsInternalReference(rmode_)); |
853 if (IsInternalReference(rmode_)) { | 848 if (IsInternalReference(rmode_)) { |
854 Memory::Address_at(pc_) = NULL; | 849 Memory::Address_at(pc_) = NULL; |
855 } else { | 850 } else { |
856 Assembler::set_target_address_at(pc_, host_, NULL); | 851 Assembler::set_target_address_at(pc_, host_, NULL); |
857 } | 852 } |
858 } | 853 } |
859 | 854 |
860 | 855 |
861 bool RelocInfo::IsPatchedReturnSequence() { | 856 bool RelocInfo::IsPatchedReturnSequence() { |
862 // The sequence must be: | 857 // The sequence must be: |
863 // ldr ip0, [pc, #offset] | 858 // ldr ip0, [pc, #offset] |
864 // blr ip0 | 859 // blr ip0 |
865 // See arm64/debug-arm64.cc BreakLocation::SetDebugBreakAtReturn(). | 860 // See arm64/debug-arm64.cc DebugCodegen::PatchDebugBreakSlot |
866 Instruction* i1 = reinterpret_cast<Instruction*>(pc_); | 861 Instruction* i1 = reinterpret_cast<Instruction*>(pc_); |
867 Instruction* i2 = i1->following(); | 862 Instruction* i2 = i1->following(); |
868 return i1->IsLdrLiteralX() && (i1->Rt() == kIp0Code) && | 863 return i1->IsLdrLiteralX() && (i1->Rt() == kIp0Code) && |
869 i2->IsBranchAndLinkToRegister() && (i2->Rn() == kIp0Code); | 864 i2->IsBranchAndLinkToRegister() && (i2->Rn() == kIp0Code); |
870 } | 865 } |
871 | 866 |
872 | 867 |
873 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { | 868 bool RelocInfo::IsPatchedDebugBreakSlotSequence() { |
874 Instruction* current_instr = reinterpret_cast<Instruction*>(pc_); | 869 Instruction* current_instr = reinterpret_cast<Instruction*>(pc_); |
875 return !current_instr->IsNop(Assembler::DEBUG_BREAK_NOP); | 870 return !current_instr->IsNop(Assembler::DEBUG_BREAK_NOP); |
876 } | 871 } |
877 | 872 |
878 | 873 |
879 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { | 874 void RelocInfo::Visit(Isolate* isolate, ObjectVisitor* visitor) { |
880 RelocInfo::Mode mode = rmode(); | 875 RelocInfo::Mode mode = rmode(); |
881 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 876 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
882 visitor->VisitEmbeddedPointer(this); | 877 visitor->VisitEmbeddedPointer(this); |
883 } else if (RelocInfo::IsCodeTarget(mode)) { | 878 } else if (RelocInfo::IsCodeTarget(mode)) { |
884 visitor->VisitCodeTarget(this); | 879 visitor->VisitCodeTarget(this); |
885 } else if (mode == RelocInfo::CELL) { | 880 } else if (mode == RelocInfo::CELL) { |
886 visitor->VisitCell(this); | 881 visitor->VisitCell(this); |
887 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { | 882 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { |
888 visitor->VisitExternalReference(this); | 883 visitor->VisitExternalReference(this); |
889 } else if (mode == RelocInfo::INTERNAL_REFERENCE) { | 884 } else if (mode == RelocInfo::INTERNAL_REFERENCE) { |
890 visitor->VisitInternalReference(this); | 885 visitor->VisitInternalReference(this); |
891 } else if (((RelocInfo::IsJSReturn(mode) && | 886 } else if (RelocInfo::IsDebugBreakSlot(mode) && |
892 IsPatchedReturnSequence()) || | 887 IsPatchedDebugBreakSlotSequence() && |
893 (RelocInfo::IsDebugBreakSlot(mode) && | |
894 IsPatchedDebugBreakSlotSequence())) && | |
895 isolate->debug()->has_break_points()) { | 888 isolate->debug()->has_break_points()) { |
896 visitor->VisitDebugTarget(this); | 889 visitor->VisitDebugTarget(this); |
897 } else if (RelocInfo::IsRuntimeEntry(mode)) { | 890 } else if (RelocInfo::IsRuntimeEntry(mode)) { |
898 visitor->VisitRuntimeEntry(this); | 891 visitor->VisitRuntimeEntry(this); |
899 } | 892 } |
900 } | 893 } |
901 | 894 |
902 | 895 |
903 template<typename StaticVisitor> | 896 template<typename StaticVisitor> |
904 void RelocInfo::Visit(Heap* heap) { | 897 void RelocInfo::Visit(Heap* heap) { |
905 RelocInfo::Mode mode = rmode(); | 898 RelocInfo::Mode mode = rmode(); |
906 if (mode == RelocInfo::EMBEDDED_OBJECT) { | 899 if (mode == RelocInfo::EMBEDDED_OBJECT) { |
907 StaticVisitor::VisitEmbeddedPointer(heap, this); | 900 StaticVisitor::VisitEmbeddedPointer(heap, this); |
908 } else if (RelocInfo::IsCodeTarget(mode)) { | 901 } else if (RelocInfo::IsCodeTarget(mode)) { |
909 StaticVisitor::VisitCodeTarget(heap, this); | 902 StaticVisitor::VisitCodeTarget(heap, this); |
910 } else if (mode == RelocInfo::CELL) { | 903 } else if (mode == RelocInfo::CELL) { |
911 StaticVisitor::VisitCell(heap, this); | 904 StaticVisitor::VisitCell(heap, this); |
912 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { | 905 } else if (mode == RelocInfo::EXTERNAL_REFERENCE) { |
913 StaticVisitor::VisitExternalReference(this); | 906 StaticVisitor::VisitExternalReference(this); |
914 } else if (mode == RelocInfo::INTERNAL_REFERENCE) { | 907 } else if (mode == RelocInfo::INTERNAL_REFERENCE) { |
915 StaticVisitor::VisitInternalReference(this); | 908 StaticVisitor::VisitInternalReference(this); |
916 } else if (heap->isolate()->debug()->has_break_points() && | 909 } else if (heap->isolate()->debug()->has_break_points() && |
917 ((RelocInfo::IsJSReturn(mode) && | 910 RelocInfo::IsDebugBreakSlot(mode) && |
918 IsPatchedReturnSequence()) || | 911 IsPatchedDebugBreakSlotSequence()) { |
919 (RelocInfo::IsDebugBreakSlot(mode) && | |
920 IsPatchedDebugBreakSlotSequence()))) { | |
921 StaticVisitor::VisitDebugTarget(heap, this); | 912 StaticVisitor::VisitDebugTarget(heap, this); |
922 } else if (RelocInfo::IsRuntimeEntry(mode)) { | 913 } else if (RelocInfo::IsRuntimeEntry(mode)) { |
923 StaticVisitor::VisitRuntimeEntry(this); | 914 StaticVisitor::VisitRuntimeEntry(this); |
924 } | 915 } |
925 } | 916 } |
926 | 917 |
927 | 918 |
928 LoadStoreOp Assembler::LoadOpFor(const CPURegister& rt) { | 919 LoadStoreOp Assembler::LoadOpFor(const CPURegister& rt) { |
929 DCHECK(rt.IsValid()); | 920 DCHECK(rt.IsValid()); |
930 if (rt.IsRegister()) { | 921 if (rt.IsRegister()) { |
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1292 | 1283 |
1293 | 1284 |
1294 void Assembler::ClearRecordedAstId() { | 1285 void Assembler::ClearRecordedAstId() { |
1295 recorded_ast_id_ = TypeFeedbackId::None(); | 1286 recorded_ast_id_ = TypeFeedbackId::None(); |
1296 } | 1287 } |
1297 | 1288 |
1298 | 1289 |
1299 } } // namespace v8::internal | 1290 } } // namespace v8::internal |
1300 | 1291 |
1301 #endif // V8_ARM64_ASSEMBLER_ARM64_INL_H_ | 1292 #endif // V8_ARM64_ASSEMBLER_ARM64_INL_H_ |
OLD | NEW |