| Index: src/mips/assembler-mips.cc
|
| diff --git a/src/mips/assembler-mips.cc b/src/mips/assembler-mips.cc
|
| index e7cfd57006ae0c10297d10484efa7d87db24231a..adc8425aeb57761fca955e0412a9e131aadaf06f 100644
|
| --- a/src/mips/assembler-mips.cc
|
| +++ b/src/mips/assembler-mips.cc
|
| @@ -197,8 +197,7 @@
|
| // 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 @@
|
| }
|
|
|
|
|
| -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 @@
|
| DCHECK(pos > delta);
|
| return pos - delta;
|
| }
|
| - } else {
|
| - UNREACHABLE();
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -
|
| -void Assembler::target_at_put(int32_t pos, int32_t target_pos,
|
| - bool is_internal) {
|
| + } 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) {
|
| 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 @@
|
|
|
| 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 @@
|
| } 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::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 @@
|
| 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::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 @@
|
|
|
|
|
| // 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 (RelocInfo::IsInternalReference(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 { // 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 @@
|
| // 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 @@
|
| *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 @@
|
| // 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));
|
| }
|
|
|