Bug 1286307 - Fix "Crash in dalvik-main space 1 (deleted)@0xc7ffffe" r=jandem a=jcristau
--- 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"
#include "jit/mips32/Simulator-mips32.h"
#include "jit/mips64/Simulator-mips64.h"
#include "jit/ProcessExecutableMemory.h"
#include "js/GCAPI.h"
#include "js/HashTable.h"
#include "js/Vector.h"
@@ -256,28 +259,44 @@ 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)
{
__clear_cache(code, (void *)((size_t)code + size));
}
#elif JS_CPU_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
@@ -656,16 +656,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 */