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:
dbaron%dbaron.org 2005-06-15 00:23:32 +00:00
Родитель b07af11b3c
Коммит ab8827c68d
2 изменённых файлов: 40 добавлений и 24 удалений

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

@ -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);
}
}
}
}