More fixes for bug 294893. When a XPCWrappedNative's scope is cleared, make sure we clear the scope for all of its XPCNativeWrappers as well. r+sr=bzbarsky@mit.edu, a=drivers

This commit is contained in:
jst%mozilla.jstenback.com 2005-05-26 19:30:36 +00:00
Родитель a68e2d534e
Коммит a81b370e90
8 изменённых файлов: 146 добавлений и 7 удалений

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

@ -723,8 +723,12 @@ XPC_NW_Finalize(JSContext *cx, JSObject *obj)
XPCWrappedNative *wrappedNative =
XPCNativeWrapper::GetWrappedNative(cx, obj);
if (wrappedNative && wrappedNative->GetNativeWrapper() == obj) {
wrappedNative->SetNativeWrapper(nsnull);
if (wrappedNative) {
XPCJSRuntime *rt = wrappedNative->GetRuntime();
// scoped lock
XPCAutoLock lock(rt->GetMapLock());
rt->GetExplicitNativeWrapperMap()->Remove(obj);
}
}
@ -911,6 +915,14 @@ XPCNativeWrapperCtor(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
*rval = OBJECT_TO_JSVAL(wrapperObj);
{
XPCJSRuntime *rt = wrappedNative->GetRuntime();
// scoped lock
XPCAutoLock lock(rt->GetMapLock());
rt->GetExplicitNativeWrapperMap()->Add(wrapperObj);
}
return JS_TRUE;
}
@ -1099,3 +1111,45 @@ XPCNativeWrapper::GetNewOrUsed(JSContext *cx, XPCWrappedNative *wrapper)
wrapper->SetNativeWrapper(obj);
return obj;
}
struct WrapperAndCxHolder
{
XPCWrappedNative* wrapper;
JSContext* cx;
};
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
ClearNativeWrapperScope(JSDHashTable *table, JSDHashEntryHdr *hdr,
uint32 number, void *arg)
{
JSDHashEntryStub* entry = (JSDHashEntryStub*)hdr;
WrapperAndCxHolder* d = (WrapperAndCxHolder*)arg;
if (d->wrapper->GetNativeWrapper() == (JSObject*)entry->key)
{
::JS_ClearScope(d->cx, (JSObject*)entry->key);
}
return JS_DHASH_NEXT;
}
// static
void
XPCNativeWrapper::ClearWrappedNativeScopes(JSContext* cx,
XPCWrappedNative* wrapper)
{
JSObject *nativeWrapper = wrapper->GetNativeWrapper();
if (nativeWrapper) {
::JS_ClearScope(cx, nativeWrapper);
}
WrapperAndCxHolder d =
{
wrapper,
cx
};
wrapper->GetRuntime()->GetExplicitNativeWrapperMap()->
Enumerate(ClearNativeWrapperScope, &d);
}

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

@ -74,6 +74,9 @@ public:
return &sXPC_NW_JSClass.base;
}
static void ClearWrappedNativeScopes(JSContext* cx,
XPCWrappedNative* wrapper);
protected:
static JSExtendedClass sXPC_NW_JSClass;
};

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

@ -79,6 +79,7 @@ class NativeSetMap;
class IID2ThisTranslatorMap;
class XPCNativeScriptableSharedMap;
class XPCWrappedNativeProtoMap;
class XPCNativeWrapperMap;
class nsXPCComponents;
class nsXPCComponents_Interfaces;

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

@ -744,6 +744,16 @@ XPCJSRuntime::~XPCJSRuntime()
delete mDetachedWrappedNativeProtoMap;
}
if(mExplicitNativeWrapperMap)
{
#ifdef XPC_DUMP_AT_SHUTDOWN
uint32 count = mExplicitNativeWrapperMap->Count();
if(count)
printf("deleting XPCJSRuntime with %d live explicit XPCNativeWrapper\n", (int)count);
#endif
delete mExplicitNativeWrapperMap;
}
// unwire the readable/JSString sharing magic
XPCStringConvert::ShutdownDOMStringFinalizer();
@ -767,6 +777,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
mNativeScriptableSharedMap(XPCNativeScriptableSharedMap::newMap(XPC_NATIVE_JSCLASS_MAP_SIZE)),
mDyingWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DYING_NATIVE_PROTO_MAP_SIZE)),
mDetachedWrappedNativeProtoMap(XPCWrappedNativeProtoMap::newMap(XPC_DETACHED_NATIVE_PROTO_MAP_SIZE)),
mExplicitNativeWrapperMap(XPCNativeWrapperMap::newMap(XPC_NATIVE_WRAPPER_MAP_SIZE)),
mMapLock(XPCAutoLock::NewLock("XPCJSRuntime::mMapLock")),
mThreadRunningGC(nsnull),
mWrappedJSToReleaseArray(),
@ -825,6 +836,7 @@ XPCJSRuntime::newXPCJSRuntime(nsXPConnect* aXPConnect,
self->GetThisTranslatorMap() &&
self->GetNativeScriptableSharedMap() &&
self->GetDyingWrappedNativeProtoMap() &&
self->GetExplicitNativeWrapperMap() &&
self->GetMapLock())
{
return self;
@ -854,7 +866,7 @@ XPCJSRuntime::GetXPCContext(JSContext* cx)
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
SweepContextsCB(JSDHashTable *table, JSDHashEntryHdr *hdr,
uint32 number, void *arg)
uint32 number, void *arg)
{
XPCContext* xpcc = ((JSContext2XPCContextMap::Entry*)hdr)->value;
if(xpcc->IsMarked())

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

@ -634,3 +634,29 @@ XPCWrappedNativeProtoMap::~XPCWrappedNativeProtoMap()
}
/***************************************************************************/
// implement XPCNativeWrapperMap...
// static
XPCNativeWrapperMap*
XPCNativeWrapperMap::newMap(int size)
{
XPCNativeWrapperMap* map = new XPCNativeWrapperMap(size);
if(map && map->mTable)
return map;
delete map;
return nsnull;
}
XPCNativeWrapperMap::XPCNativeWrapperMap(int size)
{
mTable = JS_NewDHashTable(JS_DHashGetStubOps(), nsnull,
sizeof(JSDHashEntryStub), size);
}
XPCNativeWrapperMap::~XPCNativeWrapperMap()
{
if(mTable)
JS_DHashTableDestroy(mTable);
}
/***************************************************************************/

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

