Bug 1110928 trigger full GC only when closing top level outer window , r=mccr8
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Mon, 23 Jan 2017 19:23:57 +0200
changeset 469640 bb0cdf573e9de3a08c3b08eb9ae7673ad05be6d0
parent 469639 a1bbc6ed667015ece98beb737f51614b220cf418
child 469641 2aa9841bd6e3795e69d062a68290ce11ba0ffb96
push id43793
push userdmitchell@mozilla.com
push dateThu, 02 Feb 2017 14:41:57 +0000
reviewersmccr8
bugs1110928
milestone54.0a1
Bug 1110928 trigger full GC only when closing top level outer window , r=mccr8
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1438,16 +1438,17 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalW
     mHasFocus(false),
     mShowFocusRingForContent(false),
     mFocusByKeyOccurred(false),
     mHasGamepad(false),
     mHasVREvents(false),
     mHasSeenGamepadInput(false),
     mNotifiedIDDestroyed(false),
     mAllowScriptsToClose(false),
+    mTopLevelOuterContentWindow(false),
     mSuspendDepth(0),
     mFreezeDepth(0),
     mFocusMethod(0),
     mSerial(0),
     mIdleRequestCallbackCounter(1),
     mIdleRequestExecutor(nullptr),
 #ifdef DEBUG
     mSetOpenerWindowCalled(false),
@@ -3139,17 +3140,17 @@ nsGlobalWindow::SetNewDocument(nsIDocume
       mArguments = nullptr;
     }
 
     // Give the new inner window our chrome event handler (since it
     // doesn't have one).
     newInnerWindow->mChromeEventHandler = mChromeEventHandler;
   }
 
-  nsJSContext::PokeGC(JS::gcreason::SET_NEW_DOCUMENT, nullptr);
+  nsJSContext::PokeGC(JS::gcreason::SET_NEW_DOCUMENT, GetWrapperPreserveColor());
   kungFuDeathGrip->DidInitializeContext();
 
   // We wait to fire the debugger hook until the window is all set up and hooked
   // up with the outer. See bug 969156.
   if (createdInnerWindow) {
     nsContentUtils::AddScriptRunner(
       NewRunnableMethod(newInnerWindow,
                         &nsGlobalWindow::FireOnNewGlobalObject));
@@ -3290,16 +3291,19 @@ nsGlobalWindow::SetDocShell(nsIDocShell*
     return;
   }
 
   mDocShell = aDocShell; // Weak Reference
 
   nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
   MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup || mTabGroup == Cast(parentWindow)->mTabGroup);
 
+  mTopLevelOuterContentWindow =
+    !mIsChrome && GetScriptableTopInternal() == this;
+
   NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
 
   if (mFrames) {
     mFrames->SetDocShell(aDocShell);
   }
 
   // Get our enclosing chrome shell and retrieve its global window impl, so
   // that we can do some forwarding to the chrome document.
@@ -3369,18 +3373,22 @@ nsGlobalWindow::DetachFromDocShell()
     mFocusedNode = nullptr;
   }
 
   ClearControllers();
 
   mChromeEventHandler = nullptr; // force release now
 
   if (mContext) {
+    // When we're about to destroy a top level content window
+    // (for example a tab), we trigger a full GC by passing null as the last
+    // param. We also trigger a full GC for chrome windows.
     nsJSContext::PokeGC(JS::gcreason::SET_DOC_SHELL,
-                        GetWrapperPreserveColor());
+                        (mTopLevelOuterContentWindow || mIsChrome) ?
+                          nullptr : GetWrapperPreserveColor());
     mContext = nullptr;
   }
 
   mDocShell = nullptr; // Weak Reference
 
   NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
 
   if (mFrames) {
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1869,16 +1869,18 @@ protected:
   bool mHasSeenGamepadInput;
 
   // whether we've sent the destroy notification for our window id
   bool                   mNotifiedIDDestroyed : 1;
   // whether scripts may close the window,
   // even if "dom.allow_scripts_to_close_windows" is false.
   bool                   mAllowScriptsToClose : 1;
 
+  bool mTopLevelOuterContentWindow : 1;
+
   nsCOMPtr<nsIScriptContext>    mContext;
   nsWeakPtr                     mOpener;
   nsCOMPtr<nsIControllers>      mControllers;
 
   // For |window.arguments|, via |openDialog|.
   nsCOMPtr<nsIArray>            mArguments;
 
   // For |window.dialogArguments|, via |showModalDialog|.