ART: Avoid shared cache lines for JIT code allocations

Dual view JIT exhibits some hygiene issues that causes crashes on
devices with 32-bit kernels.

This change makes JIT code allocations cache aligned. This is based on
guidance in the v7_coherent_user_range() that says "it is assumed that
the Icache does not read data from the write buffer".

Bug: 132205399

Test: >2000 boot tests on affected device with no zygote crashes.
Test: No crashes running ART JIT benchmarks on go/lem
Test: No failures with Treehugger

Change-Id: I901e2e5c07b9502876b33f572be63ec1dca19cbe
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 47a8b47..65e6d9d 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -1047,7 +1047,8 @@
     }
     // FlushInstructionCache() flushes both data and instruction caches lines. The cacheline range
     // flushed is for the executable mapping of the code just added.
-    FlushInstructionCache(code_ptr, code_ptr + code_size);
+    uint8_t* x_memory = reinterpret_cast<uint8_t*>(method_header);
+    FlushInstructionCache(x_memory, x_memory + total_size);
 
     // Ensure CPU instruction pipelines are flushed for all cores. This is necessary for
     // correctness as code may still be in instruction pipelines despite the i-cache flush. It is
@@ -2148,10 +2149,12 @@
   }
 }
 
-uint8_t* JitCodeCache::AllocateCode(size_t code_size) {
-  size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
+uint8_t* JitCodeCache::AllocateCode(size_t allocation_size) {
+  // Each allocation should be on its own set of cache lines. The allocation must be large enough
+  // for header, code, and any padding.
   uint8_t* result = reinterpret_cast<uint8_t*>(
-      mspace_memalign(exec_mspace_, alignment, code_size));
+      mspace_memalign(exec_mspace_, kJitCodeAlignment, allocation_size));
+  size_t alignment = GetInstructionSetAlignment(kRuntimeISA);
   size_t header_size = RoundUp(sizeof(OatQuickMethodHeader), alignment);
   // Ensure the header ends up at expected instruction alignment.
   DCHECK_ALIGNED_PARAM(reinterpret_cast<uintptr_t>(result + header_size), alignment);
diff --git a/runtime/jit/jit_code_cache.h b/runtime/jit/jit_code_cache.h
index fabb978..a3e10c7 100644
--- a/runtime/jit/jit_code_cache.h
+++ b/runtime/jit/jit_code_cache.h
@@ -74,8 +74,13 @@
 class MarkCodeClosure;
 class ScopedCodeCacheWrite;
 
-// Alignment in bits that will suit all architectures.
-static constexpr int kJitCodeAlignment = 16;
+// Alignment in bytes that will suit all architectures for JIT code cache allocations.  The
+// allocated block is used for method header followed by generated code. Allocations should be
+// aligned to avoid sharing cache lines between different allocations. The alignment should be
+// determined from the hardware, but this isn't readily exposed in userland plus some hardware
+// misreports.
+static constexpr int kJitCodeAlignment = 64;
+
 using CodeCacheBitmap = gc::accounting::MemoryRangeBitmap<kJitCodeAlignment>;
 
 class JitCodeCache {