OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // | 2 // |
3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
5 // met: | 5 // met: |
6 // | 6 // |
7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
10 // copyright notice, this list of conditions and the following | 10 // copyright notice, this list of conditions and the following |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 DCHECK(IsWasmGlobalReference(rmode_)); | 192 DCHECK(IsWasmGlobalReference(rmode_)); |
193 return Memory::Address_at(Assembler::target_pointer_address_at(pc_)); | 193 return Memory::Address_at(Assembler::target_pointer_address_at(pc_)); |
194 } | 194 } |
195 | 195 |
196 uint32_t RelocInfo::wasm_function_table_size_reference() { | 196 uint32_t RelocInfo::wasm_function_table_size_reference() { |
197 DCHECK(IsWasmFunctionTableSizeReference(rmode_)); | 197 DCHECK(IsWasmFunctionTableSizeReference(rmode_)); |
198 return Memory::uint32_at(Assembler::target_pointer_address_at(pc_)); | 198 return Memory::uint32_at(Assembler::target_pointer_address_at(pc_)); |
199 } | 199 } |
200 | 200 |
201 void RelocInfo::unchecked_update_wasm_memory_reference( | 201 void RelocInfo::unchecked_update_wasm_memory_reference( |
202 Address address, ICacheFlushMode flush_mode) { | 202 Isolate* isolate, Address address, ICacheFlushMode flush_mode) { |
203 Assembler::set_target_address_at(isolate_, pc_, host_, address, flush_mode); | 203 Assembler::set_target_address_at(isolate, pc_, host_, address, flush_mode); |
204 } | 204 } |
205 | 205 |
206 void RelocInfo::unchecked_update_wasm_size(uint32_t size, | 206 void RelocInfo::unchecked_update_wasm_size(Isolate* isolate, uint32_t size, |
207 ICacheFlushMode flush_mode) { | 207 ICacheFlushMode flush_mode) { |
208 Memory::uint32_at(Assembler::target_pointer_address_at(pc_)) = size; | 208 Memory::uint32_at(Assembler::target_pointer_address_at(pc_)) = size; |
209 // No icache flushing needed, see comment in set_target_address_at. | 209 // No icache flushing needed, see comment in set_target_address_at. |
210 } | 210 } |
211 | 211 |
212 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2, | 212 Register GetAllocatableRegisterThatIsNotOneOf(Register reg1, Register reg2, |
213 Register reg3, Register reg4) { | 213 Register reg3, Register reg4) { |
214 CPURegList regs(reg1, reg2, reg3, reg4); | 214 CPURegList regs(reg1, reg2, reg3, reg4); |
215 const RegisterConfiguration* config = RegisterConfiguration::Crankshaft(); | 215 const RegisterConfiguration* config = RegisterConfiguration::Crankshaft(); |
216 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { | 216 for (int i = 0; i < config->num_allocatable_double_registers(); ++i) { |
(...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
521 std::pair<SharedEntriesIterator, SharedEntriesIterator> range; | 521 std::pair<SharedEntriesIterator, SharedEntriesIterator> range; |
522 uint64_t data = value_it->first; | 522 uint64_t data = value_it->first; |
523 range = shared_entries_.equal_range(data); | 523 range = shared_entries_.equal_range(data); |
524 SharedEntriesIterator offset_it; | 524 SharedEntriesIterator offset_it; |
525 // Iterate through the offsets of a given key. | 525 // Iterate through the offsets of a given key. |
526 for (offset_it = range.first; offset_it != range.second; offset_it++) { | 526 for (offset_it = range.first; offset_it != range.second; offset_it++) { |
527 Instruction* instr = assm_->InstructionAt(offset_it->second); | 527 Instruction* instr = assm_->InstructionAt(offset_it->second); |
528 | 528 |
529 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. | 529 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. |
530 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0); | 530 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0); |
531 instr->SetImmPCOffsetTarget(assm_->isolate(), assm_->pc()); | 531 instr->SetImmPCOffsetTarget(assm_->isolate_data(), assm_->pc()); |
532 } | 532 } |
533 assm_->dc64(data); | 533 assm_->dc64(data); |
534 } | 534 } |
535 shared_entries_.clear(); | 535 shared_entries_.clear(); |
536 shared_entries_count = 0; | 536 shared_entries_count = 0; |
537 | 537 |
538 // Emit unique entries. | 538 // Emit unique entries. |
539 std::vector<std::pair<uint64_t, int> >::const_iterator unique_it; | 539 std::vector<std::pair<uint64_t, int> >::const_iterator unique_it; |
540 for (unique_it = unique_entries_.begin(); | 540 for (unique_it = unique_entries_.begin(); |
541 unique_it != unique_entries_.end(); | 541 unique_it != unique_entries_.end(); |
542 unique_it++) { | 542 unique_it++) { |
543 Instruction* instr = assm_->InstructionAt(unique_it->second); | 543 Instruction* instr = assm_->InstructionAt(unique_it->second); |
544 | 544 |
545 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. | 545 // Instruction to patch must be 'ldr rd, [pc, #offset]' with offset == 0. |
546 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0); | 546 DCHECK(instr->IsLdrLiteral() && instr->ImmLLiteral() == 0); |
547 instr->SetImmPCOffsetTarget(assm_->isolate(), assm_->pc()); | 547 instr->SetImmPCOffsetTarget(assm_->isolate_data(), assm_->pc()); |
548 assm_->dc64(unique_it->first); | 548 assm_->dc64(unique_it->first); |
549 } | 549 } |
550 unique_entries_.clear(); | 550 unique_entries_.clear(); |
551 first_use_ = -1; | 551 first_use_ = -1; |
552 } | 552 } |
553 | 553 |
554 | 554 |
555 // Assembler | 555 // Assembler |
556 Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size) | 556 Assembler::Assembler(IsolateData isolate_data, void* buffer, int buffer_size) |
557 : AssemblerBase(isolate, buffer, buffer_size), | 557 : AssemblerBase(isolate_data, buffer, buffer_size), |
558 constpool_(this), | 558 constpool_(this), |
559 recorded_ast_id_(TypeFeedbackId::None()), | 559 recorded_ast_id_(TypeFeedbackId::None()), |
560 unresolved_branches_() { | 560 unresolved_branches_() { |
561 const_pool_blocked_nesting_ = 0; | 561 const_pool_blocked_nesting_ = 0; |
562 veneer_pool_blocked_nesting_ = 0; | 562 veneer_pool_blocked_nesting_ = 0; |
563 Reset(); | 563 Reset(); |
564 } | 564 } |
565 | 565 |
566 | 566 |
567 Assembler::~Assembler() { | 567 Assembler::~Assembler() { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 // It is also the last instruction in the chain, so it is the only branch | 668 // It is also the last instruction in the chain, so it is the only branch |
669 // currently referring to this label. | 669 // currently referring to this label. |
670 label->Unuse(); | 670 label->Unuse(); |
671 } else { | 671 } else { |
672 label->link_to( | 672 label->link_to( |
673 static_cast<int>(reinterpret_cast<byte*>(next_link) - buffer_)); | 673 static_cast<int>(reinterpret_cast<byte*>(next_link) - buffer_)); |
674 } | 674 } |
675 | 675 |
676 } else if (branch == next_link) { | 676 } else if (branch == next_link) { |
677 // The branch is the last (but not also the first) instruction in the chain. | 677 // The branch is the last (but not also the first) instruction in the chain. |
678 prev_link->SetImmPCOffsetTarget(isolate(), prev_link); | 678 prev_link->SetImmPCOffsetTarget(isolate_data(), prev_link); |
679 | 679 |
680 } else { | 680 } else { |
681 // The branch is in the middle of the chain. | 681 // The branch is in the middle of the chain. |
682 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) { | 682 if (prev_link->IsTargetInImmPCOffsetRange(next_link)) { |
683 prev_link->SetImmPCOffsetTarget(isolate(), next_link); | 683 prev_link->SetImmPCOffsetTarget(isolate_data(), next_link); |
684 } else if (label_veneer != NULL) { | 684 } else if (label_veneer != NULL) { |
685 // Use the veneer for all previous links in the chain. | 685 // Use the veneer for all previous links in the chain. |
686 prev_link->SetImmPCOffsetTarget(isolate(), prev_link); | 686 prev_link->SetImmPCOffsetTarget(isolate_data(), prev_link); |
687 | 687 |
688 end_of_chain = false; | 688 end_of_chain = false; |
689 link = next_link; | 689 link = next_link; |
690 while (!end_of_chain) { | 690 while (!end_of_chain) { |
691 next_link = link->ImmPCOffsetTarget(); | 691 next_link = link->ImmPCOffsetTarget(); |
692 end_of_chain = (link == next_link); | 692 end_of_chain = (link == next_link); |
693 link->SetImmPCOffsetTarget(isolate(), label_veneer); | 693 link->SetImmPCOffsetTarget(isolate_data(), label_veneer); |
694 link = next_link; | 694 link = next_link; |
695 } | 695 } |
696 } else { | 696 } else { |
697 // The assert below will fire. | 697 // The assert below will fire. |
698 // Some other work could be attempted to fix up the chain, but it would be | 698 // Some other work could be attempted to fix up the chain, but it would be |
699 // rather complicated. If we crash here, we may want to consider using an | 699 // rather complicated. If we crash here, we may want to consider using an |
700 // other mechanism than a chain of branches. | 700 // other mechanism than a chain of branches. |
701 // | 701 // |
702 // Note that this situation currently should not happen, as we always call | 702 // Note that this situation currently should not happen, as we always call |
703 // this function with a veneer to the target label. | 703 // this function with a veneer to the target label. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 DCHECK(linkoffset < pc_offset()); | 754 DCHECK(linkoffset < pc_offset()); |
755 DCHECK((linkoffset > prevlinkoffset) || | 755 DCHECK((linkoffset > prevlinkoffset) || |
756 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); | 756 (linkoffset - prevlinkoffset == kStartOfLabelLinkChain)); |
757 DCHECK(prevlinkoffset >= 0); | 757 DCHECK(prevlinkoffset >= 0); |
758 | 758 |
759 // Update the link to point to the label. | 759 // Update the link to point to the label. |
760 if (link->IsUnresolvedInternalReference()) { | 760 if (link->IsUnresolvedInternalReference()) { |
761 // Internal references do not get patched to an instruction but directly | 761 // Internal references do not get patched to an instruction but directly |
762 // to an address. | 762 // to an address. |
763 internal_reference_positions_.push_back(linkoffset); | 763 internal_reference_positions_.push_back(linkoffset); |
764 PatchingAssembler patcher(isolate(), link, 2); | 764 PatchingAssembler patcher(isolate_data(), reinterpret_cast<byte*>(link), |
| 765 2); |
765 patcher.dc64(reinterpret_cast<uintptr_t>(pc_)); | 766 patcher.dc64(reinterpret_cast<uintptr_t>(pc_)); |
766 } else { | 767 } else { |
767 link->SetImmPCOffsetTarget(isolate(), | 768 link->SetImmPCOffsetTarget(isolate_data(), |
768 reinterpret_cast<Instruction*>(pc_)); | 769 reinterpret_cast<Instruction*>(pc_)); |
769 } | 770 } |
770 | 771 |
771 // Link the label to the previous link in the chain. | 772 // Link the label to the previous link in the chain. |
772 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { | 773 if (linkoffset - prevlinkoffset == kStartOfLabelLinkChain) { |
773 // We hit kStartOfLabelLinkChain, so the chain is fully processed. | 774 // We hit kStartOfLabelLinkChain, so the chain is fully processed. |
774 label->Unuse(); | 775 label->Unuse(); |
775 } else { | 776 } else { |
776 // Update the label for the next iteration. | 777 // Update the label for the next iteration. |
777 label->link_to(prevlinkoffset); | 778 label->link_to(prevlinkoffset); |
(...skipping 2163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2941 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos); | 2942 intptr_t* p = reinterpret_cast<intptr_t*>(buffer_ + pos); |
2942 *p += pc_delta; | 2943 *p += pc_delta; |
2943 } | 2944 } |
2944 | 2945 |
2945 // Pending relocation entries are also relative, no need to relocate. | 2946 // Pending relocation entries are also relative, no need to relocate. |
2946 } | 2947 } |
2947 | 2948 |
2948 | 2949 |
2949 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { | 2950 void Assembler::RecordRelocInfo(RelocInfo::Mode rmode, intptr_t data) { |
2950 // We do not try to reuse pool constants. | 2951 // We do not try to reuse pool constants. |
2951 RelocInfo rinfo(isolate(), reinterpret_cast<byte*>(pc_), rmode, data, NULL); | 2952 RelocInfo rinfo(reinterpret_cast<byte*>(pc_), rmode, data, NULL); |
2952 if (((rmode >= RelocInfo::COMMENT) && | 2953 if (((rmode >= RelocInfo::COMMENT) && |
2953 (rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL)) || | 2954 (rmode <= RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL)) || |
2954 (rmode == RelocInfo::INTERNAL_REFERENCE) || | 2955 (rmode == RelocInfo::INTERNAL_REFERENCE) || |
2955 (rmode == RelocInfo::CONST_POOL) || (rmode == RelocInfo::VENEER_POOL) || | 2956 (rmode == RelocInfo::CONST_POOL) || (rmode == RelocInfo::VENEER_POOL) || |
2956 (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) || | 2957 (rmode == RelocInfo::DEOPT_SCRIPT_OFFSET) || |
2957 (rmode == RelocInfo::DEOPT_INLINING_ID) || | 2958 (rmode == RelocInfo::DEOPT_INLINING_ID) || |
2958 (rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID)) { | 2959 (rmode == RelocInfo::DEOPT_REASON) || (rmode == RelocInfo::DEOPT_ID)) { |
2959 // Adjust code for new modes. | 2960 // Adjust code for new modes. |
2960 DCHECK(RelocInfo::IsDebugBreakSlot(rmode) || RelocInfo::IsComment(rmode) || | 2961 DCHECK(RelocInfo::IsDebugBreakSlot(rmode) || RelocInfo::IsComment(rmode) || |
2961 RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsDeoptId(rmode) || | 2962 RelocInfo::IsDeoptReason(rmode) || RelocInfo::IsDeoptId(rmode) || |
2962 RelocInfo::IsDeoptPosition(rmode) || | 2963 RelocInfo::IsDeoptPosition(rmode) || |
2963 RelocInfo::IsInternalReference(rmode) || | 2964 RelocInfo::IsInternalReference(rmode) || |
2964 RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)); | 2965 RelocInfo::IsConstPool(rmode) || RelocInfo::IsVeneerPool(rmode)); |
2965 // These modes do not need an entry in the constant pool. | 2966 // These modes do not need an entry in the constant pool. |
2966 } else { | 2967 } else { |
2967 constpool_.RecordEntry(data, rmode); | 2968 constpool_.RecordEntry(data, rmode); |
2968 // Make sure the constant pool is not emitted in place of the next | 2969 // Make sure the constant pool is not emitted in place of the next |
2969 // instruction for which we just recorded relocation info. | 2970 // instruction for which we just recorded relocation info. |
2970 BlockConstPoolFor(1); | 2971 BlockConstPoolFor(1); |
2971 } | 2972 } |
2972 | 2973 |
2973 if (!RelocInfo::IsNone(rmode)) { | 2974 if (!RelocInfo::IsNone(rmode)) { |
2974 // Don't record external references unless the heap will be serialized. | 2975 // Don't record external references unless the heap will be serialized. |
2975 if (rmode == RelocInfo::EXTERNAL_REFERENCE && | 2976 if (rmode == RelocInfo::EXTERNAL_REFERENCE && |
2976 !serializer_enabled() && !emit_debug_code()) { | 2977 !serializer_enabled() && !emit_debug_code()) { |
2977 return; | 2978 return; |
2978 } | 2979 } |
2979 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here | 2980 DCHECK(buffer_space() >= kMaxRelocSize); // too late to grow buffer here |
2980 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { | 2981 if (rmode == RelocInfo::CODE_TARGET_WITH_ID) { |
2981 RelocInfo reloc_info_with_ast_id(isolate(), reinterpret_cast<byte*>(pc_), | 2982 RelocInfo reloc_info_with_ast_id(reinterpret_cast<byte*>(pc_), rmode, |
2982 rmode, RecordedAstId().ToInt(), NULL); | 2983 RecordedAstId().ToInt(), NULL); |
2983 ClearRecordedAstId(); | 2984 ClearRecordedAstId(); |
2984 reloc_info_writer.Write(&reloc_info_with_ast_id); | 2985 reloc_info_writer.Write(&reloc_info_with_ast_id); |
2985 } else { | 2986 } else { |
2986 reloc_info_writer.Write(&rinfo); | 2987 reloc_info_writer.Write(&rinfo); |
2987 } | 2988 } |
2988 } | 2989 } |
2989 } | 2990 } |
2990 | 2991 |
2991 | 2992 |
2992 void Assembler::BlockConstPoolFor(int instructions) { | 2993 void Assembler::BlockConstPoolFor(int instructions) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3061 | 3062 |
3062 bool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) { | 3063 bool Assembler::ShouldEmitVeneer(int max_reachable_pc, int margin) { |
3063 // Account for the branch around the veneers and the guard. | 3064 // Account for the branch around the veneers and the guard. |
3064 int protection_offset = 2 * kInstructionSize; | 3065 int protection_offset = 2 * kInstructionSize; |
3065 return pc_offset() > max_reachable_pc - margin - protection_offset - | 3066 return pc_offset() > max_reachable_pc - margin - protection_offset - |
3066 static_cast<int>(unresolved_branches_.size() * kMaxVeneerCodeSize); | 3067 static_cast<int>(unresolved_branches_.size() * kMaxVeneerCodeSize); |
3067 } | 3068 } |
3068 | 3069 |
3069 | 3070 |
3070 void Assembler::RecordVeneerPool(int location_offset, int size) { | 3071 void Assembler::RecordVeneerPool(int location_offset, int size) { |
3071 RelocInfo rinfo(isolate(), buffer_ + location_offset, RelocInfo::VENEER_POOL, | 3072 RelocInfo rinfo(buffer_ + location_offset, RelocInfo::VENEER_POOL, |
3072 static_cast<intptr_t>(size), NULL); | 3073 static_cast<intptr_t>(size), NULL); |
3073 reloc_info_writer.Write(&rinfo); | 3074 reloc_info_writer.Write(&rinfo); |
3074 } | 3075 } |
3075 | 3076 |
3076 | 3077 |
3077 void Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) { | 3078 void Assembler::EmitVeneers(bool force_emit, bool need_protection, int margin) { |
3078 BlockPoolsScope scope(this); | 3079 BlockPoolsScope scope(this); |
3079 RecordComment("[ Veneers"); | 3080 RecordComment("[ Veneers"); |
3080 | 3081 |
3081 // The exact size of the veneer pool must be recorded (see the comment at the | 3082 // The exact size of the veneer pool must be recorded (see the comment at the |
(...skipping 22 matching lines...) Expand all Loading... |
3104 Instruction* branch = InstructionAt(it->second.pc_offset_); | 3105 Instruction* branch = InstructionAt(it->second.pc_offset_); |
3105 Label* label = it->second.label_; | 3106 Label* label = it->second.label_; |
3106 | 3107 |
3107 #ifdef DEBUG | 3108 #ifdef DEBUG |
3108 bind(&veneer_size_check); | 3109 bind(&veneer_size_check); |
3109 #endif | 3110 #endif |
3110 // Patch the branch to point to the current position, and emit a branch | 3111 // Patch the branch to point to the current position, and emit a branch |
3111 // to the label. | 3112 // to the label. |
3112 Instruction* veneer = reinterpret_cast<Instruction*>(pc_); | 3113 Instruction* veneer = reinterpret_cast<Instruction*>(pc_); |
3113 RemoveBranchFromLabelLinkChain(branch, label, veneer); | 3114 RemoveBranchFromLabelLinkChain(branch, label, veneer); |
3114 branch->SetImmPCOffsetTarget(isolate(), veneer); | 3115 branch->SetImmPCOffsetTarget(isolate_data(), veneer); |
3115 b(label); | 3116 b(label); |
3116 #ifdef DEBUG | 3117 #ifdef DEBUG |
3117 DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <= | 3118 DCHECK(SizeOfCodeGeneratedSince(&veneer_size_check) <= |
3118 static_cast<uint64_t>(kMaxVeneerCodeSize)); | 3119 static_cast<uint64_t>(kMaxVeneerCodeSize)); |
3119 veneer_size_check.Unuse(); | 3120 veneer_size_check.Unuse(); |
3120 #endif | 3121 #endif |
3121 | 3122 |
3122 it_to_delete = it++; | 3123 it_to_delete = it++; |
3123 unresolved_branches_.erase(it_to_delete); | 3124 unresolved_branches_.erase(it_to_delete); |
3124 } else { | 3125 } else { |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3217 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); | 3218 movk(scratch, (target_offset >> 32) & 0xFFFF, 32); |
3218 DCHECK((target_offset >> 48) == 0); | 3219 DCHECK((target_offset >> 48) == 0); |
3219 add(rd, rd, scratch); | 3220 add(rd, rd, scratch); |
3220 } | 3221 } |
3221 | 3222 |
3222 | 3223 |
3223 } // namespace internal | 3224 } // namespace internal |
3224 } // namespace v8 | 3225 } // namespace v8 |
3225 | 3226 |
3226 #endif // V8_TARGET_ARCH_ARM64 | 3227 #endif // V8_TARGET_ARCH_ARM64 |
OLD | NEW |