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
Родитель be4c6b909f
Коммит 70430c32f6
3 изменённых файлов: 21 добавлений и 58 удалений

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

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

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

@ -464,6 +464,18 @@ nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb,
return NS_ERROR_FAILURE; 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 #ifdef DEBUG_CC
NS_ASSERTION(!mJSRoots.ops, "Didn't call FinishCycleCollection?"); NS_ASSERTION(!mJSRoots.ops, "Didn't call FinishCycleCollection?");

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

@ -3286,7 +3286,6 @@ class nsCycleCollectorRunner : public nsRunnable
CondVar mReply; CondVar mReply;
PRBool mRunning; PRBool mRunning;
PRBool mCollected; PRBool mCollected;
PRBool mJSGCHasRun;
public: public:
NS_IMETHOD Run() NS_IMETHOD Run()
@ -3330,8 +3329,7 @@ public:
mRequest(mLock, "cycle collector request condvar"), mRequest(mLock, "cycle collector request condvar"),
mReply(mLock, "cycle collector reply condvar"), mReply(mLock, "cycle collector reply condvar"),
mRunning(PR_FALSE), mRunning(PR_FALSE),
mCollected(PR_FALSE), mCollected(PR_FALSE)
mJSGCHasRun(PR_FALSE)
{ {
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
} }
@ -3342,7 +3340,7 @@ public:
MutexAutoLock autoLock(mLock); MutexAutoLock autoLock(mLock);
if (!mRunning || !mJSGCHasRun) if (!mRunning)
return 0; return 0;
nsAutoTPtrArray<PtrInfo, 4000> whiteNodes; nsAutoTPtrArray<PtrInfo, 4000> whiteNodes;
@ -3381,14 +3379,6 @@ public:
mRequest.Notify(); mRequest.Notify();
mReply.Wait(); mReply.Wait();
} }
void JSGCHasRun()
{
NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
MutexAutoLock autoLock(mLock);
mJSGCHasRun = PR_TRUE;
}
}; };
// Holds a reference. // Holds a reference.
@ -3397,43 +3387,6 @@ static nsCycleCollectorRunner* sCollectorRunner;
// Holds a reference. // Holds a reference.
static nsIThread* sCollectorThread; 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 nsresult
nsCycleCollector_startup() nsCycleCollector_startup()
{ {
@ -3442,17 +3395,11 @@ nsCycleCollector_startup()
sCollector = new nsCycleCollector(); 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 = nsRefPtr<nsCycleCollectorRunner> runner =
new nsCycleCollectorRunner(sCollector); new nsCycleCollectorRunner(sCollector);
nsCOMPtr<nsIThread> thread; nsCOMPtr<nsIThread> thread;
rv = NS_NewThread(getter_AddRefs(thread), runner); nsresult rv = NS_NewThread(getter_AddRefs(thread), runner);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
runner.swap(sCollectorRunner); runner.swap(sCollectorRunner);