Bug 1013996 - IonMonkey ARM: Simulator alignment checks and irregexp aligned access support. r=lth
authorDouglas Crosher <dtc-moz@scieneer.com>
Fri, 03 Oct 2014 06:22:50 +1000
changeset 231913 c54a5bded1ba876f347863cd76f1672e00fd457e
parent 231912 87916d61ca999868992ae86487969ff7786e8bfe
child 231914 5c0a0cf825b86df50f1f695a599e3f1efaa10c1a
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslth
bugs1013996
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1013996 - IonMonkey ARM: Simulator alignment checks and irregexp aligned access support. r=lth
js/src/irregexp/NativeRegExpMacroAssembler.cpp
js/src/jit/arm/Architecture-arm.cpp
js/src/jit/arm/Architecture-arm.h
js/src/jit/arm/Simulator-arm.cpp
--- a/js/src/irregexp/NativeRegExpMacroAssembler.cpp
+++ b/js/src/irregexp/NativeRegExpMacroAssembler.cpp
@@ -1315,17 +1315,19 @@ NativeRegExpMacroAssembler::CheckSpecial
       default:
         return false;
     }
 }
 
 bool
 NativeRegExpMacroAssembler::CanReadUnaligned()
 {
-#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
+#if defined(JS_CODEGEN_ARM)
+    return !jit::HasAlignmentFault();
+#elif defined(JS_CODEGEN_MIPS)
     return false;
 #else
     return true;
 #endif
 }
 
 const uint8_t
 NativeRegExpMacroAssembler::word_character_map[] =
--- a/js/src/jit/arm/Architecture-arm.cpp
+++ b/js/src/jit/arm/Architecture-arm.cpp
@@ -33,30 +33,16 @@
 # if !defined(HWCAP_IDIVA)
 #  define HWCAP_IDIVA     (1 << 17)
 # endif
 # if !defined(HWCAP_VFPD32)
 #  define HWCAP_VFPD32    (1 << 19) /* set if VFP has 32 regs (not 16) */
 # endif
 #endif
 
-// Not part of the HWCAP flag, but we need to know these and these bits are not used.
-
-// A bit to flag the use of the ARMv7 arch, otherwise ARMv6.
-#define HWCAP_ARMv7 (1 << 28)
-
-// A bit to flag the use of the hardfp ABI.
-#define HWCAP_USE_HARDFP_ABI (1 << 27)
-
-// A bit to flag when alignment faults are enabled and signal.
-#define HWCAP_ALIGNMENT_FAULT (1 << 26)
-
-// A bit to flag when the flags are uninitialized, so they can be atomically set.
-#define HWCAP_UNINITIALIZED (1 << 25)
-
 namespace js {
 namespace jit {
 
 
 // Parse the Linux kernel cpuinfo features. This is also used to parse the
 // override features which has some extensions: 'armv7', 'align' and 'hardfp'.
 static uint32_t
 ParseARMCpuFeatures(const char *features, bool override = false)
@@ -137,17 +123,17 @@ CanonicalizeARMHwCapFlags(uint32_t flags
     if ((flags & HWCAP_VFPv3) && !(flags & HWCAP_VFPv3D16))
         flags |= HWCAP_VFPD32;
 
     return flags;
 }
 
 // The override flags parsed from the ARMHWCAP environment variable or from the
 // --arm-hwcap js shell argument.
-volatile static uint32_t armHwCapFlags = HWCAP_UNINITIALIZED;
+volatile uint32_t armHwCapFlags = HWCAP_UNINITIALIZED;
 
 bool
 ParseARMHwCapFlags(const char *armHwCap)
 {
     uint32_t flags = 0;
 
     if (!armHwCap)
         return false;
@@ -312,24 +298,16 @@ bool Has32DP()
 }
 
 bool HasIDIV()
 {
     MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
     return armHwCapFlags & HWCAP_IDIVA;
 }
 
-// Returns true when cpu alignment faults are enabled and signaled, and thus we
-// should ensure loads and stores are aligned.
-bool HasAlignmentFault()
-{
-    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
-    return armHwCapFlags & HWCAP_ALIGNMENT_FAULT;
-}
-
 // This is defined in the header and inlined when not using the simulator.
 #if defined(JS_ARM_SIMULATOR)
 bool UseHardFpABI()
 {
     MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
     return armHwCapFlags & HWCAP_USE_HARDFP_ABI;
 }
 #endif
--- a/js/src/jit/arm/Architecture-arm.h
+++ b/js/src/jit/arm/Architecture-arm.h
@@ -516,17 +516,41 @@ typedef VFPRegister FloatRegister;
 uint32_t GetARMFlags();
 bool HasMOVWT();
 bool HasLDSTREXBHD();           // {LD,ST}REX{B,H,D}
 bool HasDMBDSBISB();            // DMB, DSB, and ISB
 bool HasVFPv3();
 bool HasVFP();
 bool Has32DP();
 bool HasIDIV();
-bool HasAlignmentFault();
+
+extern volatile uint32_t armHwCapFlags;
+
+// Not part of the HWCAP flag, but we need to know these and these bits are not
+// used. Define these here so that their use can be inlined by the simulator.
+
+// A bit to flag when the flags are uninitialized, so they can be atomically set.
+#define HWCAP_UNINITIALIZED (1 << 25)
+
+// A bit to flag when alignment faults are enabled and signal.
+#define HWCAP_ALIGNMENT_FAULT (1 << 26)
+
+// A bit to flag the use of the hardfp ABI.
+#define HWCAP_USE_HARDFP_ABI (1 << 27)
+
+// A bit to flag the use of the ARMv7 arch, otherwise ARMv6.
+#define HWCAP_ARMv7 (1 << 28)
+
+// Returns true when cpu alignment faults are enabled and signaled, and thus we
+// should ensure loads and stores are aligned.
+inline bool HasAlignmentFault()
+{
+    MOZ_ASSERT(armHwCapFlags != HWCAP_UNINITIALIZED);
+    return armHwCapFlags & HWCAP_ALIGNMENT_FAULT;
+}
 
 // Arm/D32 has double registers that can NOT be treated as float32 and this
 // requires some dances in lowering.
 inline bool
 hasUnaliasedDouble()
 {
     return Has32DP();
 }
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -1488,18 +1488,23 @@ Simulator::setCallResult(int64_t res)
     set_register(r1, static_cast<int32_t>(res >> 32));
 }
 
 int
 Simulator::readW(int32_t addr, SimInstruction *instr)
 {
     // The regexp engine emits unaligned loads, so we don't check for them here
     // like most of the other methods do.
-    intptr_t *ptr = reinterpret_cast<intptr_t*>(addr);
-    return *ptr;
+    if ((addr & 3) == 0 || !HasAlignmentFault()) {
+        intptr_t *ptr = reinterpret_cast<intptr_t*>(addr);
+        return *ptr;
+    } else {
+        printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
+        MOZ_CRASH();
+    }
 }
 
 void
 Simulator::writeW(int32_t addr, int value, SimInstruction *instr)
 {
     if ((addr & 3) == 0) {
         intptr_t *ptr = reinterpret_cast<intptr_t*>(addr);
         *ptr = value;
@@ -1509,18 +1514,23 @@ Simulator::writeW(int32_t addr, int valu
     }
 }
 
 uint16_t
 Simulator::readHU(int32_t addr, SimInstruction *instr)
 {
     // The regexp engine emits unaligned loads, so we don't check for them here
     // like most of the other methods do.
-    uint16_t *ptr = reinterpret_cast<uint16_t*>(addr);
-    return *ptr;
+    if ((addr & 1) == 0 || !HasAlignmentFault()) {
+       uint16_t *ptr = reinterpret_cast<uint16_t*>(addr);
+       return *ptr;
+    }
+    printf("Unaligned unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
+    MOZ_CRASH();
+    return 0;
 }
 
 int16_t
 Simulator::readH(int32_t addr, SimInstruction *instr)
 {
     if ((addr & 1) == 0) {
         int16_t *ptr = reinterpret_cast<int16_t*>(addr);
         return *ptr;