Bug 1363426 - part 1 - remove #ifdeffery in Atomics.h; r=erahm
authorNathan Froyd <froydnj@mozilla.com>
Wed, 10 May 2017 09:58:28 -0400
changeset 405680 f9dda7a0f6c71999f524841296a7a3924c4e2d4c
parent 405679 cb0360c3468d376765d8710965860814d1bc22ab
child 405681 31c0760423ecb7ccd4448897d37df0b9836bb547
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1363426
milestone55.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 1363426 - part 1 - remove #ifdeffery in Atomics.h; r=erahm Every platform where we use GCC has <atomic>, so there's no need to use GCC-specific __sync* intrinsics anymore. The <atomic> header may generate better code for several operations, as well.
mfbt/Atomics.h
--- a/mfbt/Atomics.h
+++ b/mfbt/Atomics.h
@@ -159,20 +159,17 @@ enum MemoryOrdering {
    * the ordering of choice when designing lockless data structures.  If
    * you don't know what order to use, use this one.
    */
   SequentiallyConsistent,
 };
 
 } // namespace mozilla
 
-// Build up the underlying intrinsics.
-#ifdef MOZ_HAVE_CXX11_ATOMICS
-
-#  include <atomic>
+#include <atomic>
 
 namespace mozilla {
 namespace detail {
 
 /*
  * We provide CompareExchangeFailureOrder to work around a bug in some
  * versions of GCC's <atomic> header.  See bug 898491.
  */
@@ -321,224 +318,16 @@ struct AtomicIntrinsics<T*, Order>
 };
 
 template<typename T>
 struct ToStorageTypeArgument
 {
   static constexpr T convert (T aT) { return aT; }
 };
 
-} // namespace detail
-} // namespace mozilla
-
-#elif defined(__GNUC__)
-
-namespace mozilla {
-namespace detail {
-
-/*
- * The __sync_* family of intrinsics is documented here:
- *
- * http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/Atomic-Builtins.html
- *
- * While these intrinsics are deprecated in favor of the newer __atomic_*
- * family of intrincs:
- *
- * http://gcc.gnu.org/onlinedocs/gcc-4.7.3/gcc/_005f_005fatomic-Builtins.html
- *
- * any GCC version that supports the __atomic_* intrinsics will also support
- * the <atomic> header and so will be handled above.  We provide a version of
- * atomics using the __sync_* intrinsics to support older versions of GCC.
- *
- * All __sync_* intrinsics that we use below act as full memory barriers, for
- * both compiler and hardware reordering, except for __sync_lock_test_and_set,
- * which is a only an acquire barrier.  When we call __sync_lock_test_and_set,
- * we add a barrier above it as appropriate.
- */
-
-template<MemoryOrdering Order> struct Barrier;
-
-/*
- * Some processors (in particular, x86) don't require quite so many calls to
- * __sync_sychronize as our specializations of Barrier produce.  If
- * performance turns out to be an issue, defining these specializations
- * on a per-processor basis would be a good first tuning step.
- */
-
-template<>
-struct Barrier<Relaxed>
-{
-  static void beforeLoad() {}
-  static void afterLoad() {}
-  static void beforeStore() {}
-  static void afterStore() {}
-};
-
-template<>
-struct Barrier<ReleaseAcquire>
-{
-  static void beforeLoad() {}
-  static void afterLoad() { __sync_synchronize(); }
-  static void beforeStore() { __sync_synchronize(); }
-  static void afterStore() {}
-};
-
-template<>
-struct Barrier<SequentiallyConsistent>
-{
-  static void beforeLoad() { __sync_synchronize(); }
-  static void afterLoad() { __sync_synchronize(); }
-  static void beforeStore() { __sync_synchronize(); }
-  static void afterStore() { __sync_synchronize(); }
-};
-
-template<typename T, bool TIsEnum = IsEnum<T>::value>
-struct AtomicStorageType
-{
-  // For non-enums, just use the type directly.
-  typedef T Type;
-};
-
-template<typename T>
-struct AtomicStorageType<T, true>
-  : Conditional<sizeof(T) == 4, uint32_t, uint64_t>
-{
-  static_assert(sizeof(T) == 4 || sizeof(T) == 8,
-                "wrong type computed in conditional above");
-};
-
-template<typename T, MemoryOrdering Order>
-struct IntrinsicMemoryOps
-{
-  typedef typename AtomicStorageType<T>::Type ValueType;
-
-  static T load(const ValueType& aPtr)
-  {
-    Barrier<Order>::beforeLoad();
-    T val = T(aPtr);
-    Barrier<Order>::afterLoad();
-    return val;
-  }
-
-  static void store(ValueType& aPtr, T aVal)
-  {
-    Barrier<Order>::beforeStore();
-    aPtr = ValueType(aVal);
-    Barrier<Order>::afterStore();
-  }
-
-  static T exchange(ValueType& aPtr, T aVal)
-  {
-    // __sync_lock_test_and_set is only an acquire barrier; loads and stores
-    // can't be moved up from after to before it, but they can be moved down
-    // from before to after it.  We may want a stricter ordering, so we need
-    // an explicit barrier.
-    Barrier<Order>::beforeStore();
-    return T(__sync_lock_test_and_set(&aPtr, ValueType(aVal)));
-  }
-
-  static bool compareExchange(ValueType& aPtr, T aOldVal, T aNewVal)
-  {
-    return __sync_bool_compare_and_swap(&aPtr, ValueType(aOldVal), ValueType(aNewVal));
-  }
-};
-
-template<typename T, MemoryOrdering Order>
-struct IntrinsicAddSub
-  : public IntrinsicMemoryOps<T, Order>
-{
-  typedef IntrinsicMemoryOps<T, Order> Base;
-  typedef typename Base::ValueType ValueType;
-
-  static T add(ValueType& aPtr, T aVal)
-  {
-    return T(__sync_fetch_and_add(&aPtr, ValueType(aVal)));
-  }
-
-  static T sub(ValueType& aPtr, T aVal)
-  {
-    return T(__sync_fetch_and_sub(&aPtr, ValueType(aVal)));
-  }
-};
-
-template<typename T, MemoryOrdering Order>
-struct IntrinsicAddSub<T*, Order>
-  : public IntrinsicMemoryOps<T*, Order>
-{
-  typedef IntrinsicMemoryOps<T*, Order> Base;
-  typedef typename Base::ValueType ValueType;
-
-  /*
-   * The reinterpret_casts are needed so that
-   * __sync_fetch_and_{add,sub} will properly type-check.
-   *
-   * Also, these functions do not provide standard semantics for
-   * pointer types, so we need to adjust the addend.
-   */
-  static ValueType add(ValueType& aPtr, ptrdiff_t aVal)
-  {
-    ValueType amount = reinterpret_cast<ValueType>(aVal * sizeof(T));
-    return __sync_fetch_and_add(&aPtr, amount);
-  }
-
-  static ValueType sub(ValueType& aPtr, ptrdiff_t aVal)
-  {
-    ValueType amount = reinterpret_cast<ValueType>(aVal * sizeof(T));
-    return __sync_fetch_and_sub(&aPtr, amount);
-  }
-};
-
-template<typename T, MemoryOrdering Order>
-struct IntrinsicIncDec : public IntrinsicAddSub<T, Order>
-{
-  typedef IntrinsicAddSub<T, Order> Base;
-  typedef typename Base::ValueType ValueType;
-
-  static T inc(ValueType& aPtr) { return Base::add(aPtr, 1); }
-  static T dec(ValueType& aPtr) { return Base::sub(aPtr, 1); }
-};
-
-template<typename T, MemoryOrdering Order>
-struct AtomicIntrinsics : public IntrinsicIncDec<T, Order>
-{
-  static T or_( T& aPtr, T aVal) { return __sync_fetch_and_or(&aPtr, aVal); }
-  static T xor_(T& aPtr, T aVal) { return __sync_fetch_and_xor(&aPtr, aVal); }
-  static T and_(T& aPtr, T aVal) { return __sync_fetch_and_and(&aPtr, aVal); }
-};
-
-template<typename T, MemoryOrdering Order>
-struct AtomicIntrinsics<T*, Order> : public IntrinsicIncDec<T*, Order>
-{
-};
-
-template<typename T, bool TIsEnum = IsEnum<T>::value>
-struct ToStorageTypeArgument
-{
-  typedef typename AtomicStorageType<T>::Type ResultType;
-
-  static constexpr ResultType convert (T aT) { return ResultType(aT); }
-};
-
-template<typename T>
-struct ToStorageTypeArgument<T, false>
-{
-  static constexpr T convert (T aT) { return aT; }
-};
-
-} // namespace detail
-} // namespace mozilla
-
-#else
-# error "Atomic compiler intrinsics are not supported on your platform"
-#endif
-
-namespace mozilla {
-
-namespace detail {
-
 template<typename T, MemoryOrdering Order>
 class AtomicBase
 {
   static_assert(sizeof(T) == 4 || sizeof(T) == 8,
                 "mozilla/Atomics.h only supports 32-bit and 64-bit types");
 
 protected:
   typedef typename detail::AtomicIntrinsics<T, Order> Intrinsics;