mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Make some of the DEBUG_CC code accessible to code in non-debug builds so it can be used by memory tools for Web developers. (Bug 500233) r+sr=peterv
This commit is contained in:
parent
caf9fffbee
commit
dfd2b373c7
@ -36,6 +36,7 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIObserver.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
class nsCCUncollectableMarker : public nsIObserver
|
||||
{
|
||||
@ -50,8 +51,11 @@ class nsCCUncollectableMarker : public nsIObserver
|
||||
/**
|
||||
* Checks if we're collecting during a given generation
|
||||
*/
|
||||
static PRBool InGeneration(PRUint32 aGeneration) {
|
||||
return aGeneration && aGeneration == sGeneration;
|
||||
static PRBool InGeneration(nsCycleCollectionTraversalCallback &cb,
|
||||
PRUint32 aGeneration) {
|
||||
return !cb.WantAllTraces() &&
|
||||
aGeneration &&
|
||||
aGeneration == sGeneration;
|
||||
}
|
||||
|
||||
static PRUint32 sGeneration;
|
||||
|
@ -1723,7 +1723,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDocument)
|
||||
// if we're uncollectable.
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
|
||||
if (nsCCUncollectableMarker::InGeneration(tmp->GetMarkedCCGeneration())) {
|
||||
if (nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration())) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
||||
|
@ -91,7 +91,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericDOMDataNode)
|
||||
|
||||
nsIDocument* currentDoc = tmp->GetCurrentDoc();
|
||||
if (currentDoc && nsCCUncollectableMarker::InGeneration(
|
||||
currentDoc->GetMarkedCCGeneration())) {
|
||||
cb, currentDoc->GetMarkedCCGeneration())) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
||||
|
@ -4009,7 +4009,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericElement)
|
||||
|
||||
nsIDocument* currentDoc = tmp->GetCurrentDoc();
|
||||
if (currentDoc && nsCCUncollectableMarker::InGeneration(
|
||||
currentDoc->GetMarkedCCGeneration())) {
|
||||
cb, currentDoc->GetMarkedCCGeneration())) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
||||
|
@ -238,7 +238,7 @@ nsHTMLDocument::nsHTMLDocument()
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(nsHTMLDocument)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsHTMLDocument, nsDocument)
|
||||
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(tmp->GetMarkedCCGeneration()),
|
||||
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
|
||||
"Shouldn't traverse nsHTMLDocument!");
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mImageMaps)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mImages)
|
||||
|
@ -335,7 +335,7 @@ TraverseObservers(nsIURI* aKey, nsIObserver* aData, void* aContext)
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsXULDocument, nsXMLDocument)
|
||||
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(tmp->GetMarkedCCGeneration()),
|
||||
NS_ASSERTION(!nsCCUncollectableMarker::InGeneration(cb, tmp->GetMarkedCCGeneration()),
|
||||
"Shouldn't traverse nsXULDocument!");
|
||||
// XXX tmp->mForwardReferences?
|
||||
// XXX tmp->mContextStack?
|
||||
|
@ -1017,7 +1017,7 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGlobalWindow,
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
|
||||
if (tmp->mDoc && nsCCUncollectableMarker::InGeneration(
|
||||
tmp->mDoc->GetMarkedCCGeneration())) {
|
||||
cb, tmp->mDoc->GetMarkedCCGeneration())) {
|
||||
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
|
||||
}
|
||||
|
||||
|
@ -651,21 +651,23 @@ NoteJSChild(JSTracer *trc, void *thing, uint32 kind)
|
||||
if(ADD_TO_CC(kind))
|
||||
{
|
||||
TraversalTracer *tracer = static_cast<TraversalTracer*>(trc);
|
||||
#if defined(DEBUG) && defined(DEBUG_CC)
|
||||
// based on DumpNotify in jsapi.c
|
||||
if (tracer->debugPrinter) {
|
||||
char buffer[200];
|
||||
tracer->debugPrinter(trc, buffer, sizeof(buffer));
|
||||
tracer->cb.NoteNextEdgeName(buffer);
|
||||
} else if (tracer->debugPrintIndex != (size_t)-1) {
|
||||
char buffer[200];
|
||||
JS_snprintf(buffer, sizeof(buffer), "%s[%lu]",
|
||||
static_cast<const char *>(tracer->debugPrintArg),
|
||||
tracer->debugPrintIndex);
|
||||
tracer->cb.NoteNextEdgeName(buffer);
|
||||
} else {
|
||||
tracer->cb.NoteNextEdgeName(
|
||||
static_cast<const char*>(tracer->debugPrintArg));
|
||||
#if defined(DEBUG)
|
||||
if (NS_UNLIKELY(tracer->cb.WantDebugInfo())) {
|
||||
// based on DumpNotify in jsapi.c
|
||||
if (tracer->debugPrinter) {
|
||||
char buffer[200];
|
||||
tracer->debugPrinter(trc, buffer, sizeof(buffer));
|
||||
tracer->cb.NoteNextEdgeName(buffer);
|
||||
} else if (tracer->debugPrintIndex != (size_t)-1) {
|
||||
char buffer[200];
|
||||
JS_snprintf(buffer, sizeof(buffer), "%s[%lu]",
|
||||
static_cast<const char *>(tracer->debugPrintArg),
|
||||
tracer->debugPrintIndex);
|
||||
tracer->cb.NoteNextEdgeName(buffer);
|
||||
} else {
|
||||
tracer->cb.NoteNextEdgeName(
|
||||
static_cast<const char*>(tracer->debugPrintArg));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
tracer->cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, thing);
|
||||
@ -732,7 +734,6 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||
CCNodeType type;
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
{
|
||||
// Note that the conditions under which we specify GCMarked vs.
|
||||
// GCUnmarked are different between ExplainLiveExpectedGarbage and
|
||||
// the normal case. In the normal case, we're saying that anything
|
||||
@ -752,149 +753,150 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||
GCUnmarked;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Normal codepath (matches non-DEBUG_CC codepath).
|
||||
type = !markJSObject && JS_IsAboutToBeFinalized(cx, p) ? GCUnmarked :
|
||||
GCMarked;
|
||||
}
|
||||
|
||||
char name[72];
|
||||
if(traceKind == JSTRACE_OBJECT)
|
||||
{
|
||||
JSObject *obj = static_cast<JSObject*>(p);
|
||||
JSClass *clazz = OBJ_GET_CLASS(cx, obj);
|
||||
if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
|
||||
if (cb.WantDebugInfo()) {
|
||||
char name[72];
|
||||
if(traceKind == JSTRACE_OBJECT)
|
||||
{
|
||||
XPCWrappedNative* wn;
|
||||
if(XPCNativeWrapper::GetWrappedNative(cx, obj, &wn) && wn)
|
||||
JSObject *obj = static_cast<JSObject*>(p);
|
||||
JSClass *clazz = OBJ_GET_CLASS(cx, obj);
|
||||
if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
|
||||
{
|
||||
XPCNativeScriptableInfo* si = wn->GetScriptableInfo();
|
||||
if(si)
|
||||
XPCWrappedNative* wn;
|
||||
if(XPCNativeWrapper::GetWrappedNative(cx, obj, &wn) && wn)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
|
||||
si->GetJSClass()->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsIClassInfo* ci = wn->GetClassInfo();
|
||||
char* className = nsnull;
|
||||
if(ci)
|
||||
ci->GetClassDescription(&className);
|
||||
if(className)
|
||||
XPCNativeScriptableInfo* si = wn->GetScriptableInfo();
|
||||
if(si)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
|
||||
className);
|
||||
PR_Free(className);
|
||||
si->GetJSClass()->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
XPCNativeSet* set = wn->GetSet();
|
||||
XPCNativeInterface** array = set->GetInterfaceArray();
|
||||
PRUint16 count = set->GetInterfaceCount();
|
||||
|
||||
if(count > 0)
|
||||
nsIClassInfo* ci = wn->GetClassInfo();
|
||||
char* className = nsnull;
|
||||
if(ci)
|
||||
ci->GetClassDescription(&className);
|
||||
if(className)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name),
|
||||
"XPCNativeWrapper (%s)",
|
||||
array[0]->GetNameString());
|
||||
"XPCNativeWrapper (%s)", className);
|
||||
PR_Free(className);
|
||||
}
|
||||
else
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper");
|
||||
{
|
||||
XPCNativeSet* set = wn->GetSet();
|
||||
XPCNativeInterface** array =
|
||||
set->GetInterfaceArray();
|
||||
PRUint16 count = set->GetInterfaceCount();
|
||||
|
||||
if(count > 0)
|
||||
JS_snprintf(name, sizeof(name),
|
||||
"XPCNativeWrapper (%s)",
|
||||
array[0]->GetNameString());
|
||||
else
|
||||
JS_snprintf(name, sizeof(name),
|
||||
"XPCNativeWrapper");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper");
|
||||
XPCNativeScriptableInfo* si = nsnull;
|
||||
if(IS_PROTO_CLASS(clazz))
|
||||
{
|
||||
XPCWrappedNativeProto* p =
|
||||
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
|
||||
si = p->GetScriptableInfo();
|
||||
}
|
||||
if(si)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
|
||||
clazz->name, si->GetJSClass()->name);
|
||||
}
|
||||
else if(clazz == &js_ScriptClass)
|
||||
{
|
||||
JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
|
||||
if(script->filename)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name),
|
||||
"JS Object (Script - %s)",
|
||||
script->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Script)");
|
||||
}
|
||||
}
|
||||
else if(clazz == &js_FunctionClass)
|
||||
{
|
||||
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
|
||||
JSString* str = JS_GetFunctionId(fun);
|
||||
if(str)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8
|
||||
fname(JS_GetStringChars(str));
|
||||
JS_snprintf(name, sizeof(name),
|
||||
"JS Object (Function - %s)", fname.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Function)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s)",
|
||||
clazz->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XPCNativeScriptableInfo* si = nsnull;
|
||||
if(IS_PROTO_CLASS(clazz))
|
||||
{
|
||||
XPCWrappedNativeProto* p =
|
||||
(XPCWrappedNativeProto*) xpc_GetJSPrivate(obj);
|
||||
si = p->GetScriptableInfo();
|
||||
}
|
||||
if(si)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s - %s)",
|
||||
clazz->name, si->GetJSClass()->name);
|
||||
}
|
||||
else if(clazz == &js_ScriptClass)
|
||||
{
|
||||
JSScript* script = (JSScript*) xpc_GetJSPrivate(obj);
|
||||
if(script->filename)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Script - %s)",
|
||||
script->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Script)");
|
||||
}
|
||||
}
|
||||
else if(clazz == &js_FunctionClass)
|
||||
{
|
||||
JSFunction* fun = (JSFunction*) xpc_GetJSPrivate(obj);
|
||||
JSString* str = JS_GetFunctionId(fun);
|
||||
if(str)
|
||||
{
|
||||
NS_ConvertUTF16toUTF8
|
||||
fname(JS_GetStringChars(str));
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Function - %s)",
|
||||
fname.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Function)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s)", clazz->name);
|
||||
}
|
||||
static const char trace_types[JSTRACE_LIMIT][7] = {
|
||||
"Object",
|
||||
"Double",
|
||||
"String",
|
||||
"Xml"
|
||||
};
|
||||
JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char trace_types[JSTRACE_LIMIT][7] = {
|
||||
"Object",
|
||||
"Double",
|
||||
"String",
|
||||
"Xml"
|
||||
};
|
||||
JS_snprintf(name, sizeof(name), "JS %s", trace_types[traceKind]);
|
||||
}
|
||||
|
||||
if(traceKind == JSTRACE_OBJECT) {
|
||||
JSObject *global = static_cast<JSObject*>(p), *parent;
|
||||
while((parent = JS_GetParent(cx, global)))
|
||||
global = parent;
|
||||
char fullname[100];
|
||||
JS_snprintf(fullname, sizeof(fullname), "%s (global=%p)", name, global);
|
||||
cb.DescribeNode(type, 0, sizeof(JSObject), fullname);
|
||||
if(traceKind == JSTRACE_OBJECT) {
|
||||
JSObject *global = static_cast<JSObject*>(p), *parent;
|
||||
while((parent = JS_GetParent(cx, global)))
|
||||
global = parent;
|
||||
char fullname[100];
|
||||
JS_snprintf(fullname, sizeof(fullname),
|
||||
"%s (global=%p)", name, global);
|
||||
cb.DescribeNode(type, 0, sizeof(JSObject), fullname);
|
||||
} else {
|
||||
cb.DescribeNode(type, 0, sizeof(JSObject), name);
|
||||
}
|
||||
} else {
|
||||
cb.DescribeNode(type, 0, sizeof(JSObject), name);
|
||||
cb.DescribeNode(type, 0, sizeof(JSObject), "JS Object");
|
||||
}
|
||||
|
||||
}
|
||||
#else
|
||||
type = !markJSObject && JS_IsAboutToBeFinalized(cx, p) ? GCUnmarked :
|
||||
GCMarked;
|
||||
cb.DescribeNode(type, 0);
|
||||
#endif
|
||||
|
||||
if(!ADD_TO_CC(traceKind))
|
||||
return NS_OK;
|
||||
|
||||
#ifndef DEBUG_CC
|
||||
// There's no need to trace objects that have already been marked by the JS
|
||||
// GC. Any JS objects hanging from them will already be marked. Only do this
|
||||
// if DEBUG_CC is not defined, else we do want to know about all JS objects
|
||||
// to get better graphs and explanations.
|
||||
if(type == GCMarked)
|
||||
if(!cb.WantAllTraces() && type == GCMarked)
|
||||
return NS_OK;
|
||||
#endif
|
||||
|
||||
TraversalTracer trc(cb);
|
||||
|
||||
@ -968,13 +970,9 @@ public:
|
||||
// collected.
|
||||
PRInt32 refCount = nsXPConnect::GetXPConnect()->GetRequestDepth(cx) + 1;
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
cb.DescribeNode(RefCounted, refCount, sizeof(JSContext),
|
||||
"JSContext");
|
||||
cb.NoteNextEdgeName("[global object]");
|
||||
#else
|
||||
cb.DescribeNode(RefCounted, refCount);
|
||||
#endif
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[global object]");
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
cx->globalObject);
|
||||
|
||||
|
@ -414,13 +414,13 @@ void XPCJSRuntime::AddXPConnectRoots(JSContext* cx,
|
||||
JSContext *iter = nsnull, *acx;
|
||||
while((acx = JS_ContextIterator(GetJSRuntime(), &iter)))
|
||||
{
|
||||
#ifndef DEBUG_CC
|
||||
// Only skip JSContexts with outstanding requests if DEBUG_CC is not
|
||||
// defined, else we do want to know about all JSContexts to get better
|
||||
// graphs and explanations.
|
||||
if(nsXPConnect::GetXPConnect()->GetRequestDepth(acx) != 0)
|
||||
// Only skip JSContexts with outstanding requests if the
|
||||
// callback does not want all traces (a debug feature).
|
||||
// Otherwise, we do want to know about all JSContexts to get
|
||||
// better graphs and explanations.
|
||||
if(!cb.WantAllTraces() &&
|
||||
nsXPConnect::GetXPConnect()->GetRequestDepth(acx) != 0)
|
||||
continue;
|
||||
#endif
|
||||
cb.NoteRoot(nsIProgrammingLanguage::CPLUSPLUS, acx,
|
||||
nsXPConnect::JSContextParticipant());
|
||||
}
|
||||
|
@ -57,17 +57,18 @@ NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Traverse
|
||||
nsXPCWrappedJS *tmp = Downcast(s);
|
||||
|
||||
nsrefcnt refcnt = tmp->mRefCnt.get();
|
||||
#ifdef DEBUG_CC
|
||||
char name[72];
|
||||
if (tmp->GetClass())
|
||||
JS_snprintf(name, sizeof(name), "nsXPCWrappedJS (%s)",
|
||||
tmp->GetClass()->GetInterfaceName());
|
||||
else
|
||||
JS_snprintf(name, sizeof(name), "nsXPCWrappedJS");
|
||||
cb.DescribeNode(RefCounted, refcnt, sizeof(nsXPCWrappedJS), name);
|
||||
#else
|
||||
cb.DescribeNode(RefCounted, refcnt);
|
||||
#endif
|
||||
if (cb.WantDebugInfo()) {
|
||||
char name[72];
|
||||
if (tmp->GetClass())
|
||||
JS_snprintf(name, sizeof(name), "nsXPCWrappedJS (%s)",
|
||||
tmp->GetClass()->GetInterfaceName());
|
||||
else
|
||||
JS_snprintf(name, sizeof(name), "nsXPCWrappedJS");
|
||||
cb.DescribeNode(RefCounted, refcnt, sizeof(nsXPCWrappedJS), name);
|
||||
} else {
|
||||
cb.DescribeNode(RefCounted, refcnt, sizeof(nsXPCWrappedJS),
|
||||
"nsXPCWrappedJS");
|
||||
}
|
||||
|
||||
// nsXPCWrappedJS keeps its own refcount artificially at or above 1, see the
|
||||
// comment above nsXPCWrappedJS::AddRef.
|
||||
|
@ -69,20 +69,21 @@ NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Traverse(void *p,
|
||||
if(!tmp->IsValid())
|
||||
return NS_OK;
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
char name[72];
|
||||
XPCNativeScriptableInfo* si = tmp->GetScriptableInfo();
|
||||
if(si)
|
||||
JS_snprintf(name, sizeof(name), "XPCWrappedNative (%s)",
|
||||
si->GetJSClass()->name);
|
||||
else
|
||||
JS_snprintf(name, sizeof(name), "XPCWrappedNative");
|
||||
if (NS_UNLIKELY(cb.WantDebugInfo())) {
|
||||
char name[72];
|
||||
XPCNativeScriptableInfo* si = tmp->GetScriptableInfo();
|
||||
if(si)
|
||||
JS_snprintf(name, sizeof(name), "XPCWrappedNative (%s)",
|
||||
si->GetJSClass()->name);
|
||||
else
|
||||
JS_snprintf(name, sizeof(name), "XPCWrappedNative");
|
||||
|
||||
cb.DescribeNode(RefCounted, tmp->mRefCnt.get(), sizeof(XPCWrappedNative),
|
||||
name);
|
||||
#else
|
||||
cb.DescribeNode(RefCounted, tmp->mRefCnt.get());
|
||||
#endif
|
||||
cb.DescribeNode(RefCounted, tmp->mRefCnt.get(),
|
||||
sizeof(XPCWrappedNative), name);
|
||||
} else {
|
||||
cb.DescribeNode(RefCounted, tmp->mRefCnt.get(),
|
||||
sizeof(XPCWrappedNative), "XPCWrappedNative");
|
||||
}
|
||||
|
||||
if(tmp->mRefCnt.get() > 1) {
|
||||
|
||||
|
@ -412,11 +412,11 @@ WrappedNativeSuspecter(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"Suspecting wrapped natives from non-main thread");
|
||||
|
||||
#ifndef DEBUG_CC
|
||||
// Only record objects that might be part of a cycle as roots.
|
||||
if(!JS_IsAboutToBeFinalized(closure->cx, wrapper->GetFlatJSObject()))
|
||||
// Only record objects that might be part of a cycle as roots, unless
|
||||
// the callback wants all traces (a debug feature).
|
||||
if(!(closure->cb.WantAllTraces()) &&
|
||||
!JS_IsAboutToBeFinalized(closure->cx, wrapper->GetFlatJSObject()))
|
||||
return JS_DHASH_NEXT;
|
||||
#endif
|
||||
|
||||
closure->cb.NoteRoot(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
wrapper->GetFlatJSObject(),
|
||||
|
@ -239,13 +239,11 @@ nsLayoutStatics::Initialize()
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifndef DEBUG_CC
|
||||
rv = nsCCUncollectableMarker::Init();
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_ERROR("Could not initialize nsCCUncollectableMarker");
|
||||
return rv;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCSSRuleProcessor::Startup();
|
||||
|
||||
|
@ -152,6 +152,14 @@
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
#define IF_DEBUG_CC_PARAM(_p) , _p
|
||||
#define IF_DEBUG_CC_ONLY_PARAM(_p) _p
|
||||
#else
|
||||
#define IF_DEBUG_CC_PARAM(_p)
|
||||
#define IF_DEBUG_CC_ONLY_PARAM(_p)
|
||||
#endif
|
||||
|
||||
#define DEFAULT_SHUTDOWN_COLLECTIONS 5
|
||||
#ifdef DEBUG_CC
|
||||
#define SHUTDOWN_COLLECTIONS(params) params.mShutdownCollections
|
||||
@ -1289,21 +1297,15 @@ public:
|
||||
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root);
|
||||
|
||||
private:
|
||||
#ifdef DEBUG_CC
|
||||
NS_IMETHOD_(void) DescribeNode(CCNodeType type, nsrefcnt refCount,
|
||||
size_t objSz, const char *objName);
|
||||
#else
|
||||
NS_IMETHOD_(void) DescribeNode(CCNodeType type, nsrefcnt refCount);
|
||||
#endif
|
||||
NS_IMETHOD_(void) NoteRoot(PRUint32 langID, void *child,
|
||||
nsCycleCollectionParticipant* participant);
|
||||
NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child);
|
||||
NS_IMETHOD_(void) NoteNativeChild(void *child,
|
||||
nsCycleCollectionParticipant *participant);
|
||||
NS_IMETHOD_(void) NoteScriptChild(PRUint32 langID, void *child);
|
||||
#ifdef DEBUG_CC
|
||||
NS_IMETHOD_(void) NoteNextEdgeName(const char* name);
|
||||
#endif
|
||||
};
|
||||
|
||||
GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph,
|
||||
@ -1315,6 +1317,11 @@ GCGraphBuilder::GCGraphBuilder(GCGraph &aGraph,
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
|
||||
GCGraphBuilder::~GCGraphBuilder()
|
||||
@ -1404,12 +1411,8 @@ GCGraphBuilder::NoteRoot(PRUint32 langID, void *root,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
#ifdef DEBUG_CC
|
||||
GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount,
|
||||
size_t objSz, const char *objName)
|
||||
#else
|
||||
GCGraphBuilder::DescribeNode(CCNodeType type, nsrefcnt refCount)
|
||||
#endif
|
||||
{
|
||||
#ifdef DEBUG_CC
|
||||
mCurrPi->mBytes = objSz;
|
||||
@ -1517,13 +1520,13 @@ GCGraphBuilder::NoteScriptChild(PRUint32 langID, void *child)
|
||||
++childPi->mInternalRefs;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
NS_IMETHODIMP_(void)
|
||||
GCGraphBuilder::NoteNextEdgeName(const char* name)
|
||||
{
|
||||
#ifdef DEBUG_CC
|
||||
mNextEdgeName = name;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static PRBool
|
||||
AddPurpleRoot(GCGraphBuilder &builder, nsISupports *root)
|
||||
|
@ -44,14 +44,6 @@
|
||||
// *and* in nsCycleCollector.h
|
||||
//#define DEBUG_CC
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
#define IF_DEBUG_CC_PARAM(_p) , _p
|
||||
#define IF_DEBUG_CC_ONLY_PARAM(_p) _p
|
||||
#else
|
||||
#define IF_DEBUG_CC_PARAM(_p)
|
||||
#define IF_DEBUG_CC_ONLY_PARAM(_p)
|
||||
#endif
|
||||
|
||||
#define NS_CYCLECOLLECTIONPARTICIPANT_IID \
|
||||
{ \
|
||||
0x9674489b, \
|
||||
@ -97,15 +89,12 @@ public:
|
||||
// If type is RefCounted you must call DescribeNode() with an accurate
|
||||
// refcount, otherwise cycle collection will fail, and probably crash.
|
||||
// If type is not refcounted then the refcount will be ignored.
|
||||
#ifdef DEBUG_CC
|
||||
// If the callback cares about objsz or objname, it should
|
||||
// put WANT_DEBUG_INFO in mFlags.
|
||||
NS_IMETHOD_(void) DescribeNode(CCNodeType type,
|
||||
nsrefcnt refcount,
|
||||
size_t objsz,
|
||||
const char *objname) = 0;
|
||||
#else
|
||||
NS_IMETHOD_(void) DescribeNode(CCNodeType type,
|
||||
nsrefcnt refcount) = 0;
|
||||
#endif
|
||||
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports *root) = 0;
|
||||
NS_IMETHOD_(void) NoteRoot(PRUint32 langID, void *root,
|
||||
nsCycleCollectionParticipant* helper) = 0;
|
||||
@ -113,11 +102,31 @@ public:
|
||||
NS_IMETHOD_(void) NoteXPCOMChild(nsISupports *child) = 0;
|
||||
NS_IMETHOD_(void) NoteNativeChild(void *child,
|
||||
nsCycleCollectionParticipant *helper) = 0;
|
||||
#ifdef DEBUG_CC
|
||||
|
||||
// Give a name to the edge associated with the next call to
|
||||
// NoteScriptChild, NoteXPCOMChild, or NoteNativeChild.
|
||||
// Callbacks who care about this should set WANT_DEBUG_INFO in the
|
||||
// flags.
|
||||
NS_IMETHOD_(void) NoteNextEdgeName(const char* name) = 0;
|
||||
#endif
|
||||
|
||||
enum {
|
||||
// Values for flags:
|
||||
|
||||
// Caller should pass useful objsz and objname to DescribeNode
|
||||
// and should call NoteNextEdgeName.
|
||||
WANT_DEBUG_INFO = (1<<0),
|
||||
|
||||
// Caller should not skip objects that we know will be
|
||||
// uncollectable.
|
||||
WANT_ALL_TRACES = (1<<1)
|
||||
};
|
||||
PRUint32 Flags() const { return mFlags; }
|
||||
PRBool WantDebugInfo() const { return (mFlags & WANT_DEBUG_INFO) != 0; }
|
||||
PRBool WantAllTraces() const { return (mFlags & WANT_ALL_TRACES) != 0; }
|
||||
protected:
|
||||
nsCycleCollectionTraversalCallback() : mFlags(0) {}
|
||||
|
||||
PRUint32 mFlags;
|
||||
};
|
||||
|
||||
class NS_NO_VTABLE nsCycleCollectionParticipant
|
||||
@ -321,13 +330,8 @@ public:
|
||||
// Helpers for implementing nsCycleCollectionParticipant::Traverse
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \
|
||||
cb.DescribeNode(RefCounted, _refcnt, sizeof(_class), #_class);
|
||||
#else
|
||||
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \
|
||||
cb.DescribeNode(RefCounted, _refcnt);
|
||||
#endif
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_REFCNT(_class, _refcnt) \
|
||||
NS_IMETHODIMP \
|
||||
@ -374,13 +378,12 @@ public:
|
||||
_class *tmp = static_cast<_class*>(p); \
|
||||
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
|
||||
|
||||
#ifdef DEBUG_CC
|
||||
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(_cb, _name) \
|
||||
PR_BEGIN_MACRO (_cb).NoteNextEdgeName(_name); PR_END_MACRO
|
||||
#else
|
||||
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(_cb, _name) \
|
||||
PR_BEGIN_MACRO PR_END_MACRO
|
||||
#endif
|
||||
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(_cb, _name) \
|
||||
PR_BEGIN_MACRO \
|
||||
if (NS_UNLIKELY((_cb).WantDebugInfo())) { \
|
||||
(_cb).NoteNextEdgeName(_name); \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(_field) \
|
||||
PR_BEGIN_MACRO \
|
||||
|
Loading…
Reference in New Issue
Block a user