From 97585ab8b5b7bec0031dc7a8191a3d1f02d27430 Mon Sep 17 00:00:00 2001 From: "alexandre.rames@arm.com" Date: Mon, 14 Apr 2014 11:08:14 +0000 Subject: [PATCH] ARM64: Avoid iterating through all unresolved branch infos when many are pending. Instead, inspect the label chain and delete pending information for every branch in the chain. R=ulan@chromium.org Review URL: https://codereview.chromium.org/227043010 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20715 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm64/assembler-arm64.cc | 47 ++++++++++++++++++++++++++-------- src/arm64/assembler-arm64.h | 9 +++++++ src/arm64/instructions-arm64.h | 4 +++ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/arm64/assembler-arm64.cc b/src/arm64/assembler-arm64.cc index 5695623afd..b399277543 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::iterator unresolved_info_it; + std::pair 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::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; diff --git a/src/arm64/assembler-arm64.h b/src/arm64/assembler-arm64.h index 391a900763..794f87c01e 100644 --- a/src/arm64/assembler-arm64.h +++ b/src/arm64/assembler-arm64.h @@ -1694,6 +1694,10 @@ class Assembler : public AssemblerBase { return reinterpret_cast(buffer_ + offset); } + ptrdiff_t InstructionOffset(Instruction* instr) const { + return reinterpret_cast(instr) - buffer_; + } + // Register encoding. static Instr Rd(CPURegister rd) { ASSERT(rd.code() != kSPRegInternalCode); @@ -2183,6 +2187,11 @@ class Assembler : public AssemblerBase { // not later attempt (likely unsuccessfully) to patch it to branch directly to // the label. void DeleteUnresolvedBranchInfoForLabel(Label* label); + // This function deletes the information related to the label by traversing + // the label chain, and for each PC-relative instruction in the chain checking + // if pending unresolved information exists. Its complexity is proportional to + // the length of the label chain. + void DeleteUnresolvedBranchInfoForLabelTraverse(Label* label); private: PositionsRecorder positions_recorder_; diff --git a/src/arm64/instructions-arm64.h b/src/arm64/instructions-arm64.h index de76b69b6b..cfa63a345c 100644 --- a/src/arm64/instructions-arm64.h +++ b/src/arm64/instructions-arm64.h @@ -192,6 +192,10 @@ class Instruction { return Mask(TestBranchFMask) == TestBranchFixed; } + bool IsImmBranch() const { + return BranchType() != UnknownBranchType; + } + bool IsLdrLiteral() const { return Mask(LoadLiteralFMask) == LoadLiteralFixed; }