Add temporary debugging code to help figure out top crash bug 500105, part 2. r=dbaron.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 07 Oct 2009 17:44:28 -0700
changeset 32703 6b79d9973d7b
parent 32702 297f674eb90f
child 32704 51741697c83a
push id546
push userpvanderbeken@mozilla.com
push dateTue, 03 Nov 2009 13:34:16 +0000
reviewersdbaron
bugs500105
milestone1.9.2b2pre
Add temporary debugging code to help figure out top crash bug 500105, part 2. r=dbaron.
xpcom/base/nsCycleCollector.cpp
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -162,16 +162,23 @@
 
 #define DEFAULT_SHUTDOWN_COLLECTIONS 5
 #ifdef DEBUG_CC
 #define SHUTDOWN_COLLECTIONS(params) params.mShutdownCollections
 #else
 #define SHUTDOWN_COLLECTIONS(params) DEFAULT_SHUTDOWN_COLLECTIONS
 #endif
 
+#define CC_RUNTIME_ABORT_IF_FALSE(_expr, _msg)                                \
+  PR_BEGIN_MACRO                                                              \
+    if (!(_expr)) {                                                           \
+      NS_DebugBreak(NS_DEBUG_ABORT, _msg, #_expr, __FILE__, __LINE__);        \
+    }                                                                         \
+  PR_END_MACRO
+
 // Various parameters of this collector can be tuned using environment
 // variables.
 
 struct nsCycleCollectorParams
 {
     PRBool mDoNothing;
 #ifdef DEBUG_CC
     PRBool mReportStats;
@@ -371,16 +378,17 @@ public:
             return mPointer->ptrInfo;
         }
         PRBool operator==(const Iterator& aOther) const
             { return mPointer == aOther.mPointer; }
         PRBool operator!=(const Iterator& aOther) const
             { return mPointer != aOther.mPointer; }
 
     private:
+        friend class EdgePool;
         PtrInfoOrBlock *mPointer;
     };
 
     class Builder;
     friend class Builder;
     class Builder {
     public:
         Builder(EdgePool &aPool)
@@ -408,16 +416,17 @@ public:
             (mCurrent++)->ptrInfo = aEdge;
         }
     private:
         // mBlockEnd points to space for null sentinel
         PtrInfoOrBlock *mCurrent, *mBlockEnd;
         Block **mNextBlockPtr;
     };
 
+    void CheckIterator(Iterator &aIterator);
 };
 
 #ifdef DEBUG_CC
 
 struct ReversedEdge {
     PtrInfo *mTarget;
     nsCString *mEdgeName;
     ReversedEdge *mNext;
@@ -615,16 +624,18 @@ public:
         }
     private:
         Block *mFirstBlock, *mCurBlock;
         // mNext is the next value we want to return, unless mNext == mBlockEnd
         // NB: mLast is a reference to allow enumerating while building!
         PtrInfo *mNext, *mBlockEnd, *&mLast;
     };
 
+    void CheckPtrInfo(PtrInfo *aPtrInfo);
+
 private:
     Block *mBlocks;
     PtrInfo *mLast;
 };
 
 
 class GCGraphBuilder;
 
@@ -1227,35 +1238,80 @@ GraphWalker::WalkFromRoots(GCGraph& aGra
     NodePool::Enumerator etor(aGraph.mNodes);
     for (PRUint32 i = 0; i < aGraph.mRootCount; ++i) {
         queue.Push(etor.GetNext());
     }
     DoWalk(queue);
 }
 
 void
+EdgePool::CheckIterator(Iterator &aIterator)
+{
+    PtrInfoOrBlock *iteratorPos = aIterator.mPointer;
+    CC_RUNTIME_ABORT_IF_FALSE(iteratorPos, "Iterator's pos is null.");
+
+    PtrInfoOrBlock *start = &mSentinelAndBlocks[0];
+    size_t sentinelOffset = 0;
+    PtrInfoOrBlock *end;
+    Block *nextBlockPtr;
+    do {
+        end = start + sentinelOffset;
+        nextBlockPtr = (end + 1)->block;
+        // We must be in a block of edges or on a sentinel.
+        if (iteratorPos >= start && iteratorPos <= end)
+            break;
+        sentinelOffset = Block::BlockSize - 2;
+    } while ((start = nextBlockPtr ? nextBlockPtr->Start() : nsnull));
+    CC_RUNTIME_ABORT_IF_FALSE(start, "Iterator doesn't point into EdgePool.");
+
+    // If the ptrInfo is null we need to be on the sentinel.
+    CC_RUNTIME_ABORT_IF_FALSE(iteratorPos->ptrInfo || iteratorPos == end,
+                              "iteratorPos points to null, but it's not a "
+                              "sentinel!");
+}
+
+void
+NodePool::CheckPtrInfo(PtrInfo *aPtrInfo)
+{
+    // Find out if pi is null.
+    CC_RUNTIME_ABORT_IF_FALSE(aPtrInfo, "Pointer is null.");
+
+    // Find out if pi is a dangling pointer.
+    Block *block = mBlocks;
+    do {
+        if(aPtrInfo >= &block->mEntries[0] &&
+           aPtrInfo <= &block->mEntries[BlockSize - 1])
+           break;
+    } while ((block = block->mNext));
+    CC_RUNTIME_ABORT_IF_FALSE(block, "Pointer is outside blocks.");
+}
+
+void
 GraphWalker::DoWalk(nsDeque &aQueue)
 {
     // Use a aQueue to match the breadth-first traversal used when we
     // built the graph, for hopefully-better locality.
     DoWalkDebugInfo debugInfo;
     mDebugInfo = &debugInfo;
 
     while (aQueue.GetSize() > 0) {
         PtrInfo *pi = static_cast<PtrInfo*>(aQueue.PopFront());
 
+        sCollector->mGraph.mNodes.CheckPtrInfo(pi);
+
         debugInfo.mCurrentPI = pi;
         if (this->ShouldVisitNode(pi)) {
             this->VisitNode(pi);
             debugInfo.mFirstChild = pi->mFirstChild;
             debugInfo.mLastChild = pi->mLastChild;
             debugInfo.mCurrentChild = pi->mFirstChild;
             for (EdgePool::Iterator child = pi->mFirstChild,
                                 child_end = pi->mLastChild;
                  child != child_end; ++child, debugInfo.mCurrentChild = child) {
+                sCollector->mGraph.mEdges.CheckIterator(child);
                 aQueue.Push(*child);
             }
         }
     };
 
 #ifdef DEBUG_CC
     sCollector->mStats.mWalkedGraph++;
 #endif