Revision: 21380
Author:   [email protected]
Date:     Tue May 20 09:21:45 2014 UTC
Log: Avoid flushing the icache unnecessarily when updating target addresses in code.

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

[email protected], [email protected]

Review URL: https://codereview.chromium.org/284153004
http://code.google.com/p/v8/source/detail?r=21380

Modified:
 /branches/bleeding_edge/src/arm/assembler-arm-inl.h
 /branches/bleeding_edge/src/arm/assembler-arm.h
 /branches/bleeding_edge/src/arm64/assembler-arm64-inl.h
 /branches/bleeding_edge/src/arm64/assembler-arm64.h
 /branches/bleeding_edge/src/assembler.h
 /branches/bleeding_edge/src/ia32/assembler-ia32-inl.h
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/x64/assembler-x64-inl.h
 /branches/bleeding_edge/src/x64/assembler-x64.h

=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm-inl.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/arm/assembler-arm-inl.h Tue May 20 09:21:45 2014 UTC
@@ -91,7 +91,7 @@
 }


-void RelocInfo::apply(intptr_t delta) {
+void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
   if (RelocInfo::IsInternalReference(rmode_)) {
     // absolute code pointer inside code object moves with the code object.
     int32_t* p = reinterpret_cast<int32_t*>(pc_);
@@ -142,10 +142,13 @@
 }


-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));
@@ -166,12 +169,15 @@
 }


-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(
@@ -193,9 +199,11 @@


 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);
 }


@@ -212,11 +220,13 @@
 }


-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(
@@ -242,7 +252,8 @@
 }


-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);
   Memory::Address_at(pc_ +
                      (kNoCodeAgeSequenceLength - Assembler::kInstrSize)) =
@@ -504,26 +515,29 @@
   ASSERT(immediate < 0x10000);
   return ((immediate & 0xf000) << 4) | (immediate & 0xfff);
 }
+
+
+static Instr PatchMovwImmediate(Instr instruction, uint32_t immediate) {
+  instruction &= ~EncodeMovwImmediate(0xffff);
+  return instruction | EncodeMovwImmediate(immediate);
+}


 void Assembler::set_target_address_at(Address pc,
                                       ConstantPoolArray* constant_pool,
-                                      Address target) {
+                                      Address target,
+                                      ICacheFlushMode icache_flush_mode) {
   if (IsMovW(Memory::int32_at(pc))) {
     ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
     uint32_t* instr_ptr = reinterpret_cast<uint32_t*>(pc);
     uint32_t immediate = reinterpret_cast<uint32_t>(target);
-    uint32_t intermediate = instr_ptr[0];
-    intermediate &= ~EncodeMovwImmediate(0xFFFF);
-    intermediate |= EncodeMovwImmediate(immediate & 0xFFFF);
-    instr_ptr[0] = intermediate;
-    intermediate = instr_ptr[1];
-    intermediate &= ~EncodeMovwImmediate(0xFFFF);
-    intermediate |= EncodeMovwImmediate(immediate >> 16);
-    instr_ptr[1] = intermediate;
+    instr_ptr[0] = PatchMovwImmediate(instr_ptr[0], immediate & 0xFFFF);
+    instr_ptr[1] = PatchMovwImmediate(instr_ptr[1], immediate >> 16);
     ASSERT(IsMovW(Memory::int32_at(pc)));
     ASSERT(IsMovT(Memory::int32_at(pc + kInstrSize)));
-    CPU::FlushICache(pc, 2 * kInstrSize);
+    if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+      CPU::FlushICache(pc, 2 * kInstrSize);
+    }
   } else if (FLAG_enable_ool_constant_pool) {
     ASSERT(IsLdrPpImmediateOffset(Memory::int32_at(pc)));
     Memory::Address_at(
=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/arm/assembler-arm.h Tue May 20 09:21:45 2014 UTC
@@ -763,16 +763,20 @@
ConstantPoolArray* constant_pool));
   INLINE(static void set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
-                                           Address target));
+                                           Address target,
+ ICacheFlushMode icache_flush_mode =
+                                               FLUSH_ICACHE_IF_NEEDED));
   INLINE(static Address target_address_at(Address pc, Code* code)) {
     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
     return target_address_at(pc, constant_pool);
   }
   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
=======================================
--- /branches/bleeding_edge/src/arm64/assembler-arm64-inl.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/arm64/assembler-arm64-inl.h Tue May 20 09:21:45 2014 UTC
@@ -17,15 +17,18 @@
 bool CpuFeatures::SupportsCrankshaft() { return true; }


-void RelocInfo::apply(intptr_t delta) {
+void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
   UNIMPLEMENTED();
 }


-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));
@@ -625,7 +628,8 @@

 void Assembler::set_target_address_at(Address pc,
                                       ConstantPoolArray* constant_pool,
-                                      Address target) {
+                                      Address target,
+                                      ICacheFlushMode icache_flush_mode) {
   Memory::Address_at(target_pointer_address_at(pc)) = target;
   // Intuitively, we would think it is necessary to always flush the
// instruction cache after patching a target address in the code as follows:
@@ -640,9 +644,10 @@

 void Assembler::set_target_address_at(Address pc,
                                       Code* code,
-                                      Address target) {
+                                      Address target,
+                                      ICacheFlushMode icache_flush_mode) {
   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);
 }


@@ -684,12 +689,15 @@
 }


-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(
@@ -711,9 +719,12 @@


 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);
+  }
 }


@@ -730,7 +741,9 @@
 }


-void RelocInfo::set_target_cell(Cell* cell, WriteBarrierMode mode) {
+void RelocInfo::set_target_cell(Cell* cell,
+                                WriteBarrierMode write_barrier_mode,
+                                ICacheFlushMode icache_flush_mode) {
   UNIMPLEMENTED();
 }

@@ -753,7 +766,8 @@
 }


-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(!Code::IsYoungSequence(stub->GetIsolate(), pc_));
// Overwrite the stub entry point in the code age sequence. This is loaded as
=======================================
--- /branches/bleeding_edge/src/arm64/assembler-arm64.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/arm64/assembler-arm64.h Tue May 20 09:21:45 2014 UTC
@@ -788,11 +788,15 @@
ConstantPoolArray* constant_pool);
   inline static void set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
-                                           Address target);
+                                           Address target,
+ ICacheFlushMode icache_flush_mode =
+                                               FLUSH_ICACHE_IF_NEEDED);
   static inline Address target_address_at(Address pc, Code* code);
   static inline void set_target_address_at(Address pc,
                                            Code* code,
-                                           Address target);
+                                           Address target,
+ ICacheFlushMode icache_flush_mode =
+                                               FLUSH_ICACHE_IF_NEEDED);

// Return the code target address at a call site from the return address of
   // that call in the instruction stream.
=======================================
--- /branches/bleeding_edge/src/assembler.h     Fri May 16 15:18:24 2014 UTC
+++ /branches/bleeding_edge/src/assembler.h     Tue May 20 09:21:45 2014 UTC
@@ -276,6 +276,12 @@

 enum SaveFPRegsMode { kDontSaveFPRegs, kSaveFPRegs };

+// Specifies whether to perform icache flush operations on RelocInfo updates.
+// If FLUSH_ICACHE_IF_NEEDED, the icache will always be flushed if an
+// instruction was modified. If SKIP_ICACHE_FLUSH the flush will always be
+// skipped (only use this if you will flush the icache manually before it is
+// executed).
+enum ICacheFlushMode { FLUSH_ICACHE_IF_NEEDED, SKIP_ICACHE_FLUSH };

// -----------------------------------------------------------------------------
 // Relocation information
@@ -360,7 +366,6 @@
     LAST_STANDARD_NONCOMPACT_ENUM = INTERNAL_REFERENCE
   };

-
   RelocInfo() {}

   RelocInfo(byte* pc, Mode rmode, intptr_t data, Code* host)
@@ -452,7 +457,9 @@
   void set_host(Code* host) { host_ = host; }

   // Apply a relocation by delta bytes
-  INLINE(void apply(intptr_t delta));
+  INLINE(void apply(intptr_t delta,
+                    ICacheFlushMode icache_flush_mode =
+                        FLUSH_ICACHE_IF_NEEDED));

