summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/jit/jit_code_cache.cc20
1 files changed, 17 insertions, 3 deletions
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 8295f464af..eb9199ac53 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -90,7 +90,6 @@ static MemMap* SplitMemMap(MemMap* existing_map,
return new_map;
}
-
JitCodeCache* JitCodeCache::Create(size_t initial_capacity,
size_t max_capacity,
bool generate_debug_info,
@@ -802,12 +801,27 @@ uint8_t* JitCodeCache::CommitCodeInternal(Thread* self,
//
// For reference, this behavior is caused by this commit:
// https://android.googlesource.com/kernel/msm/+/3fbe6bc28a6b9939d0650f2f17eb5216c719950c
- FlushInstructionCache(reinterpret_cast<char*>(code_ptr),
- reinterpret_cast<char*>(code_ptr + code_size));
if (writable_ptr != code_ptr) {
+ // When there are two mappings of the JIT code cache, RX and
+ // RW, flush the RW version first as we've just dirtied the
+ // cache lines with new code. Flushing the RX version first
+ // can cause a permission fault as the those addresses are not
+ // writable, but can appear dirty in the cache. There is a lot
+ // of potential subtlety here depending on how the cache is
+ // indexed and tagged.
+ //
+ // Flushing the RX version after the RW version is just
+ // invalidating cachelines in the instruction cache. This is
+ // necessary as the instruction cache will often have a
+ // different set of cache lines present and because the JIT
+ // code cache can start a new function at any boundary within
+ // a cache-line.
FlushDataCache(reinterpret_cast<char*>(writable_ptr),
reinterpret_cast<char*>(writable_ptr + code_size));
}
+ FlushInstructionCache(reinterpret_cast<char*>(code_ptr),
+ reinterpret_cast<char*>(code_ptr + code_size));
+
DCHECK(!Runtime::Current()->IsAotCompiler());
if (has_should_deoptimize_flag) {
writable_method_header->SetHasShouldDeoptimizeFlag();