зеркало из https://github.com/mozilla/gecko-dev.git
Only run CC after the GC has run at least once (bug 626768, r=gal).
This commit is contained in:
Родитель
be4c6b909f
Коммит
70430c32f6
|
@ -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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче