XPCTraceableVariant::~XPCTraceableVariant() { jsval val = GetJSValPreserveColor(); NS_ASSERTION(JSVAL_IS_GCTHING(val), "Must be traceable or unlinked"); // If val is JSVAL_STRING, we don't need to clean anything up; simply // removing the string from the root set is good. if (!JSVAL_IS_STRING(val)) nsVariant::Cleanup(&mData); if (!JSVAL_IS_NULL(val)) RemoveFromRootSet(nsXPConnect::GetRuntimeInstance()->GetMapLock()); }
void nsXPCWrappedJS::Unlink() { if (IsValid()) { XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); if (rt) { if (mRoot == this) { // remove this root wrapper from the map JSObject2WrappedJSMap* map = rt->GetWrappedJSMap(); if (map) { XPCAutoLock lock(rt->GetMapLock()); map->Remove(this); } } if (mRefCnt > 1) RemoveFromRootSet(rt->GetMapLock()); } mJSObj = nsnull; } if (mRoot == this) { ClearWeakReferences(); } else if (mRoot) { // unlink this wrapper nsXPCWrappedJS* cur = mRoot; while (1) { if (cur->mNext == this) { cur->mNext = mNext; break; } cur = cur->mNext; NS_ASSERTION(cur, "failed to find wrapper in its own chain"); } // let the root go NS_RELEASE(mRoot); } NS_IF_RELEASE(mClass); if (mOuter) { XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); if (rt->GetThreadRunningGC()) { rt->DeferredRelease(mOuter); mOuter = nsnull; } else { NS_RELEASE(mOuter); } } }
nsrefcnt nsXPCWrappedJS::Release(void) { NS_PRECONDITION(0 != mRefCnt, "dup release"); if (mMainThreadOnly && !NS_IsMainThread()) { // We'd like to abort here, but this can happen if someone uses a proxy // for the nsXPCWrappedJS. nsCOMPtr<nsIThread> mainThread = do_GetMainThread(); // If we can't get the main thread anymore we just leak, but this really // shouldn't happen. NS_ASSERTION(mainThread, "Can't get main thread, leaking nsXPCWrappedJS!"); if (mainThread) { NS_ProxyRelease(mainThread, static_cast<nsIXPConnectWrappedJS*>(this)); } return mRefCnt; } // need to take the map lock here to prevent GetNewOrUsed from trying // to reuse a wrapper on one thread while it's being destroyed on another XPCJSRuntime* rt = nsXPConnect::GetRuntimeInstance(); XPCAutoLock lock(rt->GetMapLock()); do_decrement: nsrefcnt cnt = NS_AtomicDecrementRefcnt(mRefCnt); NS_LOG_RELEASE(this, cnt, "nsXPCWrappedJS"); if (0 == cnt) { delete this; // also unlinks us from chain return 0; } if (1 == cnt) { if (IsValid()) RemoveFromRootSet(rt->GetMapLock()); // If we are not the root wrapper or if we are not being used from a // weak reference, then this extra ref is not needed and we can let // ourself be deleted. // Note: HasWeakReferences() could only return true for the root. if (!HasWeakReferences()) goto do_decrement; } return cnt; }