Bug 497808. Enable dumping of cycle-collector graphs in any debug build. r=peterv,a=blocking

This commit is contained in:
Robert O'Callahan 2010-08-12 12:03:23 +12:00
parent c7b15f876d
commit 6ac771f7ba
6 changed files with 101 additions and 100 deletions

View File

@ -521,7 +521,7 @@ nsDOMWindowUtils::Focus(nsIDOMElement* aElement)
} }
NS_IMETHODIMP NS_IMETHODIMP
nsDOMWindowUtils::GarbageCollect() nsDOMWindowUtils::GarbageCollect(PRBool aDrawGraph)
{ {
// Always permit this in debug builds. // Always permit this in debug builds.
#ifndef DEBUG #ifndef DEBUG
@ -530,7 +530,7 @@ nsDOMWindowUtils::GarbageCollect()
} }
#endif #endif
nsJSContext::CC(); nsJSContext::CC(aDrawGraph);
return NS_OK; return NS_OK;
} }

View File

@ -307,7 +307,7 @@ NS_IMETHODIMP
nsCCMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic, nsCCMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData) const PRUnichar* aData)
{ {
nsJSContext::CC(); nsJSContext::CC(PR_FALSE);
return NS_OK; return NS_OK;
} }
@ -973,7 +973,7 @@ nsJSContext::DOMOperationCallback(JSContext *cx)
mem->IsLowMemory(&lowMemory); mem->IsLowMemory(&lowMemory);
if (lowMemory) { if (lowMemory) {
// try to clean up: // try to clean up:
nsJSContext::CC(); nsJSContext::CC(PR_FALSE);
// never prevent system scripts from running // never prevent system scripts from running
if (!::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx))) { if (!::JS_IsSystemObject(cx, ::JS_GetGlobalObject(cx))) {
@ -3616,7 +3616,7 @@ nsJSContext::ScriptExecuted()
//static //static
void void
nsJSContext::CC() nsJSContext::CC(PRBool aDrawGraph)
{ {
NS_TIME_FUNCTION_MIN(1.0); NS_TIME_FUNCTION_MIN(1.0);
@ -3631,7 +3631,7 @@ nsJSContext::CC()
// nsCycleCollector_collect() no longer forces a JS garbage collection, // nsCycleCollector_collect() no longer forces a JS garbage collection,
// so we have to do it ourselves here. // so we have to do it ourselves here.
nsContentUtils::XPConnect()->GarbageCollect(); nsContentUtils::XPConnect()->GarbageCollect();
sCollectedObjectsCounts = nsCycleCollector_collect(); sCollectedObjectsCounts = nsCycleCollector_collect(aDrawGraph);
sCCSuspectedCount = nsCycleCollector_suspectedCount(); sCCSuspectedCount = nsCycleCollector_suspectedCount();
sSavedGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER); sSavedGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER);
#ifdef DEBUG_smaug #ifdef DEBUG_smaug
@ -3719,7 +3719,7 @@ nsJSContext::IntervalCC()
{ {
if ((PR_Now() - sPreviousCCTime) >= if ((PR_Now() - sPreviousCCTime) >=
PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) { PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) {
nsJSContext::CC(); nsJSContext::CC(PR_FALSE);
return PR_TRUE; return PR_TRUE;
} }
#ifdef DEBUG_smaug #ifdef DEBUG_smaug

View File

@ -188,7 +188,7 @@ public:
// CC does always call cycle collector and it also updates the counters // CC does always call cycle collector and it also updates the counters
// that MaybeCC uses. // that MaybeCC uses.
static void CC(); static void CC(PRBool aDrawGraph);
// MaybeCC calls cycle collector if certain conditions are fulfilled. // MaybeCC calls cycle collector if certain conditions are fulfilled.
// The conditions are: // The conditions are:

View File

@ -53,7 +53,7 @@ interface nsIDOMEvent;
interface nsITransferable; interface nsITransferable;
interface nsIQueryContentEventResult; interface nsIQueryContentEventResult;
[scriptable, uuid(1e042706-0343-4cba-a549-6a83eefb1835)] [scriptable, uuid(bf4df3a0-4567-47ec-be6d-9ec60eaed63c)]
interface nsIDOMWindowUtils : nsISupports { interface nsIDOMWindowUtils : nsISupports {
/** /**
@ -258,8 +258,12 @@ interface nsIDOMWindowUtils : nsISupports {
* *
* Will throw a DOM security error if called without UniversalXPConnect * Will throw a DOM security error if called without UniversalXPConnect
* privileges in non-debug builds. Available to all callers in debug builds. * privileges in non-debug builds. Available to all callers in debug builds.
*
* @param aDrawGraph when true, a cycle collection graph will be
* dumped to a file named cycle-graph-*.dot in the current working
* directory
*/ */
void garbageCollect(); void garbageCollect(in boolean aDrawGraph);
/** /**
* Force processing of any queued paints * Force processing of any queued paints

View File

@ -156,6 +156,10 @@
//#define COLLECT_TIME_DEBUG //#define COLLECT_TIME_DEBUG
#if defined(DEBUG_CC) || defined(DEBUG)
#define DEBUG_CC_GRAPHS
#endif
#ifdef DEBUG_CC #ifdef DEBUG_CC
#define IF_DEBUG_CC_PARAM(_p) , _p #define IF_DEBUG_CC_PARAM(_p) , _p
#define IF_DEBUG_CC_ONLY_PARAM(_p) _p #define IF_DEBUG_CC_ONLY_PARAM(_p) _p
@ -177,10 +181,10 @@
struct nsCycleCollectorParams struct nsCycleCollectorParams
{ {
PRBool mDoNothing; PRBool mDoNothing;
PRBool mDrawGraphs;
#ifdef DEBUG_CC #ifdef DEBUG_CC
PRBool mReportStats; PRBool mReportStats;
PRBool mHookMalloc; PRBool mHookMalloc;
PRBool mDrawGraphs;
PRBool mFaultIsFatal; PRBool mFaultIsFatal;
PRBool mLogPointers; PRBool mLogPointers;
@ -198,7 +202,8 @@ struct nsCycleCollectorParams
mShutdownCollections(DEFAULT_SHUTDOWN_COLLECTIONS) mShutdownCollections(DEFAULT_SHUTDOWN_COLLECTIONS)
#else #else
mDoNothing (PR_FALSE) mDoNothing (PR_FALSE),
mDrawGraphs (PR_FALSE)
#endif #endif
{ {
#ifdef DEBUG_CC #ifdef DEBUG_CC
@ -446,9 +451,12 @@ struct PtrInfo
EdgePool::Iterator mFirstChild; // first EdgePool::Iterator mFirstChild; // first
EdgePool::Iterator mLastChild; // one after last EdgePool::Iterator mLastChild; // one after last
#ifdef DEBUG_CC_GRAPHS
char *mName;
#endif
#ifdef DEBUG_CC #ifdef DEBUG_CC
size_t mBytes; size_t mBytes;
char *mName;
PRUint32 mLangID; PRUint32 mLangID;
// For finding roots in ExplainLiveExpectedGarbage (when there are // For finding roots in ExplainLiveExpectedGarbage (when there are
@ -460,9 +468,9 @@ struct PtrInfo
ReversedEdge* mReversedEdges; // linked list ReversedEdge* mReversedEdges; // linked list
PtrInfo* mShortestPathToExpectedGarbage; PtrInfo* mShortestPathToExpectedGarbage;
nsCString* mShortestPathToExpectedGarbageEdgeName; nsCString* mShortestPathToExpectedGarbageEdgeName;
#endif
nsTArray<nsCString> mEdgeNames; nsTArray<nsCString> mEdgeNames;
#endif
PtrInfo(void *aPointer, nsCycleCollectionParticipant *aParticipant PtrInfo(void *aPointer, nsCycleCollectionParticipant *aParticipant
IF_DEBUG_CC_PARAM(PRUint32 aLangID) IF_DEBUG_CC_PARAM(PRUint32 aLangID)
@ -474,9 +482,11 @@ struct PtrInfo
mRefCount(0), mRefCount(0),
mFirstChild(), mFirstChild(),
mLastChild() mLastChild()
#ifdef DEBUG_CC_GRAPHS
, mName(nsnull)
#endif
#ifdef DEBUG_CC #ifdef DEBUG_CC
, mBytes(0), , mBytes(0),
mName(nsnull),
mLangID(aLangID), mLangID(aLangID),
mSCCIndex(0), mSCCIndex(0),
mReversedEdges(nsnull), mReversedEdges(nsnull),
@ -486,12 +496,12 @@ struct PtrInfo
{ {
} }
#ifdef DEBUG_CC
void Destroy() { void Destroy() {
#ifdef DEBUG_CC_GRAPHS
PL_strfree(mName); PL_strfree(mName);
#endif
mEdgeNames.~nsTArray<nsCString>(); mEdgeNames.~nsTArray<nsCString>();
} }
#endif
// Allow NodePool::Block's constructor to compile. // Allow NodePool::Block's constructor to compile.
PtrInfo() { PtrInfo() {
@ -651,7 +661,7 @@ struct GCGraph
// Add/Remove/Has rather than PutEntry/RemoveEntry/GetEntry. // Add/Remove/Has rather than PutEntry/RemoveEntry/GetEntry.
typedef nsTHashtable<nsVoidPtrHashKey> PointerSet; typedef nsTHashtable<nsVoidPtrHashKey> PointerSet;
#ifdef DEBUG_CC #ifdef DEBUG_CC_GRAPHS
static void static void
WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr); WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr);
#endif #endif
@ -995,7 +1005,7 @@ struct nsCycleCollector
nsPurpleBufferEntry* Suspect2(nsISupports *n); nsPurpleBufferEntry* Suspect2(nsISupports *n);
PRBool Forget2(nsPurpleBufferEntry *e); PRBool Forget2(nsPurpleBufferEntry *e);
PRUint32 Collect(PRUint32 aTryCollections = 1); PRUint32 Collect(PRUint32 aTryCollections, PRBool aDrawGraph);
PRBool BeginCollection(); PRBool BeginCollection();
PRBool FinishCollection(); PRBool FinishCollection();
PRUint32 SuspectedCount(); PRUint32 SuspectedCount();
@ -1008,12 +1018,15 @@ struct nsCycleCollector
mGraph.mRootCount = 0; mGraph.mRootCount = 0;
} }
#ifdef DEBUG_CC_GRAPHS
void MaybeDrawGraphs();
#endif
#ifdef DEBUG_CC #ifdef DEBUG_CC
nsCycleCollectorStats mStats; nsCycleCollectorStats mStats;
FILE *mPtrLog; FILE *mPtrLog;
void MaybeDrawGraphs();
void Allocated(void *n, size_t sz); void Allocated(void *n, size_t sz);
void Freed(void *n); void Freed(void *n);
@ -1301,13 +1314,12 @@ private:
PLDHashTable mPtrToNodeMap; PLDHashTable mPtrToNodeMap;
PtrInfo *mCurrPi; PtrInfo *mCurrPi;
nsCycleCollectionLanguageRuntime **mRuntimes; // weak, from nsCycleCollector nsCycleCollectionLanguageRuntime **mRuntimes; // weak, from nsCycleCollector
#ifdef DEBUG_CC
nsCString mNextEdgeName; nsCString mNextEdgeName;
#endif
public: public:
GCGraphBuilder(GCGraph &aGraph, GCGraphBuilder(GCGraph &aGraph,
nsCycleCollectionLanguageRuntime **aRuntimes); nsCycleCollectionLanguageRuntime **aRuntimes,
PRBool aDrawGraph);
~GCGraphBuilder(); ~GCGraphBuilder();
bool Initialized(); bool Initialized();
@ -1342,7 +1354,8 @@ private:
}; };
GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph, GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph,
nsCycleCollectionLanguageRuntime **aRuntimes) nsCycleCollectionLanguageRuntime **aRuntimes,
PRBool aDrawGraph)
: mNodeBuilder(aGraph.mNodes), : mNodeBuilder(aGraph.mNodes),
mEdgeBuilder(aGraph.mEdges), mEdgeBuilder(aGraph.mEdges),
mRuntimes(aRuntimes) mRuntimes(aRuntimes)
@ -1350,11 +1363,13 @@ GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph,
if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nsnull, if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nsnull,
sizeof(PtrToNodeEntry), 32768)) sizeof(PtrToNodeEntry), 32768))
mPtrToNodeMap.ops = nsnull; mPtrToNodeMap.ops = nsnull;
#ifdef DEBUG_CC #ifndef DEBUG_CC
// Do we need to set these all the time? if (aDrawGraph)
mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
#endif #endif
{
mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
}
} }
GCGraphBuilder::~GCGraphBuilder() GCGraphBuilder::~GCGraphBuilder()
@ -1458,7 +1473,11 @@ GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount,
{ {
#ifdef DEBUG_CC #ifdef DEBUG_CC
mCurrPi->mBytes = objSz; mCurrPi->mBytes = objSz;
mCurrPi->mName = PL_strdup(objName); #endif
#ifdef DEBUG_CC_GRAPHS
if (WantDebugInfo()) {
mCurrPi->mName = PL_strdup(objName);
}
#endif #endif
if (type == RefCounted) { if (type == RefCounted) {
@ -1478,10 +1497,11 @@ GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount,
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
GCGraphBuilder::NoteXPCOMChild(nsISupports *child) GCGraphBuilder::NoteXPCOMChild(nsISupports *child)
{ {
#ifdef DEBUG_CC nsCString edgeName;
nsCString edgeName(mNextEdgeName); if (WantDebugInfo()) {
mNextEdgeName.Truncate(); edgeName.Assign(mNextEdgeName);
#endif mNextEdgeName.Truncate();
}
if (!child || !(child = canonicalize(child))) if (!child || !(child = canonicalize(child)))
return; return;
@ -1497,9 +1517,9 @@ GCGraphBuilder::NoteXPCOMChild(nsISupports *child)
if (!childPi) if (!childPi)
return; return;
mEdgeBuilder.Add(childPi); mEdgeBuilder.Add(childPi);
#ifdef DEBUG_CC if (WantDebugInfo()) {
mCurrPi->mEdgeNames.AppendElement(edgeName); mCurrPi->mEdgeNames.AppendElement(edgeName);
#endif }
++childPi->mInternalRefs; ++childPi->mInternalRefs;
} }
} }
@ -1508,10 +1528,11 @@ NS_IMETHODIMP_(void)
GCGraphBuilder::NoteNativeChild(void *child, GCGraphBuilder::NoteNativeChild(void *child,
nsCycleCollectionParticipant *participant) nsCycleCollectionParticipant *participant)
{ {
#ifdef DEBUG_CC nsCString edgeName;
nsCString edgeName(mNextEdgeName); if (WantDebugInfo()) {
mNextEdgeName.Truncate(); edgeName.Assign(mNextEdgeName);
#endif mNextEdgeName.Truncate();
}
if (!child) if (!child)
return; return;
@ -1521,19 +1542,17 @@ GCGraphBuilder::NoteNativeChild(void *child,
if (!childPi) if (!childPi)
return; return;
mEdgeBuilder.Add(childPi); mEdgeBuilder.Add(childPi);
#ifdef DEBUG_CC if (WantDebugInfo()) {
mCurrPi->mEdgeNames.AppendElement(edgeName); mCurrPi->mEdgeNames.AppendElement(edgeName);
#endif }
++childPi->mInternalRefs; ++childPi->mInternalRefs;
} }
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child) GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child)
{ {
#ifdef DEBUG_CC
nsCString edgeName(mNextEdgeName); nsCString edgeName(mNextEdgeName);
mNextEdgeName.Truncate(); mNextEdgeName.Truncate();
#endif
if (!child) if (!child)
return; return;
@ -1556,18 +1575,18 @@ GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child)
if (!childPi) if (!childPi)
return; return;
mEdgeBuilder.Add(childPi); mEdgeBuilder.Add(childPi);
#ifdef DEBUG_CC if (WantDebugInfo()) {
mCurrPi->mEdgeNames.AppendElement(edgeName); mCurrPi->mEdgeNames.AppendElement(edgeName);
#endif }
++childPi->mInternalRefs; ++childPi->mInternalRefs;
} }
NS_IMETHODIMP_(void) NS_IMETHODIMP_(void)
GCGraphBuilder::NoteNextEdgeName(const char* name) GCGraphBuilder::NoteNextEdgeName(const char* name)
{ {
#ifdef DEBUG_CC if (WantDebugInfo()) {
mNextEdgeName = name; mNextEdgeName = name;
#endif }
} }
static PRBool static PRBool
@ -2079,8 +2098,7 @@ nsCycleCollector::ForgetRuntime(PRUint32 langID)
mRuntimes[langID] = nsnull; mRuntimes[langID] = nsnull;
} }
#ifdef DEBUG_CC_GRAPHS
#ifdef DEBUG_CC
static void static void
WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr) WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr)
{ {
@ -2108,62 +2126,36 @@ WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr)
"\", fillcolor=%s, fontcolor=%s]\n", "\", fillcolor=%s, fontcolor=%s]\n",
(redPtr && redPtr == p ? "red" : (pi->mColor == black ? "black" : "white")), (redPtr && redPtr == p ? "red" : (pi->mColor == black ? "black" : "white")),
(pi->mColor == black ? "white" : "black")); (pi->mColor == black ? "white" : "black"));
PRInt32 i = 0;
for (EdgePool::Iterator child = pi->mFirstChild, for (EdgePool::Iterator child = pi->mFirstChild,
child_end = pi->mLastChild; child_end = pi->mLastChild;
child != child_end; ++child) { child != child_end; ++child) {
fprintf(stream, "n%p -> n%p\n", p, (*child)->mPointer); fprintf(stream, "n%p -> n%p [label=\"%s\"]\n", p,
(*child)->mPointer, pi->mEdgeNames[i].get());
++i;
} }
} }
fprintf(stream, "\n}\n"); fprintf(stream, "\n}\n");
} }
static PRUint32 gCounter;
void void
nsCycleCollector::MaybeDrawGraphs() nsCycleCollector::MaybeDrawGraphs()
{ {
if (mParams.mDrawGraphs) { if (mParams.mDrawGraphs) {
// We draw graphs only if there were any white nodes. FILE *stream;
PRBool anyWhites = PR_FALSE; char name[255];
NodePool::Enumerator fwetor(mGraph.mNodes); sprintf(name, "cycle-graph-%d.dot", ++gCounter);
while (!fwetor.IsDone()) stream = fopen(name, "w");
{ WriteGraph(stream, mGraph, nsnull);
PtrInfo *pinfo = fwetor.GetNext(); fclose(stream);
if (pinfo->mColor == white) {
anyWhites = PR_TRUE;
break;
}
}
if (anyWhites) {
// We can't just use _popen here because graphviz-for-windows
// doesn't set up its stdin stream properly, sigh.
FILE *stream;
#ifdef WIN32
stream = fopen("c:\\cycle-graph.dot", "w+");
#else
stream = popen("dotty -", "w");
#endif
WriteGraph(stream, mGraph, nsnull);
#ifdef WIN32
fclose(stream);
// Even dotty doesn't work terribly well on windows, since
// they execute lefty asynchronously. So we'll just run
// lefty ourselves.
_spawnlp(_P_WAIT,
"lefty",
"lefty",
"-e",
"\"load('dotty.lefty');"
"dotty.simple('c:\\cycle-graph.dot');\"",
NULL);
unlink("c:\\cycle-graph.dot");
#else
pclose(stream);
#endif
}
} }
} }
#endif
#ifdef DEBUG_CC
class Suppressor : class Suppressor :
public nsCycleCollectionTraversalCallback public nsCycleCollectionTraversalCallback
@ -2416,7 +2408,7 @@ nsCycleCollector::Freed(void *n)
#endif #endif
PRUint32 PRUint32
nsCycleCollector::Collect(PRUint32 aTryCollections) nsCycleCollector::Collect(PRUint32 aTryCollections, PRBool aDrawGraph)
{ {
#if defined(DEBUG_CC) && !defined(__MINGW32__) #if defined(DEBUG_CC) && !defined(__MINGW32__)
if (!mParams.mDoNothing && mParams.mHookMalloc) if (!mParams.mDoNothing && mParams.mHookMalloc)
@ -2434,6 +2426,9 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
PRTime start = PR_Now(); PRTime start = PR_Now();
#endif #endif
PRBool drawGraphs = mParams.mDrawGraphs;
mParams.mDrawGraphs |= aDrawGraph;
mCollectionInProgress = PR_TRUE; mCollectionInProgress = PR_TRUE;
nsCOMPtr<nsIObserverService> obs = nsCOMPtr<nsIObserverService> obs =
@ -2503,6 +2498,8 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
mCollectionInProgress = PR_FALSE; mCollectionInProgress = PR_FALSE;
mParams.mDrawGraphs = drawGraphs;
#ifdef XP_OS2 #ifdef XP_OS2
// Now that the cycle collector has freed some memory, we can try to // Now that the cycle collector has freed some memory, we can try to
// force the C library to give back as much memory to the system as // force the C library to give back as much memory to the system as
@ -2526,7 +2523,7 @@ nsCycleCollector::BeginCollection()
if (mParams.mDoNothing) if (mParams.mDoNothing)
return PR_FALSE; return PR_FALSE;
GCGraphBuilder builder(mGraph, mRuntimes); GCGraphBuilder builder(mGraph, mRuntimes, mParams.mDrawGraphs);
if (!builder.Initialized()) if (!builder.Initialized())
return PR_FALSE; return PR_FALSE;
@ -2604,7 +2601,7 @@ nsCycleCollector::BeginCollection()
(PR_Now() - now) / PR_USEC_PER_MSEC); (PR_Now() - now) / PR_USEC_PER_MSEC);
#endif #endif
#ifdef DEBUG_CC #ifdef DEBUG_CC_GRAPHS
MaybeDrawGraphs(); MaybeDrawGraphs();
#endif #endif
@ -2692,7 +2689,7 @@ nsCycleCollector::Shutdown()
mRuntimes[i]->CommenceShutdown(); mRuntimes[i]->CommenceShutdown();
} }
Collect(SHUTDOWN_COLLECTIONS(mParams)); Collect(SHUTDOWN_COLLECTIONS(mParams), PR_FALSE);
#ifdef DEBUG_CC #ifdef DEBUG_CC
GCGraphBuilder builder(mGraph, mRuntimes); GCGraphBuilder builder(mGraph, mRuntimes);
@ -3163,9 +3160,9 @@ NS_CycleCollectorForget2(nsPurpleBufferEntry *e)
PRUint32 PRUint32
nsCycleCollector_collect() nsCycleCollector_collect(PRBool aDrawGraph)
{ {
return sCollector ? sCollector->Collect() : 0; return sCollector ? sCollector->Collect(1, aDrawGraph) : 0;
} }
PRUint32 PRUint32

View File

@ -63,7 +63,7 @@ struct nsCycleCollectionLanguageRuntime
nsresult nsCycleCollector_startup(); nsresult nsCycleCollector_startup();
// Returns the number of collected nodes. // Returns the number of collected nodes.
NS_COM PRUint32 nsCycleCollector_collect(); NS_COM PRUint32 nsCycleCollector_collect(PRBool aDrawGraph);
NS_COM PRUint32 nsCycleCollector_suspectedCount(); NS_COM PRUint32 nsCycleCollector_suspectedCount();
void nsCycleCollector_shutdown(); void nsCycleCollector_shutdown();