зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
2b8d7b6266
Коммит
f530205ebe
|
@ -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));
|
||||||
|
|
Загрузка…
Ссылка в новой задаче