Revert of MIPS: Fix 'Assembler support for internal references.' (patchset #1 id:1 of https://codereview.chromium.org/922043005/)

Reason for revert:
Breaks http://build.chromium.org/p/chromium.fyi/builders/Android%20MIPS%20Builder%20(dbg)

Original issue's description:
> MIPS: Fix 'Assembler support for internal references.'
>
> Added new INTERNAL_REFERENCE_ENCODED RelocInfo type to differentiate MIPS existing use of internal references in instructions from the new raw pointer reference needed for dd(Label*).
>
> BUG=
> TEST=cctest/test-assembler-mips/jump_tables1, cctest/test-assembler-mips/jump_tables2, cctest/test-assembler-mips/jump_tables3, cctest/test-run-machops/RunSwitch1
>
> Committed: https://crrev.com/244ac6de8316259bc5878480e05348a369c08e2f
> Cr-Commit-Position: refs/heads/master@{#26651}

TBR=danno@chromium.org,bmeurer@chromium.org,jkummerow@chromium.org,paul.lind@imgtec.com,gergely.kis@imgtec.com,akos.palfi@imgtec.com,dusan.milosavljevic@imgtec.com,balazs.kilvady@imgtec.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=

Review URL: https://codereview.chromium.org/934623003

Cr-Commit-Position: refs/heads/master@{#26675}
This commit is contained in:
machenbach 2015-02-16 10:49:38 -08:00 committed by Commit bot
parent 90734ca186
commit 4fdac75d9f
6 changed files with 90 additions and 116 deletions

View File

@ -393,11 +393,6 @@ class RelocInfo {
NONE64, // never recorded 64-bit value
CODE_AGE_SEQUENCE, // Not stored in RelocInfo array, used explictly by
// code aging.
// Encoded internal reference, used only on MIPS and MIPS64.
// Re-uses previous ARM-only encoding, to fit in RealRelocMode space.
INTERNAL_REFERENCE_ENCODED = CONST_POOL,
FIRST_REAL_RELOC_MODE = CODE_TARGET,
LAST_REAL_RELOC_MODE = VENEER_POOL,
FIRST_PSEUDO_RELOC_MODE = CODE_AGE_SEQUENCE,
@ -470,9 +465,6 @@ class RelocInfo {
static inline bool IsInternalReference(Mode mode) {
return mode == INTERNAL_REFERENCE;
}
static inline bool IsInternalReferenceEncoded(Mode mode) {
return mode == INTERNAL_REFERENCE_ENCODED;
}
static inline bool IsDebugBreakSlot(Mode mode) {
return mode == DEBUG_BREAK_SLOT;
}

View File

@ -126,10 +126,10 @@ void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
Assembler::JumpLabelToJumpRegister(pc_);
}
}
if (IsInternalReference(rmode_) || IsInternalReferenceEncoded(rmode_)) {
if (IsInternalReference(rmode_)) {
// Absolute code pointer inside code object moves with the code object.
byte* p = reinterpret_cast<byte*>(pc_);
int count = Assembler::RelocateInternalReference(rmode_, p, delta);
int count = Assembler::RelocateInternalReference(p, delta);
CpuFeatures::FlushICache(p, count * sizeof(uint32_t));
}
}

View File

@ -197,8 +197,7 @@ Register ToRegister(int num) {
// Implementation of RelocInfo.
const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
1 << RelocInfo::INTERNAL_REFERENCE |
1 << RelocInfo::INTERNAL_REFERENCE_ENCODED;
1 << RelocInfo::INTERNAL_REFERENCE;
bool RelocInfo::IsCodedSpecially() {
@ -663,18 +662,8 @@ bool Assembler::IsAndImmediate(Instr instr) {
}
int Assembler::target_at(int32_t pos, bool is_internal) {
int Assembler::target_at(int32_t pos) {
Instr instr = instr_at(pos);
if (is_internal) {
if (instr == 0) {
return kEndOfChain;
} else {
int32_t instr_address = reinterpret_cast<int32_t>(buffer_ + pos);
int32_t delta = instr_address - instr;
DCHECK(pos > delta);
return pos - delta;
}
}
if ((instr & ~kImm16Mask) == 0) {
// Emitted label constant, not part of a branch.
if (instr == 0) {
@ -723,22 +712,20 @@ int Assembler::target_at(int32_t pos, bool is_internal) {
DCHECK(pos > delta);
return pos - delta;
}
} else {
UNREACHABLE();
return 0;
} else { // IsLabel(instr)
int32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
if (imm28 == kEndOfJumpChain) {
// EndOfChain sentinel is returned directly, not relative to pc or pos.
return kEndOfChain;
} else {
return pos + imm28;
}
}
}
void Assembler::target_at_put(int32_t pos, int32_t target_pos,
bool is_internal) {
void Assembler::target_at_put(int32_t pos, int32_t target_pos) {
Instr instr = instr_at(pos);
if (is_internal) {
uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
instr_at_put(pos, imm);
return;
}
if ((instr & ~kImm16Mask) == 0) {
DCHECK(target_pos == kEndOfChain || target_pos >= 0);
// Emitted label constant, not part of a branch.
@ -781,7 +768,8 @@ void Assembler::target_at_put(int32_t pos, int32_t target_pos,
instr_at_put(pos, instr | (imm26 & kImm26Mask));
} else {
UNREACHABLE();
uint32_t imm = reinterpret_cast<uint32_t>(buffer_) + target_pos;
instr_at_put(pos, imm);
}
}
@ -802,8 +790,7 @@ void Assembler::print(Label* L) {
} else {
PrintF("%d\n", instr);
}
next(&l, internal_reference_positions_.find(l.pos()) !=
internal_reference_positions_.end());
next(&l);
}
} else {
PrintF("label in inconsistent state (pos = %d)\n", L->pos_);
@ -814,7 +801,6 @@ 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;
@ -823,27 +809,22 @@ void Assembler::bind_to(Label* L, int pos) {
while (L->is_linked()) {
int32_t fixup_pos = L->pos();
int32_t dist = pos - 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.
next(L); // Call next before overwriting link with target at fixup_pos.
Instr instr = instr_at(fixup_pos);
if (is_internal) {
target_at_put(fixup_pos, pos, is_internal);
} else if (!is_internal && IsBranch(instr)) {
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, false);
target_at_put(fixup_pos, trampoline_pos);
fixup_pos = trampoline_pos;
dist = pos - fixup_pos;
}
target_at_put(fixup_pos, pos, false);
target_at_put(fixup_pos, pos);
} else {
target_at_put(fixup_pos, pos, false);
target_at_put(fixup_pos, pos);
}
}
L->bind_to(pos);
@ -861,9 +842,9 @@ void Assembler::bind(Label* L) {
}
void Assembler::next(Label* L, bool is_internal) {
void Assembler::next(Label* L) {
DCHECK(L->is_linked());
int link = target_at(L->pos(), is_internal);
int link = target_at(L->pos());
if (link == kEndOfChain) {
L->Unuse();
} else {
@ -2351,58 +2332,51 @@ void Assembler::bc1t(int16_t offset, uint16_t cc) {
// Debugging.
int Assembler::RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
intptr_t pc_delta) {
int Assembler::RelocateInternalReference(byte* pc, intptr_t pc_delta) {
Instr instr = instr_at(pc);
if (IsLui(instr)) {
Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
DCHECK(IsOri(instr_ori));
int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
if (imm == kEndOfJumpChain) {
return 0; // Number of instructions patched.
}
imm += pc_delta;
DCHECK((imm & 3) == 0);
if (RelocInfo::IsInternalReference(rmode)) {
instr_lui &= ~kImm16Mask;
instr_ori &= ~kImm16Mask;
instr_at_put(pc + 0 * Assembler::kInstrSize,
instr_lui | ((imm >> kLuiShift) & kImm16Mask));
instr_at_put(pc + 1 * Assembler::kInstrSize,
instr_ori | (imm & kImm16Mask));
return 2; // Number of instructions patched.
} else if (IsJ(instr)) {
uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
return 0; // Number of instructions patched.
}
imm28 += pc_delta;
imm28 &= kImm28Mask;
DCHECK((imm28 & 3) == 0);
instr &= ~kImm26Mask;
uint32_t imm26 = imm28 >> 2;
DCHECK(is_uint26(imm26));
instr_at_put(pc, instr | (imm26 & kImm26Mask));
return 1; // Number of instructions patched.
} else { // IsLabel(instr)
int32_t* p = reinterpret_cast<int32_t*>(pc);
if (*p == 0) {
uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
return 0; // Number of instructions patched.
}
*p += pc_delta;
return 1; // Number of instructions patched.
} else {
DCHECK(RelocInfo::IsInternalReferenceEncoded(rmode));
if (IsLui(instr)) {
Instr instr_lui = instr_at(pc + 0 * Assembler::kInstrSize);
Instr instr_ori = instr_at(pc + 1 * Assembler::kInstrSize);
DCHECK(IsOri(instr_ori));
int32_t imm = (instr_lui & static_cast<int32_t>(kImm16Mask)) << kLuiShift;
imm |= (instr_ori & static_cast<int32_t>(kImm16Mask));
if (imm == kEndOfJumpChain) {
return 0; // Number of instructions patched.
}
imm += pc_delta;
DCHECK((imm & 3) == 0);
instr_lui &= ~kImm16Mask;
instr_ori &= ~kImm16Mask;
instr_at_put(pc + 0 * Assembler::kInstrSize,
instr_lui | ((imm >> kLuiShift) & kImm16Mask));
instr_at_put(pc + 1 * Assembler::kInstrSize,
instr_ori | (imm & kImm16Mask));
return 2; // Number of instructions patched.
} else if (IsJ(instr)) {
uint32_t imm28 = (instr & static_cast<int32_t>(kImm26Mask)) << 2;
if (static_cast<int32_t>(imm28) == kEndOfJumpChain) {
return 0; // Number of instructions patched.
}
imm28 += pc_delta;
imm28 &= kImm28Mask;
DCHECK((imm28 & 3) == 0);
instr &= ~kImm26Mask;
uint32_t imm26 = imm28 >> 2;
DCHECK(is_uint26(imm26));
instr_at_put(pc, instr | (imm26 & kImm26Mask));
return 1; // Number of instructions patched.
} else {
UNREACHABLE();
return 0;
}
}
}
@ -2443,12 +2417,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_ENCODED ||
rmode == RelocInfo::INTERNAL_REFERENCE) {
if (rmode == RelocInfo::INTERNAL_REFERENCE) {
byte* p = reinterpret_cast<byte*>(it.rinfo()->pc());
RelocateInternalReference(rmode, p, pc_delta);
RelocateInternalReference(p, pc_delta);
}
}
DCHECK(!overflow());
}
@ -2475,9 +2449,23 @@ void Assembler::dd(Label* label) {
*reinterpret_cast<uint32_t*>(pc_) = data;
pc_ += sizeof(uint32_t);
} else {
uint32_t target_pos = jump_address(label);
emit(target_pos);
internal_reference_positions_.insert(label->pos());
int target_pos;
if (label->is_linked()) {
// Point to previous instruction that uses the link.
target_pos = label->pos();
} else {
// First entry of the link chain points to itself.
target_pos = pc_offset();
}
label->link_to(pc_offset());
// Encode internal reference to unbound label. We set the least significant
// bit to distinguish unbound internal references in GrowBuffer() below.
int diff = target_pos - pc_offset();
DCHECK_EQ(0, diff & 3);
int imm26 = diff >> 2;
DCHECK(is_int26(imm26));
// Emit special LABEL instruction.
emit(LABEL | (imm26 & kImm26Mask));
}
}
@ -2562,7 +2550,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_ENCODED);
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
}

View File

@ -38,8 +38,6 @@
#include <stdio.h>
#include <tr1/unordered_set>
#include "src/assembler.h"
#include "src/mips/constants-mips.h"
#include "src/serialize.h"
@ -1023,8 +1021,7 @@ class Assembler : public AssemblerBase {
void RecordDeoptReason(const int reason, const int raw_position);
static int RelocateInternalReference(RelocInfo::Mode rmode, byte* pc,
intptr_t pc_delta);
static int RelocateInternalReference(byte* pc, intptr_t pc_delta);
// Writes a single byte or word of data in the code stream. Used for
// inline tables, e.g., jump-tables.
@ -1129,10 +1126,10 @@ class Assembler : public AssemblerBase {
int32_t buffer_space() const { return reloc_info_writer.pos() - pc_; }
// Decode branch instruction at pos and return branch target pos.
int target_at(int32_t pos, bool is_internal);
int target_at(int32_t pos);
// Patch branch instruction at pos to branch to given branch target pos.
void target_at_put(int32_t pos, int32_t target_pos, bool is_internal);
void target_at_put(int32_t pos, int32_t target_pos);
// Say if we need to relocate with this mode.
bool MustUseReg(RelocInfo::Mode rmode);
@ -1301,7 +1298,7 @@ class Assembler : public AssemblerBase {
// Labels.
void print(Label* L);
void bind_to(Label* L, int pos);
void next(Label* L, bool is_internal);
void next(Label* L);
// One trampoline consists of:
// - space for trampoline slots,
@ -1366,10 +1363,6 @@ class Assembler : public AssemblerBase {
static const int kMaxBranchOffset = (1 << (18 - 1)) - 1;
static const int kInvalidSlotPos = -1;
// Internal reference positions, required for unbounded internal reference
// labels.
std::tr1::unordered_set<int> internal_reference_positions_;
Trampoline trampoline_;
bool internal_trampoline_exception_;

View File

@ -339,6 +339,7 @@ enum Opcode {
DADDI = ((3 << 3) + 0) << kOpcodeShift, // This is also BNEC.
SPECIAL2 = ((3 << 3) + 4) << kOpcodeShift,
LABEL = ((3 << 3) + 5) << kOpcodeShift,
SPECIAL3 = ((3 << 3) + 7) << kOpcodeShift,
LB = ((4 << 3) + 0) << kOpcodeShift,

View File

@ -3087,7 +3087,7 @@ void MacroAssembler::J(Label* L, BranchDelaySlot bdslot) {
{ BlockGrowBufferScope block_buf_growth(this);
// Buffer growth (and relocation) must be blocked for internal references
// until associated instructions are emitted and available to be patched.
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
j(imm28);
}
// Emit a nop in the branch delay slot if required.
@ -3104,7 +3104,7 @@ void MacroAssembler::Jr(Label* L, BranchDelaySlot bdslot) {
{ BlockGrowBufferScope block_buf_growth(this);
// Buffer growth (and relocation) must be blocked for internal references
// until associated instructions are emitted and available to be patched.
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
}
@ -3124,7 +3124,7 @@ void MacroAssembler::Jalr(Label* L, BranchDelaySlot bdslot) {
{ BlockGrowBufferScope block_buf_growth(this);
// Buffer growth (and relocation) must be blocked for internal references
// until associated instructions are emitted and available to be patched.
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE_ENCODED);
RecordRelocInfo(RelocInfo::INTERNAL_REFERENCE);
lui(at, (imm32 & kHiMask) >> kLuiShift);
ori(at, at, (imm32 & kImm16Mask));
}