зеркало из https://github.com/mozilla/gecko-dev.git
Fix for bug 372960 (Make XPConnect traverse more JS edges). r=brendan, sr=jst.
This commit is contained in:
Родитель
6cdd22b723
Коммит
a5505bbe92
|
@ -2015,9 +2015,20 @@ void
|
|||
js_MarkAtom(JSContext *cx, JSAtom *atom)
|
||||
{
|
||||
jsval key;
|
||||
void *thing;
|
||||
uint8 *flagp;
|
||||
|
||||
if (atom->flags & ATOM_MARK) {
|
||||
if (ATOM_IS_OBJECT(atom) && cx->runtime->gcThingCallback) {
|
||||
thing = ATOM_TO_OBJECT(atom);
|
||||
flagp = js_GetGCThingFlags(thing);
|
||||
cx->runtime->gcThingCallback(thing, *flagp,
|
||||
cx->runtime->gcThingCallbackClosure);
|
||||
}
|
||||
|
||||
if (atom->flags & ATOM_MARK)
|
||||
return;
|
||||
}
|
||||
|
||||
atom->flags |= ATOM_MARK;
|
||||
key = ATOM_KEY(atom);
|
||||
if (JSVAL_IS_GCTHING(key)) {
|
||||
|
|
|
@ -204,11 +204,9 @@ js_IsAboutToBeFinalized(JSContext *cx, void *thing);
|
|||
extern void
|
||||
js_MarkAtom(JSContext *cx, JSAtom *atom);
|
||||
|
||||
/* We avoid a large number of unnecessary calls by doing the flag check first */
|
||||
#define GC_MARK_ATOM(cx, atom) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!((atom)->flags & ATOM_MARK)) \
|
||||
js_MarkAtom(cx, atom); \
|
||||
js_MarkAtom(cx, atom); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
|
|
|
@ -46,7 +46,10 @@
|
|||
#include "XPCNativeWrapper.h"
|
||||
#include "nsBaseHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsobj.h"
|
||||
#include "jsscript.h"
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(nsXPConnect,nsIXPConnect,nsISupportsWeakReference)
|
||||
|
||||
|
@ -577,6 +580,22 @@ nsXPConnect::Unroot(const nsDeque &nodes)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
TraverseJSScript(JSScript* script, nsCycleCollectionTraversalCallback& cb)
|
||||
{
|
||||
JSAtomMap* map = &script->atomMap;
|
||||
uintN i, length = map->length;
|
||||
JSAtom** vector = map->vector;
|
||||
|
||||
for(i = 0; i < length; i++)
|
||||
{
|
||||
JSAtom* atom = vector[i];
|
||||
if(ATOM_IS_OBJECT(atom))
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
ATOM_TO_OBJECT(atom));
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
|
@ -594,14 +613,46 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
|||
if(XPCNativeWrapper::IsNativeWrapperClass(clazz))
|
||||
{
|
||||
XPCWrappedNative* wn = XPCNativeWrapper::GetWrappedNative(cx, obj);
|
||||
XPCNativeScriptableInfo* si = wn ? wn->GetScriptableInfo() : nsnull;
|
||||
if(si)
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
|
||||
si->GetJSClass()->name);
|
||||
if(wn)
|
||||
{
|
||||
XPCNativeScriptableInfo* si = wn->GetScriptableInfo();
|
||||
if(si)
|
||||
{
|
||||
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)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "XPCNativeWrapper (%s)",
|
||||
className);
|
||||
PR_Free(className);
|
||||
}
|
||||
else
|
||||
{
|
||||
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 if(obj)
|
||||
else
|
||||
{
|
||||
XPCNativeScriptableInfo* si = nsnull;
|
||||
if(IS_PROTO_CLASS(clazz))
|
||||
|
@ -611,15 +662,42 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
|||
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*) JS_GetPrivate(cx, 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*) JS_GetPrivate(cx, obj);
|
||||
if(fun->atom)
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Function - %s)",
|
||||
js_AtomToPrintableString(cx, fun->atom));
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (Function)");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object (%s)", clazz->name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
JS_snprintf(name, sizeof(name), "JS Object");
|
||||
}
|
||||
|
||||
cb.DescribeNode(refcount, sizeof(JSObject), name);
|
||||
#else
|
||||
cb.DescribeNode(refcount, sizeof(JSObject), "JS Object");
|
||||
|
@ -658,6 +736,24 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
|||
{
|
||||
cb.NoteXPCOMChild(NS_STATIC_CAST(nsISupports*, JS_GetPrivate(cx, obj)));
|
||||
}
|
||||
else if(clazz == &js_ScriptClass)
|
||||
{
|
||||
JSScript* script = (JSScript*) JS_GetPrivate(cx, obj);
|
||||
TraverseJSScript(script, cb);
|
||||
}
|
||||
else if(clazz == &js_FunctionClass)
|
||||
{
|
||||
JSFunction* fun = (JSFunction*) JS_GetPrivate(cx, obj);
|
||||
if (fun) {
|
||||
JSAtom* atom = fun->atom;
|
||||
if(atom && ATOM_IS_OBJECT(atom))
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
ATOM_TO_OBJECT(atom));
|
||||
JSScript* script = FUN_SCRIPT(fun);
|
||||
if (script)
|
||||
TraverseJSScript(script, cb);
|
||||
}
|
||||
}
|
||||
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
OBJ_GET_PARENT(cx, obj));
|
||||
|
@ -672,6 +768,28 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
|
|||
JSVAL_TO_OBJECT(val));
|
||||
}
|
||||
|
||||
JSScope* scope;
|
||||
if(OBJ_IS_NATIVE(obj) && (scope = OBJ_SCOPE(obj)))
|
||||
{
|
||||
JSScopeProperty* sprop;
|
||||
for(sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent)
|
||||
{
|
||||
if(SCOPE_HAD_MIDDLE_DELETE(scope) &&
|
||||
!SCOPE_HAS_PROPERTY(scope, sprop))
|
||||
continue;
|
||||
jsid id = sprop->id;
|
||||
if(JSID_IS_OBJECT(id))
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
JSID_TO_OBJECT(id));
|
||||
if(sprop->attrs & JSPROP_GETTER)
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
JSVAL_TO_GCTHING((jsval)sprop->getter));
|
||||
if(sprop->attrs & JSPROP_SETTER)
|
||||
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
|
||||
JSVAL_TO_GCTHING((jsval)sprop->setter));
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef XPCONNECT_STANDALONE
|
||||
if(clazz->flags & JSCLASS_IS_GLOBAL)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче