| 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 |