Bug 1146817 - Introduce AtomicOperations::hasAtomic8(). r=sstangl
authorLars T Hansen <lhansen@mozilla.com>
Fri, 01 Sep 2017 11:41:40 +0200
changeset 378844 39eb143530ce3583c8f44dcccac8adbb0c86a18b
parent 378843 eaa3ad46271ea6f3813cd7254c7b18fd06ac694b
child 378845 2cdac401110fbe54de4305a37628399ffd51a569
push id32443
push userarchaeopteryx@coole-files.de
push dateTue, 05 Sep 2017 09:41:20 +0000
treeherdermozilla-central@3ecda4678c49 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs1146817
milestone57.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 1146817 - Introduce AtomicOperations::hasAtomic8(). r=sstangl
js/src/jit/AtomicOperations.h
js/src/jit/arm/AtomicOperations-arm.h
js/src/jit/arm64/AtomicOperations-arm64.h
js/src/jit/mips-shared/AtomicOperations-mips-shared.h
js/src/jit/none/AtomicOperations-feeling-lucky.h
js/src/jit/x86-shared/AtomicOperations-x86-shared-gcc.h
js/src/jit/x86-shared/AtomicOperations-x86-shared-msvc.h
--- a/js/src/jit/AtomicOperations.h
+++ b/js/src/jit/AtomicOperations.h
@@ -150,27 +150,32 @@ class AtomicOperations
     // Test lock-freedom for any int32 value.  This implements the
     // Atomics::isLockFree() operation in the ECMAScript Shared Memory and
     // Atomics specification, as follows:
     //
     // 4-byte accesses are always lock free (in the spec).
     // 1- and 2-byte accesses are always lock free (in SpiderMonkey).
     //
     // Lock-freedom for 8 bytes is determined by the platform's isLockfree8().
-    // However, the spec stipulates that isLockFree(8) is true only if there is
-    // an integer array that admits atomic operations whose BYTES_PER_ELEMENT=8;
-    // at the moment (August 2017) there are no such arrays.
+    // However, the ES spec stipulates that isLockFree(8) is true only if there
+    // is an integer array that admits atomic operations whose
+    // BYTES_PER_ELEMENT=8; at the moment (August 2017) there are no such
+    // arrays.
     //
-    // There is no lock-freedom for any other values on any platform.
+    // There is no lock-freedom for JS for any other values on any platform.
     static inline bool isLockfreeJS(int32_t n);
 
-    // If the return value is true then a call to the 64-bit (8-byte)
-    // routines below will work, otherwise those functions will assert in
-    // debug builds and may crash in release build.  (See the code in
-    // ../arm for an example.)  The value of this call does not change
+    // If the return value is true then the templated functions below are
+    // supported for int64_t and uint64_t.  If the return value is false then
+    // those functions will MOZ_CRASH.  The value of this call does not change
+    // during execution.
+    static inline bool hasAtomic8();
+
+    // If the return value is true then hasAtomic8() is true and the atomic
+    // operations are indeed lock-free.  The value of this call does not change
     // during execution.
     static inline bool isLockfree8();
 
     // Execute a full memory barrier (LoadLoad+LoadStore+StoreLoad+StoreStore).
     static inline void fenceSeqCst();
 
     // All clients should use the APIs that take SharedMem pointers.
     // See above for semantics and acceptable types.
--- a/js/src/jit/arm/AtomicOperations-arm.h
+++ b/js/src/jit/arm/AtomicOperations-arm.h
@@ -26,36 +26,42 @@
 // ordered operations, but these reorderings are not allowed by JS.  To do
 // better we will end up with inline assembler or JIT-generated code.
 
 #if !defined(__clang__) && !defined(__GNUC__)
 # error "This file only for gcc-compatible compilers"
 #endif
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    // This guard is really only for tier-2 and tier-3 systems: LDREXD and
+    // STREXD have been available since ARMv6K, and only ARMv7 and later are
+    // tier-1.
+    return HasLDSTREXBHD();
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     // The JIT and the C++ compiler must agree on whether to use atomics
     // for 64-bit accesses.  There are two ways to do this: either the
     // JIT defers to the C++ compiler (so if the C++ code is compiled
     // for ARMv6, say, and __atomic_always_lock_free(8) is false, then the
     // JIT ignores the fact that the program is running on ARMv7 or newer);
     // or the C++ code in this file calls out to run-time generated code
     // to do whatever the JIT does.
     //
     // For now, make the JIT defer to the C++ compiler when we know what
     // the C++ compiler will do, otherwise assume a lock is needed.
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
 
-    // This guard is really only for tier-2 and tier-3 systems: LDREXD and
-    // STREXD have been available since ARMv6K, and only ARMv7 and later are
-    // tier-1.
-    return HasLDSTREXBHD() && __atomic_always_lock_free(sizeof(int64_t), 0);
+    return hasAtomic8() && __atomic_always_lock_free(sizeof(int64_t), 0);
 }
 
 inline void
 js::jit::AtomicOperations::fenceSeqCst()
 {
     __atomic_thread_fence(__ATOMIC_SEQ_CST);
 }
 
--- a/js/src/jit/arm64/AtomicOperations-arm64.h
+++ b/js/src/jit/arm64/AtomicOperations-arm64.h
@@ -12,16 +12,22 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Types.h"
 
 #if !defined(__clang__) && !defined(__GNUC__)
 # error "This file only for gcc-compatible compilers"
 #endif
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    return true;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
     return true;
 }
--- a/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
+++ b/js/src/jit/mips-shared/AtomicOperations-mips-shared.h
@@ -29,18 +29,29 @@
 // compatible option for older compilers: enable this to use GCC's old
 // __sync functions instead of the newer __atomic functions.  This
 // will be required for GCC 4.6.x and earlier, and probably for Clang
 // 3.1, should we need to use those versions.
 
 //#define ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    // NOTE, change this when primitives below have been properly changed to
+    // support 8-byte atomics.
+    return false;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
+    if (!hasAtomic8())
+        return false;
+
 #ifndef ATOMICS_IMPLEMENTED_WITH_SYNC_INTRINSICS
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
     // NOTE, this condition is obsolete.  See comment above.
 # if _MIPS_SIM == _ABI64
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
 # endif
--- a/js/src/jit/none/AtomicOperations-feeling-lucky.h
+++ b/js/src/jit/none/AtomicOperations-feeling-lucky.h
@@ -87,16 +87,26 @@
 #  error "This combination of features is senseless, please fix"
 #endif
 
 // Try to avoid platform #ifdefs below this point.
 
 #ifdef GNUC_COMPATIBLE
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+#if defined(HAS_64BIT_ATOMICS)
+    return true;
+#else
+    return false;
+#endif
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
 #if defined(HAS_64BIT_LOCKFREE)
     return true;
 #else
     return false;
 #endif
 }
--- a/js/src/jit/x86-shared/AtomicOperations-x86-shared-gcc.h
+++ b/js/src/jit/x86-shared/AtomicOperations-x86-shared-gcc.h
@@ -57,16 +57,22 @@
 
 // For now, we require that the C++ compiler's atomics are lock free, even for
 // 64-bit accesses.
 
 // When compiling with Clang on 32-bit linux it will be necessary to link with
 // -latomic to get the proper 64-bit intrinsics.
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    return true;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int8_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int16_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int32_t), 0));
     MOZ_ASSERT(__atomic_always_lock_free(sizeof(int64_t), 0));
     return true;
 }
--- a/js/src/jit/x86-shared/AtomicOperations-x86-shared-msvc.h
+++ b/js/src/jit/x86-shared/AtomicOperations-x86-shared-msvc.h
@@ -30,16 +30,22 @@
 // 32-bit operations, and 64-bit operations on 64-bit systems) and otherwise
 // falls back on CMPXCHG8B for 64-bit operations on 32-bit systems.  We could be
 // using those functions in many cases here (though not all).  I have not done
 // so because (a) I don't yet know how far back those functions are supported
 // and (b) I expect we'll end up dropping into assembler here eventually so as
 // to guarantee that the C++ compiler won't optimize the code.
 
 inline bool
+js::jit::AtomicOperations::hasAtomic8()
+{
+    return true;
+}
+
+inline bool
 js::jit::AtomicOperations::isLockfree8()
 {
     // The MSDN docs suggest very strongly that if code is compiled for Pentium
     // or better the 64-bit primitives will be lock-free, see eg the "Remarks"
     // secion of the page for _InterlockedCompareExchange64, currently here:
     // https://msdn.microsoft.com/en-us/library/ttk2z1ws%28v=vs.85%29.aspx
     //
     // But I've found no way to assert that at compile time or run time, there