// Is the pointer this relocation info refers to coded like a plain pointer // or is it strange in some way (e.g. relative or patched into a series of
@@ -468,22 +475,35 @@
   // can only be called if IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)
   INLINE(Address target_address());
   INLINE(void set_target_address(Address target,
- WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
+                                 WriteBarrierMode write_barrier_mode =
+                                     UPDATE_WRITE_BARRIER,
+                                 ICacheFlushMode icache_flush_mode =
+                                     FLUSH_ICACHE_IF_NEEDED));
   INLINE(Object* target_object());
   INLINE(Handle<Object> target_object_handle(Assembler* origin));
   INLINE(void set_target_object(Object* target,
- WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
+                                WriteBarrierMode write_barrier_mode =
+                                    UPDATE_WRITE_BARRIER,
+                                ICacheFlushMode icache_flush_mode =
+                                    FLUSH_ICACHE_IF_NEEDED));
   INLINE(Address target_runtime_entry(Assembler* origin));
   INLINE(void set_target_runtime_entry(Address target,
-                                       WriteBarrierMode mode =
-                                           UPDATE_WRITE_BARRIER));
+ WriteBarrierMode write_barrier_mode =
+                                           UPDATE_WRITE_BARRIER,
+                                       ICacheFlushMode icache_flush_mode =
+                                           FLUSH_ICACHE_IF_NEEDED));
   INLINE(Cell* target_cell());
   INLINE(Handle<Cell> target_cell_handle());
   INLINE(void set_target_cell(Cell* cell,
- WriteBarrierMode mode = UPDATE_WRITE_BARRIER));
+                              WriteBarrierMode write_barrier_mode =
+                                  UPDATE_WRITE_BARRIER,
+                              ICacheFlushMode icache_flush_mode =
+                                  FLUSH_ICACHE_IF_NEEDED));
   INLINE(Handle<Object> code_age_stub_handle(Assembler* origin));
   INLINE(Code* code_age_stub());
-  INLINE(void set_code_age_stub(Code* stub));
+  INLINE(void set_code_age_stub(Code* stub,
+                                ICacheFlushMode icache_flush_mode =
+                                    FLUSH_ICACHE_IF_NEEDED));

// Returns the address of the constant pool entry where the target address
   // is held.  This should only be called if IsInConstantPool returns true.
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32-inl.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/ia32/assembler-ia32-inl.h Tue May 20 09:21:45 2014 UTC
@@ -53,34 +53,35 @@


 // The modes possibly affected by apply must be in kApplyMask.
-void RelocInfo::apply(intptr_t delta) {
+void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
+  bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH;
   if (IsRuntimeEntry(rmode_) || IsCodeTarget(rmode_)) {
     int32_t* p = reinterpret_cast<int32_t*>(pc_);
     *p -= delta;  // Relocate entry.
-    CPU::FlushICache(p, sizeof(uint32_t));
+    if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t));
   } else if (rmode_ == CODE_AGE_SEQUENCE) {
     if (*pc_ == kCallOpcode) {
       int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
       *p -= delta;  // Relocate entry.
-      CPU::FlushICache(p, sizeof(uint32_t));
+    if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t));
     }
   } else if (rmode_ == JS_RETURN && IsPatchedReturnSequence()) {
     // Special handling of js_return when a break point is set (call
     // instruction has been inserted).
     int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
     *p -= delta;  // Relocate entry.
-    CPU::FlushICache(p, sizeof(uint32_t));
+    if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t));
} else if (rmode_ == DEBUG_BREAK_SLOT && IsPatchedDebugBreakSlotSequence()) { // Special handling of a debug break slot when a break point is set (call
     // instruction has been inserted).
     int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
     *p -= delta;  // Relocate entry.
-    CPU::FlushICache(p, sizeof(uint32_t));
+    if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t));
   } else if (IsInternalReference(rmode_)) {
     // absolute code pointer inside code object moves with the code object.
     int32_t* p = reinterpret_cast<int32_t*>(pc_);
     *p += delta;  // Relocate entry.
-    CPU::FlushICache(p, sizeof(uint32_t));
+    if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t));
   }
 }

@@ -110,10 +111,13 @@
 }


-void RelocInfo::set_target_address(Address target, WriteBarrierMode mode) {
-  Assembler::set_target_address_at(pc_, host_, target);
+void RelocInfo::set_target_address(Address target,
+                                   WriteBarrierMode write_barrier_mode,
+                                   ICacheFlushMode icache_flush_mode) {
+  Assembler::set_target_address_at(pc_, host_, target, icache_flush_mode);
   ASSERT(IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_));
- 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);
     host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
         host(), this, HeapObject::cast(target_code));
@@ -133,12 +137,16 @@
 }


