Bug 845441: Remove DEBUG_CC. r=mccr8
authorKyle Huey <khuey@kylehuey.com>
Tue, 26 Feb 2013 13:34:32 -0800
changeset 123086 c5dd0f5ef51766032cdb890dc34b1a7bf828315b
parent 123085 6f0afe551e178f12c6fefa947bd0c6c1f13fc1c1
child 123087 f246412bcadb5e89555cc0cc3eb8d7743fe94c2d
push id24372
push useremorley@mozilla.com
push dateWed, 27 Feb 2013 13:22:59 +0000
treeherdermozilla-central@0a91da5f5eab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs845441
milestone22.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 845441: Remove DEBUG_CC. r=mccr8
xpcom/base/nsCycleCollector.cpp
xpcom/base/nsCycleCollector.h
xpcom/glue/nsISupportsImpl.h
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -146,21 +146,17 @@
 #include "mozilla/StandardInteger.h"
 #include "mozilla/Telemetry.h"
 
 using namespace mozilla;
 
 //#define COLLECT_TIME_DEBUG
 
 #define DEFAULT_SHUTDOWN_COLLECTIONS 5
-#ifdef DEBUG_CC
-#define SHUTDOWN_COLLECTIONS(params) params.mShutdownCollections
-#else
 #define SHUTDOWN_COLLECTIONS(params) DEFAULT_SHUTDOWN_COLLECTIONS
-#endif
 
 #if defined(XP_WIN)
 // Defined in nsThreadManager.cpp.
 extern DWORD gTLSThreadIDIndex;
 #elif defined(NS_TLS)
 // Defined in nsThreadManager.cpp.
 extern NS_TLS mozilla::threads::ID gTLSThreadID;
 #else
@@ -173,18 +169,18 @@ PRThread* gCycleCollectorThread = nullpt
 //
 // XPCOM_CC_LOG_SHUTDOWN: If defined, log cycle collector heaps at shutdown.
 //
 // XPCOM_CC_ALL_TRACES_AT_SHUTDOWN: If defined, any cycle collector
 // logging done at shutdown will be WantAllTraces, which disables
 // various cycle collector optimizations to give a fuller picture of
 // the heap.
 //
