Bug 1286307 - Fix "Crash in dalvik-main space 1 (deleted)@0xc7ffffe" r=jandem a=gchang
authorHannes Verschore <hv1989>
Wed, 08 Feb 2017 04:35:00 +0100
changeset 378308 522951ff7046fd2bdf3916c973fbfde27be0af31
parent 378307 eae7e45deb55defb86c7c30fdfcf20c5d017b98d
child 378309 0a095d70f2b130a6550fab143163d40eecb79f0f
push id1419
push userjlund@mozilla.com
push dateMon, 10 Apr 2017 20:44:07 +0000
treeherdermozilla-release@5e6801b73ef6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem, gchang
bugs1286307
milestone53.0a2
Bug 1286307 - Fix "Crash in dalvik-main space 1 (deleted)@0xc7ffffe" r=jandem a=gchang
js/src/jit/ExecutableAllocator.h
js/src/jit/arm/Architecture-arm.cpp
js/src/jit/arm/Architecture-arm.h
--- a/js/src/jit/ExecutableAllocator.h
+++ b/js/src/jit/ExecutableAllocator.h
@@ -31,16 +31,19 @@
 #include "mozilla/Maybe.h"
 #include "mozilla/XorShift128PlusRNG.h"
 
 #include <limits>
 #include <stddef.h> // for ptrdiff_t
 
 #include "jsalloc.h"
 
+#ifdef JS_CODEGEN_ARM
+#include "jit/arm/Architecture-arm.h"
+#endif
 #include "jit/arm/Simulator-arm.h"
 #if defined(JS_CODEGEN_ARM64)
 #include "jit/arm64/vixl/Cpu-vixl.h"
 #endif
 #include "jit/mips32/Simulator-mips32.h"
 #include "jit/mips64/Simulator-mips64.h"
 #include "jit/ProcessExecutableMemory.h"
 #include "js/GCAPI.h"
@@ -259,28 +262,45 @@ class ExecutableAllocator
 #elif defined(JS_CODEGEN_ARM) && defined(XP_IOS)
     static void cacheFlush(void* code, size_t size)
     {
         sys_icache_invalidate(code, size);
     }
 #elif defined(JS_CODEGEN_ARM) && (defined(__linux__) || defined(ANDROID)) && defined(__GNUC__)
     static void cacheFlush(void* code, size_t size)
     {
+        void* end = (void*)(reinterpret_cast<char*>(code) + size);
         asm volatile (
             "push    {r7}\n"
             "mov     r0, %0\n"
             "mov     r1, %1\n"
             "mov     r7, #0xf0000\n"
             "add     r7, r7, #0x2\n"
             "mov     r2, #0x0\n"
             "svc     0x0\n"
             "pop     {r7}\n"
             :
-            : "r" (code), "r" (reinterpret_cast<char*>(code) + size)
+            : "r" (code), "r" (end)
             : "r0", "r1", "r2");
+
+        if (ForceDoubleCacheFlush()) {
+            void* start = (void*)((uintptr_t)code + 1);
+            asm volatile (
+                "push    {r7}\n"
+                "mov     r0, %0\n"
+                "mov     r1, %1\n"
+                "mov     r7, #0xf0000\n"
+                "add     r7, r7, #0x2\n"
+                "mov     r2, #0x0\n"
+                "svc     0x0\n"
+                "pop     {r7}\n"
+                :
+                : "r" (start), "r" (end)
+                : "r0", "r1", "r2");
+        }
     }
 #elif defined(JS_CODEGEN_ARM64) && (defined(__linux__) || defined(ANDROID)) && defined(__GNUC__)
     static void cacheFlush(void* code, size_t size)
     {
         vixl::CPU::EnsureIAndDCacheCoherency(code, size);
     }
 #elif defined(__sparc__)
     static void cacheFlush(void* code, size_t size)
--- a/js/src/jit/arm/Architecture-arm.cpp
+++ b/js/src/jit/arm/Architecture-arm.cpp
@@ -129,16 +129,23 @@ CanonicalizeARMHwCapFlags(uint32_t flags
 
     // Older kernels do not implement the HWCAP_VFPD32 flag.
     if ((flags & HWCAP_VFPv3) && !(flags & HWCAP_VFPv3D16))
         flags |= HWCAP_VFPD32;
 
     return flags;
 }
 