@ -651,4 +651,40 @@ private:
JSDHashTable *mTable;
};
class XPCNativeWrapperMap
{
public:
static XPCNativeWrapperMap* newMap(int size);
inline JSObject* Add(JSObject* nw)
{
NS_PRECONDITION(nw,"bad param");
JSDHashEntryStub* entry = (JSDHashEntryStub*)
JS_DHashTableOperate(mTable, nw, JS_DHASH_ADD);
if(!entry)
return nsnull;
if(entry->key)
return (JSObject*) entry->key;
entry->key = nw;
return nw;
}
inline void Remove(JSObject* nw)
{
NS_PRECONDITION(nw,"bad param");
JS_DHashTableOperate(mTable, nw, JS_DHASH_REMOVE);
}
inline uint32 Count() {return mTable->entryCount;}
inline uint32 Enumerate(JSDHashEnumerator f, void *arg)
{return JS_DHashTableEnumerate(mTable, f, arg);}
~XPCNativeWrapperMap();
private:
XPCNativeWrapperMap(); // no implementation
XPCNativeWrapperMap(int size);
private:
JSDHashTable *mTable;
};
#endif /* xpcmaps_h___ */

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

@ -208,6 +208,7 @@ void DEBUG_CheckWrapperThreadSafety(const XPCWrappedNative* wrapper);
#define XPC_NATIVE_SET_MAP_SIZE 64
#define XPC_NATIVE_JSCLASS_MAP_SIZE 32
#define XPC_THIS_TRANSLATOR_MAP_SIZE 8
#define XPC_NATIVE_WRAPPER_MAP_SIZE 16
/***************************************************************************/
// data declarations...
@ -520,6 +521,9 @@ public:
XPCWrappedNativeProtoMap* GetDetachedWrappedNativeProtoMap() const
{return mDetachedWrappedNativeProtoMap;}
XPCNativeWrapperMap* GetExplicitNativeWrapperMap() const
{return mExplicitNativeWrapperMap;}
XPCLock* GetMapLock() const {return mMapLock;}
XPCContext* GetXPCContext(JSContext* cx);
@ -635,6 +639,7 @@ private:
XPCNativeScriptableSharedMap* mNativeScriptableSharedMap;
XPCWrappedNativeProtoMap* mDyingWrappedNativeProtoMap;
XPCWrappedNativeProtoMap* mDetachedWrappedNativeProtoMap;
XPCNativeWrapperMap* mExplicitNativeWrapperMap;
XPCLock* mMapLock;
PRThread* mThreadRunningGC;
nsVoidArray mWrappedJSToReleaseArray;
@ -1917,6 +1922,11 @@ public:
{
if(mScriptableInfo) mScriptableInfo->Mark();
if(HasProto()) mMaybeProto->MarkBeforeJSFinalize(cx);
if(mNativeWrapper)
{
JS_MarkGCThing(cx, mNativeWrapper,
"XPCWrappedNative::mNativeWrapper", nsnull);
}
}
#ifdef DEBUG

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

@ -1149,10 +1149,7 @@ XPC_WN_JSOp_Clear(JSContext *cx, JSObject *obj)
if(wrapper && wrapper->IsValid())
{
JSObject *nativeWrapper = wrapper->GetNativeWrapper();
if(nativeWrapper)
JS_ClearScope(cx, nativeWrapper);
XPCNativeWrapper::ClearWrappedNativeScopes(cx, wrapper);
}
js_ObjectOps.clear(cx, obj);