-// XPCOM_CC_RUN_DURING_SHUTDOWN: In non-DEBUG or non-DEBUG_CC builds,
-// if this is set, run cycle collections at shutdown.
+// XPCOM_CC_RUN_DURING_SHUTDOWN: In non-DEBUG or builds, if this is set,
+// run cycle collections at shutdown.
 //
 // MOZ_CC_LOG_DIRECTORY: The directory in which logs are placed (such as
 // logs from XPCOM_CC_LOG_ALL and XPCOM_CC_LOG_SHUTDOWN, or other uses
 // of nsICycleCollectorListener)
 
 MOZ_NEVER_INLINE void
 CC_AbortIfNull(void *ptr)
 {
@@ -196,102 +192,26 @@ CC_AbortIfNull(void *ptr)
 // variables.
 
 struct nsCycleCollectorParams
 {
     bool mLogAll;
     bool mLogShutdown;
     bool mAllTracesAtShutdown;
     bool mDoNothing;
-#ifdef DEBUG_CC
-    bool mReportStats;
-    bool mLogPointers;
-    uint32_t mShutdownCollections;
-#endif
     
     nsCycleCollectorParams() :
         mLogAll      (PR_GetEnv("XPCOM_CC_LOG_ALL") != NULL),
         mLogShutdown (PR_GetEnv("XPCOM_CC_LOG_SHUTDOWN") != NULL),
         mAllTracesAtShutdown (PR_GetEnv("XPCOM_CC_ALL_TRACES_AT_SHUTDOWN") != NULL),
-#ifdef DEBUG_CC
-        mDoNothing   (PR_GetEnv("XPCOM_CC_DO_NOTHING") != NULL),
-        mReportStats (PR_GetEnv("XPCOM_CC_REPORT_STATS") != NULL),
-        mLogPointers (PR_GetEnv("XPCOM_CC_LOG_POINTERS") != NULL),
-        mShutdownCollections(DEFAULT_SHUTDOWN_COLLECTIONS)
-#else
         mDoNothing   (false)
-#endif
     {
-#ifdef DEBUG_CC
-        char *s = PR_GetEnv("XPCOM_CC_SHUTDOWN_COLLECTIONS");
-        if (s)
-            PR_sscanf(s, "%d", &mShutdownCollections);
-#endif
     }
 };
 
-#ifdef DEBUG_CC
-// Various operations involving the collector are recorded in a
-// statistics table. These are for diagnostics.
-
-struct nsCycleCollectorStats
-{
-    uint32_t mFailedQI;
-    uint32_t mSuccessfulQI;
-
-    uint32_t mVisitedNode;
-    uint32_t mWalkedGraph;
-    uint32_t mFreedBytes;
-
-    uint32_t mSetColorBlack;
-    uint32_t mSetColorWhite;
-
-    uint32_t mFailedUnlink;
-    uint32_t mCollectedNode;
-
-    uint32_t mSuspectNode;
-    uint32_t mForgetNode;
-  
-    uint32_t mCollection;
-
-    nsCycleCollectorStats()
-    {
-        memset(this, 0, sizeof(nsCycleCollectorStats));
-    }
-  
-    void Dump()
-    {
-        fprintf(stderr, "\f\n");
-#define DUMP(entry) fprintf(stderr, "%30.30s: %-20.20d\n", #entry, entry)
-        DUMP(mFailedQI);
-        DUMP(mSuccessfulQI);
-    
-        DUMP(mVisitedNode);
-        DUMP(mWalkedGraph);
-        DUMP(mFreedBytes);
-    
-        DUMP(mSetColorBlack);
-        DUMP(mSetColorWhite);
-    
-        DUMP(mFailedUnlink);
-        DUMP(mCollectedNode);
-    
-        DUMP(mSuspectNode);
-        DUMP(mForgetNode);
-    
-        DUMP(mCollection);
-#undef DUMP
-    }
-};
-#endif
-
-#ifdef DEBUG_CC
-static bool nsCycleCollector_shouldSuppress(nsISupports *s);
-#endif
-
 #ifdef COLLECT_TIME_DEBUG
 class TimeLog
 {
 public:
     TimeLog() : mLastCheckpoint(TimeStamp::Now()) {}
 
     void
     Checkpoint(const char* aEvent)
@@ -478,40 +398,28 @@ struct PtrInfo
     nsCycleCollectionParticipant *mParticipant;
     uint32_t mColor : 2;
     uint32_t mInternalRefs : 30;
     uint32_t mRefCount;
 private:
     EdgePool::Iterator mFirstChild;
 
 public:
-#ifdef DEBUG_CC
-    char *mName;
-#endif
 
     PtrInfo(void *aPointer, nsCycleCollectionParticipant *aParticipant)
         : mPointer(aPointer),
           mParticipant(aParticipant),
           mColor(grey),
           mInternalRefs(0),
           mRefCount(0),
           mFirstChild()
-#ifdef DEBUG_CC
-        , mName(nullptr)
-#endif
     {
         MOZ_ASSERT(aParticipant);
     }
 
-#ifdef DEBUG_CC
-    void Destroy() {
-        PL_strfree(mName);
-    }
-#endif
-
     // Allow NodePool::Block's constructor to compile.
     PtrInfo() {
         NS_NOTREACHED("should never be called");
     }
 
     EdgePool::Iterator FirstChild()
     {
         return mFirstChild;
@@ -564,24 +472,16 @@ public:
 
     ~NodePool()
     {
         MOZ_ASSERT(!mBlocks, "Didn't call Clear()?");
     }
 
     void Clear()
     {
-#ifdef DEBUG_CC
-        {
-            Enumerator queue(*this);
-            while (!queue.IsDone()) {
-                queue.GetNext()->Destroy();
-            }
-        }
-#endif
         Block *b = mBlocks;
         while (b) {
             Block *n = b->mNext;
             NS_Free(b);
             b = n;
         }
 
         mBlocks = nullptr;
@@ -754,57 +654,39 @@ private:
         // Try to match the size of a jemalloc bucket, to minimize slop bytes.
         // - On 32-bit platforms sizeof(nsPurpleBufferEntry) is 12, so mEntries
         //   is 16,380 bytes, which leaves 4 bytes for mNext.
         // - On 64-bit platforms sizeof(nsPurpleBufferEntry) is 24, so mEntries
         //   is 32,544 bytes, which leaves 8 bytes for mNext.
         nsPurpleBufferEntry mEntries[1365];
 
         Block() : mNext(nullptr) {
-#ifndef DEBUG_CC
             // Ensure Block is the right size (see above).
             MOZ_STATIC_ASSERT(
                 sizeof(Block) == 16384 ||       // 32-bit
                 sizeof(Block) == 32768,         // 64-bit
                 "ill-sized nsPurpleBuffer::Block"
             );
-#endif
         }
         void StaticAsserts();
     };
 public:
     // This class wraps a linked list of the elements in the purple
     // buffer.
 
     nsCycleCollectorParams &mParams;
     uint32_t mCount;
     Block mFirstBlock;
     nsPurpleBufferEntry *mFreeList;
 
-#ifdef DEBUG_CC
-    PointerSet mNormalObjects; // duplicates our blocks
-    nsCycleCollectorStats &mStats;
-#endif
-
-#ifdef DEBUG_CC
-    nsPurpleBuffer(nsCycleCollectorParams &params,
-                   nsCycleCollectorStats &stats)
-        : mParams(params),
-          mStats(stats)
-    {
-        InitBlocks();
-        mNormalObjects.Init();
-    }
-#else
     nsPurpleBuffer(nsCycleCollectorParams &params)
         : mParams(params)
     {
         InitBlocks();
     }
-#endif
 
     ~nsPurpleBuffer()
     {
         FreeBlocks();
     }
 
     void InitBlocks()
     {
@@ -870,23 +752,16 @@ public:
     // nsPurpleBufferEntry::mObject is null or if the object's
     // nsXPCOMCycleCollectionParticipant::CanSkip() returns true or
     // if nsPurpleBufferEntry::mNotPurple is true.
     // 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(bool removeChildlessNodes);
 
-#ifdef DEBUG_CC
-    bool Exists(void *p) const
-    {
-        return mNormalObjects.GetEntry(p);
-    }
-#endif
-
     nsPurpleBufferEntry* NewEntry()
     {
         if (!mFreeList) {
             Block *b = new Block;
             if (!b) {
                 return nullptr;
             }
             StartBlock(b);
@@ -918,20 +793,16 @@ public:
         // Caller is responsible for filling in result's mRefCnt.
         return e;
     }
 
     void Remove(nsPurpleBufferEntry *e)
     {
         MOZ_ASSERT(mCount != 0, "must have entries");
 
-#ifdef DEBUG_CC
-        mNormalObjects.RemoveEntry(e->mObject);
-#endif
-
         e->mNextInFreeList =
             (nsPurpleBufferEntry*)(uintptr_t(mFreeList) | uintptr_t(1));
         mFreeList = e;
 
         --mCount;
     }
 
     uint32_t Count() const
@@ -949,50 +820,30 @@ public:
             n += aMallocSizeOf(block);
             block = block->mNext;
         }
 
         // These fields are deliberately not measured:
         // - mParams: because it only contains scalars.
         // - mFreeList: because it points into the purple buffer, which is
         //   within mFirstBlock and thus within |this|.
-        // - mNormalObjects, mStats: because they're DEBUG_CC-only.
         //
         // We also don't measure the things pointed to by mEntries[] because
         // those pointers are non-owning.
 
         return n;
     }
 };
 
 static bool
 AddPurpleRoot(GCGraphBuilder &builder, void *root, nsCycleCollectionParticipant *cp);
 
 void
 nsPurpleBuffer::SelectPointers(GCGraphBuilder &aBuilder)
 {
-#ifdef DEBUG_CC
-    // Can't use mCount here, since it may include null entries.
-    uint32_t realCount = 0;
-    for (Block *b = &mFirstBlock; b; b = b->mNext) {
-        for (nsPurpleBufferEntry *e = b->mEntries,
-                              *eEnd = ArrayEnd(b->mEntries);
-            e != eEnd; ++e) {
-            if (!(uintptr_t(e->mObject) & uintptr_t(1))) {
-                if (e->mObject && !e->mNotPurple) {
-                    ++realCount;
-                }
-            }
-        }
-    }
-
-    NS_ABORT_IF_FALSE(mNormalObjects.Count() == realCount,
-                      "count out of sync");
-#endif
-
     // Walk through all the blocks.
     for (Block *b = &mFirstBlock; b; b = b->mNext) {
         for (nsPurpleBufferEntry *e = b->mEntries,
                               *eEnd = ArrayEnd(b->mEntries);
             e != eEnd; ++e) {
             if (!(uintptr_t(e->mObject) & uintptr_t(1))) {
                 // This is a real entry (rather than something on the
                 // free list).
@@ -1095,24 +946,16 @@ struct nsCycleCollector
     }
 
     void SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
                              size_t *aObjectSize,
                              size_t *aGraphNodesSize,
                              size_t *aGraphEdgesSize,
                              size_t *aWhiteNodeSize,
                              size_t *aPurpleBufferSize) const;
-
-#ifdef DEBUG_CC
-    nsCycleCollectorStats mStats;
-    FILE *mPtrLog;
-
-    bool LogPurpleAddition(void* aObject, nsCycleCollectionParticipant *cp);
-    void LogPurpleRemoval(void* aObject);
-#endif
 };
 
 
 /**
  * GraphWalker is templatized over a Visitor class that must provide
  * the following two methods:
  *
  * bool ShouldVisitNode(PtrInfo const *pi);
@@ -1153,47 +996,21 @@ Fault(const char *msg, const void *ptr=n
     if (ptr)
         printf("Fault in cycle collector: %s (ptr: %p)\n", msg, ptr);
     else
         printf("Fault in cycle collector: %s\n", msg);
 
     NS_RUNTIMEABORT("cycle collector fault");
 }
 
-#ifdef DEBUG_CC
-static void
-Fault(const char *msg, PtrInfo *pi)
-{
-    printf("Fault in cycle collector: %s\n"
-           "  while operating on pointer %p %s\n",
-           msg, pi->mPointer, pi->mName);
-    if (pi->mInternalRefs) {
-        printf("  which has internal references from:\n");
-        NodePool::Enumerator queue(sCollector->mGraph.mNodes);
-        while (!queue.IsDone()) {
-            PtrInfo *ppi = queue.GetNext();
-            for (EdgePool::Iterator e = ppi->FirstChild(),
-                                e_end = ppi->LastChild();
-                 e != e_end; ++e) {
-                if (*e == pi) {
-                    printf("    %p %s\n", ppi->mPointer, ppi->mName);
-                }
-            }
-        }
-    }
-
-    Fault(msg, pi->mPointer);
-}
-#else
 static void
 Fault(const char *msg, PtrInfo *pi)
 {
     Fault(msg, pi->mPointer);
 }
-#endif
 
 static inline void
 AbortIfOffMainThreadIfCheckFast()
 {
 #if defined(XP_WIN) || defined(NS_TLS)
     if (!NS_IsMainThread() && !NS_IsCycleCollectorThread()) {
         NS_RUNTIMEABORT("Main-thread-only object used off the main thread");
     }
@@ -1203,22 +1020,16 @@ AbortIfOffMainThreadIfCheckFast()
 static inline void
 ToParticipant(nsISupports *s, nsXPCOMCycleCollectionParticipant **cp)
 {
     // We use QI to move from an nsISupports to an
     // nsXPCOMCycleCollectionParticipant, which is a per-class singleton helper
     // object that implements traversal and unlinking logic for the nsISupports
     // in question.
     CallQueryInterface(s, cp);
-#ifdef DEBUG_CC
-    if (cp)
-        ++sCollector->mStats.mSuccessfulQI;
-    else
-        ++sCollector->mStats.mFailedQI;
-#endif
 }
 
 template <class Visitor>
 MOZ_NEVER_INLINE void
 GraphWalker<Visitor>::Walk(PtrInfo *s0)
 {
     nsDeque queue;
     CC_AbortIfNull(s0);
@@ -1255,20 +1066,16 @@ GraphWalker<Visitor>::DoWalk(nsDeque &aQ
             for (EdgePool::Iterator child = pi->FirstChild(),
                                 child_end = pi->LastChild();
                  child != child_end; ++child) {
                 CC_AbortIfNull(*child);
                 aQueue.Push(*child);
             }
         }
     };
-
-#ifdef DEBUG_CC
-    sCollector->mStats.mWalkedGraph++;
-#endif
 }
 
 struct CCGraphDescriber
 {
   CCGraphDescriber()
   : mAddress("0x"), mToAddress("0x"), mCnt(0), mType(eUnknown) {}
 
   enum Type
@@ -1717,20 +1524,16 @@ public:
     PtrInfo* AddWeakMapNode(void* node);
     void Traverse(PtrInfo* aPtrInfo);
     void SetLastChild();
 
 private:
     void DescribeNode(uint32_t refCount, const char *objName)
     {
         mCurrPi->mRefCount = refCount;
-#ifdef DEBUG_CC
-        mCurrPi->mName = PL_strdup(objName);
-        sCollector->mStats.mVisitedNode++;
-#endif
     }
 
 public:
     // nsCycleCollectionTraversalCallback methods.
     NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt refCount,
                                              const char *objName);
     NS_IMETHOD_(void) DescribeGCedNode(bool isMarked, const char *objName);
 
@@ -1799,20 +1602,16 @@ GCGraphBuilder::GCGraphBuilder(GCGraph &
                            sizeof(PtrToNodeEntry), 32768))
         mPtrToNodeMap.ops = nullptr;
 
     if (aJSRuntime) {
         mJSParticipant = aJSRuntime->GetParticipant();
     }
 
     uint32_t flags = 0;
-#ifdef DEBUG_CC
-    flags = nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
-            nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
-#endif
     if (!flags && mListener) {
         flags = nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO;
         bool all = false;
         mListener->GetWantAllTraces(&all);
         if (all) {
             flags |= nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
         }
     }
@@ -1858,23 +1657,16 @@ GCGraphBuilder::AddNode(void *s, nsCycle
     return result;
 }
 
 MOZ_NEVER_INLINE void
 GCGraphBuilder::Traverse(PtrInfo* aPtrInfo)
 {
     mCurrPi = aPtrInfo;
 
-#ifdef DEBUG_CC
-    if (!mCurrPi->mParticipant) {
-        Fault("unknown pointer during walk", aPtrInfo);
-        return;
-    }
-#endif
-
     mCurrPi->SetFirstChild(mEdgeBuilder.Mark());
 
     nsresult rv = aPtrInfo->mParticipant->Traverse(aPtrInfo->mPointer, *this);
     if (NS_FAILED(rv)) {
         Fault("script pointer traversal failed", aPtrInfo);
     }
 }
 
@@ -1886,21 +1678,16 @@ GCGraphBuilder::SetLastChild()
 
 NS_IMETHODIMP_(void)
 GCGraphBuilder::NoteXPCOMRoot(nsISupports *root)
 {
     root = CanonicalizeXPCOMParticipant(root);
     NS_ASSERTION(root,
                  "Don't add objects that don't participate in collection!");
 
-#ifdef DEBUG_CC
-    if (nsCycleCollector_shouldSuppress(root))
-        return;
-#endif
-
     nsXPCOMCycleCollectionParticipant *cp;
     ToParticipant(root, &cp);
 
     NoteRoot(root, cp);
 }
 
 NS_IMETHODIMP_(void)
 GCGraphBuilder::NoteJSRoot(void *root)
@@ -1955,21 +1742,16 @@ GCGraphBuilder::NoteXPCOMChild(nsISuppor
     nsCString edgeName;
     if (WantDebugInfo()) {
         edgeName.Assign(mNextEdgeName);
         mNextEdgeName.Truncate();
     }
     if (!child || !(child = CanonicalizeXPCOMParticipant(child)))
         return;
 
-#ifdef DEBUG_CC
-    if (nsCycleCollector_shouldSuppress(child))
-        return;
-#endif
-
     nsXPCOMCycleCollectionParticipant *cp;
     ToParticipant(child, &cp);
     if (cp && (!cp->CanSkipThis(child) || WantAllTraces())) {
         NoteChild(child, cp, edgeName);
     }
 }
 
 NS_IMETHODIMP_(void)
@@ -2210,19 +1992,16 @@ struct ScanBlackVisitor
         return pi->mColor != black;
     }
 
     MOZ_NEVER_INLINE void VisitNode(PtrInfo *pi)
     {
         if (pi->mColor == white)
             --mWhiteNodeCount;
         pi->mColor = black;
-#ifdef DEBUG_CC
-        sCollector->mStats.mSetColorBlack++;
-#endif
     }
 
     uint32_t &mWhiteNodeCount;
 };
 
 
 struct scanVisitor
 {
@@ -2238,19 +2017,16 @@ struct scanVisitor
     MOZ_NEVER_INLINE void VisitNode(PtrInfo *pi)
     {
         if (pi->mInternalRefs > pi->mRefCount && pi->mRefCount > 0)
             Fault("traversed refs exceed refcount", pi);
 
         if (pi->mInternalRefs == pi->mRefCount || pi->mRefCount == 0) {
             pi->mColor = white;
             ++mWhiteNodeCount;
-#ifdef DEBUG_CC
-            sCollector->mStats.mSetColorWhite++;
-#endif
         } else {
             GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(mWhiteNodeCount)).Walk(pi);
             MOZ_ASSERT(pi->mColor == black,
                        "Why didn't ScanBlackVisitor make pi black?");
         }
     }
 
     uint32_t &mWhiteNodeCount;
@@ -2301,29 +2077,16 @@ nsCycleCollector::ScanRoots()
     mWhiteNodeCount = 0;
 
     // On the assumption that most nodes will be black, it's
     // probably faster to use a GraphWalker than a
     // NodePool::Enumerator.
     GraphWalker<scanVisitor>(scanVisitor(mWhiteNodeCount)).WalkFromRoots(mGraph); 
 
     ScanWeakMaps();
-
-#ifdef DEBUG_CC
-    // Sanity check: scan should have colored all grey nodes black or
-    // white. So we ensure we have no grey nodes at this point.
-    NodePool::Enumerator etor(mGraph.mNodes);
-    while (!etor.IsDone())
-    {
-        PtrInfo *pinfo = etor.GetNext();
-        if (pinfo->mColor == grey) {
-            Fault("valid grey node after scanning", pinfo);
-        }
-    }
-#endif
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // Bacon & Rajan's |CollectWhite| routine, somewhat modified.
 ////////////////////////////////////////////////////////////////////////
 
 bool
@@ -2377,20 +2140,16 @@ nsCycleCollector::CollectWhite(nsICycleC
     }
 
     timeLog.Checkpoint("CollectWhite::Root");
 
     if (mBeforeUnlinkCB) {
         mBeforeUnlinkCB();
         timeLog.Checkpoint("CollectWhite::BeforeUnlinkCB");
     }
-#if defined(DEBUG_CC) && !defined(__MINGW32__) && defined(WIN32)
-    struct _CrtMemState ms1, ms2;
-    _CrtMemCheckpoint(&ms1);
-#endif
 
     if (aListener) {
         for (uint32_t i = 0; i < count; ++i) {
             PtrInfo *pinfo = mWhiteNodes->ElementAt(i);
             aListener->DescribeGarbage((uint64_t)pinfo->mPointer);
         }
         aListener->End();
     }
@@ -2406,42 +2165,28 @@ nsCycleCollector::CollectWhite(nsICycleC
 #ifdef DEBUG
         if (mJSRuntime) {
             mJSRuntime->SetObjectToUnlink(nullptr);
             mJSRuntime->AssertNoObjectsToTrace(pinfo->mPointer);
         }
 #endif
         if (NS_FAILED(rv)) {
             Fault("Failed unlink call while unlinking", pinfo);
-#ifdef DEBUG_CC
-            mStats.mFailedUnlink++;
-#endif
-        }
-        else {
-#ifdef DEBUG_CC
-            ++mStats.mCollectedNode;
-#endif
         }
     }
     timeLog.Checkpoint("CollectWhite::Unlink");
 
     for (uint32_t i = 0; i < count; ++i) {
         PtrInfo *pinfo = mWhiteNodes->ElementAt(i);
         rv = pinfo->mParticipant->Unroot(pinfo->mPointer);
         if (NS_FAILED(rv))
             Fault("Failed unroot call while unlinking", pinfo);
     }
     timeLog.Checkpoint("CollectWhite::Unroot");
 
-#if defined(DEBUG_CC) && !defined(__MINGW32__) && defined(WIN32)
-    _CrtMemCheckpoint(&ms2);
-    if (ms2.lTotalCount < ms1.lTotalCount)
-        mStats.mFreedBytes += (ms1.lTotalCount - ms2.lTotalCount);
-#endif
-
     return count > 0;
 }
 
 
 ////////////////////////
 // Memory reporter
 ////////////////////////
 
@@ -2533,22 +2278,17 @@ nsCycleCollector::nsCycleCollector() :
     mJSRuntime(nullptr),
     mWhiteNodes(nullptr),
     mWhiteNodeCount(0),
     mVisitedRefCounted(0),
     mVisitedGCed(0),
     mBeforeUnlinkCB(nullptr),
     mForgetSkippableCB(nullptr),
     mReporter(nullptr),
-#ifdef DEBUG_CC
-    mPurpleBuf(mParams, mStats),
-    mPtrLog(nullptr)
-#else
     mPurpleBuf(mParams)
-#endif
 {
 }
 
 
 nsCycleCollector::~nsCycleCollector()
 {
     NS_UnregisterMemoryMultiReporter(mReporter);
 }
@@ -2582,85 +2322,16 @@ nsCycleCollector::ForgetJSRuntime()
         return;
 
     if (!mJSRuntime)
         Fault("forgetting non-registered cycle collector JS runtime");
 
     mJSRuntime = nullptr;
 }
 
-#ifdef DEBUG_CC
-
-class Suppressor :
-    public nsCycleCollectionTraversalCallback
-{
-protected:
-    static char *sSuppressionList;
-    static bool sInitialized;
-    bool mSuppressThisNode;
-public:
-    Suppressor()
-    {
-    }
-
-    bool shouldSuppress(nsISupports *s)
-    {
-        if (!sInitialized) {
-            sSuppressionList = PR_GetEnv("XPCOM_CC_SUPPRESS");
-            sInitialized = true;
-        }
-        if (sSuppressionList == nullptr) {
-            mSuppressThisNode = false;
-        } else {
-            nsresult rv;
-            nsXPCOMCycleCollectionParticipant *cp;
-            rv = CallQueryInterface(s, &cp);
-            if (NS_FAILED(rv)) {
-                Fault("checking suppression on wrong type of pointer", s);
-                return true;
-            }
-            cp->Traverse(s, *this);
-        }
-        return mSuppressThisNode;
-    }
-
-    NS_IMETHOD_(void) DescribeRefCountedNode(nsrefcnt refCount,
-                                             const char *objName)
-    {
-        mSuppressThisNode = (PL_strstr(sSuppressionList, objName) != nullptr);
-    }
-
-    NS_IMETHOD_(void) DescribeGCedNode(bool isMarked, const char *objName)
-    {
-        mSuppressThisNode = (PL_strstr(sSuppressionList, objName) != nullptr);
-    }
-
-    NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) {}
-    NS_IMETHOD_(void) NoteJSRoot(void *root) {}
-    NS_IMETHOD_(void) NoteNativeRoot(void *root,
-                                     nsCycleCollectionParticipant *participant) {}
-    NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child) {}
-    NS_IMETHOD_(void) NoteJSChild(void *child) {}
-    NS_IMETHOD_(void) NoteNativeChild(void *child,
-                                     nsCycleCollectionParticipant *participant) {}
-    NS_IMETHOD_(void) NoteNextEdgeName(const char* name) {}
-    NS_IMETHOD_(void) NoteWeakMapping(void *map, void *key, void *kdelegate, void *val) {}
-};
-
-char *Suppressor::sSuppressionList = nullptr;
-bool Suppressor::sInitialized = false;
-
-static bool
-nsCycleCollector_shouldSuppress(nsISupports *s)
-{
-    Suppressor supp;
-    return supp.shouldSuppress(s);
-}
-#endif
-
 #ifdef DEBUG
 static bool
 nsCycleCollector_isScanSafe(void *s, nsCycleCollectionParticipant *cp)
 {
     if (!s)
         return false;
 
     if (cp)
@@ -2686,21 +2357,16 @@ nsCycleCollector::Suspect2(void *n, nsCy
         return nullptr;
 
     MOZ_ASSERT(nsCycleCollector_isScanSafe(n, cp),
                "suspected a non-scansafe pointer");
 
     if (mParams.mDoNothing)
         return nullptr;
 
-#ifdef DEBUG_CC
-    if (!LogPurpleAddition(n, cp))
-        return nullptr;
-#endif
-
     // Caller is responsible for filling in result's mRefCnt.
     return mPurpleBuf.Put(n, cp);
 }
 
 
 bool
 nsCycleCollector::Forget2(nsPurpleBufferEntry *e)
 {
@@ -2708,85 +2374,20 @@ nsCycleCollector::Forget2(nsPurpleBuffer
 
     // Re-entering ::Forget 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)
         return false;
 
-#ifdef DEBUG_CC
-    LogPurpleRemoval(e->mObject);
-#endif
-
     mPurpleBuf.Remove(e);
     return true;
 }
 
-#ifdef DEBUG_CC
-void
-nsCycleCollector_logPurpleAddition(void* aObject,
-                                   nsCycleCollectionParticipant *cp)
-{
-    if (sCollector) {
-        sCollector->LogPurpleAddition(aObject, cp);
-    }
-}
-
-bool
-nsCycleCollector::LogPurpleAddition(void* aObject,
-                                    nsCycleCollectionParticipant *cp)
-{
-
-    if (mScanInProgress)
-        return false;
-
-    if (mParams.mDoNothing)
-        return false;
-
-    mStats.mSuspectNode++;
-
-    if (!cp &&
-        nsCycleCollector_shouldSuppress(static_cast<nsISupports *>(aObject)))
-        return false;
-
-    if (mParams.mLogPointers) {
-        if (!mPtrLog)
-            mPtrLog = fopen("pointer_log", "w");
-        fprintf(mPtrLog, "S %p\n", static_cast<void*>(aObject));
-    }
-
-    mPurpleBuf.mNormalObjects.PutEntry(aObject);
-    return true;
-}
-
-void
-nsCycleCollector_logPurpleRemoval(void* aObject)
-{
-    if (sCollector) {
-        sCollector->LogPurpleRemoval(aObject);
-    }
-}
-
-void
-nsCycleCollector::LogPurpleRemoval(void* aObject)
-{
-    AbortIfOffMainThreadIfCheckFast();
-
-    mStats.mForgetNode++;
-
-    if (mParams.mLogPointers) {
-        if (!mPtrLog)
-            mPtrLog = fopen("pointer_log", "w");
-        fprintf(mPtrLog, "F %p\n", aObject);
-    }
-    mPurpleBuf.mNormalObjects.RemoveEntry(aObject);
-}
-#endif
-
 // The cycle collector uses the mark bitmap to discover what JS objects
 // were reachable only from XPConnect roots that might participate in
 // cycles. We ask the JS runtime whether we need to force a GC before
 // this CC. It returns true on startup (before the mark bits have been set),
 // and also when UnmarkGray has run out of stack.  We also force GCs on shut 
 // down to collect cycles involving both DOM and JS.
 void
 nsCycleCollector::FixGrayBits(bool aForceGC)
@@ -2930,40 +2531,18 @@ nsCycleCollector::BeginCollection(bool a
     if (!builder.Initialized())
         return false;
 
     if (mJSRuntime) {
         mJSRuntime->BeginCycleCollection(builder);
         timeLog.Checkpoint("mJSRuntime->BeginCycleCollection()");
     }
 
-#ifdef DEBUG_CC
-    uint32_t purpleStart = builder.Count();
-#endif
     mScanInProgress = true;
     SelectPurple(builder);
-#ifdef DEBUG_CC
-    uint32_t purpleEnd = builder.Count();
-
-    if (purpleStart != purpleEnd) {
-        if (mParams.mLogPointers && !mPtrLog)
-            mPtrLog = fopen("pointer_log", "w");
-
-        uint32_t i = 0;
-        NodePool::Enumerator queue(mGraph.mNodes);
-        while (i++ < purpleStart) {
-            queue.GetNext();
-        }
-        while (i++ < purpleEnd) {
-            mStats.mForgetNode++;
-            if (mParams.mLogPointers)
-                fprintf(mPtrLog, "F %p\n", queue.GetNext()->mPointer);
-        }
-    }
-#endif
 
     timeLog.Checkpoint("SelectPurple()");
 
     if (builder.Count() > 0) {
         // The main Bacon & Rajan collection algorithm.
 
         MarkRoots(builder);
         timeLog.Checkpoint("MarkRoots()");
@@ -2983,35 +2562,16 @@ nsCycleCollector::BeginCollection(bool a
                     pi->mRefCount > 0 && pi->mRefCount < UINT32_MAX &&
                     pi->mInternalRefs != pi->mRefCount) {
                     aListener->DescribeRoot((uint64_t)pi->mPointer,
                                             pi->mInternalRefs);
                 }
             }
         }
 
-#ifdef DEBUG_CC
-        if (mFollowupCollection && purpleStart != purpleEnd) {
-            uint32_t i = 0;
-            NodePool::Enumerator queue(mGraph.mNodes);
-            while (i++ < purpleStart) {
-                queue.GetNext();
-            }
-            while (i++ < purpleEnd) {
-                PtrInfo *pi = queue.GetNext();
-                if (pi->mColor == white) {
-                    printf("nsCycleCollector: a later shutdown collection collected the additional\n"
-                           "  suspect %p %s\n"
-                           "  (which could be fixed by improving traversal)\n",
-                           pi->mPointer, pi->mName);
-                }
-            }
-        }
-#endif
-
         if (mJSRuntime) {
             mJSRuntime->FinishTraverse();
             timeLog.Checkpoint("mJSRuntime->FinishTraverse()");
         }
     } else {
         mScanInProgress = false;
     }
 
@@ -3020,38 +2580,18 @@ nsCycleCollector::BeginCollection(bool a
 
 bool
 nsCycleCollector::FinishCollection(nsICycleCollectorListener *aListener)
 {
     TimeLog timeLog;
     bool collected = CollectWhite(aListener);
     timeLog.Checkpoint("CollectWhite()");
 
-#ifdef DEBUG_CC
-    mStats.mCollection++;
-    if (mParams.mReportStats)
-        mStats.Dump();
-#endif
-
     mFollowupCollection = true;
 
-#ifdef DEBUG_CC
-    uint32_t i, count = mWhiteNodes->Length();
-    for (i = 0; i < count; ++i) {
-        PtrInfo *pinfo = mWhiteNodes->ElementAt(i);
-        if (mPurpleBuf.Exists(pinfo->mPointer)) {
-            printf("nsCycleCollector: %s object @%p is still alive after\n"
-                   "  calling RootAndUnlinkJSObjects, Unlink, and Unroot on"
-                   " it!  This probably\n"
-                   "  means the Unlink implementation was insufficient.\n",
-                   pinfo->mName, pinfo->mPointer);
-        }
-    }
-#endif
-
     mWhiteNodes->Clear();
     ClearGraph();
     timeLog.Checkpoint("ClearGraph()");
 
     mParams.mDoNothing = false;
 
     return collected;
 }
@@ -3061,42 +2601,29 @@ nsCycleCollector::SuspectedCount()
 {
     return mPurpleBuf.Count();
 }
 
 void
 nsCycleCollector::Shutdown()
 {
 #ifndef DEBUG
-#ifndef DEBUG_CC
     if (PR_GetEnv("XPCOM_CC_RUN_DURING_SHUTDOWN"))
 #endif
-#endif
     {
         nsCOMPtr<nsCycleCollectorLogger> listener;
         if (mParams.mLogAll || mParams.mLogShutdown) {
             listener = new nsCycleCollectorLogger();
             if (mParams.mAllTracesAtShutdown) {
                 listener->SetAllTraces();
             }
         }
         Collect(false, nullptr,  SHUTDOWN_COLLECTIONS(mParams), listener);
     }
 
-#ifdef DEBUG_CC
-    GCGraphBuilder builder(mGraph, mJSRuntime, nullptr, false);
-    mScanInProgress = true;
-    SelectPurple(builder);
-    mScanInProgress = false;
-    if (builder.Count() != 0) {
-        printf("Might have been able to release more cycles if the cycle collector would "
-               "run once more at shutdown.\n");
-    }
-    ClearGraph();
-#endif
     mParams.mDoNothing = true;
 }
 
 void
 nsCycleCollector::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf,
                                       size_t *aObjectSize,
                                       size_t *aGraphNodesSize,
                                       size_t *aGraphEdgesSize,
@@ -3114,17 +2641,16 @@ nsCycleCollector::SizeOfIncludingThis(ns
                     : 0;
 
     *aPurpleBufferSize = mPurpleBuf.SizeOfExcludingThis(aMallocSizeOf);
 
     // These fields are deliberately not measured:
     // - mResults: because it's tiny and only contains scalars.
     // - mJSRuntime: because it's non-owning and measured by JS reporters.
     // - mParams: because it only contains scalars.
-    // - mStats, mPtrLog: because they're DEBUG_CC-only.
 }
 
 
 ////////////////////////////////////////////////////////////////////////
 // Module public API (exported in nsCycleCollector.h)
 // Just functions that redirect into the singleton, once it's built.
 ////////////////////////////////////////////////////////////////////////
 
--- a/xpcom/base/nsCycleCollector.h
+++ b/xpcom/base/nsCycleCollector.h
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef nsCycleCollector_h__
 #define nsCycleCollector_h__
 
-//#define DEBUG_CC
-
 class nsISupports;
 class nsICycleCollectorListener;
 class nsCycleCollectionParticipant;
 class nsCycleCollectionTraversalCallback;
 
 // Contains various stats about the cycle collection.
 class nsCycleCollectorResults
 {
@@ -32,22 +30,16 @@ nsresult nsCycleCollector_startup();
 typedef void (*CC_BeforeUnlinkCallback)(void);
 void nsCycleCollector_setBeforeUnlinkCallback(CC_BeforeUnlinkCallback aCB);
 
 typedef void (*CC_ForgetSkippableCallback)(void);
 void nsCycleCollector_setForgetSkippableCallback(CC_ForgetSkippableCallback aCB);
 
 void nsCycleCollector_forgetSkippable(bool aRemoveChildlessNodes = false);
 
-#ifdef DEBUG_CC
-void nsCycleCollector_logPurpleAddition(void* aObject,
-                                        nsCycleCollectionParticipant* cp);
-void nsCycleCollector_logPurpleRemoval(void* aObject);
-#endif
-
 void nsCycleCollector_collect(bool aMergeCompartments,
                               nsCycleCollectorResults *aResults,
                               nsICycleCollectorListener *aListener);
 uint32_t nsCycleCollector_suspectedCount();
 void nsCycleCollector_shutdownThreads();
 void nsCycleCollector_shutdown();
 
 // Various methods the cycle collector needs to deal with Javascript.
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -140,22 +140,16 @@ public:
     }
 
     nsrefcnt refcount;
     if (HasPurpleBufferEntry()) {
       nsPurpleBufferEntry *e = NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged);
       MOZ_ASSERT(e->mObject == owner, "wrong entry");
       MOZ_ASSERT(int32_t(e->mRefCnt) > 0, "purple ISupports with bad refcnt");
       refcount = ++(e->mRefCnt);
-#ifdef DEBUG_CC
-      if (!e->mNotPurple) {
-        nsCycleCollector_logPurpleRemoval(
-          NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject);
-      }
-#endif
       e->mNotPurple = true;
     } else {
       refcount = NS_CCAR_TAGGED_TO_REFCNT(mTagged);
       MOZ_ASSERT(int32_t(refcount) >= 0, "bad refcount");
       ++refcount;
       mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
     }
 
@@ -179,29 +173,19 @@ public:
 
     nsrefcnt refcount;
     if (HasPurpleBufferEntry()) {
       nsPurpleBufferEntry *e = NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged);
       MOZ_ASSERT(e->mObject == owner, "wrong entry");
       MOZ_ASSERT(int32_t(e->mRefCnt) > 0, "purple ISupports with bad refcnt");
       refcount = --(e->mRefCnt);
       if (MOZ_UNLIKELY(refcount == 0)) {
-#ifdef DEBUG_CC
-        nsCycleCollector_logPurpleRemoval(
-          NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject);
-#endif
         e->mObject = nullptr;
         mTagged = NS_CCAR_REFCNT_TO_TAGGED(0);
       } else {
-#ifdef DEBUG_CC
-        if (e->mNotPurple) {
-          nsCycleCollector_logPurpleAddition(
-            NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject, p);
-        }
-#endif
         e->mNotPurple = false;
       }
     } else {
       refcount = NS_CCAR_TAGGED_TO_REFCNT(mTagged);
       MOZ_ASSERT(int32_t(refcount) > 0, "bad refcount");
       --refcount;
 
       nsPurpleBufferEntry *e;
@@ -222,20 +206,16 @@ public:
     MOZ_ASSERT(HasPurpleBufferEntry(), "must have purple buffer entry");
     nsrefcnt refcount = NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mRefCnt;
     mTagged = NS_CCAR_REFCNT_TO_TAGGED(refcount);
   }
 
   MOZ_ALWAYS_INLINE void RemovePurple()
   {
     MOZ_ASSERT(IsPurple(), "must be purple");
-#ifdef DEBUG_CC
-    nsCycleCollector_logPurpleRemoval(
-      NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject);
-#endif
     // The entry will be added to the free list later. 
     NS_CCAR_TAGGED_TO_PURPLE_ENTRY(mTagged)->mObject = nullptr;
     ReleasePurpleBufferEntry();
   }
 
   MOZ_ALWAYS_INLINE bool HasPurpleBufferEntry() const
   {
     MOZ_ASSERT(mTagged != NS_CCAR_TAGGED_STABILIZED_REFCNT,