Bug 927813 - Some micro-optimizations for Suspect, r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Thu, 17 Oct 2013 17:05:13 +0300
changeset 165890 616980966644f34c3e96a2b44517ca8f553364ff
parent 165889 f7e452886b4f339ab7a3cee08fd96ae49414758d
child 165891 6c1e6cff2e434366e8b9db02f3826363aae2c81d
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs927813
milestone27.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 927813 - Some micro-optimizations for Suspect, r=mccr8
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -774,35 +774,35 @@ public:
     // (4) If removeChildlessNodes is true, then any nodes in the purple buffer
     //     that will have no children in the cycle collector graph will also be
     //     removed. CanSkip() may be run on these children.
     void RemoveSkippable(nsCycleCollector* aCollector,
                          bool removeChildlessNodes,
                          bool aAsyncSnowWhiteFreeing,
                          CC_ForgetSkippableCallback aCb);
 
-    nsPurpleBufferEntry* NewEntry()
+    MOZ_ALWAYS_INLINE nsPurpleBufferEntry* NewEntry()
     {
-        if (!mFreeList) {
+        if (MOZ_UNLIKELY(!mFreeList)) {
             Block *b = new Block;
             StartBlock(b);
 
             // Add the new block as the second block in the list.
             b->mNext = mFirstBlock.mNext;
             mFirstBlock.mNext = b;
         }
 
         nsPurpleBufferEntry *e = mFreeList;
         mFreeList = (nsPurpleBufferEntry*)
             (uintptr_t(mFreeList->mNextInFreeList) & ~uintptr_t(1));
         return e;
     }
 
-    void Put(void *p, nsCycleCollectionParticipant *cp,
-             nsCycleCollectingAutoRefCnt *aRefCnt)
+    MOZ_ALWAYS_INLINE void Put(void *p, nsCycleCollectionParticipant *cp,
+                               nsCycleCollectingAutoRefCnt *aRefCnt)
     {
         nsPurpleBufferEntry *e = NewEntry();
 
         ++mCount;
 
         e->mObject = p;
         e->mRefCnt = aRefCnt;
         e->mParticipant = cp;
@@ -2536,27 +2536,27 @@ nsCycleCollector_isScanSafe(void *s, nsC
 
     nsXPCOMCycleCollectionParticipant *xcp;
     ToParticipant(static_cast<nsISupports*>(s), &xcp);
 
     return xcp != nullptr;
 }
 #endif
 
-void
+MOZ_ALWAYS_INLINE void
 nsCycleCollector::Suspect(void *n, nsCycleCollectionParticipant *cp,
                           nsCycleCollectingAutoRefCnt *aRefCnt)
 {
     CheckThreadSafety();
 
     // Re-entering ::Suspect during collection used to be a fault, but
     // we are canonicalizing nsISupports pointers using QI, so we will
     // see some spurious refcount traffic here.
 
-    if (mScanInProgress)
+    if (MOZ_UNLIKELY(mScanInProgress))
         return;
 
     MOZ_ASSERT(nsCycleCollector_isScanSafe(n, cp),
                "suspected a non-scansafe pointer");
 
     mPurpleBuf.Put(n, cp, aRefCnt);
 }
 
@@ -2998,43 +2998,50 @@ DeferredFinalize(DeferredFinalizeAppendF
 
     data->mRuntime->DeferredFinalize(aAppendFunc, aFunc, aThing);
 }
 
 } // namespace cyclecollector
 } // namespace mozilla
 
 
+MOZ_NEVER_INLINE static void
+SuspectAfterShutdown(void* n, nsCycleCollectionParticipant* cp,
+                     nsCycleCollectingAutoRefCnt* aRefCnt,
+                     bool* aShouldDelete)
+{
+    if (aRefCnt->get() == 0) {
+        if (!aShouldDelete) {
+            CanonicalizeParticipant(&n, &cp);
+            aRefCnt->stabilizeForDeletion();
+            cp->DeleteCycleCollectable(n);
+        } else {
+            *aShouldDelete = true;
+        }
+    } else {
+        // Make sure we'll get called again.
+        aRefCnt->RemoveFromPurpleBuffer();
+    }
+}
+
 void
 NS_CycleCollectorSuspect3(void *n, nsCycleCollectionParticipant *cp,
                           nsCycleCollectingAutoRefCnt *aRefCnt,
                           bool* aShouldDelete)
 {
     CollectorData *data = sCollectorData.get();
 
     // We should have started the cycle collector by now.
     MOZ_ASSERT(data);
 
-    if (!data->mCollector) {
-        if (aRefCnt->get() == 0) {
-            if (!aShouldDelete) {
-                CanonicalizeParticipant(&n, &cp);
-                aRefCnt->stabilizeForDeletion();
-                cp->DeleteCycleCollectable(n);
-            } else {
-                *aShouldDelete = true;
-            }
-        } else {
-          // Make sure we'll get called again.
-          aRefCnt->RemoveFromPurpleBuffer();
-        }
+    if (MOZ_LIKELY(data->mCollector)) {
+        data->mCollector->Suspect(n, cp, aRefCnt);
         return;
     }
-
-    return data->mCollector->Suspect(n, cp, aRefCnt);
+    SuspectAfterShutdown(n, cp, aRefCnt, aShouldDelete);
 }
 
 uint32_t
 nsCycleCollector_suspectedCount()
 {
     CollectorData *data = sCollectorData.get();
 
     // We should have started the cycle collector by now.