Bug 1110928 trigger full GC only when closing top level outer window , r=mccr8
--- 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|.