Print shortest path to expected garbage for unlink deficiencies as well. b=422848 r+sr=peterv a=DEBUG_CC only (not part of default build)

This commit is contained in:
dbaron%dbaron.org 2008-03-27 17:09:51 +00:00
Родитель 048953d8b5
Коммит caf78b3e20
1 изменённых файлов: 111 добавлений и 105 удалений

Просмотреть файл

@ -2511,6 +2511,25 @@ struct SetNonRootGreyWalker : public GraphWalker
void VisitNode(PtrInfo *pi) { pi->mColor = grey; }
};
static void
PrintPathToExpectedGarbage(PtrInfo *pi)
{
printf(" An object expected to be garbage could be "
"reached from it by the path:\n");
for (PtrInfo *path = pi, *prev = nsnull; prev != path;
prev = path,
path = path->mShortestPathToExpectedGarbage) {
if (prev) {
nsCString *edgeName = prev
->mShortestPathToExpectedGarbageEdgeName;
printf(" via %s\n",
edgeName->IsEmpty() ? "<unknown edge>"
: edgeName->get());
}
printf(" %s %p\n", path->mName, path->mPointer);
}
}
void
nsCycleCollector::ExplainLiveExpectedGarbage()
{
@ -2566,10 +2585,8 @@ nsCycleCollector::ExplainLiveExpectedGarbage()
}
}
// The describeExtraRefcounts check isn't much use now that
// we're traversing from suspectCurrent roots too. But it's
// just extra work, not extra output.
if (describeExtraRefcounts && CreateReversedEdges()) {
if ((describeExtraRefcounts || findCycleRoots) &&
CreateReversedEdges()) {
// Note that the external references may have been external
// to a different node in the cycle collection that just
// happened, if that different node was purple and then
@ -2628,20 +2645,7 @@ nsCycleCollector::ExplainLiveExpectedGarbage()
pi->mRefCount, pi->mInternalRefs);
}
printf(" An object expected to be garbage could be "
"reached from it by the path:\n");
for (PtrInfo *path = pi, *prev = nsnull; prev != path;
prev = path,
path = path->mShortestPathToExpectedGarbage) {
if (prev) {
nsCString *edgeName = prev
->mShortestPathToExpectedGarbageEdgeName;
printf(" via %s\n",
edgeName->IsEmpty() ? "<unknown edge>"
: edgeName->get());
}
printf(" %s %p\n", path->mName, path->mPointer);
}
PrintPathToExpectedGarbage(pi);
if (pi->mRefCount == PR_UINT32_MAX) {
printf(" The known references to it were from:\n");
@ -2663,111 +2667,113 @@ nsCycleCollector::ExplainLiveExpectedGarbage()
}
}
DestroyReversedEdges();
}
if (findCycleRoots) {
// NOTE: This code changes the white nodes that are not
// roots to gray.
if (findCycleRoots) {
// NOTE: This code changes the white nodes that are not
// roots to gray.
// Put the nodes in post-order traversal order from a
// depth-first search.
nsDeque DFSPostOrder;
// Put the nodes in post-order traversal order from a
// depth-first search.
nsDeque DFSPostOrder;
{
// Use mSCCIndex temporarily to track the DFS numbering:
const PRUint32 INDEX_UNREACHED = 0;
const PRUint32 INDEX_TRAVERSING = 1;
const PRUint32 INDEX_NUMBERED = 2;
{
// Use mSCCIndex temporarily to track the DFS numbering:
const PRUint32 INDEX_UNREACHED = 0;
const PRUint32 INDEX_TRAVERSING = 1;
const PRUint32 INDEX_NUMBERED = 2;
NodePool::Enumerator etor_clear(mGraph.mNodes);
while (!etor_clear.IsDone()) {
PtrInfo *pi = etor_clear.GetNext();
pi->mSCCIndex = INDEX_UNREACHED;
}
NodePool::Enumerator etor_clear(mGraph.mNodes);
while (!etor_clear.IsDone()) {
PtrInfo *pi = etor_clear.GetNext();
pi->mSCCIndex = INDEX_UNREACHED;
nsDeque stack;
NodePool::Enumerator etor_roots(mGraph.mNodes);
for (PRUint32 i = 0; i < mGraph.mRootCount; ++i) {
PtrInfo *root_pi = etor_roots.GetNext();
stack.Push(root_pi);
}
while (stack.GetSize() > 0) {
PtrInfo *pi = (PtrInfo*)stack.Peek();
if (pi->mSCCIndex == INDEX_UNREACHED) {
pi->mSCCIndex = INDEX_TRAVERSING;
for (EdgePool::Iterator child = pi->mFirstChild,
child_end = pi->mLastChild;
child != child_end; ++child) {
stack.Push(*child);
}
} else {
stack.Pop();
// Somebody else might have numbered it already
// (since this is depth-first, not breadth-first).
// This happens if a node is pushed on the stack
// a second time while it is on the stack in
// UNREACHED state.
if (pi->mSCCIndex == INDEX_TRAVERSING) {
pi->mSCCIndex = INDEX_NUMBERED;
DFSPostOrder.Push(pi);
}
}
}
}
nsDeque stack;
// Put the nodes into strongly-connected components.
{
NodePool::Enumerator etor_clear(mGraph.mNodes);
while (!etor_clear.IsDone()) {
PtrInfo *pi = etor_clear.GetNext();
pi->mSCCIndex = 0;
}
NodePool::Enumerator etor_roots(mGraph.mNodes);
for (PRUint32 i = 0; i < mGraph.mRootCount; ++i) {
PtrInfo *root_pi = etor_roots.GetNext();
stack.Push(root_pi);
PRUint32 currentSCC = 1;
while (DFSPostOrder.GetSize() > 0) {
SetSCCWalker(currentSCC).Walk((PtrInfo*)DFSPostOrder.PopFront());
++currentSCC;
}
}
while (stack.GetSize() > 0) {
PtrInfo *pi = (PtrInfo*)stack.Peek();
if (pi->mSCCIndex == INDEX_UNREACHED) {
pi->mSCCIndex = INDEX_TRAVERSING;
// Mark any white nodes reachable from other components as
// grey.
{
NodePool::Enumerator queue(mGraph.mNodes);
while (!queue.IsDone()) {
PtrInfo *pi = queue.GetNext();
if (pi->mColor != white)
continue;
for (EdgePool::Iterator child = pi->mFirstChild,
child_end = pi->mLastChild;
child != child_end; ++child) {
stack.Push(*child);
if ((*child)->mSCCIndex != pi->mSCCIndex) {
SetNonRootGreyWalker().Walk(*child);
}
}
} else {
stack.Pop();
// Somebody else might have numbered it already
// (since this is depth-first, not breadth-first).
// This happens if a node is pushed on the stack
// a second time while it is on the stack in
// UNREACHED state.
if (pi->mSCCIndex == INDEX_TRAVERSING) {
pi->mSCCIndex = INDEX_NUMBERED;
DFSPostOrder.Push(pi);
}
}
{
NodePool::Enumerator queue(mGraph.mNodes);
while (!queue.IsDone()) {
PtrInfo *pi = queue.GetNext();
if (pi->mColor == white) {
printf("nsCycleCollector: %s %p in component %d\n"
" was not collected due to missing call to "
"suspect, failure to unlink,\n"
" or deficiency in traverse that causes "
"cycles referenced only from other\n"
" cycles to require multiple rounds of cycle "
"collection\n",
pi->mName, pi->mPointer, pi->mSCCIndex);
if (pi->mShortestPathToExpectedGarbage)
PrintPathToExpectedGarbage(pi);
}
}
}
}
// Put the nodes into strongly-connected components.
{
NodePool::Enumerator etor_clear(mGraph.mNodes);
while (!etor_clear.IsDone()) {
PtrInfo *pi = etor_clear.GetNext();
pi->mSCCIndex = 0;
}
PRUint32 currentSCC = 1;
while (DFSPostOrder.GetSize() > 0) {
SetSCCWalker(currentSCC).Walk((PtrInfo*)DFSPostOrder.PopFront());
++currentSCC;
}
}
// Mark any white nodes reachable from other components as
// grey.
{
NodePool::Enumerator queue(mGraph.mNodes);
while (!queue.IsDone()) {
PtrInfo *pi = queue.GetNext();
if (pi->mColor != white)
continue;
for (EdgePool::Iterator child = pi->mFirstChild,
child_end = pi->mLastChild;
child != child_end; ++child) {
if ((*child)->mSCCIndex != pi->mSCCIndex) {
SetNonRootGreyWalker().Walk(*child);
}
}
}
}
{
NodePool::Enumerator queue(mGraph.mNodes);
while (!queue.IsDone()) {
PtrInfo *pi = queue.GetNext();
if (pi->mColor == white) {
printf("nsCycleCollector: %s %p in component %d\n"
" was not collected due to missing call to "
"suspect, failure to unlink,\n"
" or deficiency in traverse that causes "
"cycles referenced only from other\n"
" cycles to require multiple rounds of cycle "
"collection\n",
pi->mName, pi->mPointer, pi->mSCCIndex);
}
}
}
DestroyReversedEdges();
}
}