зеркало из https://github.com/mozilla/gecko-dev.git
Fix releasing of nsISupportsWeakReference wrapped JS objects so it doesn't crash when we do multiple iterations of JS GC. b=292027 r=jst sr=brendan a=brendan
This commit is contained in:
Родитель
b07af11b3c
Коммит
ab8827c68d
|
@ -313,6 +313,31 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
|||
NS_ASSERTION(self->mDoingFinalization, "bad state");
|
||||
self->mDoingFinalization = JS_FALSE;
|
||||
|
||||
// Release all the members whose JSObjects are now known
|
||||
// to be dead.
|
||||
|
||||
dyingWrappedJSArray = &self->mWrappedJSToReleaseArray;
|
||||
XPCLock* mapLock = self->GetMainThreadOnlyGC() ?
|
||||
nsnull : self->GetMapLock();
|
||||
while(1)
|
||||
{
|
||||
nsXPCWrappedJS* wrapper;
|
||||
{
|
||||
XPCAutoLock al(mapLock); // lock if necessary
|
||||
PRInt32 count = dyingWrappedJSArray->Count();
|
||||
if(!count)
|
||||
{
|
||||
dyingWrappedJSArray->Compact();
|
||||
break;
|
||||
}
|
||||
wrapper = NS_STATIC_CAST(nsXPCWrappedJS*,
|
||||
dyingWrappedJSArray->ElementAt(count-1));
|
||||
dyingWrappedJSArray->RemoveElementAt(count-1);
|
||||
}
|
||||
NS_RELEASE(wrapper);
|
||||
}
|
||||
|
||||
|
||||
#ifdef XPC_REPORT_NATIVE_INTERFACE_AND_SET_FLUSHING
|
||||
printf("--------------------------------------------------------------\n");
|
||||
int setsBefore = (int) self->mNativeSetMap->Count();
|
||||
|
@ -505,32 +530,11 @@ JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
|||
case JSGC_END:
|
||||
{
|
||||
// NOTE that this event happens outside of the gc lock in
|
||||
// the js engine. So this could be sumultaneous with the
|
||||
// the js engine. So this could be simultaneous with the
|
||||
// events above.
|
||||
|
||||
// Release all the members whose JSObjects are now known
|
||||
// to be dead.
|
||||
|
||||
dyingWrappedJSArray = &self->mWrappedJSToReleaseArray;
|
||||
XPCLock* lock = self->GetMainThreadOnlyGC() ?
|
||||
nsnull : self->GetMapLock();
|
||||
while(1)
|
||||
{
|
||||
nsXPCWrappedJS* wrapper;
|
||||
{
|
||||
XPCAutoLock al(lock); // lock if necessary
|
||||
PRInt32 count = dyingWrappedJSArray->Count();
|
||||
if(!count)
|
||||
{
|
||||
dyingWrappedJSArray->Compact();
|
||||
break;
|
||||
}
|
||||
wrapper = NS_REINTERPRET_CAST(nsXPCWrappedJS*,
|
||||
dyingWrappedJSArray->ElementAt(count-1));
|
||||
dyingWrappedJSArray->RemoveElementAt(count-1);
|
||||
}
|
||||
NS_RELEASE(wrapper);
|
||||
}
|
||||
|
||||
// Do any deferred released of native objects.
|
||||
if(self->GetDeferReleases())
|
||||
|
|
|
@ -348,6 +348,8 @@ nsXPCWrappedJS::~nsXPCWrappedJS()
|
|||
{
|
||||
NS_PRECONDITION(0 == mRefCnt, "refcounting error");
|
||||
|
||||
XPCJSRuntime* rt = nsXPConnect::GetRuntime();
|
||||
|
||||
if(mRoot != this)
|
||||
{
|
||||
// unlink this wrapper
|
||||
|
@ -373,7 +375,6 @@ nsXPCWrappedJS::~nsXPCWrappedJS()
|
|||
ClearWeakReferences();
|
||||
|
||||
// remove this root wrapper from the map
|
||||
XPCJSRuntime* rt = nsXPConnect::GetRuntime();
|
||||
if(rt)
|
||||
{
|
||||
JSObject2WrappedJSMap* map = rt->GetWrappedJSMap();
|
||||
|
@ -388,7 +389,18 @@ nsXPCWrappedJS::~nsXPCWrappedJS()
|
|||
if(IsValid())
|
||||
{
|
||||
NS_IF_RELEASE(mClass);
|
||||
NS_IF_RELEASE(mOuter);
|
||||
if (mOuter)
|
||||
{
|
||||
if (rt && rt->GetThreadRunningGC())
|
||||
{
|
||||
rt->DeferredRelease(mOuter);
|
||||
mOuter = nsnull;
|
||||
}
|
||||
else
|
||||
{
|
||||
NS_RELEASE(mOuter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче