Bug 1207696 Part 4a - Make recording optional in mozilla::RefCounted, r=ehsan.
authorBrian Hackett <bhackett1024@gmail.com>
Sat, 21 Jul 2018 14:21:39 +0000
changeset 427685 20f8e61b78f5bbda8e2819ce07162f56271b9cf3
parent 427684 e5393e123ee299192b0eb9dfde29c328c07d6bc6
child 427686 ca20a3fbb10beac6fa22050279b4226f585a90d8
push id66686
push userrgurzau@mozilla.com
push dateSun, 22 Jul 2018 09:50:29 +0000
treeherderautoland@05d5b407013c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan
bugs1207696
milestone63.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 1207696 Part 4a - Make recording optional in mozilla::RefCounted, r=ehsan.
mfbt/RefCounted.h
--- a/mfbt/RefCounted.h
+++ b/mfbt/RefCounted.h
@@ -86,85 +86,92 @@ public:
 
 // This is used WeakPtr.h as well as this file.
 enum RefCountAtomicity
 {
   AtomicRefCount,
   NonAtomicRefCount
 };
 
-template<typename T, RefCountAtomicity Atomicity>
+template<typename T, RefCountAtomicity Atomicity, recordreplay::Behavior Recording>
 class RC
 {
 public:
   explicit RC(T aCount) : mValue(aCount) {}
 
   T operator++() { return ++mValue; }
   T operator--() { return --mValue; }
 
   void operator=(const T& aValue) { mValue = aValue; }
 
   operator T() const { return mValue; }
 
 private:
   T mValue;
 };
 
-template<typename T>
-class RC<T, AtomicRefCount>
+template<typename T, recordreplay::Behavior Recording>
+class RC<T, AtomicRefCount, Recording>
 {
 public:
-  explicit RC(T aCount) : mValue(aCount) {}
+  explicit RC(T aCount) : mValue(aCount) { }
 
   T operator++()
   {
     // Memory synchronization is not required when incrementing a
     // reference count.  The first increment of a reference count on a
     // thread is not important, since the first use of the object on a
     // thread can happen before it.  What is important is the transfer
     // of the pointer to that thread, which may happen prior to the
     // first increment on that thread.  The necessary memory
     // synchronization is done by the mechanism that transfers the
     // pointer between threads.
+    AutoRecordAtomicAccess<Recording> record;
     return mValue.fetch_add(1, std::memory_order_relaxed) + 1;
   }
 
   T operator--()
   {
     // Since this may be the last release on this thread, we need
     // release semantics so that prior writes on this thread are visible
     // to the thread that destroys the object when it reads mValue with
     // acquire semantics.
+    AutoRecordAtomicAccess<Recording> record;
     T result = mValue.fetch_sub(1, std::memory_order_release) - 1;
     if (result == 0) {
       // We're going to destroy the object on this thread, so we need
       // acquire semantics to synchronize with the memory released by
       // the last release on other threads, that is, to ensure that
       // writes prior to that release are now visible on this thread.
       std::atomic_thread_fence(std::memory_order_acquire);
     }
     return result;
   }
 
   // This method is only called in debug builds, so we're not too concerned
   // about its performance.
-  void operator=(const T& aValue) { mValue.store(aValue, std::memory_order_seq_cst); }
+  void operator=(const T& aValue) {
+    AutoRecordAtomicAccess<Recording> record;
+    mValue.store(aValue, std::memory_order_seq_cst);
+  }
 
   operator T() const
   {
     // Use acquire semantics since we're not sure what the caller is
     // doing.
+    AutoRecordAtomicAccess<Recording> record;
     return mValue.load(std::memory_order_acquire);
   }
 
 private:
   std::atomic<T> mValue;
 };
 
-template<typename T, RefCountAtomicity Atomicity>
+template<typename T, RefCountAtomicity Atomicity,
+         recordreplay::Behavior Recording = recordreplay::Behavior::Preserve>
 class RefCounted
 {
 protected:
   RefCounted() : mRefCnt(0) {}
   ~RefCounted() { MOZ_ASSERT(mRefCnt == detail::DEAD); }
 
 public:
   // Compatibility with nsRefPtr.
@@ -215,17 +222,17 @@ public:
   MozRefCountType refCount() const { return mRefCnt; }
   bool hasOneRef() const
   {
     MOZ_ASSERT(mRefCnt > 0);
     return mRefCnt == 1;
   }
 
 private:
-  mutable RC<MozRefCountType, Atomicity> mRefCnt;
+  mutable RC<MozRefCountType, Atomicity, Recording> mRefCnt;
 };
 
 #ifdef MOZ_REFCOUNTED_LEAK_CHECKING
 // Passing override for the optional argument marks the typeName and
 // typeSize functions defined by this macro as overrides.
 #define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T, ...) \
   virtual const char* typeName() const __VA_ARGS__ { return #T; } \
   virtual size_t typeSize() const __VA_ARGS__ { return sizeof(*this); }
@@ -257,19 +264,19 @@ namespace external {
 
 /**
  * AtomicRefCounted<T> is like RefCounted<T>, with an atomically updated
  * reference counter.
  *
  * NOTE: Please do not use this class, use NS_INLINE_DECL_THREADSAFE_REFCOUNTING
  * instead.
  */
-template<typename T>
+template<typename T, recordreplay::Behavior Recording = recordreplay::Behavior::Preserve>
 class AtomicRefCounted :
-  public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount>
+  public mozilla::detail::RefCounted<T, mozilla::detail::AtomicRefCount, Recording>
 {
 public:
   ~AtomicRefCounted()
   {
     static_assert(IsBaseOf<AtomicRefCounted, T>::value,
                   "T must derive from AtomicRefCounted<T>");
   }
 };