Fix for bug 466157 (Enable dumping of cycle-collector graphs in any build). r=dbaron, a=jst.

--HG--
extra : rebase_source : b47d149434c735981a9a80ae6016624120fee371
This commit is contained in:
Robert O'Callahan 2010-08-12 12:03:23 +12:00
parent da189d241a
commit b096738cb6
11 changed files with 281 additions and 156 deletions

View File

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

View File

@ -307,7 +307,7 @@ NS_IMETHODIMP
nsCCMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
const PRUnichar* aData)
{
nsJSContext::CC();
nsJSContext::CC(nsnull);
return NS_OK;
}
@ -3512,7 +3512,7 @@ nsJSContext::ScriptExecuted()
//static
void
nsJSContext::CC()
nsJSContext::CC(nsICycleCollectorListener *aListener)
{
NS_TIME_FUNCTION_MIN(1.0);
@ -3527,7 +3527,7 @@ nsJSContext::CC()
// nsCycleCollector_collect() no longer forces a JS garbage collection,
// so we have to do it ourselves here.
nsContentUtils::XPConnect()->GarbageCollect();
sCollectedObjectsCounts = nsCycleCollector_collect();
sCollectedObjectsCounts = nsCycleCollector_collect(aListener);
sCCSuspectedCount = nsCycleCollector_suspectedCount();
sSavedGCCount = JS_GetGCParameter(nsJSRuntime::sRuntime, JSGC_NUMBER);
#ifdef DEBUG_smaug
@ -3615,7 +3615,7 @@ nsJSContext::IntervalCC()
{
if ((PR_Now() - sPreviousCCTime) >=
PRTime(NS_MIN_CC_INTERVAL * PR_USEC_PER_MSEC)) {
nsJSContext::CC();
nsJSContext::CC(nsnull);
return PR_TRUE;
}
#ifdef DEBUG_smaug

View File

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

View File

@ -45,6 +45,7 @@
* getInterface on a DOMWindow.
*/
interface nsICycleCollectorListener;
interface nsIDOMNode;
interface nsIDOMNodeList;
interface nsIDOMElement;
@ -53,7 +54,7 @@ interface nsIDOMEvent;
interface nsITransferable;
interface nsIQueryContentEventResult;
[scriptable, uuid(8430e730-a085-421e-bb72-39fcf73fe57b)]
[scriptable, uuid(bf4df3a0-4567-47ec-be6d-9ec60eaed63c)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -267,13 +268,16 @@ interface nsIDOMWindowUtils : nsISupports {
void focus(in nsIDOMElement aElement);
/**
* Force a garbage collection. This will run the cycle-collector twice to
* make sure all garbage is collected.
* Force a garbage collection followed by a cycle collection.
*
* Will throw a DOM security error if called without UniversalXPConnect
* privileges in non-debug builds. Available to all callers in debug builds.
*
* @param aListener listener that receives information about the CC graph
* (see @mozilla.org/cycle-collector-logger;1 for a logger
* component)
*/
void garbageCollect();
void garbageCollect([optional] in nsICycleCollectorListener aListener);
/**
* Force processing of any queued paints

View File

@ -126,6 +126,7 @@ XPIDLSRCS = \
nsIConsoleListener.idl \
nsIConsoleMessage.idl \
nsIConsoleService.idl \
nsICycleCollectorListener.idl \
nsIDebug2.idl \
nsIErrorService.idl \
nsIException.idl \

View File

@ -146,6 +146,7 @@
#include "nsTPtrArray.h"
#include "nsTArray.h"
#include "mozilla/Services.h"
#include "nsICycleCollectorListener.h"
#include <stdio.h>
#include <string.h>
@ -651,11 +652,6 @@ struct GCGraph
// Add/Remove/Has rather than PutEntry/RemoveEntry/GetEntry.
typedef nsTHashtable<nsVoidPtrHashKey> PointerSet;
#ifdef DEBUG_CC
static void
WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr);
#endif
static inline void
ToParticipant(nsISupports *s, nsXPCOMCycleCollectionParticipant **cp);
@ -995,8 +991,9 @@ struct nsCycleCollector
nsPurpleBufferEntry* Suspect2(nsISupports *n);
PRBool Forget2(nsPurpleBufferEntry *e);
PRUint32 Collect(PRUint32 aTryCollections = 1);
PRBool BeginCollection();
PRUint32 Collect(PRUint32 aTryCollections,
nsICycleCollectorListener *aListener);
PRBool BeginCollection(nsICycleCollectorListener *aListener);
PRBool FinishCollection();
PRUint32 SuspectedCount();
void Shutdown();
@ -1013,7 +1010,6 @@ struct nsCycleCollector
FILE *mPtrLog;
void MaybeDrawGraphs();
void Allocated(void *n, size_t sz);
void Freed(void *n);
@ -1105,20 +1101,6 @@ Fault(const char *msg, const void *ptr=nsnull)
else
printf("Fatal fault in cycle collector: %s\n", msg);
if (sCollector->mGraph.mRootCount > 0) {
FILE *stream;
#ifdef WIN32
const char fname[] = "c:\\fault-graph.dot";
#else
const char fname[] = "/tmp/fault-graph.dot";
#endif
printf("depositing faulting cycle-collection graph in %s\n", fname);
stream = fopen(fname, "w+");
WriteGraph(stream, sCollector->mGraph, ptr);
fclose(stream);
}
exit(1);
}
#endif
@ -1263,6 +1245,95 @@ GraphWalker<Visitor>::DoWalk(nsDeque &aQueue)
}
class nsCycleCollectorLogger : public nsICycleCollectorListener
{
public:
nsCycleCollectorLogger() : mStream(nsnull)
{
}
~nsCycleCollectorLogger()
{
if (mStream) {
fclose(mStream);
}
}
NS_DECL_ISUPPORTS
NS_IMETHOD Begin()
{
char name[255];
sprintf(name, "cc-edges-%d.log", ++gLogCounter);
mStream = fopen(name, "w");
return mStream ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHOD NoteObject(PRUint64 aAddress, const char *aObjectDescription)
{
fprintf(mStream, "%p %s\n", (void*)aAddress, aObjectDescription);
return NS_OK;
}
NS_IMETHOD NoteEdge(PRUint64 aFromAddress, PRUint64 aToAddress,
const char *aEdgeName)
{
fprintf(mStream, "> %p %s\n", (void*)aToAddress, aEdgeName);
return NS_OK;
}
NS_IMETHOD BeginDescriptions()
{
fputs("==========\n", mStream);
return NS_OK;
}
NS_IMETHOD DescribeRefcountedObject(PRUint64 aAddress, PRUint32 aKnownEdges,
PRUint32 aTotalEdges)
{
PRBool root = aKnownEdges != aTotalEdges;
fprintf(mStream, "%p", (void*)aAddress);
if (root) {
fprintf(mStream, " [root] [%u/%u]", aKnownEdges, aTotalEdges);
}
fputc('\n', mStream);
return NS_OK;
}
NS_IMETHOD DescribeGCedObject(PRUint64 aAddress, PRBool aMarked)
{
fprintf(mStream, "%p%s\n", (void*)aAddress, aMarked ? " [root]" : "");
return NS_OK;
}
NS_IMETHOD End()
{
fclose(mStream);
mStream = nsnull;
return NS_OK;
}
private:
FILE *mStream;
static PRUint32 gLogCounter;
};
NS_IMPL_ISUPPORTS1(nsCycleCollectorLogger, nsICycleCollectorListener)
PRUint32 nsCycleCollectorLogger::gLogCounter = 0;
nsresult
nsCycleCollectorLoggerConstructor(nsISupports* aOuter,
const nsIID& aIID,
void* *aInstancePtr)
{
NS_ENSURE_TRUE(!aOuter, NS_ERROR_NO_AGGREGATION);
nsISupports *logger = new nsCycleCollectorLogger();
return logger->QueryInterface(aIID, aInstancePtr);
}
////////////////////////////////////////////////////////////////////////
// Bacon & Rajan's |MarkRoots| routine.
////////////////////////////////////////////////////////////////////////
@ -1301,13 +1372,13 @@ private:
PLDHashTable mPtrToNodeMap;
PtrInfo *mCurrPi;
nsCycleCollectionLanguageRuntime **mRuntimes; // weak, from nsCycleCollector
#ifdef DEBUG_CC
nsCString mNextEdgeName;
#endif
nsCOMPtr<nsICycleCollectorListener> mListener;
public:
GCGraphBuilder(GCGraph &aGraph,
nsCycleCollectionLanguageRuntime **aRuntimes);
nsCycleCollectionLanguageRuntime **aRuntimes,
nsICycleCollectorListener *aListener);
~GCGraphBuilder();
bool Initialized();
@ -1342,19 +1413,25 @@ private:
};
GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph,
nsCycleCollectionLanguageRuntime **aRuntimes)
nsCycleCollectionLanguageRuntime **aRuntimes,
nsICycleCollectorListener *aListener)
: mNodeBuilder(aGraph.mNodes),
mEdgeBuilder(aGraph.mEdges),
mRuntimes(aRuntimes)
mRuntimes(aRuntimes),
mListener(aListener)
{
if (!PL_DHashTableInit(&mPtrToNodeMap, &PtrNodeOps, nsnull,
sizeof(PtrToNodeEntry), 32768))
mPtrToNodeMap.ops = nsnull;
#ifdef DEBUG_CC
// Do we need to set these all the time?
mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
// We want all edges and all info if DEBUG_CC is set or if we have a
// listener. Do we want them all the time?
#ifndef DEBUG_CC
if (mListener)
#endif
{
mFlags |= nsCycleCollectionTraversalCallback::WANT_DEBUG_INFO |
nsCycleCollectionTraversalCallback::WANT_ALL_TRACES;
}
}
GCGraphBuilder::~GCGraphBuilder()
@ -1461,6 +1538,10 @@ GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount,
mCurrPi->mName = PL_strdup(objName);
#endif
if (mListener) {
mListener->NoteObject((PRUint64)mCurrPi->mPointer, objName);
}
if (type == RefCounted) {
if (refCount == 0 || refCount == PR_UINT32_MAX)
Fault("zero or overflowing refcount", mCurrPi);
@ -1478,10 +1559,11 @@ GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount,
NS_IMETHODIMP_(void)
GCGraphBuilder::NoteXPCOMChild(nsISupports *child)
{
#ifdef DEBUG_CC
nsCString edgeName(mNextEdgeName);
mNextEdgeName.Truncate();
#endif
nsCString edgeName;
if (WantDebugInfo()) {
edgeName.Assign(mNextEdgeName);
mNextEdgeName.Truncate();
}
if (!child || !(child = canonicalize(child)))
return;
@ -1500,6 +1582,10 @@ GCGraphBuilder::NoteXPCOMChild(nsISupports *child)
#ifdef DEBUG_CC
mCurrPi->mEdgeNames.AppendElement(edgeName);
#endif
if (mListener) {
mListener->NoteEdge((PRUint64)mCurrPi->mPointer, (PRUint64)child,
edgeName.get());
}
++childPi->mInternalRefs;
}
}
@ -1508,10 +1594,11 @@ NS_IMETHODIMP_(void)
GCGraphBuilder::NoteNativeChild(void *child,
nsCycleCollectionParticipant *participant)
{
#ifdef DEBUG_CC
nsCString edgeName(mNextEdgeName);
mNextEdgeName.Truncate();
#endif
nsCString edgeName;
if (WantDebugInfo()) {
edgeName.Assign(mNextEdgeName);
mNextEdgeName.Truncate();
}
if (!child)
return;
@ -1524,16 +1611,21 @@ GCGraphBuilder::NoteNativeChild(void *child,
#ifdef DEBUG_CC
mCurrPi->mEdgeNames.AppendElement(edgeName);
#endif
if (mListener) {
mListener->NoteEdge((PRUint64)mCurrPi->mPointer, (PRUint64)child,
edgeName.get());
}
++childPi->mInternalRefs;
}
NS_IMETHODIMP_(void)
GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child)
{
#ifdef DEBUG_CC
nsCString edgeName(mNextEdgeName);
mNextEdgeName.Truncate();
#endif
nsCString edgeName;
if (WantDebugInfo()) {
edgeName.Assign(mNextEdgeName);
mNextEdgeName.Truncate();
}
if (!child)
return;
@ -1559,15 +1651,19 @@ GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child)
#ifdef DEBUG_CC
mCurrPi->mEdgeNames.AppendElement(edgeName);
#endif
if (mListener) {
mListener->NoteEdge((PRUint64)mCurrPi->mPointer, (PRUint64)child,
edgeName.get());
}
++childPi->mInternalRefs;
}
NS_IMETHODIMP_(void)
GCGraphBuilder::NoteNextEdgeName(const char* name)
{
#ifdef DEBUG_CC
mNextEdgeName = name;
#endif
if (WantDebugInfo()) {
mNextEdgeName = name;
}
}
static PRBool
@ -2079,91 +2175,7 @@ nsCycleCollector::ForgetRuntime(PRUint32 langID)
mRuntimes[langID] = nsnull;
}
#ifdef DEBUG_CC
static void
WriteGraph(FILE *stream, GCGraph &graph, const void *redPtr)
{
fprintf(stream,
"digraph collection {\n"
"rankdir=LR\n"
"node [fontname=fixed, fontsize=10, style=filled, shape=box]\n"
);
NodePool::Enumerator etor(graph.mNodes);
while (!etor.IsDone()) {
PtrInfo *pi = etor.GetNext();
const void *p = pi->mPointer;
fprintf(stream,
"n%p [label=\"%s\\n%p\\n",
p,
pi->mName,
p);
if (pi->mRefCount != 0 && pi->mRefCount != PR_UINT32_MAX) {
fprintf(stream,
"%u/%u refs found",
pi->mInternalRefs, pi->mRefCount);
}
fprintf(stream,
"\", fillcolor=%s, fontcolor=%s]\n",
(redPtr && redPtr == p ? "red" : (pi->mColor == black ? "black" : "white")),
(pi->mColor == black ? "white" : "black"));
for (EdgePool::Iterator child = pi->mFirstChild,
child_end = pi->mLastChild;
child != child_end; ++child) {
fprintf(stream, "n%p -> n%p\n", p, (*child)->mPointer);
}
}
fprintf(stream, "\n}\n");
}
void
nsCycleCollector::MaybeDrawGraphs()
{
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;
#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
}
}
}
class Suppressor :
public nsCycleCollectionTraversalCallback
@ -2416,7 +2428,8 @@ nsCycleCollector::Freed(void *n)
#endif
PRUint32
nsCycleCollector::Collect(PRUint32 aTryCollections)
nsCycleCollector::Collect(PRUint32 aTryCollections,
nsICycleCollectorListener *aListener)
{
#if defined(DEBUG_CC) && !defined(__MINGW32__)
if (!mParams.mDoNothing && mParams.mHookMalloc)
@ -2434,6 +2447,12 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
PRTime start = PR_Now();
#endif
#ifdef DEBUG_CC
if (!aListener && mParams.mDrawGraphs) {
aListener = new nsCycleCollectorLogger();
}
#endif
mCollectionInProgress = PR_TRUE;
nsCOMPtr<nsIObserverService> obs =
@ -2468,7 +2487,7 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
#endif
}
PRBool collected = BeginCollection() && FinishCollection();
PRBool collected = BeginCollection(aListener) && FinishCollection();
#ifdef DEBUG_CC
// We wait until after FinishCollection to check the white nodes because
@ -2521,12 +2540,16 @@ nsCycleCollector::Collect(PRUint32 aTryCollections)
}
PRBool
nsCycleCollector::BeginCollection()
nsCycleCollector::BeginCollection(nsICycleCollectorListener *aListener)
{
if (mParams.mDoNothing)
return PR_FALSE;
GCGraphBuilder builder(mGraph, mRuntimes);
if (aListener && NS_FAILED(aListener->Begin())) {
aListener = nsnull;
}
GCGraphBuilder builder(mGraph, mRuntimes, aListener);
if (!builder.Initialized())
return PR_FALSE;
@ -2604,12 +2627,29 @@ nsCycleCollector::BeginCollection()
(PR_Now() - now) / PR_USEC_PER_MSEC);
#endif
#ifdef DEBUG_CC
MaybeDrawGraphs();
#endif
mScanInProgress = PR_FALSE;
if (aListener) {
aListener->BeginDescriptions();
NodePool::Enumerator etor(mGraph.mNodes);
while (!etor.IsDone()) {
PtrInfo *pi = etor.GetNext();
if (pi->mColor == black) {
PRUint64 p = (PRUint64)pi->mPointer;
if (pi->mRefCount > 0 && pi->mRefCount < PR_UINT32_MAX) {
aListener->DescribeRefcountedObject(p, pi->mInternalRefs,
pi->mRefCount);
}
else {
aListener->DescribeGCedObject(p, pi->mRefCount != 0);
}
}
}
aListener->End();
}
#ifdef DEBUG_CC
if (mFollowupCollection && purpleStart != purpleEnd) {
PRUint32 i = 0;
@ -2692,10 +2732,10 @@ nsCycleCollector::Shutdown()
mRuntimes[i]->CommenceShutdown();
}
Collect(SHUTDOWN_COLLECTIONS(mParams));
Collect(SHUTDOWN_COLLECTIONS(mParams), nsnull);
#ifdef DEBUG_CC
GCGraphBuilder builder(mGraph, mRuntimes);
GCGraphBuilder builder(mGraph, mRuntimes, nsnull);
mScanInProgress = PR_TRUE;
SelectPurple(builder);
mScanInProgress = PR_FALSE;
@ -2770,7 +2810,7 @@ nsCycleCollector::ExplainLiveExpectedGarbage()
mScanInProgress = PR_TRUE;
{
GCGraphBuilder builder(mGraph, mRuntimes);
GCGraphBuilder builder(mGraph, mRuntimes, nsnull);
// Instead of adding roots from the purple buffer, we add them
// from the list of nodes we were expected to collect.
@ -3163,9 +3203,9 @@ NS_CycleCollectorForget2(nsPurpleBufferEntry *e)
PRUint32
nsCycleCollector_collect()
nsCycleCollector_collect(nsICycleCollectorListener *aListener)
{
return sCollector ? sCollector->Collect() : 0;
return sCollector ? sCollector->Collect(1, aListener) : 0;
}
PRUint32

View File

@ -43,6 +43,7 @@
//#define DEBUG_CC
class nsISupports;
class nsICycleCollectorListener;
class nsCycleCollectionParticipant;
class nsCycleCollectionTraversalCallback;
@ -63,7 +64,7 @@ struct nsCycleCollectionLanguageRuntime
nsresult nsCycleCollector_startup();
// Returns the number of collected nodes.
NS_COM PRUint32 nsCycleCollector_collect();
NS_COM PRUint32 nsCycleCollector_collect(nsICycleCollectorListener *aListener);
NS_COM PRUint32 nsCycleCollector_suspectedCount();
void nsCycleCollector_shutdown();
@ -91,4 +92,13 @@ NS_COM void nsCycleCollector_registerRuntime(PRUint32 langID, nsCycleCollectionL
NS_COM nsCycleCollectionLanguageRuntime * nsCycleCollector_getRuntime(PRUint32 langID);
NS_COM void nsCycleCollector_forgetRuntime(PRUint32 langID);
#define NS_CYCLE_COLLECTOR_LOGGER_CID \
{ 0x58be81b4, 0x39d2, 0x437c, \
{ 0x94, 0xea, 0xae, 0xde, 0x2c, 0x62, 0x08, 0xd3 } }
extern nsresult
nsCycleCollectorLoggerConstructor(nsISupports* outer,
const nsIID& aIID,
void* *aInstancePtr);
#endif // nsCycleCollector_h__

View File

@ -0,0 +1,64 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is XPCOM cycle collector.
*
* The Initial Developer of the Original Code is
* Mozilla Corporation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/**
* Interface to pass to the cycle collector to get information about the CC
* graph while it's being built. The order of calls will be call to begin();
* then for every node in the graph a call to noteObject() and calls to
* noteEdge() for every edge starting at that node; then a call to
* beginDescriptions(); then for every black node in the CC graph a call to
* either describeRefcountedObject() or to describeGCedObject(); and then a
* call to end(). If begin() returns an error none of the other functions will
* be called.
*/
[scriptable, uuid(194b749a-4ceb-4dd1-928d-d30b5f14c23e)]
interface nsICycleCollectorListener : nsISupports
{
void begin();
void noteObject(in unsigned long long aAddress,
in string aObjectDescription);
void noteEdge(in unsigned long long aFromAddress,
in unsigned long long aToAddress,
in string aEdgeName);
void beginDescriptions();
void describeRefcountedObject(in unsigned long long aAddress,
in unsigned long aKnownEdges,
in unsigned long aTotalEdges);
void describeGCedObject(in unsigned long long aAddress, in boolean aMarked);
void end();
};

View File

@ -87,3 +87,4 @@
COMPONENT(SYSTEMINFO, nsSystemInfoConstructor)
COMPONENT(MEMORY_REPORTER_MANAGER, nsMemoryReporterManagerConstructor)
COMPONENT(IOUTIL, nsIOUtilConstructor)
COMPONENT(CYCLE_COLLECTOR_LOGGER, nsCycleCollectorLoggerConstructor)

View File

@ -276,7 +276,7 @@ void XXXNeverCalled()
}
nsXPCOMCycleCollectionParticipant();
nsCycleCollector_collect();
nsCycleCollector_collect(nsnull);
#ifdef XP_WIN
sXPCOMHasLoadedNewDLLs = !sXPCOMHasLoadedNewDLLs;
NS_SetHasLoadedNewDLLs();

View File

@ -102,6 +102,11 @@
*/
#define NS_MEMORY_REPORTER_MANAGER_CONTRACTID "@mozilla.org/memory-reporter-manager;1"
/**
* Cycle collector logger contract id
*/
#define NS_CYCLE_COLLECTOR_LOGGER_CONTRACTID "@mozilla.org/cycle-collector-logger;1"
/**
* The following are the CIDs and Contract IDs of the nsISupports wrappers for
* primative types.