mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-01 19:39:13 +00:00
Make GraphWalker use templates instead of virtual functions. (Bug 537547) r=smaug
This commit is contained in:
parent
bae4d300f3
commit
51ff23326f
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user