Memory::Address_at(constant_pool_entry_address(pc, constant_pool)) = target;
// Intuitively, we would think it is necessary to always flush the
// instruction cache after patching a target address in the code as follows:
- // CpuFeatures::FlushICache(pc, sizeof(target));
+ // Assembler::FlushICacheWithoutIsolate(pc, sizeof(target));
// However, on ARM, no instruction is actually patched in the case
// of embedded constants of the form:
// ldr ip, [pp, #...]
DCHECK(IsMovW(Memory::int32_at(pc)));
DCHECK(IsMovT(Memory::int32_at(pc + kInstrSize)));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc, 2 * kInstrSize);
+ Assembler::FlushICacheWithoutIsolate(pc, 2 * kInstrSize);
}
} else {
// This is an mov / orr immediate load. Patch the immediate embedded in
IsOrrImmed(Memory::int32_at(pc + 2 * kInstrSize)) &&
IsOrrImmed(Memory::int32_at(pc + 3 * kInstrSize)));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc, 4 * kInstrSize);
+ Assembler::FlushICacheWithoutIsolate(pc, 4 * kInstrSize);
}
}
}
break;
}
DCHECK(GetMode(stub) == mode);
- CpuFeatures::FlushICache(stub->instruction_start(),
- 2 * Assembler::kInstrSize);
+ Assembler::FlushICache(stub->GetIsolate(), stub->instruction_start(),
+ 2 * Assembler::kInstrSize);
}
DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
#if !defined(USE_SIMULATOR)
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<MemCopyUint8Function>(buffer);
#endif
CodeDesc desc;
masm.GetCode(&desc);
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<MemCopyUint16Uint8Function>(buffer);
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<UnaryMathFunction>(buffer);
#endif
uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
if (age == kNoAgeCodeAge) {
isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
- CpuFeatures::FlushICache(sequence, young_length);
+ Assembler::FlushICache(isolate, sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(isolate, age, parity);
CodePatcher patcher(sequence, young_length / Assembler::kInstrSize);
#include "src/assembler.h"
#include "src/macro-assembler.h"
-#include "src/simulator.h" // for cache flushing.
namespace v8 {
namespace internal {
-
void CpuFeatures::FlushICache(void* start, size_t size) {
- if (size == 0) return;
-
- if (CpuFeatures::IsSupported(COHERENT_CACHE)) return;
-
-#if defined(USE_SIMULATOR)
- // Not generating ARM instructions for C-code. This means that we are
- // building an ARM emulator based target. We should notify the simulator
- // that the Icache was flushed.
- // None of this code ends up in the snapshot so there are no issues
- // around whether or not to generate the code when building snapshots.
- Simulator::FlushICache(Isolate::Current()->simulator_i_cache(), start, size);
-
-#elif V8_OS_QNX
+#if !defined(USE_SIMULATOR)
+#if V8_OS_QNX
msync(start, size, MS_SYNC | MS_INVALIDATE_ICACHE);
-
#else
register uint32_t beg asm("r0") = reinterpret_cast<uint32_t>(start);
register uint32_t end asm("r1") = beg + size;
: "memory");
#endif
#endif
+#endif // !USE_SIMULATOR
}
} // namespace internal
CodePatcher::~CodePatcher() {
// Indicate that code has changed.
if (flush_cache_ == FLUSH) {
- CpuFeatures::FlushICache(address_, size_);
+ Assembler::FlushICacheWithoutIsolate(address_, size_);
}
// Check that the code was patched as expected.
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:
- // CpuFeatures::FlushICache(pc, sizeof(target));
+ // Assembler::FlushICacheWithoutIsolate(pc, sizeof(target));
// However, on ARM, an instruction is actually patched in the case of
// embedded constants of the form:
// ldr ip, [pc, #...]
DCHECK(IsConstPoolEmpty());
// Flush the Instruction cache.
size_t length = buffer_size_ - kGap;
- CpuFeatures::FlushICache(buffer_, length);
+ Assembler::FlushICacheWithoutIsolate(buffer_, length);
}
// See definition of PatchAdrFar() for details.
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
#if !defined(USE_SIMULATOR)
void CpuFeatures::FlushICache(void* address, size_t length) {
- if (length == 0) return;
-
- if (CpuFeatures::IsSupported(COHERENT_CACHE)) return;
-
-#ifdef USE_SIMULATOR
- // TODO(all): consider doing some cache simulation to ensure every address
- // run has been synced.
- USE(address);
- USE(length);
-#else
+#ifdef V8_HOST_ARCH_ARM64
// The code below assumes user space cache operations are allowed. The goal
// of this routine is to make sure the code generated is visible to the I
// side of the CPU.
// move this code before the code is generated.
: "cc", "memory"
); // NOLINT
-#endif
+#endif // V8_HOST_ARCH_ARM64
}
} // namespace internal
class Simulator : public DecoderVisitor {
public:
+ static void FlushICache(v8::internal::HashMap* i_cache, void* start,
+ size_t size) {
+ USE(i_cache);
+ USE(start);
+ USE(size);
+ }
+
explicit Simulator(Decoder<DispatchingDecoderVisitor>* decoder,
Isolate* isolate = NULL,
FILE* stream = stderr);
#include "src/regexp/regexp-macro-assembler.h"
#include "src/regexp/regexp-stack.h"
#include "src/runtime/runtime.h"
+#include "src/simulator.h" // For flushing instruction cache.
#include "src/snapshot/serialize.h"
#include "src/token.h"
}
+void AssemblerBase::FlushICache(Isolate* isolate, void* start, size_t size) {
+ if (size == 0) return;
+ if (CpuFeatures::IsSupported(COHERENT_CACHE)) return;
+
+#if defined(USE_SIMULATOR)
+ Simulator::FlushICache(isolate->simulator_i_cache(), start, size);
+#else
+ CpuFeatures::FlushICache(start, size);
+#endif // USE_SIMULATOR
+}
+
+
+void AssemblerBase::FlushICacheWithoutIsolate(void* start, size_t size) {
+ // Ideally we would just call Isolate::Current() here. However, this flushes
+ // out issues because we usually only need the isolate when in the simulator.
+ Isolate* isolate;
+#if defined(USE_SIMULATOR)
+ isolate = Isolate::Current();
+#else
+ isolate = nullptr;
+#endif // USE_SIMULATOR
+ FlushICache(isolate, start, size);
+}
+
+
// -----------------------------------------------------------------------------
// Implementation of PredictableCodeSizeScope
ExternalReference ExternalReference::flush_icache_function(Isolate* isolate) {
return ExternalReference(
- Redirect(isolate, FUNCTION_ADDR(CpuFeatures::FlushICache)));
+ Redirect(isolate, FUNCTION_ADDR(Assembler::FlushICacheWithoutIsolate)));
}
static const int kMinimalBufferSize = 4*KB;
+ static void FlushICache(Isolate* isolate, void* start, size_t size);
+
+ // TODO(all): Help get rid of this one.
+ static void FlushICacheWithoutIsolate(void* start, size_t size);
+
protected:
// The buffer into which code and relocation info are generated. It could
// either be owned by the assembler or be provided externally.
}
CopyBytes(chunk->area_start(), desc.buffer,
static_cast<size_t>(desc.instr_size));
- CpuFeatures::FlushICache(chunk->area_start(), desc.instr_size);
+ Assembler::FlushICache(isolate, chunk->area_start(), desc.instr_size);
data->deopt_entry_code_entries_[type] = entry_count;
}
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
Memory::Object_at(pc_) = target;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(pc_, sizeof(Address));
}
if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
host() != NULL &&
Address address = cell->address() + Cell::kValueOffset;
Memory::Address_at(pc_) = address;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(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
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
visitor->VisitEmbeddedPointer(this);
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
visitor->VisitCodeTarget(this);
} else if (mode == RelocInfo::CELL) {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
StaticVisitor::VisitEmbeddedPointer(heap, this);
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(heap, this);
} else if (mode == RelocInfo::CELL) {
int32_t* p = reinterpret_cast<int32_t*>(pc);
*p = target - (pc + sizeof(int32_t));
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(p, sizeof(int32_t));
+ Assembler::FlushICacheWithoutIsolate(p, sizeof(int32_t));
}
}
break;
}
DCHECK(GetMode(stub) == mode);
- CpuFeatures::FlushICache(stub->instruction_start(), 7);
+ Assembler::FlushICache(stub->GetIsolate(), stub->instruction_start(), 7);
}
DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<UnaryMathFunction>(buffer);
}
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<UnaryMathFunction>(buffer);
}
CodeDesc desc;
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
// TODO(jkummerow): It would be nice to register this code creation event
// with the PROFILE / GDBJIT system.
uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
if (age == kNoAgeCodeAge) {
isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
- CpuFeatures::FlushICache(sequence, young_length);
+ Assembler::FlushICache(isolate, sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(isolate, age, parity);
CodePatcher patcher(sequence, young_length);
CodePatcher::~CodePatcher() {
// Indicate that code has changed.
- CpuFeatures::FlushICache(address_, size_);
+ Assembler::FlushICacheWithoutIsolate(address_, size_);
// Check that the code was patched as expected.
DCHECK(masm_.pc_ == address_ + size_);
for (RelocIterator it(this, RelocInfo::kApplyMask); !it.done(); it.next()) {
it.rinfo()->apply(delta);
}
- CpuFeatures::FlushICache(instruction_start(), instruction_size());
+ Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
}
it.rinfo()->apply(delta);
}
}
- CpuFeatures::FlushICache(instruction_start(), instruction_size());
+ Assembler::FlushICache(GetIsolate(), instruction_start(), instruction_size());
}
Add(ExternalReference::invoke_accessor_getter_callback(isolate).address(),
"InvokeAccessorGetterCallback");
Add(ExternalReference::flush_icache_function(isolate).address(),
- "CpuFeatures::FlushICache");
+ "Assembler::FlushICacheWithoutIsolate");
Add(ExternalReference::log_enter_external_function(isolate).address(),
"Logger::EnterExternal");
Add(ExternalReference::log_leave_external_function(isolate).address(),
PageIterator it(isolate_->heap()->code_space());
while (it.has_next()) {
Page* p = it.next();
- CpuFeatures::FlushICache(p->area_start(), p->area_end() - p->area_start());
+ Assembler::FlushICache(isolate_, p->area_start(),
+ p->area_end() - p->area_start());
}
}
void Deserializer::FlushICacheForNewCodeObjects() {
DCHECK(deserializing_user_code_);
for (Code* code : new_code_objects_) {
- CpuFeatures::FlushICache(code->instruction_start(),
- code->instruction_size());
+ Assembler::FlushICache(isolate_, code->instruction_start(),
+ code->instruction_size());
}
}
ICacheFlushMode icache_flush_mode) {
Memory::int32_at(pc) = static_cast<int32_t>(target - pc - 4);
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc, sizeof(int32_t));
+ Assembler::FlushICacheWithoutIsolate(pc, sizeof(int32_t));
}
}
DCHECK(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
Memory::Object_at(pc_) = target;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(pc_, sizeof(Address));
}
if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
host() != NULL &&
Address address = cell->address() + Cell::kValueOffset;
Memory::Address_at(pc_) = address;
if (icache_flush_mode != SKIP_ICACHE_FLUSH) {
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(pc_, sizeof(Address));
}
if (write_barrier_mode == UPDATE_WRITE_BARRIER &&
host() != NULL) {
DCHECK(IsDebugBreakSlot(rmode()) && IsPatchedDebugBreakSlotSequence());
Memory::Address_at(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset) =
target;
- CpuFeatures::FlushICache(pc_ + Assembler::kPatchDebugBreakSlotAddressOffset,
- sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(
+ pc_ + Assembler::kPatchDebugBreakSlotAddressOffset, sizeof(Address));
if (host() != NULL) {
Object* target_code = Code::GetCodeFromTargetAddress(target);
host()->GetHeap()->incremental_marking()->RecordWriteIntoCode(
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
visitor->VisitEmbeddedPointer(this);
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICacheWithoutIsolate(pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
visitor->VisitCodeTarget(this);
} else if (mode == RelocInfo::CELL) {
RelocInfo::Mode mode = rmode();
if (mode == RelocInfo::EMBEDDED_OBJECT) {
StaticVisitor::VisitEmbeddedPointer(heap, this);
- CpuFeatures::FlushICache(pc_, sizeof(Address));
+ Assembler::FlushICache(heap->isolate(), pc_, sizeof(Address));
} else if (RelocInfo::IsCodeTarget(mode)) {
StaticVisitor::VisitCodeTarget(heap, this);
} else if (mode == RelocInfo::CELL) {
break;
}
DCHECK(GetMode(stub) == mode);
- CpuFeatures::FlushICache(stub->instruction_start(), 7);
+ Assembler::FlushICache(stub->GetIsolate(), stub->instruction_start(), 7);
}
DEFINE_NULL_CALL_INTERFACE_DESCRIPTOR();
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<UnaryMathFunction>(buffer);
}
masm.GetCode(&desc);
DCHECK(!RelocInfo::RequiresRelocation(desc));
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICacheWithoutIsolate(buffer, actual_size);
base::OS::ProtectCode(buffer, actual_size);
return FUNCTION_CAST<UnaryMathFunction>(buffer);
}
uint32_t young_length = isolate->code_aging_helper()->young_sequence_length();
if (age == kNoAgeCodeAge) {
isolate->code_aging_helper()->CopyYoungSequenceTo(sequence);
- CpuFeatures::FlushICache(sequence, young_length);
+ Assembler::FlushICache(isolate, sequence, young_length);
} else {
Code* stub = GetCodeAgeStub(isolate, age, parity);
CodePatcher patcher(sequence, young_length);
CodePatcher::~CodePatcher() {
// Indicate that code has changed.
- CpuFeatures::FlushICache(address_, size_);
+ Assembler::FlushICacheWithoutIsolate(address_, size_);
// Check that the code was patched as expected.
DCHECK(masm_.pc_ == address_ + size_);
RESET(); \
START_AFTER_RESET();
-#define RUN() \
- CpuFeatures::FlushICache(buf, masm.SizeOfGeneratedCode()); \
- { \
- void (*test_function)(void); \
- memcpy(&test_function, &buf, sizeof(buf)); \
- test_function(); \
+#define RUN() \
+ Assembler::FlushICache(isolate, buf, masm.SizeOfGeneratedCode()); \
+ { \
+ void (*test_function)(void); \
+ memcpy(&test_function, &buf, sizeof(buf)); \
+ test_function(); \
}
#define END() \
CodeDesc desc;
masm.GetCode(&desc);
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICache(isolate, buffer, actual_size);
return (reinterpret_cast<ConvertDToIFunc>(
reinterpret_cast<intptr_t>(buffer)));
}
CodeDesc desc;
masm.GetCode(&desc);
- CpuFeatures::FlushICache(buffer, actual_size);
+ Assembler::FlushICache(isolate, buffer, actual_size);
return (reinterpret_cast<ConvertDToIFunc>(
reinterpret_cast<intptr_t>(buffer)));
}