Index: src/mips64/assembler-mips64.cc |
diff --git a/src/mips64/assembler-mips64.cc b/src/mips64/assembler-mips64.cc |
index 7c0c76e9fcbd600dff16a3561fa11ab8259cf26a..4ce970da332c9e3a2a6ff0fbed5fedef7209a1c3 100644 |
--- a/src/mips64/assembler-mips64.cc |
+++ b/src/mips64/assembler-mips64.cc |
@@ -175,7 +175,8 @@ Register ToRegister(int num) { |
// Implementation of RelocInfo. |
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | |
- 1 << RelocInfo::INTERNAL_REFERENCE; |
+ 1 << RelocInfo::INTERNAL_REFERENCE | |
+ 1 << RelocInfo::INTERNAL_REFERENCE_ENCODED; |
bool RelocInfo::IsCodedSpecially() { |
@@ -634,7 +635,19 @@ bool Assembler::IsAndImmediate(Instr instr) { |
} |
-int64_t Assembler::target_at(int64_t pos) { |
+int64_t Assembler::target_at(int64_t pos, bool is_internal) { |
+ if (is_internal) { |
+ int64_t* p = reinterpret_cast<int64_t*>(buffer_ + pos); |
+ int64_t address = *p; |
+ if (address == kEndOfJumpChain) { |
+ return kEndOfChain; |
+ } else { |
+ int64_t instr_address = reinterpret_cast<int64_t>(p); |
+ int64_t delta = instr_address - address; |
+ DCHECK(pos > delta); |
+ return pos - delta; |
+ } |
+ } |
Instr instr = instr_at(pos); |
if ((instr & ~kImm16Mask) == 0) { |
// Emitted label constant, not part of a branch. |
@@ -696,7 +709,13 @@ int64_t Assembler::target_at(int64_t pos) { |
} |
-void Assembler::target_at_put(int64_t pos, int64_t target_pos) { |
+void Assembler::target_at_put(int64_t pos, int64_t target_pos, |
+ bool is_internal) { |
+ if (is_internal) { |
+ uint64_t imm = reinterpret_cast<uint64_t>(buffer_) + target_pos; |
+ *reinterpret_cast<uint64_t*>(buffer_ + pos) = imm; |
+ return; |
+ } |
Instr instr = instr_at(pos); |
if ((instr & ~kImm16Mask) == 0) { |
DCHECK(target_pos == kEndOfChain || target_pos >= 0); |
@@ -766,7 +785,8 @@ void Assembler::print(Label* L) { |
} else { |
PrintF("%d\n", instr); |
} |
- next(&l); |
+ next(&l, internal_reference_positions_.find(l.pos()) != |
+ internal_reference_positions_.end()); |
} |
} else { |
PrintF("label in inconsistent state (pos = %d)\n", L->pos_); |
@@ -777,6 +797,7 @@ void Assembler::print(Label* L) { |
void Assembler::bind_to(Label* L, int pos) { |
DCHECK(0 <= pos && pos <= pc_offset()); // Must have valid binding position. |
int32_t trampoline_pos = kInvalidSlotPos; |
+ bool is_internal = false; |
if (L->is_linked() && !trampoline_emitted_) { |
unbound_labels_count_--; |
next_buffer_check_ += kTrampolineSlotsSize; |
@@ -785,23 +806,28 @@ void Assembler::bind_to(Label* L, int pos) { |
while (L->is_linked()) { |
int32_t fixup_pos = L->pos(); |
int32_t dist = pos - fixup_pos; |
- next(L); // Call next before overwriting link with target at fixup_pos. |
+ is_internal = internal_reference_positions_.find(fixup_pos) != |
+ internal_reference_positions_.end(); |
+ next(L, is_internal); // Call next before overwriting link with target at |
+ // fixup_pos. |
Instr instr = instr_at(fixup_pos); |
- if (IsBranch(instr)) { |
+ if (is_internal) { |
+ target_at_put(fixup_pos, pos, is_internal); |
+ } else if (IsBranch(instr)) { |
if (dist > kMaxBranchOffset) { |
if (trampoline_pos == kInvalidSlotPos) { |
trampoline_pos = get_trampoline_entry(fixup_pos); |
CHECK(trampoline_pos != kInvalidSlotPos); |
} |
DCHECK((trampoline_pos - fixup_pos) <= kMaxBranchOffset); |
- target_at_put(fixup_pos, trampoline_pos); |
+ target_at_put(fixup_pos, trampoline_pos, false); |
fixup_pos = trampoline_pos; |
dist = pos - fixup_pos; |
} |
- target_at_put(fixup_pos, pos); |
+ target_at_put(fixup_pos, pos, false); |
} else { |
DCHECK(IsJ(instr) || IsLui(instr) || IsEmittedConstant(instr)); |
- target_at_put(fixup_pos, pos); |
+ target_at_put(fixup_pos, pos, false); |
} |
} |
L->bind_to(pos); |
@@ -819,9 +845,9 @@ void Assembler::bind(Label* L) { |
} |
-void Assembler::next(Label* L) { |
+void Assembler::next(Label* L, bool is_internal) { |
DCHECK(L->is_linked()); |
- int link = target_at(L->pos()); |
+ int link = target_at(L->pos(), is_internal); |
if (link == kEndOfChain) { |
L->Unuse(); |
} else { |
@@ -2559,8 +2585,18 @@ void Assembler::bc1t(int16_t offset, uint16_t cc) { |
// Debugging. |
-int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) { |
+int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc, |
+ intptr_t pc_delta) { |
+ if (RelocInfo::IsInternalReference(rmode)) { |
+ int64_t* p = reinterpret_cast<int64_t*>(pc); |
+ if (*p == kEndOfJumpChain) { |
+ return 0; // Number of instructions patched. |
+ } |
+ *p += pc_delta; |
+ return 2; // Number of instructions patched. |
+ } |
Instr instr = instr_at(pc); |
+ DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode)); |
DCHECK(IsJ(instr) || IsLui(instr)); |
if (IsLui(instr)) { |
Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize); |
@@ -2649,12 +2685,12 @@ void Assembler::GrowBuffer() { |
// Relocate runtime entries. |
for (RelocIterator it(desc); !it.done(); it.next()) { |
RelocInfo::Mode rmode = it.rinfo()->rmode(); |
- if (rmode == RelocInfo::INTERNAL_REFERENCE) { |
+ if (rmode == RelocInfo::INTERNAL_REFERENCE_ENCODED || |
+ rmode == RelocInfo::INTERNAL_REFERENCE) { |
byte* p = reinterpret_cast<byte*>(it.rinfo()->pc()); |
- RelocateInternalReference(p, pc_delta); |
+ RelocateInternalReference(rmode, p, pc_delta); |
} |
} |
- |
DCHECK(!overflow()); |
} |
@@ -2673,6 +2709,21 @@ void Assembler::dd(uint32_t data) { |
} |
+void Assembler::dd(Label* label) { |
+ CheckBuffer(); |
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
+ if (label->is_bound()) { |
+ uint64_t data = reinterpret_cast<uint64_t>(buffer_ + label->pos()); |
+ *reinterpret_cast<uint64_t*>(pc_) = data; |
+ pc_ += sizeof(uint64_t); |
+ } else { |
+ uint64_t target_pos = jump_address(label); |
+ emit(target_pos); |
+ internal_reference_positions_.insert(label->pos()); |
+ } |
+} |
+ |
+ |
void Assembler::emit_code_stub_address(Code* stub) { |
CheckBuffer(); |
*reinterpret_cast<uint64_t*>(pc_) = |
@@ -2753,7 +2804,7 @@ void Assembler::CheckTrampolinePool() { |
// Buffer growth (and relocation) must be blocked for internal |
// references until associated instructions are emitted and available |
// to be patched. |
- RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE); |
+ RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED); |
// TODO(plind): Verify this, presume I cannot use macro-assembler |
// here. |
lui(at, (imm64 >> 32) & kImm16Mask); |