+volatile bool forceDoubleCacheFlush = false;
+
+bool
+ForceDoubleCacheFlush() {
+    return forceDoubleCacheFlush;
+}
+
 // The override flags parsed from the ARMHWCAP environment variable or from the
 // --arm-hwcap js shell argument.
 volatile uint32_t armHwCapFlags = HWCAP_UNINITIALIZED;
 
 bool
 ParseARMHwCapFlags(const char* armHwCap)
 {
     uint32_t flags = 0;
@@ -198,50 +205,58 @@ InitARMFlags()
 #ifdef JS_SIMULATOR_ARM
     // HWCAP_FIXUP_FAULT is on by default even if HWCAP_ALIGNMENT_FAULT is
     // not on by default, because some memory access instructions always fault.
     // Notably, this is true for floating point accesses.
     flags = HWCAP_ARMv7 | HWCAP_VFP | HWCAP_VFPv3 | HWCAP_VFPv4 | HWCAP_NEON | HWCAP_IDIVA
           | HWCAP_FIXUP_FAULT;
 #else
 
-#if defined(__linux__)
+#if defined(__linux__) || defined(ANDROID)
     // This includes Android and B2G.
     bool readAuxv = false;
     int fd = open("/proc/self/auxv", O_RDONLY);
     if (fd > 0) {
         struct { uint32_t a_type; uint32_t a_val; } aux;
         while (read(fd, &aux, sizeof(aux))) {
             if (aux.a_type == AT_HWCAP) {
                 flags = aux.a_val;
                 readAuxv = true;
                 break;
             }
         }
         close(fd);
     }
 
-    if (!readAuxv) {
+    FILE* fp = fopen("/proc/cpuinfo", "r");
+    if (fp) {
+        char buf[1024];
+        memset(buf, 0, sizeof(buf));
+        size_t len = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+        fclose(fp);
+        buf[len] = '\0';
+
         // Read the cpuinfo Features if the auxv is not available.
-        FILE* fp = fopen("/proc/cpuinfo", "r");
-        if (fp) {
-            char buf[1024];
-            memset(buf, 0, sizeof(buf));
-            size_t len = fread(buf, sizeof(char), sizeof(buf) - 1, fp);
-            fclose(fp);
-            buf[len] = '\0';
+        if (!readAuxv) {
             char* featureList = strstr(buf, "Features");
             if (featureList) {
                 if (char* featuresEnd = strstr(featureList, "\n"))
                     *featuresEnd = '\0';
                 flags = ParseARMCpuFeatures(featureList + 8);
             }
             if (strstr(buf, "ARMv7"))
                 flags |= HWCAP_ARMv7;
         }
+
+        // The exynos7420 cpu (EU galaxy S6 (Note)) has a bug where sometimes
+        // flushing doesn't invalidate the instruction cache. As a result we force
+        // it by calling the cacheFlush twice on different start addresses.
+        char* exynos7420 = strstr(buf, "Exynos7420");
+        if (exynos7420)
+            forceDoubleCacheFlush = true;
     }
 #endif
 
     // If compiled to use specialized features then these features can be
     // assumed to be present otherwise the compiler would fail to run.
 
 #ifdef JS_CODEGEN_ARM_HARDFP
     // Compiled to use the hardfp ABI.
--- a/js/src/jit/arm/Architecture-arm.h
+++ b/js/src/jit/arm/Architecture-arm.h
@@ -772,16 +772,18 @@ static inline bool UseHardFpABI()
 #if defined(JS_CODEGEN_ARM_HARDFP)
     return true;
 #else
     return false;
 #endif
 }
 #endif
 
+bool ForceDoubleCacheFlush();
+
 // In order to handle SoftFp ABI calls, we need to be able to express that we
 // have ABIArg which are represented by pair of general purpose registers.
 #define JS_CODEGEN_REGISTER_PAIR 1
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_arm_Architecture_arm_h */