From a0ddf20ce70ec4545180e0afaab7e403aaecaebf Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Fri, 19 Aug 2016 15:26:56 -0700 Subject: [PATCH] Bug 1110928, part 4 - Try to pass a relevant zone to PokeGC. r=smaug This means the browser will do less full GCs. MozReview-Commit-ID: BXf4GGhmbMx --- dom/base/nsGlobalWindow.cpp | 6 +++-- dom/base/nsJSEnvironment.cpp | 33 ++++++++++++++++++++------ dom/base/nsJSEnvironment.h | 3 ++- layout/base/nsDocumentViewer.cpp | 7 ++++-- xpcom/base/CycleCollectedJSRuntime.cpp | 1 + 5 files changed, 38 insertions(+), 12 deletions(-) diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 8448044911c2..7ceadd668324 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2890,7 +2890,8 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, newInnerWindow->mChromeEventHandler = mChromeEventHandler; } - nsJSContext::PokeGC(JS::gcreason::SET_NEW_DOCUMENT); + nsJSContext::PokeGC(JS::gcreason::SET_NEW_DOCUMENT, + GetWrapperPreserveColor()); mContext->DidInitializeContext(); // We wait to fire the debugger hook until the window is all set up and hooked @@ -3107,7 +3108,8 @@ nsGlobalWindow::DetachFromDocShell() mChromeEventHandler = nullptr; // force release now if (mContext) { - nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL); + nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL, + GetWrapperPreserveColor()); mContext = nullptr; } diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index dfcc512148a8..7629953e646d 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -608,7 +608,7 @@ void nsJSContext::Destroy() { if (mGCOnDestruction) { - PokeGC(JS::gcreason::NSJSCONTEXT_DESTROY); + PokeGC(JS::gcreason::NSJSCONTEXT_DESTROY, mWindowProxy); } DropJSObjects(this); @@ -1208,8 +1208,11 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason, JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL; - if (sNeedsFullGC || aReason != JS::gcreason::CC_WAITING) { - sNeedsFullGC = false; + if (aIncremental == NonIncrementalGC || aReason == JS::gcreason::FULL_GC_TIMER) { + sNeedsFullGC = true; + } + + if (sNeedsFullGC) { JS::PrepareForFullGC(sContext); } else { CycleCollectedJSRuntime::Get()->PrepareWaitingZonesForGC(); @@ -1586,7 +1589,7 @@ nsJSContext::EndCycleCollectionCallback(CycleCollectorResults &aResults) uint32_t ccNowDuration = TimeBetween(gCCStats.mBeginTime, endCCTimeStamp); if (NeedsGCAfterCC()) { - PokeGC(JS::gcreason::CC_WAITING, + PokeGC(JS::gcreason::CC_WAITING, nullptr, NS_GC_DELAY - std::min(ccNowDuration, kMaxICCDuration)); } @@ -1923,11 +1926,22 @@ nsJSContext::RunNextCollectorTimer() // static void -nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay) +nsJSContext::PokeGC(JS::gcreason::Reason aReason, + JSObject* aObj, + int aDelay) { - sNeedsFullGC = sNeedsFullGC || aReason != JS::gcreason::CC_WAITING; + if (sShuttingDown) { + return; + } - if (sGCTimer || sInterSliceGCTimer || sShuttingDown) { + if (aObj) { + JS::Zone* zone = JS::GetObjectZone(aObj); + CycleCollectedJSRuntime::Get()->AddZoneWaitingForGC(zone); + } else if (aReason != JS::gcreason::CC_WAITING) { + sNeedsFullGC = true; + } + + if (sGCTimer || sInterSliceGCTimer) { // There's already a timer for GC'ing, just return return; } @@ -2110,6 +2124,11 @@ DOMGCSliceCallback(JSContext* aCx, JS::GCProgress aProgress, const JS::GCDescrip case JS::GC_CYCLE_BEGIN: { // Prevent cycle collections and shrinking during incremental GC. sCCLockedOut = true; + + if (!aDesc.isCompartment_) { + sNeedsFullGC = false; + } + break; } diff --git a/dom/base/nsJSEnvironment.h b/dom/base/nsJSEnvironment.h index ff66467a8254..d356d7c7a9a9 100644 --- a/dom/base/nsJSEnvironment.h +++ b/dom/base/nsJSEnvironment.h @@ -108,7 +108,8 @@ public: static void RunNextCollectorTimer(); - static void PokeGC(JS::gcreason::Reason aReason, int aDelay = 0); + // The GC should probably run soon, in the zone of object aObj (if given). + static void PokeGC(JS::gcreason::Reason aReason, JSObject* aObj, int aDelay = 0); static void KillGCTimer(); static void PokeShrinkingGC(); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index bf843d80126e..93263bd835f9 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -1038,7 +1038,8 @@ nsDocumentViewer::LoadComplete(nsresult aStatus) nsJSContext::LoadEnd(); // It's probably a good idea to GC soon since we have finished loading. - PokeGC(JS::gcreason::LOAD_END); + nsJSContext::PokeGC(JS::gcreason::LOAD_END, + mDocument ? mDocument->GetWrapperPreserveColor() : nullptr); #ifdef NS_PRINTING // Check to see if someone tried to print during the load @@ -1286,7 +1287,9 @@ nsDocumentViewer::PageHide(bool aIsUnload) if (aIsUnload) { // Poke the GC. The window might be collectable garbage now. - nsJSContext::PokeGC(JS::gcreason::PAGE_HIDE, NS_GC_DELAY * 2); + nsJSContext::PokeGC(JS::gcreason::PAGE_HIDE, + mDocument->GetWrapperPreserveColor(), + NS_GC_DELAY * 2); } mDocument->OnPageHide(!aIsUnload, nullptr); diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp index 210f6d6eecc8..ce9ba95c41e4 100644 --- a/xpcom/base/CycleCollectedJSRuntime.cpp +++ b/xpcom/base/CycleCollectedJSRuntime.cpp @@ -1668,6 +1668,7 @@ CycleCollectedJSRuntime::PrepareWaitingZonesForGC() if (mZonesWaitingForGC.Count() == 0) { JS::PrepareForFullGC(Context()); } else { + JS::PrepareSystemZoneForGC(Context()); for (auto iter = mZonesWaitingForGC.Iter(); !iter.Done(); iter.Next()) { JS::PrepareZoneForGC(iter.Get()->GetKey()); }