Index: src/arm64/assembler-arm64.cc |
diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc |
index 5695623afd54e033ca6ec9ebfb349cef159b14c4..b399277543ff039911c1884e7c022d288fb401e7 100644 |
--- a/src/arm64/assembler-arm64.cc |
+++ b/src/arm64/assembler-arm64.cc |
@@ -545,6 +545,40 @@ int Assembler::LinkAndGetByteOffsetTo(Label* label) { |
} |
+void Assembler::DeleteUnresolvedBranchInfoForLabelTraverse(Label* label) { |
+ ASSERT(label->is_linked()); |
+ CheckLabelLinkChain(label); |
+ |
+ int link_offset = label->pos(); |
+ int link_pcoffset; |
+ bool end_of_chain = false; |
+ |
+ while (!end_of_chain) { |
+ Instruction * link = InstructionAt(link_offset); |
+ link_pcoffset = link->ImmPCOffset(); |
+ |
+ // ADR instructions are not handled by veneers. |
+ if (link->IsImmBranch()) { |
+ int max_reachable_pc = InstructionOffset(link) + |
+ Instruction::ImmBranchRange(link->BranchType()); |
+ typedef std::multimap<int, FarBranchInfo>::iterator unresolved_info_it; |
+ std::pair<unresolved_info_it, unresolved_info_it> range; |
+ range = unresolved_branches_.equal_range(max_reachable_pc); |
+ unresolved_info_it it; |
+ for (it = range.first; it != range.second; ++it) { |
+ if (it->second.pc_offset_ == link_offset) { |
+ unresolved_branches_.erase(it); |
+ break; |
+ } |
+ } |
+ } |
+ |
+ end_of_chain = (link_pcoffset == 0); |
+ link_offset = link_offset + link_pcoffset; |
+ } |
+} |
+ |
+ |
void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) { |
if (unresolved_branches_.empty()) { |
ASSERT(next_veneer_pool_check_ == kMaxInt); |
@@ -552,16 +586,9 @@ void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) { |
} |
if (label->is_linked()) { |
- // Branches to this label will be resolved when the label is bound below. |
- std::multimap<int, FarBranchInfo>::iterator it_tmp, it; |
- it = unresolved_branches_.begin(); |
- while (it != unresolved_branches_.end()) { |
- it_tmp = it++; |
- if (it_tmp->second.label_ == label) { |
- CHECK(it_tmp->first >= pc_offset()); |
- unresolved_branches_.erase(it_tmp); |
- } |
- } |
+ // Branches to this label will be resolved when the label is bound, normally |
+ // just after all the associated info has been deleted. |
+ DeleteUnresolvedBranchInfoForLabelTraverse(label); |
} |
if (unresolved_branches_.empty()) { |
next_veneer_pool_check_ = kMaxInt; |