-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());
   Memory::Object_at(pc_) = target;
-  CPU::FlushICache(pc_, sizeof(Address));
-  if (mode == UPDATE_WRITE_BARRIER &&
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    CPU::FlushICache(pc_, sizeof(Address));
+  }
+  if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
       host() != NULL &&
       target->IsHeapObject()) {
     host()->GetHeap()->incremental_marking()->RecordWrite(
@@ -160,9 +168,12 @@


 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);
+  }
 }


@@ -179,12 +190,16 @@
 }


-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;
-  CPU::FlushICache(pc_, sizeof(Address));
-  if (mode == UPDATE_WRITE_BARRIER && host() != NULL) {
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    CPU::FlushICache(pc_, sizeof(Address));
+  }
+  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(
@@ -208,10 +223,12 @@
 }


-void RelocInfo::set_code_age_stub(Code* stub) {
+void RelocInfo::set_code_age_stub(Code* stub,
+                                  ICacheFlushMode icache_flush_mode) {
   ASSERT(*pc_ == kCallOpcode);
   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
- Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start()); + Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start(),
+                                   icache_flush_mode);
 }


@@ -451,10 +468,13 @@

 void Assembler::set_target_address_at(Address pc,
                                       ConstantPoolArray* constant_pool,
-                                      Address target) {
+                                      Address target,
+                                      ICacheFlushMode icache_flush_mode) {
   int32_t* p = reinterpret_cast<int32_t*>(pc);
   *p = target - (pc + sizeof(int32_t));
-  CPU::FlushICache(p, sizeof(int32_t));
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    CPU::FlushICache(p, sizeof(int32_t));
+  }
 }


=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Tue May 20 09:21:45 2014 UTC
@@ -493,14 +493,18 @@
ConstantPoolArray* constant_pool);
   inline static void set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
-                                           Address target);
+                                           Address target,
+ ICacheFlushMode icache_flush_mode =
+                                               FLUSH_ICACHE_IF_NEEDED);
   static inline Address target_address_at(Address pc, Code* code) {
     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
     return target_address_at(pc, constant_pool);
   }
   static inline 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);
   }
=======================================
--- /branches/bleeding_edge/src/objects.cc      Wed May 14 09:12:21 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc      Tue May 20 09:21:45 2014 UTC
@@ -10969,7 +10969,7 @@

 void Code::Relocate(intptr_t delta) {
for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
-    it.rinfo()->apply(delta);
+    it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
   }
   CPU::FlushICache(instruction_start(), instruction_size());
 }
@@ -11001,26 +11001,28 @@
     RelocInfo::Mode mode = it.rinfo()->rmode();
     if (mode == RelocInfo::EMBEDDED_OBJECT) {
       Handle<Object> p = it.rinfo()->target_object_handle(origin);
-      it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER);
+ it.rinfo()->set_target_object(*p, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     } else if (mode == RelocInfo::CELL) {
       Handle<Cell> cell  = it.rinfo()->target_cell_handle();
-      it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER);
+ it.rinfo()->set_target_cell(*cell, SKIP_WRITE_BARRIER, SKIP_ICACHE_FLUSH);
     } else if (RelocInfo::IsCodeTarget(mode)) {
       // rewrite code handles in inline cache targets to direct
       // pointers to the first instruction in the code object
       Handle<Object> p = it.rinfo()->target_object_handle(origin);
       Code* code = Code::cast(*p);
       it.rinfo()->set_target_address(code->instruction_start(),
-                                     SKIP_WRITE_BARRIER);
+                                     SKIP_WRITE_BARRIER,
+                                     SKIP_ICACHE_FLUSH);
     } else if (RelocInfo::IsRuntimeEntry(mode)) {
       Address p = it.rinfo()->target_runtime_entry(origin);
-      it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER);
+      it.rinfo()->set_target_runtime_entry(p, SKIP_WRITE_BARRIER,
+                                           SKIP_ICACHE_FLUSH);
     } else if (mode == RelocInfo::CODE_AGE_SEQUENCE) {
       Handle<Object> p = it.rinfo()->code_age_stub_handle(origin);
       Code* code = Code::cast(*p);
-      it.rinfo()->set_code_age_stub(code);
+      it.rinfo()->set_code_age_stub(code, SKIP_ICACHE_FLUSH);
     } else {
-      it.rinfo()->apply(delta);
+      it.rinfo()->apply(delta, SKIP_ICACHE_FLUSH);
     }
   }
   CPU::FlushICache(instruction_start(), instruction_size());
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64-inl.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64-inl.h Tue May 20 09:21:45 2014 UTC
@@ -193,9 +193,12 @@

 void Assembler::set_target_address_at(Address pc,
                                       ConstantPoolArray* constant_pool,
-                                      Address target) {
+                                      Address target,
+                                      ICacheFlushMode icache_flush_mode) {
   Memory::int32_at(pc) = static_cast<int32_t>(target - pc - 4);
-  CPU::FlushICache(pc, sizeof(int32_t));
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    CPU::FlushICache(pc, sizeof(int32_t));
+  }
 }


