Commit fe916cd2 authored by Miran.Karic's avatar Miran.Karic Committed by Commit bot

MIPS: Use JIC/JIALC offset when possible

Until now JIC and JIALC compact branches were emited without using their
offset. Here we optimize their use by using offset after addition and/or
load immediate operations.

The CL also fixes a problem with deserialization that occurs when a code
object ends with an optimized LUI/AUI and JIC/JIALC instruction pair.
Deserializer processed these instruction pairs by moving to a location
immediately after it, but when this location is the end of the object it
would finish with the current object before doing relocation. This is
fixed by moving the deserializer one instruction before the location of
the instruction pair end.

BUG=

Review-Url: https://codereview.chromium.org/2542403002
Cr-Commit-Position: refs/heads/master@{#44841}
parent 9372dd95
......@@ -396,8 +396,7 @@ void Builtins::Generate_StringConstructor_ConstructStub(MacroAssembler* masm) {
static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
__ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
__ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, a2, Code::kHeaderSize - kHeapObjectTag);
}
static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
......@@ -421,8 +420,7 @@ static void GenerateTailCallToReturnedCode(MacroAssembler* masm,
__ SmiUntag(a0);
}
__ Addu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, v0, Code::kHeaderSize - kHeapObjectTag);
}
void Builtins::Generate_InOptimizationQueue(MacroAssembler* masm) {
......@@ -1191,8 +1189,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// context at this point).
__ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kConstructStubOffset));
__ Addu(at, t0, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, t0, Code::kHeaderSize - kHeapObjectTag);
} else if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
// Call the constructor with a0, a1, and a3 unmodified.
__ Jump(masm->isolate()->builtins()->ConstructWithSpread(),
......@@ -1572,8 +1569,7 @@ void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
__ PushStandardFrame(a1);
// Jump to point after the code-age stub.
__ Addu(a0, a0, Operand(kNoCodeAgeSequenceLength));
__ Jump(a0);
__ Jump(a0, kNoCodeAgeSequenceLength);
}
void Builtins::Generate_MarkCodeAsExecutedTwice(MacroAssembler* masm) {
......@@ -2492,8 +2488,7 @@ void Builtins::Generate_CallBoundFunctionImpl(MacroAssembler* masm,
__ li(at, Operand(ExternalReference(Builtins::kCall_ReceiverIsAny,
masm->isolate())));
__ lw(at, MemOperand(at));
__ Addu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, Code::kHeaderSize - kHeapObjectTag);
}
// static
......@@ -2717,8 +2712,7 @@ void Builtins::Generate_ConstructFunction(MacroAssembler* masm) {
// context at this point).
__ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kConstructStubOffset));
__ Addu(at, t0, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, t0, Code::kHeaderSize - kHeapObjectTag);
}
// static
......@@ -2808,8 +2802,7 @@ void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) {
__ lw(a1, FieldMemOperand(a1, JSBoundFunction::kBoundTargetFunctionOffset));
__ li(at, Operand(ExternalReference(Builtins::kConstruct, masm->isolate())));
__ lw(at, MemOperand(at));
__ Addu(at, at, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, Code::kHeaderSize - kHeapObjectTag);
}
// static
......@@ -3081,8 +3074,7 @@ void Builtins::Generate_WasmCompileLazy(MacroAssembler* masm) {
__ MultiPop(gp_regs);
}
// Now jump to the instructions of the returned code object.
__ Addu(at, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, v0, Code::kHeaderSize - kHeapObjectTag);
}
#undef __
......
......@@ -622,8 +622,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Call(Handle<Code>::cast(i.InputHeapObject(0)),
RelocInfo::CODE_TARGET);
} else {
__ addiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag);
__ Call(at);
__ Call(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag);
}
RecordCallPosition(instr);
frame_access_state()->ClearSPDelta();
......@@ -640,8 +639,7 @@ CodeGenerator::CodeGenResult CodeGenerator::AssembleArchInstruction(
__ Jump(Handle<Code>::cast(i.InputHeapObject(0)),
RelocInfo::CODE_TARGET);
} else {
__ addiu(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag);
__ Jump(at);
__ Jump(at, i.InputRegister(0), Code::kHeaderSize - kHeapObjectTag);
}
frame_access_state()->ClearSPDelta();
frame_access_state()->SetFrameAccessToDefault();
......
......@@ -375,9 +375,7 @@ bool LCodeGen::GenerateJumpTable() {
}
// Add the base address to the offset previously loaded in entry_offset.
__ Addu(entry_offset, entry_offset,
Operand(ExternalReference::ForDeoptEntry(base)));
__ Jump(entry_offset);
__ Jump(entry_offset, Operand(ExternalReference::ForDeoptEntry(base)));
}
__ RecordComment("]");
......@@ -3538,8 +3536,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
} else {
DCHECK(instr->target()->IsRegister());
Register target = ToRegister(instr->target());
__ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(target);
__ Jump(target, Code::kHeaderSize - kHeapObjectTag);
}
} else {
LPointerMap* pointers = instr->pointer_map();
......@@ -3554,8 +3551,7 @@ void LCodeGen::DoCallWithDescriptor(LCallWithDescriptor* instr) {
DCHECK(instr->target()->IsRegister());
Register target = ToRegister(instr->target());
generator.BeforeCall(__ CallSize(target));
__ Addu(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Call(target);
__ Call(target, Code::kHeaderSize - kHeapObjectTag);
}
generator.AfterCall();
}
......
......@@ -53,9 +53,17 @@ void DebugCodegen::PatchDebugBreakSlot(Isolate* isolate, Address pc,
// to a call to the debug break slot code.
// li t9, address (lui t9 / ori t9 instruction pair)
// call t9 (jalr t9 / nop instruction pair)
// Add a label for checking the size of the code used for returning.
Label check_codesize;
patcher.masm()->bind(&check_codesize);
patcher.masm()->li(v8::internal::t9,
Operand(reinterpret_cast<int32_t>(code->entry())));
patcher.masm()->Call(v8::internal::t9);
// Check that the size of the code generated is as expected.
DCHECK_EQ(Assembler::kDebugBreakSlotLength,
patcher.masm()->SizeOfCodeGeneratedSince(&check_codesize));
}
bool DebugCodegen::DebugBreakSlotIsPatched(Address pc) {
......
......@@ -121,8 +121,17 @@ Address RelocInfo::target_address_address() {
// place, ready to be patched with the target. After jump optimization,
// that is the address of the instruction that follows J/JAL/JR/JALR
// instruction.
return reinterpret_cast<Address>(
pc_ + Assembler::kInstructionsFor32BitConstant * Assembler::kInstrSize);
if (IsMipsArchVariant(kMips32r6)) {
// On R6 we don't move to the end of the instructions to be patched, but one
// instruction before, because if these instructions are at the end of the
// code object it can cause errors in the deserializer.
return reinterpret_cast<Address>(
pc_ +
(Assembler::kInstructionsFor32BitConstant - 1) * Assembler::kInstrSize);
} else {
return reinterpret_cast<Address>(
pc_ + Assembler::kInstructionsFor32BitConstant * Assembler::kInstrSize);
}
}
......
......@@ -2077,6 +2077,7 @@ void Assembler::lui(Register rd, int32_t j) {
void Assembler::aui(Register rt, Register rs, int32_t j) {
// This instruction uses same opcode as 'lui'. The difference in encoding is
// 'lui' has zero reg. for rs field.
DCHECK(IsMipsArchVariant(kMips32r6));
DCHECK(!(rs.is(zero_reg)));
DCHECK(is_uint16(j));
GenInstrImmediate(LUI, rs, rt, j);
......@@ -3746,11 +3747,17 @@ void Assembler::CheckTrampolinePool() {
Address Assembler::target_address_at(Address pc) {
Instr instr1 = instr_at(pc);
Instr instr2 = instr_at(pc + kInstrSize);
// Interpret 2 instructions generated by li: lui/ori
if (IsLui(instr1) && IsOri(instr2)) {
// Assemble the 32 bit value.
return reinterpret_cast<Address>((GetImmediate16(instr1) << kLuiShift) |
GetImmediate16(instr2));
// Interpret 2 instructions generated by li (lui/ori) or optimized pairs
// lui/jic, aui/jic or lui/jialc.
if (IsLui(instr1)) {
if (IsOri(instr2)) {
// Assemble the 32 bit value.
return reinterpret_cast<Address>((GetImmediate16(instr1) << kLuiShift) |
GetImmediate16(instr2));
} else if (IsJicOrJialc(instr2)) {
// Assemble the 32 bit value.
return reinterpret_cast<Address>(CreateTargetAddress(instr1, instr2));
}
}
// We should never get here, force a bad address if we do.
......
......@@ -439,6 +439,8 @@ class Operand BASE_EMBEDDED {
Register rm() const { return rm_; }
RelocInfo::Mode rmode() const { return rmode_; }
private:
Register rm_;
int32_t imm32_; // Valid if rm_ == no_reg.
......@@ -594,10 +596,19 @@ class Assembler : public AssemblerBase {
inline static void deserialization_set_special_target_at(
Isolate* isolate, Address instruction_payload, Code* code,
Address target) {
set_target_address_at(
isolate,
instruction_payload - kInstructionsFor32BitConstant * kInstrSize, code,
target);
if (IsMipsArchVariant(kMips32r6)) {
// On R6 the address location is shifted by one instruction
set_target_address_at(
isolate,
instruction_payload -
(kInstructionsFor32BitConstant - 1) * kInstrSize,
code, target);
} else {
set_target_address_at(
isolate,
instruction_payload - kInstructionsFor32BitConstant * kInstrSize,
code, target);
}
}
// This sets the internal reference at the pc.
......@@ -628,7 +639,7 @@ class Assembler : public AssemblerBase {
// Distance between the instruction referring to the address of the call
// target and the return address.
#ifdef _MIPS_ARCH_MIPS32R6
static constexpr int kCallTargetAddressOffset = 3 * kInstrSize;
static constexpr int kCallTargetAddressOffset = 2 * kInstrSize;
#else
static constexpr int kCallTargetAddressOffset = 4 * kInstrSize;
#endif
......
......@@ -1102,9 +1102,8 @@ void CEntryStub::Generate(MacroAssembler* masm) {
__ lw(a1, MemOperand(a1));
__ li(a2, Operand(pending_handler_offset_address));
__ lw(a2, MemOperand(a2));
__ Addu(a1, a1, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Addu(t9, a1, a2);
__ Jump(t9);
__ Jump(t9, Code::kHeaderSize - kHeapObjectTag);
}
......@@ -1237,8 +1236,7 @@ void JSEntryStub::Generate(MacroAssembler* masm) {
__ lw(t9, MemOperand(t0)); // Deref address.
// Call JSEntryTrampoline.
__ addiu(t9, t9, Code::kHeaderSize - kHeapObjectTag);
__ Call(t9);
__ Call(t9, Code::kHeaderSize - kHeapObjectTag);
// Unlink this frame from the handler chain.
__ PopStackHandler();
......@@ -1421,8 +1419,7 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
// context at this point).
__ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
__ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kConstructStubOffset));
__ Addu(at, t0, Operand(Code::kHeaderSize - kHeapObjectTag));
__ Jump(at);
__ Jump(at, t0, Code::kHeaderSize - kHeapObjectTag);
__ bind(&non_function);
__ mov(a3, a1);
......
This diff is collapsed.
......@@ -180,12 +180,15 @@ class MacroAssembler: public Assembler {
#define COND_ARGS Condition cond = al, Register rs = zero_reg, \
const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
void Jump(Register target, COND_ARGS);
void Jump(Register target, int16_t offset = 0, COND_ARGS);
void Jump(Register target, Register base, int16_t offset = 0, COND_ARGS);
void Jump(Register target, const Operand& offset, COND_ARGS);
void Jump(intptr_t target, RelocInfo::Mode rmode, COND_ARGS);
void Jump(Address target, RelocInfo::Mode rmode, COND_ARGS);
void Jump(Handle<Code> code, RelocInfo::Mode rmode, COND_ARGS);
static int CallSize(Register target, COND_ARGS);
void Call(Register target, COND_ARGS);
static int CallSize(Register target, int16_t offset = 0, COND_ARGS);
void Call(Register target, int16_t offset = 0, COND_ARGS);
void Call(Register target, Register base, int16_t offset = 0, COND_ARGS);
static int CallSize(Address target, RelocInfo::Mode rmode, COND_ARGS);
void Call(Address target, RelocInfo::Mode rmode, COND_ARGS);
int CallSize(Handle<Code> code,
......@@ -1664,9 +1667,8 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
bool IsDoubleZeroRegSet() { return has_double_zero_reg_set_; }
private:
void CallCFunctionHelper(Register function,
int num_reg_arguments,
int num_double_arguments);
void CallCFunctionHelper(Register function_base, int16_t function_offset,
int num_reg_arguments, int num_double_arguments);
inline Register GetRtAsRegisterHelper(const Operand& rt, Register scratch);
inline int32_t GetOffset(int32_t offset, Label* L, OffsetSize bits);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment