try: -b do -p all -u all -t all draft
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 21 Aug 2017 00:06:12 +0300
changeset 1265707 2893c0ecfa01
parent 1264887 ab9127aaa432
child 1568320 070e259b401c
push id214571
push useropettay@mozilla.com
push dateSun, 20 Aug 2017 21:06:59 +0000
treeherdertry@2893c0ecfa01 [default view] [failures only]
milestone57.0a1
try: -b do -p all -u all -t all
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsISupportsImpl.h
xpcom/build/nsXPCOM.h
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -3528,16 +3528,17 @@ nsCycleCollector::Suspect(void* aPtr, ns
              "Suspect nsISupports pointer must be canonical");
 
   mPurpleBuf.Put(aPtr, aParti, aRefCnt);
 }
 
 void
 nsCycleCollector::SuspectNurseryEntries()
 {
+  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
   CheckThreadSafety();
   while (gNurseryPurpleBufferEntryCount) {
     NurseryPurpleBufferEntry& entry =
       gNurseryPurpleBufferEntry[--gNurseryPurpleBufferEntryCount];
     mPurpleBuf.Put(entry.mPtr, entry.mParticipant, entry.mRefCnt);
   }
 }
 
@@ -4092,32 +4093,36 @@ NS_CycleCollectorSuspect3(void* aPtr, ns
     data->mCollector->Suspect(aPtr, aCp, aRefCnt);
     return;
   }
   SuspectAfterShutdown(aPtr, aCp, aRefCnt, aShouldDelete);
 }
 
 void ClearNurseryPurpleBuffer()
 {
+  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
   CollectorData* data = sCollectorData.get();
   MOZ_ASSERT(data);
   MOZ_ASSERT(data->mCollector);
   data->mCollector->SuspectNurseryEntries();
 }
 
-bool
+void
 NS_CycleCollectorSuspectUsingNursery(void* aPtr,
                                      nsCycleCollectionParticipant* aCp,
-                                     nsCycleCollectingAutoRefCnt* aRefCnt)
+                                     nsCycleCollectingAutoRefCnt* aRefCnt,
+                                     bool* aShouldDelete)
 {
+  MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
   if (!gNurseryPurpleBufferEnabled) {
-    return false;
-  }
+    NS_CycleCollectorSuspect3(aPtr, aCp, aRefCnt, aShouldDelete);
+    return;
+  }
+
   SuspectUsingNurseryPurpleBuffer(aPtr, aCp, aRefCnt);
-  return true;
 }
 
 uint32_t
 nsCycleCollector_suspectedCount()
 {
   CollectorData* data = sCollectorData.get();
 
   // We should have started the cycle collector by now.
--- a/xpcom/base/nsISupportsImpl.h
+++ b/xpcom/base/nsISupportsImpl.h
@@ -185,120 +185,81 @@ do {                                    
 #define NS_IN_PURPLE_BUFFER (1 << 0)
 #define NS_IS_PURPLE (1 << 1)
 #define NS_REFCOUNT_CHANGE (1 << NS_NUMBER_OF_FLAGS_IN_REFCNT)
 #define NS_REFCOUNT_VALUE(_val) (_val >> NS_NUMBER_OF_FLAGS_IN_REFCNT)
 
 class nsCycleCollectingAutoRefCnt
 {
 public:
+
+  typedef void (*Suspect)(void* aPtr,
+                          nsCycleCollectionParticipant* aCp,
+                          nsCycleCollectingAutoRefCnt* aRefCnt,
+                          bool* aShouldDelete);
+
   nsCycleCollectingAutoRefCnt() : mRefCntAndFlags(0) {}
 
   explicit nsCycleCollectingAutoRefCnt(uintptr_t aValue)
     : mRefCntAndFlags(aValue << NS_NUMBER_OF_FLAGS_IN_REFCNT)
   {
   }
 
   nsCycleCollectingAutoRefCnt(const nsCycleCollectingAutoRefCnt&) = delete;
   void operator=(const nsCycleCollectingAutoRefCnt&) = delete;
 
+  template<Suspect suspect = NS_CycleCollectorSuspect3>
   MOZ_ALWAYS_INLINE uintptr_t incr(nsISupports* aOwner)
   {
-    return incr(aOwner, nullptr);
+    return incr<suspect>(aOwner, nullptr);
   }
 
+  template<Suspect suspect = NS_CycleCollectorSuspect3>
   MOZ_ALWAYS_INLINE uintptr_t incr(void* aOwner,
                                    nsCycleCollectionParticipant* aCp)
   {
     mRefCntAndFlags += NS_REFCOUNT_CHANGE;
     mRefCntAndFlags &= ~NS_IS_PURPLE;
     // For incremental cycle collection, use the purple buffer to track objects
     // that have been AddRef'd.
     if (!IsInPurpleBuffer()) {
       mRefCntAndFlags |= NS_IN_PURPLE_BUFFER;
       // Refcount isn't zero, so Suspect won't delete anything.
       MOZ_ASSERT(get() > 0);
-      NS_CycleCollectorSuspect3(aOwner, aCp, this, nullptr);
-    }
-    return NS_REFCOUNT_VALUE(mRefCntAndFlags);
-  }
-
-  MOZ_ALWAYS_INLINE uintptr_t incrUsingNursery(nsISupports* aOwner)
-  {
-    return incrUsingNursery(aOwner, nullptr);
-  }
-
-  MOZ_ALWAYS_INLINE uintptr_t
-  incrUsingNursery(void* aOwner, nsCycleCollectionParticipant* aCp)
-  {
-    mRefCntAndFlags += NS_REFCOUNT_CHANGE;
-    mRefCntAndFlags &= ~NS_IS_PURPLE;
-    // For incremental cycle collection, use the purple buffer to track objects
-    // that have been AddRef'd.
-    if (!IsInPurpleBuffer()) {
-      mRefCntAndFlags |= NS_IN_PURPLE_BUFFER;
-      // Refcount isn't zero, so Suspect won't delete anything.
-      MOZ_ASSERT(get() > 0);
-      if (!NS_CycleCollectorSuspectUsingNursery(aOwner, aCp, this)) {
-        NS_CycleCollectorSuspect3(aOwner, aCp, this, nullptr);
-      }
+      suspect(aOwner, aCp, this, nullptr);
     }
     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
   }
 
   MOZ_ALWAYS_INLINE void stabilizeForDeletion()
   {
     // Set refcnt to 1 and mark us to be in the purple buffer.
     // This way decr won't call suspect again.
     mRefCntAndFlags = NS_REFCOUNT_CHANGE | NS_IN_PURPLE_BUFFER;
   }
 
+  template<Suspect suspect = NS_CycleCollectorSuspect3>
   MOZ_ALWAYS_INLINE uintptr_t decr(nsISupports* aOwner,
                                    bool* aShouldDelete = nullptr)
   {
-    return decr(aOwner, nullptr, aShouldDelete);
+    return decr<suspect>(aOwner, nullptr, aShouldDelete);
   }
 
+  template<Suspect suspect = NS_CycleCollectorSuspect3>
   MOZ_ALWAYS_INLINE uintptr_t decr(void* aOwner,
                                    nsCycleCollectionParticipant* aCp,
                                    bool* aShouldDelete = nullptr)
   {
     MOZ_ASSERT(get() > 0);
     if (!IsInPurpleBuffer()) {
       mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
       mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
       uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags);
       // Suspect may delete 'aOwner' and 'this'!
-      NS_CycleCollectorSuspect3(aOwner, aCp, this, aShouldDelete);
-      return retval;
-    }
-    mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
-    mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
-    return NS_REFCOUNT_VALUE(mRefCntAndFlags);
-  }
-
-  MOZ_ALWAYS_INLINE uintptr_t decrUsingNursery(nsISupports* aOwner,
-                                               bool* aShouldDelete = nullptr)
-  {
-    return decrUsingNursery(aOwner, nullptr, aShouldDelete);
-  }
-
-  MOZ_ALWAYS_INLINE uintptr_t
-  decrUsingNursery(void* aOwner, nsCycleCollectionParticipant* aCp,
-                   bool* aShouldDelete = nullptr)
-  {
-    MOZ_ASSERT(get() > 0);
-    if (!IsInPurpleBuffer()) {
-      mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
-      mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
-      uintptr_t retval = NS_REFCOUNT_VALUE(mRefCntAndFlags);
-      if (!NS_CycleCollectorSuspectUsingNursery(aOwner, aCp, this)) {
-        // Suspect may delete 'aOwner' and 'this'!
-        NS_CycleCollectorSuspect3(aOwner, aCp, this, aShouldDelete);
-      }
+      suspect(aOwner, aCp, this, aShouldDelete);
       return retval;
     }
     mRefCntAndFlags -= NS_REFCOUNT_CHANGE;
     mRefCntAndFlags |= (NS_IN_PURPLE_BUFFER | NS_IS_PURPLE);
     return NS_REFCOUNT_VALUE(mRefCntAndFlags);
   }
 
   MOZ_ALWAYS_INLINE void RemovePurple()
@@ -761,17 +722,17 @@ NS_IMETHODIMP_(MozExternalRefCountType) 
 
 #define NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_ADDREF(_class)              \
 NS_IMETHODIMP_(MozExternalRefCountType) _class::AddRef(void)                  \
 {                                                                             \
   MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                  \
   MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                        \
   NS_ASSERT_OWNINGTHREAD(_class);                                             \
   nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
-  nsrefcnt count = mRefCnt.incrUsingNursery(base);                            \
+  nsrefcnt count = mRefCnt.incr<NS_CycleCollectorSuspectUsingNursery>(base);  \
   NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                         \
   return count;                                                               \
 }
 
 #define NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_DESTROY(_class, _destroy)       \
 NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
 {                                                                             \
   MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
@@ -813,39 +774,39 @@ NS_IMETHODIMP_(MozExternalRefCountType) 
 }                                                                             \
 NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                     \
 {                                                                             \
   delete this;                                                                \
 }
 
 // _LAST_RELEASE can be useful when certain resources should be released
 // as soon as we know the object will be deleted.
-#define NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last) \
-NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                 \
-{                                                                             \
-  MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                            \
-  NS_ASSERT_OWNINGTHREAD(_class);                                             \
-  bool shouldDelete = false;                                                  \
-  nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);    \
-  nsrefcnt count = mRefCnt.decrUsingNursery(base, &shouldDelete);             \
-  NS_LOG_RELEASE(this, count, #_class);                                       \
-  if (count == 0) {                                                           \
-      mRefCnt.incrUsingNursery(base);                                         \
-      _last;                                                                  \
-      mRefCnt.decrUsingNursery(base);                                         \
-      if (shouldDelete) {                                                     \
-          mRefCnt.stabilizeForDeletion();                                     \
-          DeleteCycleCollectable();                                           \
-      }                                                                       \
-  }                                                                           \
-  return count;                                                               \
-}                                                                             \
-NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                     \
-{                                                                             \
-  delete this;                                                                \
+#define NS_IMPL_MAIN_THREAD_ONLY_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(_class, _last)  \
+NS_IMETHODIMP_(MozExternalRefCountType) _class::Release(void)                               \
+{                                                                                           \
+  MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                                          \
+  NS_ASSERT_OWNINGTHREAD(_class);                                                           \
+  bool shouldDelete = false;                                                                \
+  nsISupports *base = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this);                  \
+  nsrefcnt count = mRefCnt.decr<NS_CycleCollectorSuspectUsingNursery>(base, &shouldDelete); \
+  NS_LOG_RELEASE(this, count, #_class);                                                     \
+  if (count == 0) {                                                                         \
+      mRefCnt.incr<NS_CycleCollectorSuspectUsingNursery>(base);                             \
+      _last;                                                                                \
+      mRefCnt.decr<NS_CycleCollectorSuspectUsingNursery>(base);                             \
+      if (shouldDelete) {                                                                   \
+          mRefCnt.stabilizeForDeletion();                                                   \
+          DeleteCycleCollectable();                                                         \
+      }                                                                                     \
+  }                                                                                         \
+  return count;                                                                             \
+}                                                                                           \
+NS_IMETHODIMP_(void) _class::DeleteCycleCollectable(void)                                   \
+{                                                                                           \
+  delete this;                                                                              \
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * There are two ways of implementing QueryInterface, and we use both:
  *
  * Table-driven QueryInterface uses a static table of IID->offset mappings
--- a/xpcom/build/nsXPCOM.h
+++ b/xpcom/build/nsXPCOM.h
@@ -353,20 +353,21 @@ XPCOM_API(void) NS_LogCOMPtrRelease(void
 class nsCycleCollectionParticipant;
 class nsCycleCollectingAutoRefCnt;
 
 XPCOM_API(void) NS_CycleCollectorSuspect3(void* aPtr,
                                           nsCycleCollectionParticipant* aCp,
                                           nsCycleCollectingAutoRefCnt* aRefCnt,
                                           bool* aShouldDelete);
 
-XPCOM_API(bool)
+XPCOM_API(void)
 NS_CycleCollectorSuspectUsingNursery(void* aPtr,
                                      nsCycleCollectionParticipant* aCp,
-                                     nsCycleCollectingAutoRefCnt* aRefCnt);
+                                     nsCycleCollectingAutoRefCnt* aRefCnt,
+                                     bool* aShouldDelete);
 
 #endif
 
 /**
  * Categories (in the category manager service) used by XPCOM:
  */
 
 /**