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
This commit is contained in:
alexandre.rames@arm.com 2014-04-14 11:08:14 +00:00
parent b0938269dc
commit 97585ab8b5
3 changed files with 50 additions and 10 deletions

View File

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

View File

@ -1694,6 +1694,10 @@ class Assembler : public AssemblerBase {
return reinterpret_cast<Instruction*>(buffer_ + offset);
}
ptrdiff_t InstructionOffset(Instruction* instr) const {
return reinterpret_cast<byte*>(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_;

View File

@ -192,6 +192,10 @@ class Instruction {
return Mask(TestBranchFMask) == TestBranchFixed;
}
bool IsImmBranch() const {
return BranchType() != UnknownBranchType;
}
bool IsLdrLiteral() const {
return Mask(LoadLiteralFMask) == LoadLiteralFixed;
}