Commit eabf0602 authored by plind44@gmail.com's avatar plind44@gmail.com

MIPS: Avoid flushing the icache unnecessarily when updating target addresses in code.

Port r21380 (ef20a0a)

Original commit message:
This CL updates RelocInfo update operations and set_target_address_at to enable
skipping of the icache flush if it going to be batched up later.
Code::CopyFrom and Code::Relocate are modified to avoid individual icache
flushes since the whole code area will be flushed after the reloc info is
updated.

These changes reduce a regression when enabling the OOL constant pool on Arm,
since this change can cause MovT/MovW instructions for relocatable targets
if the constant pool is full.

Scores for Mandreel latency on a Nexus 5:
- OOL CP disabled: 3533
- OOL CP enabled, without this CL: 1825
- OOL CP enabled, with change: 3015

BUG=
R=plind44@gmail.com

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

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@21390 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 70c3a714
......@@ -112,7 +112,7 @@ int FPURegister::ToAllocationIndex(FPURegister reg) {
// -----------------------------------------------------------------------------
// RelocInfo.
void RelocInfo::apply(intptr_t delta) {
void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
if (IsCodeTarget(rmode_)) {
uint32_t scope1 = (uint32_t) target_address() & ~kImm28Mask;
uint32_t scope2 = reinterpret_cast<uint32_t>(pc_) & ~kImm28Mask;
......@@ -171,10 +171,13 @@ int RelocInfo::target_address_size() {
}
void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
void RelocInfo::set_target_address(Address target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
Assembler::set_target_address_at(pc_, host_, target);
if (mode == UPDATE_WRITE_BARRIER && host() != NULL && IsCodeTarget(rmode_)) {
Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode);
if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
host() != NULL && IsCodeTarget(rmode_)) {
Object* target_code = Code::GetCodeFromTargetAddress(target);
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
host(), this, HeapObject::cast(target_code));
......@@ -200,12 +203,15 @@ Handle<Object> RelocInfo::target_object_handle(Assembler* origin) {
}
void RelocInfo::set_target_object(Object* target, WriteBarrierMode mode) {
void RelocInfo::set_target_object(Object* target,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
ASSERT(!target->IsConsString());
Assembler::set_target_address_at(pc_, host_,
reinterpret_cast<Address>(target));
if (mode == UPDATE_WRITE_BARRIER &&
reinterpret_cast<Address>(target),
icache_flush_mode);
if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
host() != NULL &&
target->IsHeapObject()) {
host()->GetHeap()->incremental_marking()->RecordWrite(
......@@ -227,9 +233,11 @@ Address RelocInfo::target_runtime_entry(Assembler* origin) {
void RelocInfo::set_target_runtime_entry(Address target,
WriteBarrierMode mode) {
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
ASSERT(IsRuntimeEntry(rmode_));
if (target_address() != target) set_target_address(target, mode);
if (target_address() != target)
set_target_address(target, write_barrier_mode, icache_flush_mode);
}
......@@ -246,11 +254,13 @@ Cell* RelocInfo::target_cell() {
}
void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
void RelocInfo::set_target_cell(Cell* cell,
WriteBarrierMode write_barrier_mode,
ICacheFlushMode icache_flush_mode) {
ASSERT(rmode_ == RelocInfo::CELL);
Address address = cell->address() + Cell::kValueOffset;
Memory::Address_at(pc_) = address;
if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
if (write_barrier_mode == UPDATE_WRITE_BARRIER && host() != NULL) {
// TODO(1550) We are passing NULL as a slot because cell can never be on
// evacuation candidate.
host()->GetHeap()->incremental_marking()->RecordWrite(
......@@ -275,7 +285,8 @@ Code* RelocInfo::code_age_stub() {
}
void RelocInfo::set_code_age_stub(Code* stub) {
void RelocInfo::set_code_age_stub(Code* stub,
ICacheFlushMode icache_flush_mode) {
ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
Assembler::set_target_address_at(pc_ + Assembler::kInstrSize,
host_,
......
......@@ -2166,7 +2166,9 @@ void Assembler::QuietNaN(HeapObject* object) {
// There is an optimization below, which emits a nop when the address
// fits in just 16 bits. This is unlikely to help, and should be benchmarked,
// and possibly removed.
void Assembler::set_target_address_at(Address pc, Address target) {
void Assembler::set_target_address_at(Address pc,
Address target,
ICacheFlushMode icache_flush_mode) {
Instr instr2 = instr_at(pc + kInstrSize);
uint32_t rt_code = GetRtField(instr2);
uint32_t* p = reinterpret_cast<uint32_t*>(pc);
......@@ -2260,7 +2262,9 @@ void Assembler::set_target_address_at(Address pc, Address target) {
patched_jump = true;
}
CPU::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
CPU::FlushICache(pc, (patched_jump ? 3 : 2) * sizeof(int32_t));
}
}
......
......@@ -478,7 +478,10 @@ class Assembler : public AssemblerBase {
// Read/Modify the code target address in the branch/call instruction at pc.
static Address target_address_at(Address pc);
static void set_target_address_at(Address pc, Address target);
static void set_target_address_at(Address pc,
Address target,
ICacheFlushMode icache_flush_mode =
FLUSH_ICACHE_IF_NEEDED);
// On MIPS there is no Constant Pool so we skip that parameter.
INLINE(static Address target_address_at(Address pc,
ConstantPoolArray* constant_pool)) {
......@@ -486,8 +489,10 @@ class Assembler : public AssemblerBase {
}
INLINE(static void set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
Address target)) {
set_target_address_at(pc, target);
Address target,
ICacheFlushMode icache_flush_mode =
FLUSH_ICACHE_IF_NEEDED)) {
set_target_address_at(pc, target, icache_flush_mode);
}
INLINE(static Address target_address_at(Address pc, Code* code)) {
ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
......@@ -495,9 +500,11 @@ class Assembler : public AssemblerBase {
}
INLINE(static void set_target_address_at(Address pc,
Code* code,
Address target)) {
Address target,
ICacheFlushMode icache_flush_mode =
FLUSH_ICACHE_IF_NEEDED)) {
ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
set_target_address_at(pc, constant_pool, target);
set_target_address_at(pc, constant_pool, target, icache_flush_mode);
}
// Return the code target address at a call site from the return address
......
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