Bug 811206, Fix JSHolder drop handling, part 2 (assert), r=mccr8

--HG--
extra : rebase_source : e7731c7d1f81e250ea6992e4a15c3dc52bb136d0
This commit is contained in:
Olli Pettay 2012-11-28 02:56:06 +02:00
parent 48ba02265b
commit 2e7f4ef4ba
5 changed files with 74 additions and 0 deletions

View File

@ -259,9 +259,35 @@ XPCJSRuntime::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
return NS_OK;
}
#ifdef DEBUG
static void
AssertNoGcThing(void* aGCThing, const char* aName, void* aClosure)
{
MOZ_ASSERT(!aGCThing);
}
void
XPCJSRuntime::AssertNoObjectsToTrace(void* aPossibleJSHolder)
{
nsScriptObjectTracer* tracer = mJSHolders.Get(aPossibleJSHolder);
if (tracer && tracer->Trace) {
tracer->Trace(aPossibleJSHolder, AssertNoGcThing, nullptr);
}
}
#endif
nsresult
XPCJSRuntime::RemoveJSHolder(void* aHolder)
{
#ifdef DEBUG
// Assert that the holder doesn't try to keep any GC things alive.
// In case of unlinking cycle collector calls AssertNoObjectsToTrace
// manually because we don't want to check the holder before we are
// finished unlinking it
if (aHolder != mObjectToUnlink) {
AssertNoObjectsToTrace(aHolder);
}
#endif
bool hadOne = mJSHolders.Count() == 1;
mJSHolders.Remove(aHolder);
if (hadOne && mJSHolders.Count() == 0) {
@ -2411,6 +2437,9 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
mWatchdogHibernating(false),
mLastActiveTime(-1),
mExceptionManagerNotAvailable(false)
#ifdef DEBUG
, mObjectToUnlink(nullptr)
#endif
{
#ifdef XPC_CHECK_WRAPPERS_AT_SHUTDOWN
DEBUG_WrappedNativeHashtable =

View File

@ -2713,6 +2713,22 @@ nsXPConnect::ReadFunction(nsIObjectInputStream *stream, JSContext *cx, JSObject
return ReadScriptOrFunction(stream, cx, nullptr, functionObjp);
}
#ifdef DEBUG
void
nsXPConnect::SetObjectToUnlink(void* aObject)
{
if (mRuntime)
mRuntime->SetObjectToUnlink(aObject);
}
void
nsXPConnect::AssertNoObjectsToTrace(void* aPossibleJSHolder)
{
if (mRuntime)
mRuntime->AssertNoObjectsToTrace(aPossibleJSHolder);
}
#endif
/* These are here to be callable from a debugger */
JS_BEGIN_EXTERN_C
JS_EXPORT_API(void) DumpJSStack()

View File

@ -485,6 +485,11 @@ public:
static XPCJSRuntime* GetRuntimeInstance();
XPCJSRuntime* GetRuntime() {return mRuntime;}
#ifdef DEBUG
void SetObjectToUnlink(void* aObject);
void AssertNoObjectsToTrace(void* aPossibleJSHolder);
#endif
// Gets addref'd pointer
static nsresult GetInterfaceInfoManager(nsIInterfaceInfoSuperManager** iim,
nsXPConnect* xpc = nullptr);
@ -825,6 +830,10 @@ public:
nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
nsresult RemoveJSHolder(void* aHolder);
nsresult TestJSHolder(void* aHolder, bool* aRetval);
#ifdef DEBUG
void SetObjectToUnlink(void* aObject) { mObjectToUnlink = aObject; }
void AssertNoObjectsToTrace(void* aPossibleJSHolder);
#endif
static void SuspectWrappedNative(XPCWrappedNative *wrapper,
nsCycleCollectionTraversalCallback &cb);
@ -990,6 +999,10 @@ private:
friend class AutoLockWatchdog;
friend class XPCIncrementalReleaseRunnable;
#ifdef DEBUG
void* mObjectToUnlink;
#endif
};
/***************************************************************************/

View File

@ -2381,7 +2381,18 @@ nsCycleCollector::CollectWhite(nsICycleCollectorListener *aListener)
for (uint32_t i = 0; i < count; ++i) {
PtrInfo *pinfo = mWhiteNodes->ElementAt(i);
#ifdef DEBUG
if (mJSRuntime) {
mJSRuntime->SetObjectToUnlink(pinfo->mPointer);
}
#endif
rv = pinfo->mParticipant->Unlink(pinfo->mPointer);
#ifdef DEBUG
if (mJSRuntime) {
mJSRuntime->SetObjectToUnlink(nullptr);
mJSRuntime->AssertNoObjectsToTrace(pinfo->mPointer);
}
#endif
if (NS_FAILED(rv)) {
Fault("Failed unlink call while unlinking", pinfo);
#ifdef DEBUG_CC

View File

@ -81,6 +81,11 @@ struct nsCycleCollectionJSRuntime
* Get the JS cycle collection participant.
*/
virtual nsCycleCollectionParticipant *GetParticipant() = 0;
#ifdef DEBUG
virtual void SetObjectToUnlink(void* aObject) = 0;
virtual void AssertNoObjectsToTrace(void* aPossibleJSHolder) = 0;
#endif
};
// Helpers for interacting with JS