Only run CC after the GC has run at least once (bug 626768, r=gal).

This commit is contained in:
bent.mozilla@gmail.com 2011-02-23 00:08:36 -08:00
parent 649f67b373
commit 4a59c6cf4e
3 changed files with 21 additions and 58 deletions

View File

@ -148,6 +148,8 @@ static PRLogModuleInfo* gJSDiagnostics;
static nsITimer *sGCTimer;
static nsITimer *sCCTimer;
static bool sGCHasRun;
// The number of currently pending document loads. This count isn't
// guaranteed to always reflect reality and can't easily as we don't
// have an easy place to know when a load ends or is interrupted in
@ -3392,8 +3394,8 @@ nsJSContext::MaybePokeCC()
void
nsJSContext::PokeCC()
{
if (sCCTimer) {
// There's already a timer for GC'ing, just return
if (sCCTimer || !sGCHasRun) {
// There's already a timer for GC'ing, or GC hasn't run yet, just return.
return;
}
@ -3477,6 +3479,7 @@ DOMGCCallback(JSContext *cx, JSGCStatus status)
} else {
// If this was a full GC, poke the CC to run soon.
if (!cx->runtime->gcTriggerCompartment) {
sGCHasRun = true;
nsJSContext::PokeCC();
}
}
@ -3589,6 +3592,7 @@ nsJSRuntime::Startup()
{
// initialize all our statics, so that we can restart XPCOM
sGCTimer = sCCTimer = nsnull;
sGCHasRun = false;
sPendingLoadCount = 0;
sLoadingInProgress = PR_FALSE;
sPostGCEventsToConsole = PR_FALSE;

View File

@ -464,6 +464,18 @@ nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
return NS_ERROR_FAILURE;
}
static bool gcHasRun = false;
if(!gcHasRun)
{
JSRuntime* rt = JS_GetRuntime(mCycleCollectionContext->GetJSContext());
if(!rt)
NS_RUNTIMEABORT("Failed to get JS runtime!");
uint32 gcNumber = JS_GetGCParameter(rt, JSGC_NUMBER);
if(!gcNumber)
NS_RUNTIMEABORT("Cannot cycle collect if GC has not run first!");
gcHasRun = true;
}
#ifdef DEBUG_CC
NS_ASSERTION(!mJSRoots.ops, "Didn't call FinishCycleCollection?");

View File

@ -3286,7 +3286,6 @@ class nsCycleCollectorRunner : public nsRunnable
CondVar mReply;
PRBool mRunning;
PRBool mCollected;
PRBool mJSGCHasRun;
public:
NS_IMETHOD Run()
@ -3330,8 +3329,7 @@ public:
mRequest(mLock, "cycle collector request condvar"),
mReply(mLock, "cycle collector reply condvar"),
mRunning(PR_FALSE),
mCollected(PR_FALSE),
mJSGCHasRun(PR_FALSE)
mCollected(PR_FALSE)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
}
@ -3342,7 +3340,7 @@ public:
MutexAutoLock autoLock(mLock);
if (!mRunning || !mJSGCHasRun)
if (!mRunning)
return 0;
nsAutoTPtrArray<PtrInfo, 4000> whiteNodes;
@ -3381,14 +3379,6 @@ public:
mRequest.Notify();
mReply.Wait();
}
void JSGCHasRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
MutexAutoLock autoLock(mLock);
mJSGCHasRun = PR_TRUE;
}
};
// Holds a reference.
@ -3397,43 +3387,6 @@ static nsCycleCollectorRunner* sCollectorRunner;
// Holds a reference.
static nsIThread* sCollectorThread;
static JSBool
nsCycleCollector_gccallback(JSContext *cx, JSGCStatus status)
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
if (status == JSGC_END) {
if (sCollectorRunner)
sCollectorRunner->JSGCHasRun();
nsCOMPtr<nsIJSRuntimeService> rts =
do_GetService(nsIXPConnect::GetCID());
NS_WARN_IF_FALSE(rts, "Failed to get XPConnect?!");
if (rts)
rts->UnregisterGCCallback(nsCycleCollector_gccallback);
}
return JS_TRUE;
}
class nsCycleCollectorGCHookRunnable : public nsRunnable
{
public:
NS_IMETHOD Run()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
nsCOMPtr<nsIJSRuntimeService> rts =
do_GetService(nsIXPConnect::GetCID());
if (!rts) {
NS_RUNTIMEABORT("This must never fail!");
}
rts->RegisterGCCallback(nsCycleCollector_gccallback);
return NS_OK;
}
};
nsresult
nsCycleCollector_startup()
{
@ -3442,17 +3395,11 @@ nsCycleCollector_startup()
sCollector = new nsCycleCollector();
// We can't get XPConnect yet as it hasn't been initialized yet.
nsRefPtr<nsCycleCollectorGCHookRunnable> hook =
new nsCycleCollectorGCHookRunnable();
nsresult rv = NS_DispatchToCurrentThread(hook);
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<nsCycleCollectorRunner> runner =
new nsCycleCollectorRunner(sCollector);
nsCOMPtr<nsIThread> thread;
rv = NS_NewThread(getter_AddRefs(thread), runner);
nsresult rv = NS_NewThread(getter_AddRefs(thread), runner);
NS_ENSURE_SUCCESS(rv, rv);
runner.swap(sCollectorRunner);