Fix leaked roots (and occasional asserts or potentially crashes) by unconditionally rooting/unrooting in the ctor/dtor of nsXULPrototypeScript. This means a JS object obtained from the XUL cache is rooted multiple times (it was already unrooted multiple times). Also add some assertions to warn against similar failures that can happen when RemoveJSGCRoot is called more than AddJSGCRoot. b=93146 r=brendan sr=waterson

This commit is contained in:
dbaron%fas.harvard.edu 2001-08-02 02:07:51 +00:00
Родитель 2b8d7b6266
Коммит f530205ebe
1 изменённых файлов: 28 добавлений и 25 удалений

Просмотреть файл

@ -168,26 +168,33 @@ static NS_DEFINE_CID(kDOMScriptObjectFactoryCID, NS_DOM_SCRIPT_OBJECT_FACTORY_C
//---------------------------------------------------------------------- //----------------------------------------------------------------------
#include "nsIJSRuntimeService.h" #include "nsIJSRuntimeService.h"
static nsIJSRuntimeService* gJSRuntimeService; static nsIJSRuntimeService* gJSRuntimeService = nsnull;
static JSRuntime* gScriptRuntime; static JSRuntime* gScriptRuntime = nsnull;
static PRInt32 gScriptRuntimeRefcnt; static PRInt32 gScriptRuntimeRefcnt = 0;
static nsresult static nsresult
AddJSGCRoot(JSContext* cx, void* aScriptObjectRef, const char* aName) AddJSGCRoot(void* aScriptObjectRef, const char* aName)
{ {
PRBool ok; if (++gScriptRuntimeRefcnt == 1 || !gScriptRuntime) {
ok = ::JS_AddNamedRoot(cx, aScriptObjectRef, aName); CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
if (! ok) return NS_ERROR_OUT_OF_MEMORY; &gJSRuntimeService);
if (! gJSRuntimeService) {
if (gScriptRuntimeRefcnt++ == 0) { NS_NOTREACHED("couldn't add GC root");
nsServiceManager::GetService("@mozilla.org/js/xpc/RuntimeService;1", // contractid
NS_GET_IID(nsIJSRuntimeService),
(nsISupports**) &gJSRuntimeService);
if (! gJSRuntimeService)
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
gJSRuntimeService->GetRuntime(&gScriptRuntime); gJSRuntimeService->GetRuntime(&gScriptRuntime);
if (! gScriptRuntime) {
NS_NOTREACHED("couldn't add GC root");
return NS_ERROR_FAILURE;
}
}
PRBool ok;
ok = ::JS_AddNamedRootRT(gScriptRuntime, aScriptObjectRef, aName);
if (! ok) {
NS_NOTREACHED("couldn't add GC root");
return NS_ERROR_OUT_OF_MEMORY;
} }
return NS_OK; return NS_OK;
@ -196,8 +203,10 @@ AddJSGCRoot(JSContext* cx, void* aScriptObjectRef, const char* aName)
static nsresult static nsresult
RemoveJSGCRoot(void* aScriptObjectRef) RemoveJSGCRoot(void* aScriptObjectRef)
{ {
if (! gScriptRuntime) if (! gScriptRuntime) {
NS_NOTREACHED("couldn't remove GC root");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
}
::JS_RemoveRootRT(gScriptRuntime, aScriptObjectRef); ::JS_RemoveRootRT(gScriptRuntime, aScriptObjectRef);
@ -2315,7 +2324,8 @@ nsXULElement::CompileEventHandler(nsIScriptContext* aContext,
if (!cx) if (!cx)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
rv = AddJSGCRoot(cx, &attr->mEventHandler, "nsXULPrototypeAttribute::mEventHandler"); rv = AddJSGCRoot(&attr->mEventHandler,
"nsXULPrototypeAttribute::mEventHandler");
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
} }
@ -4801,13 +4811,13 @@ nsXULPrototypeScript::nsXULPrototypeScript(PRInt32 aLineNo, const char *aVersion
mLangVersion(aVersion) mLangVersion(aVersion)
{ {
MOZ_COUNT_CTOR(nsXULPrototypeScript); MOZ_COUNT_CTOR(nsXULPrototypeScript);
AddJSGCRoot(&mJSObject, "nsXULPrototypeScript::mJSObject");
} }
nsXULPrototypeScript::~nsXULPrototypeScript() nsXULPrototypeScript::~nsXULPrototypeScript()
{ {
if (mJSObject) RemoveJSGCRoot(&mJSObject);
RemoveJSGCRoot(&mJSObject);
MOZ_COUNT_DTOR(nsXULPrototypeScript); MOZ_COUNT_DTOR(nsXULPrototypeScript);
} }
@ -4918,9 +4928,6 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
if (! mJSObject) { if (! mJSObject) {
rv = NS_ERROR_OUT_OF_MEMORY; // certain error rv = NS_ERROR_OUT_OF_MEMORY; // certain error
::JS_DestroyScript(cx, script); ::JS_DestroyScript(cx, script);
} else {
rv = AddJSGCRoot(cx, &mJSObject,
"nsXULPrototypeScript::mJSObject");
} }
} }
@ -5046,10 +5053,6 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
if (!cx) if (!cx)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
rv = AddJSGCRoot(cx, &mJSObject, "nsXULPrototypeScript::mJSObject");
if (NS_FAILED(rv))
return rv;
// XXXbe temporary, until we serialize/deserialize everything from the // XXXbe temporary, until we serialize/deserialize everything from the
// nsXULPrototypeDocument on down... // nsXULPrototypeDocument on down...
nsCOMPtr<nsIFastLoadService> fastLoadService(do_GetService(NS_FAST_LOAD_SERVICE_CONTRACTID)); nsCOMPtr<nsIFastLoadService> fastLoadService(do_GetService(NS_FAST_LOAD_SERVICE_CONTRACTID));