Make GraphWalker use templates instead of virtual functions. (Bug 537547) r=smaug

This commit is contained in:
L. David Baron 2010-01-12 08:51:39 -08:00
parent bae4d300f3
commit 51ff23326f

View File

@ -1042,9 +1042,18 @@ struct DoWalkDebugInfo
EdgePool::Iterator mCurrentChild;
};
/**
* GraphWalker is templatized over a Visitor class that must provide
* the following two methods:
*
* PRBool ShouldVisitNode(PtrInfo const *pi);
* void VisitNode(PtrInfo *pi);
*/
template <class Visitor>
class GraphWalker
{
private:
Visitor mVisitor;
DoWalkDebugInfo *mDebugInfo;
void DoWalk(nsDeque &aQueue);
@ -1052,10 +1061,9 @@ private:
public:
void Walk(PtrInfo *s0);
void WalkFromRoots(GCGraph &aGraph);
// Provided by concrete walker subtypes.
virtual PRBool ShouldVisitNode(PtrInfo const *pi) = 0;
virtual void VisitNode(PtrInfo *pi) = 0;
// copy-constructing the visitor should be cheap, and less
// indirection than using a reference
GraphWalker(const Visitor aVisitor) : mVisitor(aVisitor) {}
};
@ -1225,16 +1233,18 @@ nsCycleCollectionXPCOMRuntime::ToParticipant(void *p)
}
template <class Visitor>
void
GraphWalker::Walk(PtrInfo *s0)
GraphWalker<Visitor>::Walk(PtrInfo *s0)
{
nsDeque queue;
queue.Push(s0);
DoWalk(queue);
}
template <class Visitor>
void
GraphWalker::WalkFromRoots(GCGraph& aGraph)
GraphWalker<Visitor>::WalkFromRoots(GCGraph& aGraph)
{
nsDeque queue;
NodePool::Enumerator etor(aGraph.mNodes);
@ -1286,8 +1296,9 @@ NodePool::CheckPtrInfo(PtrInfo *aPtrInfo)
CC_RUNTIME_ABORT_IF_FALSE(block, "Pointer is outside blocks.");
}
template <class Visitor>
void
GraphWalker::DoWalk(nsDeque &aQueue)
GraphWalker<Visitor>::DoWalk(nsDeque &aQueue)
{
// Use a aQueue to match the breadth-first traversal used when we
// built the graph, for hopefully-better locality.
@ -1300,8 +1311,8 @@ GraphWalker::DoWalk(nsDeque &aQueue)
sCollector->mGraph.mNodes.CheckPtrInfo(pi);
debugInfo.mCurrentPI = pi;
if (this->ShouldVisitNode(pi)) {
this->VisitNode(pi);
if (mVisitor.ShouldVisitNode(pi)) {
mVisitor.VisitNode(pi);
debugInfo.mFirstChild = pi->mFirstChild;
debugInfo.mLastChild = pi->mLastChild;
debugInfo.mCurrentChild = pi->mFirstChild;
@ -1693,9 +1704,10 @@ nsCycleCollector::MarkRoots(GCGraphBuilder &builder)
////////////////////////////////////////////////////////////////////////
struct ScanBlackWalker : public GraphWalker
struct ScanBlackVisitor
{
ScanBlackWalker(PRUint32 &aWhiteNodeCount) : mWhiteNodeCount(aWhiteNodeCount)
ScanBlackVisitor(PRUint32 &aWhiteNodeCount)
: mWhiteNodeCount(aWhiteNodeCount)
{
}
@ -1718,9 +1730,9 @@ struct ScanBlackWalker : public GraphWalker
};
struct scanWalker : public GraphWalker
struct scanVisitor
{
scanWalker(PRUint32 &aWhiteNodeCount) : mWhiteNodeCount(aWhiteNodeCount)
scanVisitor(PRUint32 &aWhiteNodeCount) : mWhiteNodeCount(aWhiteNodeCount)
{
}
@ -1741,9 +1753,9 @@ struct scanWalker : public GraphWalker
sCollector->mStats.mSetColorWhite++;
#endif
} else {
ScanBlackWalker(mWhiteNodeCount).Walk(pi);
GraphWalker<ScanBlackVisitor>(ScanBlackVisitor(mWhiteNodeCount)).Walk(pi);
NS_ASSERTION(pi->mColor == black,
"Why didn't ScanBlackWalker make pi black?");
"Why didn't ScanBlackVisitor make pi black?");
}
}
@ -1758,7 +1770,7 @@ nsCycleCollector::ScanRoots()
// On the assumption that most nodes will be black, it's
// probably faster to use a GraphWalker than a
// NodePool::Enumerator.
scanWalker(mWhiteNodeCount).WalkFromRoots(mGraph);
GraphWalker<scanVisitor>(scanVisitor(mWhiteNodeCount)).WalkFromRoots(mGraph);
#ifdef DEBUG_CC
// Sanity check: scan should have colored all grey nodes black or
@ -2760,16 +2772,16 @@ AddExpectedGarbage(nsVoidPtrHashKey *p, void *arg)
return PL_DHASH_NEXT;
}
struct SetSCCWalker : public GraphWalker
struct SetSCCVisitor
{
SetSCCWalker(PRUint32 aIndex) : mIndex(aIndex) {}
SetSCCVisitor(PRUint32 aIndex) : mIndex(aIndex) {}
PRBool ShouldVisitNode(PtrInfo const *pi) { return pi->mSCCIndex == 0; }
void VisitNode(PtrInfo *pi) { pi->mSCCIndex = mIndex; }
private:
PRUint32 mIndex;
};
struct SetNonRootGreyWalker : public GraphWalker
struct SetNonRootGreyVisitor
{
PRBool ShouldVisitNode(PtrInfo const *pi) { return pi->mColor == white; }
void VisitNode(PtrInfo *pi) { pi->mColor = grey; }
@ -3005,7 +3017,7 @@ nsCycleCollector::ExplainLiveExpectedGarbage()
PRUint32 currentSCC = 1;
while (DFSPostOrder.GetSize() > 0) {
SetSCCWalker(currentSCC).Walk((PtrInfo*)DFSPostOrder.PopFront());
GraphWalker<SetSCCVisitor>(SetSCCVisitor(currentSCC)).Walk((PtrInfo*)DFSPostOrder.PopFront());
++currentSCC;
}
}
@ -3022,7 +3034,7 @@ nsCycleCollector::ExplainLiveExpectedGarbage()
child_end = pi->mLastChild;
child != child_end; ++child) {
if ((*child)->mSCCIndex != pi->mSCCIndex) {
SetNonRootGreyWalker().Walk(*child);
GraphWalker<SetNonRootGreyVisitor>(SetNonRootGreyVisitor()).Walk(*child);
}
}
}