Keep the purple bit in sync with the purple buffer when suspect and forget calls are dropped on the floor. b=385548 r=graydon

This commit is contained in:
dbaron@dbaron.org 2007-06-27 10:51:48 -07:00
parent 1c48e99b24
commit 0ecbf11058
3 changed files with 35 additions and 22 deletions

View File

@ -834,8 +834,8 @@ struct nsCycleCollector
nsCycleCollector();
~nsCycleCollector();
void Suspect(nsISupports *n, PRBool current = PR_FALSE);
void Forget(nsISupports *n);
PRBool Suspect(nsISupports *n, PRBool current = PR_FALSE);
PRBool Forget(nsISupports *n);
void Allocated(void *n, size_t sz);
void Freed(void *n);
void Collect(PRUint32 aTryCollections = 1);
@ -1365,7 +1365,8 @@ nsCycleCollector::CollectWhite(GCGraph &graph)
if (pinfo->mWasPurple) {
nsISupports* s = NS_STATIC_CAST(nsISupports*, p);
Forget(s);
PRBool forgetResult = Forget(s);
NS_ASSERTION(forgetResult, "Forget failed");
}
}
else if (pinfo->mWasPurple) {
@ -1380,7 +1381,8 @@ nsCycleCollector::CollectWhite(GCGraph &graph)
"QI should return the same participant!");
#endif
cp->UnmarkPurple(s);
Forget(s);
PRBool forgetResult = Forget(s);
NS_ASSERTION(forgetResult, "Forget failed");
}
}
@ -1831,7 +1833,7 @@ nsCycleCollector_isScanSafe(nsISupports *s)
}
#endif
void
PRBool
nsCycleCollector::Suspect(nsISupports *n, PRBool current)
{
// Re-entering ::Suspect during collection used to be a fault, but
@ -1839,20 +1841,20 @@ nsCycleCollector::Suspect(nsISupports *n, PRBool current)
// see some spurious refcount traffic here.
if (mScanInProgress)
return;
return PR_FALSE;
NS_ASSERTION(nsCycleCollector_isScanSafe(n),
"suspected a non-scansafe pointer");
NS_ASSERTION(NS_IsMainThread(), "trying to suspect from non-main thread");
if (mParams.mDoNothing)
return;
return PR_FALSE;
#ifdef DEBUG_CC
mStats.mSuspectNode++;
if (nsCycleCollector_shouldSuppress(n))
return;
return PR_FALSE;
#ifndef __MINGW32__
if (mParams.mHookMalloc)
@ -1870,10 +1872,12 @@ nsCycleCollector::Suspect(nsISupports *n, PRBool current)
mBuf.Push(n);
else
mPurpleBuf.Put(n);
return PR_TRUE;
}
void
PRBool
nsCycleCollector::Forget(nsISupports *n)
{
// Re-entering ::Forget during collection used to be a fault, but
@ -1881,12 +1885,12 @@ nsCycleCollector::Forget(nsISupports *n)
// see some spurious refcount traffic here.
if (mScanInProgress)
return;
return PR_FALSE;
NS_ASSERTION(NS_IsMainThread(), "trying to forget from non-main thread");
if (mParams.mDoNothing)
return;
return PR_TRUE; // it's as good as forgotten
#ifdef DEBUG_CC
mStats.mForgetNode++;
@ -1904,6 +1908,7 @@ nsCycleCollector::Forget(nsISupports *n)
#endif
mPurpleBuf.Remove(n);
return PR_TRUE;
}
#ifdef DEBUG_CC
@ -2371,27 +2376,31 @@ nsCycleCollector_forgetRuntime(PRUint32 langID)
}
void
PRBool
nsCycleCollector_suspect(nsISupports *n)
{
if (sCollector)
sCollector->Suspect(n);
return sCollector->Suspect(n);
return PR_FALSE;
}
void
nsCycleCollector_suspectCurrent(nsISupports *n)
{
if (sCollector)
sCollector->Suspect(n, PR_TRUE);
if (sCollector) {
PRBool res = sCollector->Suspect(n, PR_TRUE);
NS_ASSERTION(res, "suspectCurrent should not fail");
}
}
void
PRBool
nsCycleCollector_forget(nsISupports *n)
{
if (sCollector)
sCollector->Forget(n);
return sCollector->Forget(n);
return PR_FALSE;
}

View File

@ -51,9 +51,9 @@ struct nsCycleCollectionLanguageRuntime
virtual nsCycleCollectionParticipant *ToParticipant(void *p) = 0;
};
NS_COM void nsCycleCollector_suspect(nsISupports *n);
NS_COM PRBool nsCycleCollector_suspect(nsISupports *n);
NS_COM void nsCycleCollector_suspectCurrent(nsISupports *n);
NS_COM void nsCycleCollector_forget(nsISupports *n);
NS_COM PRBool nsCycleCollector_forget(nsISupports *n);
nsresult nsCycleCollector_startup();
NS_COM void nsCycleCollector_collect();
void nsCycleCollector_shutdown();

View File

@ -130,7 +130,8 @@ public:
if (NS_UNLIKELY(purple)) {
NS_ASSERTION(tmp != 0, "purple ISupports pointer with zero refcnt");
nsCycleCollector_forget(owner);
if (!nsCycleCollector_forget(owner))
tmp |= NS_PURPLE_BIT;
}
mValue = tmp + 1;
@ -154,9 +155,12 @@ public:
PRBool shouldBePurple = tmp > 1;
if (NS_UNLIKELY(shouldBePurple && !purple)) {
nsCycleCollector_suspect(owner);
if (!nsCycleCollector_suspect(owner))
shouldBePurple = PR_FALSE;
} else if (NS_UNLIKELY(tmp == 1 && purple)) {
nsCycleCollector_forget(owner);
if (!nsCycleCollector_forget(owner)) {
NS_NOTREACHED("forget should not fail when reference count hits 0");
}
}
--tmp;