mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 497808. Enable dumping of cycle-collector graphs in any debug build. r=peterv,a=blocking
This commit is contained in:
parent
c7b15f876d
commit
6ac771f7ba
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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:
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
|
mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
|
||||||
nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
|
nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
|
||||||
#endif
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
#endif
|
||||||
|
#ifdef DEBUG_CC_GRAPHS
|
||||||
|
if (WantDebugInfo()) {
|
||||||
mCurrPi->mName = PL_strdup(objName);
|
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()) {
|
||||||
|
edgeName.Assign(mNextEdgeName);
|
||||||
mNextEdgeName.Truncate();
|
mNextEdgeName.Truncate();
|
||||||
#endif
|
}
|
||||||
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()) {
|
||||||
|
edgeName.Assign(mNextEdgeName);
|
||||||
mNextEdgeName.Truncate();
|
mNextEdgeName.Truncate();
|
||||||
#endif
|
}
|
||||||
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.
|
|
||||||
PRBool anyWhites = PR_FALSE;
|
|
||||||
NodePool::Enumerator fwetor(mGraph.mNodes);
|
|
||||||
while (!fwetor.IsDone())
|
|
||||||
{
|
|
||||||
PtrInfo *pinfo = fwetor.GetNext();
|
|
||||||
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;
|
FILE *stream;
|
||||||
#ifdef WIN32
|
char name[255];
|
||||||
stream = fopen("c:\\cycle-graph.dot", "w+");
|
sprintf(name, "cycle-graph-%d.dot", ++gCounter);
|
||||||
#else
|
stream = fopen(name, "w");
|
||||||
stream = popen("dotty -", "w");
|
|
||||||
#endif
|
|
||||||
WriteGraph(stream, mGraph, nsnull);
|
WriteGraph(stream, mGraph, nsnull);
|
||||||
#ifdef WIN32
|
|
||||||
fclose(stream);
|
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
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user