Bug 1402939 - Completely ban unaligned exclusive accesses on ARM simulator. r=bbouvier
authorLars T Hansen <lhansen@mozilla.com>
Fri, 29 Sep 2017 17:36:55 +0200
changeset 676115 f255dd895929afdebe976673ba51675c67758f7c
parent 676114 12d671fcc1f1c25898ebb0723e1eb0b20b5b4838
child 676116 c6c355f7633a4d291e38c382a48695c52f9a9ccd
push id83398
push userbmo:rail@mozilla.com
push dateFri, 06 Oct 2017 17:12:44 +0000
reviewersbbouvier
bugs1402939
milestone58.0a1
Bug 1402939 - Completely ban unaligned exclusive accesses on ARM simulator. r=bbouvier
js/src/jit/arm/Simulator-arm.cpp
--- a/js/src/jit/arm/Simulator-arm.cpp
+++ b/js/src/jit/arm/Simulator-arm.cpp
@@ -1730,50 +1730,44 @@ static
 T compareExchangeRelaxed(SharedMem<T*> addr, T oldval, T newval)
 {
     return AtomicOperations::compareExchangeSeqCst(addr, oldval, newval);
 }
 
 int
 Simulator::readExW(int32_t addr, SimInstruction* instr)
 {
+    if (addr & 3)
+        MOZ_CRASH("Unaligned exclusive read");
+
     if (handleWasmFault(addr, 4))
         return -1;
 
-    // The regexp engine emits unaligned loads, so we don't check for them here
-    // like most of the other methods do.
-    if ((addr & 3) == 0 || !HasAlignmentFault()) {
-        SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
-        int32_t value = loadRelaxed(ptr);
-        exclusiveMonitorSet(value);
-        return value;
-    }
-
-    printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
-    MOZ_CRASH();
+    SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
+    int32_t value = loadRelaxed(ptr);
+    exclusiveMonitorSet(value);
+    return value;
 }
 
 int32_t
 Simulator::writeExW(int32_t addr, int value, SimInstruction* instr)
 {
+    if (addr & 3)
+        MOZ_CRASH("Unaligned exclusive write");
+
     if (handleWasmFault(addr, 4))
         return -1;
 
-    if ((addr & 3) == 0) {
-        SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
-        bool held;
-        int32_t expected = int32_t(exclusiveMonitorGetAndClear(&held));
-        if (!held)
-            return 1;
-        int32_t old = compareExchangeRelaxed(ptr, expected, int32_t(value));
-        return old != expected;
-    }
-
-    printf("Unaligned write at 0x%08x, pc=%p\n", addr, instr);
-    MOZ_CRASH();
+    SharedMem<int32_t*> ptr = SharedMem<int32_t*>::shared(reinterpret_cast<int32_t*>(addr));
+    bool held;
+    int32_t expected = int32_t(exclusiveMonitorGetAndClear(&held));
+    if (!held)
+        return 1;
+    int32_t old = compareExchangeRelaxed(ptr, expected, int32_t(value));
+    return old != expected;
 }
 
 uint16_t
 Simulator::readHU(int32_t addr, SimInstruction* instr)
 {
     if (handleWasmFault(addr, 2))
         return UINT16_MAX;
 
@@ -1865,51 +1859,44 @@ Simulator::writeH(int32_t addr, int16_t 
 
     printf("Unaligned halfword write at 0x%08x, pc=%p\n", addr, instr);
     MOZ_CRASH();
 }
 
 uint16_t
 Simulator::readExHU(int32_t addr, SimInstruction* instr)
 {
+    if (addr & 1)
+        MOZ_CRASH("Unaligned exclusive read");
+
     if (handleWasmFault(addr, 2))
         return UINT16_MAX;
 
-    // The regexp engine emits unaligned loads, so we don't check for them here
-    // like most of the other methods do.
-    if ((addr & 1) == 0 || !HasAlignmentFault()) {
-        SharedMem<uint16_t*> ptr = SharedMem<uint16_t*>::shared(reinterpret_cast<uint16_t*>(addr));
-        uint16_t value = loadRelaxed(ptr);
-        exclusiveMonitorSet(value);
-        return value;
-    }
-
-    printf("Unaligned atomic unsigned halfword read at 0x%08x, pc=%p\n", addr, instr);
-    MOZ_CRASH();
-    return 0;
+    SharedMem<uint16_t*> ptr = SharedMem<uint16_t*>::shared(reinterpret_cast<uint16_t*>(addr));
+    uint16_t value = loadRelaxed(ptr);
+    exclusiveMonitorSet(value);
+    return value;
 }
 
 int32_t
 Simulator::writeExH(int32_t addr, uint16_t value, SimInstruction* instr)
 {
+    if (addr & 1)
+        MOZ_CRASH("Unaligned exclusive write");
+
     if (handleWasmFault(addr, 2))
         return -1;
 
-    if ((addr & 1) == 0) {
-        SharedMem<uint16_t*> ptr = SharedMem<uint16_t*>::shared(reinterpret_cast<uint16_t*>(addr));
-        bool held;
-        uint16_t expected = uint16_t(exclusiveMonitorGetAndClear(&held));
-        if (!held)
-            return 1;
-        uint16_t old = compareExchangeRelaxed(ptr, expected, value);
-        return old != expected;
-    }
-
-    printf("Unaligned atomic unsigned halfword write at 0x%08x, pc=%p\n", addr, instr);
-    MOZ_CRASH();
+    SharedMem<uint16_t*> ptr = SharedMem<uint16_t*>::shared(reinterpret_cast<uint16_t*>(addr));
+    bool held;
+    uint16_t expected = uint16_t(exclusiveMonitorGetAndClear(&held));
+    if (!held)
+        return 1;
+    uint16_t old = compareExchangeRelaxed(ptr, expected, value);
+    return old != expected;
 }
 
 uint8_t
 Simulator::readBU(int32_t addr)
 {
     if (handleWasmFault(addr, 1))
         return UINT8_MAX;
 
@@ -2004,59 +1991,55 @@ Simulator::writeDW(int32_t addr, int32_t
 
     printf("Unaligned write at 0x%08x\n", addr);
     MOZ_CRASH();
 }
 
 int32_t
 Simulator::readExDW(int32_t addr, int32_t* hibits)
 {
+    if (addr & 3)
+        MOZ_CRASH("Unaligned exclusive read");
+
     if (handleWasmFault(addr, 8))
         return -1;
 
-    if ((addr & 3) == 0) {
-        SharedMem<uint64_t*> ptr = SharedMem<uint64_t*>::shared(reinterpret_cast<uint64_t*>(addr));
-        // The spec says that the low part of value shall be read from addr and
-        // the high part shall be read from addr+4.  On a little-endian system
-        // where we read a 64-bit quadword the low part of the value will be in
-        // the low part of the quadword, and the high part of the value in the
-        // high part of the quadword.
-        uint64_t value = loadRelaxed(ptr);
-        exclusiveMonitorSet(value);
-        *hibits = int32_t(value >> 32);
-        return int32_t(value);
-    }
-
-    printf("Unaligned read at 0x%08x\n", addr);
-    MOZ_CRASH();
+    SharedMem<uint64_t*> ptr = SharedMem<uint64_t*>::shared(reinterpret_cast<uint64_t*>(addr));
+    // The spec says that the low part of value shall be read from addr and
+    // the high part shall be read from addr+4.  On a little-endian system
+    // where we read a 64-bit quadword the low part of the value will be in
+    // the low part of the quadword, and the high part of the value in the
+    // high part of the quadword.
+    uint64_t value = loadRelaxed(ptr);
+    exclusiveMonitorSet(value);
+    *hibits = int32_t(value >> 32);
+    return int32_t(value);
 }
 
 int32_t
 Simulator::writeExDW(int32_t addr, int32_t value1, int32_t value2)
 {
+    if (addr & 3)
+        MOZ_CRASH("Unaligned exclusive write");
+
     if (handleWasmFault(addr, 8))
         return -1;
 
-    if ((addr & 3) == 0) {
-        SharedMem<uint64_t*> ptr = SharedMem<uint64_t*>::shared(reinterpret_cast<uint64_t*>(addr));
-        // The spec says that value1 shall be stored at addr and value2 at
-        // addr+4.  On a little-endian system that means constructing a 64-bit
-        // value where value1 is in the low half of a 64-bit quadword and value2
-        // is in the high half of the quadword.
-        uint64_t value = (uint64_t(value2) << 32) | uint32_t(value1);
-        bool held;
-        uint64_t expected = exclusiveMonitorGetAndClear(&held);
-        if (!held)
-            return 1;
-        uint64_t old = compareExchangeRelaxed(ptr, expected, value);
-        return old != expected;
-    }
-
-    printf("Unaligned write at 0x%08x\n", addr);
-    MOZ_CRASH();
+    SharedMem<uint64_t*> ptr = SharedMem<uint64_t*>::shared(reinterpret_cast<uint64_t*>(addr));
+    // The spec says that value1 shall be stored at addr and value2 at
+    // addr+4.  On a little-endian system that means constructing a 64-bit
+    // value where value1 is in the low half of a 64-bit quadword and value2
+    // is in the high half of the quadword.
+    uint64_t value = (uint64_t(value2) << 32) | uint32_t(value1);
+    bool held;
+    uint64_t expected = exclusiveMonitorGetAndClear(&held);
+    if (!held)
+        return 1;
+    uint64_t old = compareExchangeRelaxed(ptr, expected, value);
+    return old != expected;
 }
 
 uintptr_t
 Simulator::stackLimit() const
 {
     return stackLimit_;
 }