@@ -218,19 +221,20 @@
 // Implementation of RelocInfo

 // The modes possibly affected by apply must be in kApplyMask.
-void RelocInfo::apply(intptr_t delta) {
+void RelocInfo::apply(intptr_t delta, ICacheFlushMode icache_flush_mode) {
+  bool flush_icache = icache_flush_mode != SKIP_ICACHE_FLUSH;
   if (IsInternalReference(rmode_)) {
     // absolute code pointer inside code object moves with the code object.
     Memory::Address_at(pc_) += static_cast<int32_t>(delta);
-    CPU::FlushICache(pc_, sizeof(Address));
+    if (flush_icache) CPU::FlushICache(pc_, sizeof(Address));
   } else if (IsCodeTarget(rmode_) || IsRuntimeEntry(rmode_)) {
     Memory::int32_at(pc_) -= static_cast<int32_t>(delta);
-    CPU::FlushICache(pc_, sizeof(int32_t));
+    if (flush_icache) CPU::FlushICache(pc_, sizeof(int32_t));
   } else if (rmode_ == CODE_AGE_SEQUENCE) {
     if (*pc_ == kCallOpcode) {
       int32_t* p = reinterpret_cast<int32_t*>(pc_ + 1);
       *p -= static_cast<int32_t>(delta);  // Relocate entry.
-      CPU::FlushICache(p, sizeof(uint32_t));
+      if (flush_icache) CPU::FlushICache(p, sizeof(uint32_t));
     }
   }
 }
@@ -265,10 +269,13 @@
 }


-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));
@@ -298,12 +305,16 @@
 }


-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());
   Memory::Object_at(pc_) = target;
-  CPU::FlushICache(pc_, sizeof(Address));
-  if (mode == UPDATE_WRITE_BARRIER &&
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    CPU::FlushICache(pc_, sizeof(Address));
+  }
+  if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
       host() != NULL &&
       target->IsHeapObject()) {
     host()->GetHeap()->incremental_marking()->RecordWrite(
@@ -319,9 +330,12 @@


 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);
+  }
 }


@@ -338,12 +352,16 @@
 }


-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;
-  CPU::FlushICache(pc_, sizeof(Address));
-  if (mode == UPDATE_WRITE_BARRIER &&
+  if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
+    CPU::FlushICache(pc_, sizeof(Address));
+  }
+  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.
@@ -397,10 +415,12 @@
 }


-void RelocInfo::set_code_age_stub(Code* stub) {
+void RelocInfo::set_code_age_stub(Code* stub,
+                                  ICacheFlushMode icache_flush_mode) {
   ASSERT(*pc_ == kCallOpcode);
   ASSERT(rmode_ == RelocInfo::CODE_AGE_SEQUENCE);
- Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start()); + Assembler::set_target_address_at(pc_ + 1, host_, stub->instruction_start(),
+                                   icache_flush_mode);
 }


=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h Fri May 16 15:18:24 2014 UTC +++ /branches/bleeding_edge/src/x64/assembler-x64.h Tue May 20 09:21:45 2014 UTC
@@ -518,16 +518,20 @@
ConstantPoolArray* constant_pool);
   static inline void set_target_address_at(Address pc,
ConstantPoolArray* constant_pool,
-                                           Address target);
+                                           Address target,
+ ICacheFlushMode icache_flush_mode =
+                                               FLUSH_ICACHE_IF_NEEDED) ;
   static inline Address target_address_at(Address pc, Code* code) {
     ConstantPoolArray* constant_pool = code ? code->constant_pool() : NULL;
     return target_address_at(pc, constant_pool);
   }
   static inline 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

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to