зеркало из https://github.com/mozilla/pjs.git
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:
Родитель
048953d8b5
Коммит
caf78b3e20
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче