From 70430c32f6ef6b4b6618534741f62a44e55dbaeb Mon Sep 17 00:00:00 2001 From: "bent.mozilla@gmail.com" Date: Wed, 23 Feb 2011 00:08:36 -0800 Subject: [PATCH] Only run CC after the GC has run at least once (bug 626768, r=gal). --- dom/base/nsJSEnvironment.cpp | 8 +++- js/src/xpconnect/src/nsXPConnect.cpp | 12 ++++++ xpcom/base/nsCycleCollector.cpp | 59 ++-------------------------- 3 files changed, 21 insertions(+), 58 deletions(-) diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index f19e7c9eb780..991d100c86aa 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -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; diff --git a/js/src/xpconnect/src/nsXPConnect.cpp b/js/src/xpconnect/src/nsXPConnect.cpp index 6aa40e28c52c..c64d79813c44 100644 --- a/js/src/xpconnect/src/nsXPConnect.cpp +++ b/js/src/xpconnect/src/nsXPConnect.cpp @@ -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?"); diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index a5dc5a76fd16..d11bd4a58eff 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -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 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 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 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 hook = - new nsCycleCollectorGCHookRunnable(); - nsresult rv = NS_DispatchToCurrentThread(hook); - NS_ENSURE_SUCCESS(rv, rv); - nsRefPtr runner = new nsCycleCollectorRunner(sCollector); nsCOMPtr thread; - rv = NS_NewThread(getter_AddRefs(thread), runner); + nsresult rv = NS_NewThread(getter_AddRefs(thread), runner); NS_ENSURE_SUCCESS(rv, rv); runner.swap(sCollectorRunner);