Commit a6be7b0f authored by palfia@homejinni.com's avatar palfia@homejinni.com

MIPS: Fix and simplify code aging.

This commit fixes a lot of test failures that we saw earlier in the buildbots (http://build.chromium.org/p/client.v8/builders/V8%20Linux%20-%20mips%20-%20sim/builds/3034/steps/Check/logs/stdio).

In some very rare cases the code age stub address can be 0xXXXX0000 and in this case the li maco instruction emits only 1 instruction (instead of the expected 2). Thus the code age sequence will be 6 instructions long instead of 7, which breaks the code aging feature. This change makes sure that li always emits 2 instructions and it also simplifies the code aging sequence.

Also fixes a small mistake in the simulator at the jalr instruction.

BUG=
R=gergely@homejinni.com

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18030 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 89829712
...@@ -260,16 +260,14 @@ Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) { ...@@ -260,16 +260,14 @@ Handle<Object> RelocInfo::code_age_stub_handle(Assembler* origin) {
Code* RelocInfo::code_age_stub() { Code* RelocInfo::code_age_stub() {
ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
return Code::GetCodeFromTargetAddress( return Code::GetCodeFromTargetAddress(
Memory::Address_at(pc_ + Assembler::kInstrSize * Assembler::target_address_at(pc_ + Assembler::kInstrSize));
(kNoCodeAgeSequenceLength - 1)));
} }
void RelocInfo::set_code_age_stub(Code* stub) { void RelocInfo::set_code_age_stub(Code* stub) {
ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE); ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
Memory::Address_at(pc_ + Assembler::kInstrSize * Assembler::set_target_address_at(pc_ + Assembler::kInstrSize,
(kNoCodeAgeSequenceLength - 1)) = stub->instruction_start());
stub->instruction_start();
} }
......
...@@ -813,12 +813,9 @@ static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) { ...@@ -813,12 +813,9 @@ static void GenerateMakeCodeYoungAgainCommon(MacroAssembler* masm) {
// internal frame to make the code faster, since we shouldn't have to do stack // internal frame to make the code faster, since we shouldn't have to do stack
// crawls in MakeCodeYoung. This seems a bit fragile. // crawls in MakeCodeYoung. This seems a bit fragile.
__ mov(a0, ra); // Set a0 to point to the head of the PlatformCodeAge sequence.
// Adjust a0 to point to the head of the PlatformCodeAge sequence
__ Subu(a0, a0, __ Subu(a0, a0,
Operand((kNoCodeAgeSequenceLength - 1) * Assembler::kInstrSize)); Operand((kNoCodeAgeSequenceLength - 1) * Assembler::kInstrSize));
// Restore the original return address of the function
__ mov(ra, at);
// The following registers must be saved and restored when calling through to // The following registers must be saved and restored when calling through to
// the runtime: // the runtime:
...@@ -855,12 +852,9 @@ void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) { ...@@ -855,12 +852,9 @@ void Builtins::Generate_MarkCodeAsExecutedOnce(MacroAssembler* masm) {
// save/restore the registers without worrying about which of them contain // save/restore the registers without worrying about which of them contain
// pointers. // pointers.
__ mov(a0, ra); // Set a0 to point to the head of the PlatformCodeAge sequence.
// Adjust a0 to point to the head of the PlatformCodeAge sequence
__ Subu(a0, a0, __ Subu(a0, a0,
Operand((kNoCodeAgeSequenceLength - 1) * Assembler::kInstrSize)); Operand((kNoCodeAgeSequenceLength - 1) * Assembler::kInstrSize));
// Restore the original return address of the function
__ mov(ra, at);
// The following registers must be saved and restored when calling through to // The following registers must be saved and restored when calling through to
// the runtime: // the runtime:
......
...@@ -642,8 +642,8 @@ void Code::GetCodeAgeAndParity(byte* sequence, Age* age, ...@@ -642,8 +642,8 @@ void Code::GetCodeAgeAndParity(byte* sequence, Age* age,
*age = kNoAgeCodeAge; *age = kNoAgeCodeAge;
*parity = NO_MARKING_PARITY; *parity = NO_MARKING_PARITY;
} else { } else {
Address target_address = Memory::Address_at( Address target_address = Assembler::target_address_at(
sequence + Assembler::kInstrSize * (kNoCodeAgeSequenceLength - 1)); sequence + Assembler::kInstrSize);
Code* stub = GetCodeFromTargetAddress(target_address); Code* stub = GetCodeFromTargetAddress(target_address);
GetCodeAgeAndParity(stub, age, parity); GetCodeAgeAndParity(stub, age, parity);
} }
...@@ -662,17 +662,18 @@ void Code::PatchPlatformCodeAge(Isolate* isolate, ...@@ -662,17 +662,18 @@ void Code::PatchPlatformCodeAge(Isolate* isolate,
} else { } else {
Code* stub = GetCodeAgeStub(isolate, age, parity); Code* stub = GetCodeAgeStub(isolate, age, parity);
CodePatcher patcher(sequence, young_length / Assembler::kInstrSize); CodePatcher patcher(sequence, young_length / Assembler::kInstrSize);
// Mark this code sequence for FindPlatformCodeAgeSequence() // Mark this code sequence for FindPlatformCodeAgeSequence().
patcher.masm()->nop(Assembler::CODE_AGE_MARKER_NOP); patcher.masm()->nop(Assembler::CODE_AGE_MARKER_NOP);
// Save the function's original return address // Load the stub address to t9 and call it,
// (it will be clobbered by Call(t9)) // GetCodeAgeAndParity() extracts the stub address from this instruction.
patcher.masm()->mov(at, ra); patcher.masm()->li(
// Load the stub address to t9 and call it t9,
patcher.masm()->li(t9, Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
Operand(reinterpret_cast<uint32_t>(stub->instruction_start()))); CONSTANT_SIZE);
patcher.masm()->Call(t9); patcher.masm()->nop(); // Prevent jalr to jal optimization.
// Record the stub address in the empty space for GetCodeAgeAndParity() patcher.masm()->jalr(t9, a0);
patcher.masm()->emit_code_stub_address(stub); patcher.masm()->nop(); // Branch delay slot nop.
patcher.masm()->nop(); // Pad the empty space.
} }
} }
......
...@@ -4532,15 +4532,15 @@ void MacroAssembler::Prologue(PrologueFrameMode frame_mode) { ...@@ -4532,15 +4532,15 @@ void MacroAssembler::Prologue(PrologueFrameMode frame_mode) {
// Pre-age the code. // Pre-age the code.
Code* stub = Code::GetPreAgedCodeAgeStub(isolate()); Code* stub = Code::GetPreAgedCodeAgeStub(isolate());
nop(Assembler::CODE_AGE_MARKER_NOP); nop(Assembler::CODE_AGE_MARKER_NOP);
// Save the function's original return address // Load the stub address to t9 and call it,
// (it will be clobbered by Call(t9)). // GetCodeAgeAndParity() extracts the stub address from this instruction.
mov(at, ra);
// Load the stub address to t9 and call it.
li(t9, li(t9,
Operand(reinterpret_cast<uint32_t>(stub->instruction_start()))); Operand(reinterpret_cast<uint32_t>(stub->instruction_start())),
Call(t9); CONSTANT_SIZE);
// Record the stub address in the empty space for GetCodeAgeAndParity(). nop(); // Prevent jalr to jal optimization.
emit_code_stub_address(stub); jalr(t9, a0);
nop(); // Branch delay slot nop.
nop(); // Pad the empty space.
} else { } else {
Push(ra, fp, cp, a1); Push(ra, fp, cp, a1);
nop(Assembler::CODE_AGE_SEQUENCE_NOP); nop(Assembler::CODE_AGE_SEQUENCE_NOP);
......
...@@ -1722,6 +1722,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr, ...@@ -1722,6 +1722,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
int64_t& i64hilo, int64_t& i64hilo,
uint64_t& u64hilo, uint64_t& u64hilo,
int32_t& next_pc, int32_t& next_pc,
int32_t& return_addr_reg,
bool& do_interrupt) { bool& do_interrupt) {
// Every local variable declared here needs to be const. // Every local variable declared here needs to be const.
// This is to make sure that changed values are sent back to // This is to make sure that changed values are sent back to
...@@ -1782,6 +1783,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr, ...@@ -1782,6 +1783,7 @@ void Simulator::ConfigureTypeRegister(Instruction* instr,
case JR: case JR:
case JALR: case JALR:
next_pc = get_register(instr->RsValue()); next_pc = get_register(instr->RsValue());
return_addr_reg = instr->RdValue();
break; break;
case SLL: case SLL:
alu_out = rt << sa; alu_out = rt << sa;
...@@ -1986,6 +1988,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) { ...@@ -1986,6 +1988,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
int32_t current_pc = get_pc(); int32_t current_pc = get_pc();
// Next pc // Next pc
int32_t next_pc = 0; int32_t next_pc = 0;
int32_t return_addr_reg = 31;
// Set up the variables if needed before executing the instruction. // Set up the variables if needed before executing the instruction.
ConfigureTypeRegister(instr, ConfigureTypeRegister(instr,
...@@ -1993,6 +1996,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) { ...@@ -1993,6 +1996,7 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
i64hilo, i64hilo,
u64hilo, u64hilo,
next_pc, next_pc,
return_addr_reg,
do_interrupt); do_interrupt);
// ---------- Raise exceptions triggered. // ---------- Raise exceptions triggered.
...@@ -2258,7 +2262,8 @@ void Simulator::DecodeTypeRegister(Instruction* instr) { ...@@ -2258,7 +2262,8 @@ void Simulator::DecodeTypeRegister(Instruction* instr) {
Instruction* branch_delay_instr = reinterpret_cast<Instruction*>( Instruction* branch_delay_instr = reinterpret_cast<Instruction*>(
current_pc+Instruction::kInstrSize); current_pc+Instruction::kInstrSize);
BranchDelayInstructionDecode(branch_delay_instr); BranchDelayInstructionDecode(branch_delay_instr);
set_register(31, current_pc + 2 * Instruction::kInstrSize); set_register(return_addr_reg,
current_pc + 2 * Instruction::kInstrSize);
set_pc(next_pc); set_pc(next_pc);
pc_modified_ = true; pc_modified_ = true;
break; break;
......
...@@ -289,6 +289,7 @@ class Simulator { ...@@ -289,6 +289,7 @@ class Simulator {
int64_t& i64hilo, int64_t& i64hilo,
uint64_t& u64hilo, uint64_t& u64hilo,
int32_t& next_pc, int32_t& next_pc,
int32_t& return_addr_reg,
bool& do_interrupt); bool& do_interrupt);
void DecodeTypeImmediate(Instruction* instr); void DecodeTypeImmediate(Instruction* instr);
......
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