Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Unified Diff: src/a64/assembler-a64.cc

Issue 169893002: A64: Let the MacroAssembler resolve branches to distant targets. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed Ulan's comments. Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/a64/assembler-a64.cc
diff --git a/src/a64/assembler-a64.cc b/src/a64/assembler-a64.cc
index 06acffbaacbd83ec98375775f8d0f69010911f2a..c19148f1f8f78943345d88f9993090e95328fb44 100644
--- a/src/a64/assembler-a64.cc
+++ b/src/a64/assembler-a64.cc
@@ -289,6 +289,7 @@ bool Operand::NeedsRelocation() const {
Assembler::Assembler(Isolate* isolate, void* buffer, int buffer_size)
: AssemblerBase(isolate, buffer, buffer_size),
recorded_ast_id_(TypeFeedbackId::None()),
+ unresolved_branches_(),
positions_recorder_(this) {
const_pool_blocked_nesting_ = 0;
Reset();
@@ -347,13 +348,13 @@ void Assembler::CheckLabelLinkChain(Label const * label) {
#ifdef DEBUG
if (label->is_linked()) {
int linkoffset = label->pos();
- bool start_of_chain = false;
- while (!start_of_chain) {
+ bool end_of_chain = false;
+ while (!end_of_chain) {
Instruction * link = InstructionAt(linkoffset);
int linkpcoffset = link->ImmPCOffset();
int prevlinkoffset = linkoffset + linkpcoffset;
- start_of_chain = (linkoffset == prevlinkoffset);
+ end_of_chain = (linkoffset == prevlinkoffset);
linkoffset = linkoffset + linkpcoffset;
}
}
@@ -361,6 +362,86 @@ void Assembler::CheckLabelLinkChain(Label const * label) {
}
+void Assembler::RemoveBranchFromLabelLinkChain(Instruction* branch,
+ Label* label,
+ Instruction* label_veneer) {
+ ASSERT(label->is_linked());
+
+ CheckLabelLinkChain(label);
+
+ Instruction* link = InstructionAt(label->pos());
+ Instruction* prev_link = link;
+ Instruction* next_link;
+ bool end_of_chain = false;
+
+ while (link != branch && !end_of_chain) {
+ next_link = link->ImmPCOffsetTarget();
+ end_of_chain = (link == next_link);
+ prev_link = link;
+ link = next_link;
+ }
+
+ ASSERT(branch == link);
+ next_link = branch->ImmPCOffsetTarget();
+
+ if (branch == prev_link) {
+ // The branch is the first instruction in the chain.
+ if (branch == next_link) {
+ // It is also the last instruction in the chain, so it is the only branch
+ // currently referring to this label.
+ label->Unuse();
+ } else {
+ label->link_to(reinterpret_cast<byte*>(next_link) - buffer_);
+ }
+
+ } else if (branch == next_link) {
+ // The branch is the last (but not also the first) instruction in the chain.
+ prev_link->SetImmPCOffsetTarget(prev_link);
+
+ } else {
+ // The branch is in the middle of the chain.
+ if (prev_link->IsTargetInImmPCOffsetRange(next_link)) {
+ prev_link->SetImmPCOffsetTarget(next_link);
+ } else if (label_veneer != NULL) {
+ // Use the veneer for all previous links in the chain.
+ prev_link->SetImmPCOffsetTarget(prev_link);
+
+ end_of_chain = false;
+ link = next_link;
+ while (!end_of_chain) {
+ next_link = link->ImmPCOffsetTarget();
+ end_of_chain = (link == next_link);
+ link->SetImmPCOffsetTarget(label_veneer);
+ link = next_link;
+ }
+ } else {
+ // The assert below will fire.
+ // Some other work could be attempted to fix up the chain, but it would be
+ // rather complicated. If we crash here, we may want to consider using an
+ // other mechanism than a chain of branches.
+ //
+ // Note that this situation currently should not happen, as we always call
+ // this function with a veneer to the target label.
+ // However this could happen with a MacroAssembler in the following state:
+ // [previous code]
+ // B(label);
+ // [20KB code]
+ // Tbz(label); // First tbz. Pointing to unconditional branch.
+ // [20KB code]
+ // Tbz(label); // Second tbz. Pointing to the first tbz.
+ // [more code]
+ // and this function is called to remove the first tbz from the label link
+ // chain. Since tbz has a range of +-32KB, the second tbz cannot point to
+ // the unconditional branch.
+ CHECK(prev_link->IsTargetInImmPCOffsetRange(next_link));
+ UNREACHABLE();
+ }
+ }
+
+ CheckLabelLinkChain(label);
+}
+
+
void Assembler::bind(Label* label) {
// Bind label to the address at pc_. All instructions (most likely branches)
// that are linked to this label will be updated to point to the newly-bound
@@ -410,6 +491,8 @@ void Assembler::bind(Label* label) {
ASSERT(label->is_bound());
ASSERT(!label->is_linked());
+
+ DeleteUnresolvedBranchInfoForLabel(label);
}
@@ -456,6 +539,20 @@ int Assembler::LinkAndGetByteOffsetTo(Label* label) {
}
+void Assembler::DeleteUnresolvedBranchInfoForLabel(Label* label) {
+ // 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);
+ }
+ }
+}
+
+
void Assembler::StartBlockConstPool() {
if (const_pool_blocked_nesting_++ == 0) {
// Prevent constant pool checks happening by setting the next check to
@@ -526,8 +623,7 @@ void Assembler::ConstantPoolGuard() {
instr->preceding()->Rt() == xzr.code());
#endif
- // Crash by branching to 0. lr now points near the fault.
- // TODO(all): update the simulator to trap this pattern.
+ // We must generate only one instruction.
Emit(BLR | Rn(xzr));
}

Powered by Google App Engine
This is Rietveld 408576698