зеркало из https://github.com/mozilla/gecko-dev.git
Bug 663532 - Run GC from cycle collector in main thread, not CC thread. r=bent
This commit is contained in:
Родитель
38d068a45d
Коммит
81ec3bd93a
|
@ -1047,12 +1047,12 @@ struct nsCycleCollector
|
|||
nsICycleCollectorListener *aListener);
|
||||
|
||||
// Prepare for and cleanup after one or more collection(s).
|
||||
PRBool PrepareForCollection(nsTPtrArray<PtrInfo> *aWhiteNodes);
|
||||
PRBool PrepareForCollection(nsTPtrArray<PtrInfo> *aWhiteNodes,
|
||||
PRBool aForceGC);
|
||||
void CleanupAfterCollection();
|
||||
|
||||
// Start and finish an individual collection.
|
||||
PRBool BeginCollection(PRBool aForceGC,
|
||||
nsICycleCollectorListener *aListener);
|
||||
PRBool BeginCollection(nsICycleCollectorListener *aListener);
|
||||
PRBool FinishCollection();
|
||||
|
||||
PRUint32 SuspectedCount();
|
||||
|
@ -2499,8 +2499,12 @@ nsCycleCollector::Freed(void *n)
|
|||
#endif
|
||||
|
||||
PRBool
|
||||
nsCycleCollector::PrepareForCollection(nsTPtrArray<PtrInfo> *aWhiteNodes)
|
||||
nsCycleCollector::PrepareForCollection(nsTPtrArray<PtrInfo> *aWhiteNodes,
|
||||
PRBool aForceGC)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(),
|
||||
"PrepareForCollection must be called on the main thread.");
|
||||
|
||||
#if defined(DEBUG_CC) && !defined(__MINGW32__)
|
||||
if (!mParams.mDoNothing && mParams.mHookMalloc)
|
||||
InitMemHook();
|
||||
|
@ -2529,6 +2533,29 @@ nsCycleCollector::PrepareForCollection(nsTPtrArray<PtrInfo> *aWhiteNodes)
|
|||
|
||||
mWhiteNodes = aWhiteNodes;
|
||||
|
||||
// The cycle collector uses the mark bitmap to discover what JS objects
|
||||
// were reachable only from XPConnect roots that might participate in
|
||||
// cycles. We ask the JS runtime whether we need to force a GC before
|
||||
// this CC. It returns true on startup (before the mark bits have been set),
|
||||
// and also when UnmarkGray has run out of stack.
|
||||
if (mRuntimes[nsIProgrammingLanguage::JAVASCRIPT]) {
|
||||
nsCycleCollectionJSRuntime* rt =
|
||||
static_cast<nsCycleCollectionJSRuntime*>
|
||||
(mRuntimes[nsIProgrammingLanguage::JAVASCRIPT]);
|
||||
if (rt->NeedCollect() || aForceGC) {
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
PRTime start = PR_Now();
|
||||
#endif
|
||||
// rt->Collect() must be called from the main thread,
|
||||
// because it invokes XPCJSRuntime::GCCallback(cx, JSGC_BEGIN)
|
||||
// which returns false if not in the main thread.
|
||||
rt->Collect();
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
printf("cc: GC() took %lldms\n", (PR_Now() - start) / PR_USEC_PER_MSEC);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -2563,13 +2590,13 @@ nsCycleCollector::Collect(PRUint32 aTryCollections,
|
|||
{
|
||||
nsAutoTPtrArray<PtrInfo, 4000> whiteNodes;
|
||||
|
||||
if (!PrepareForCollection(&whiteNodes))
|
||||
if (!PrepareForCollection(&whiteNodes, PR_TRUE))
|
||||
return 0;
|
||||
|
||||
PRUint32 totalCollections = 0;
|
||||
while (aTryCollections > totalCollections) {
|
||||
// Synchronous cycle collection. Always force a JS GC as well.
|
||||
if (!(BeginCollection(PR_TRUE, aListener) && FinishCollection()))
|
||||
if (!(BeginCollection(aListener) && FinishCollection()))
|
||||
break;
|
||||
|
||||
++totalCollections;
|
||||
|
@ -2581,32 +2608,11 @@ nsCycleCollector::Collect(PRUint32 aTryCollections,
|
|||
}
|
||||
|
||||
PRBool
|
||||
nsCycleCollector::BeginCollection(PRBool aForceGC,
|
||||
nsICycleCollectorListener *aListener)
|
||||
nsCycleCollector::BeginCollection(nsICycleCollectorListener *aListener)
|
||||
{
|
||||
if (mParams.mDoNothing)
|
||||
return PR_FALSE;
|
||||
|
||||
// The cycle collector uses the mark bitmap to discover what JS objects
|
||||
// were reachable only from XPConnect roots that might participate in
|
||||
// cycles. We ask the JS runtime whether we need to force a GC before
|
||||
// this CC. It returns true on startup (before the mark bits have been set),
|
||||
// and also when UnmarkGray has run out of stack.
|
||||
if (mRuntimes[nsIProgrammingLanguage::JAVASCRIPT]) {
|
||||
nsCycleCollectionJSRuntime* rt =
|
||||
static_cast<nsCycleCollectionJSRuntime*>
|
||||
(mRuntimes[nsIProgrammingLanguage::JAVASCRIPT]);
|
||||
if (rt->NeedCollect() || aForceGC) {
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
PRTime start = PR_Now();
|
||||
#endif
|
||||
rt->Collect();
|
||||
#ifdef COLLECT_TIME_DEBUG
|
||||
printf("cc: GC() took %lldms\n", (PR_Now() - start) / PR_USEC_PER_MSEC);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (aListener && NS_FAILED(aListener->Begin())) {
|
||||
aListener = nsnull;
|
||||
}
|
||||
|
@ -3358,7 +3364,7 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
mCollected = mCollector->BeginCollection(PR_FALSE, mListener);
|
||||
mCollected = mCollector->BeginCollection(mListener);
|
||||
|
||||
mReply.Notify();
|
||||
}
|
||||
|
@ -3389,7 +3395,7 @@ public:
|
|||
return 0;
|
||||
|
||||
nsAutoTPtrArray<PtrInfo, 4000> whiteNodes;
|
||||
if (!mCollector->PrepareForCollection(&whiteNodes))
|
||||
if (!mCollector->PrepareForCollection(&whiteNodes, PR_FALSE))
|
||||
return 0;
|
||||
|
||||
NS_ASSERTION(!mListener, "Should have cleared this already!");
|
||||
|
|
Загрузка…
Ссылка в новой задаче