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