Bug 1338241 - Part 1: Use remoteType to propagate Large-Allocation status, r=mikedeboer
authorMichael Layzell <michael@thelayzells.com>
Thu, 09 Feb 2017 16:30:59 -0500
changeset 372641 d242fcdfb7de8b1688522a4af3c2edfe0369e797
parent 372640 a622d810dcb5220e20effe67f56dc2ec3b0ce5cc
child 372642 1e634483cd57815e44047de944e86c169431142e
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1338241
milestone54.0a1
Bug 1338241 - Part 1: Use remoteType to propagate Large-Allocation status, r=mikedeboer MozReview-Commit-ID: LfavqjMcZUq
browser/base/content/tabbrowser.xml
browser/modules/E10SUtils.jsm
dom/base/nsFrameLoader.cpp
dom/base/nsIFrameLoader.idl
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1699,19 +1699,18 @@
               }
               if (!isRemote && aBrowser.contentWindow.opener != aOptions.opener) {
                 throw new Error("Cannot change opener on an already non-remote browser!");
               }
             }
 
             // Abort if we're not going to change anything
             let currentRemoteType = aBrowser.getAttribute("remoteType");
-            if (isRemote == aShouldBeRemote && !aOptions.newFrameloader && !aOptions.freshProcess &&
-                (!isRemote || currentRemoteType == aOptions.remoteType) &&
-                !aBrowser.frameLoader.isFreshProcess) {
+            if (isRemote == aShouldBeRemote && !aOptions.newFrameloader &&
+                (!isRemote || currentRemoteType == aOptions.remoteType)) {
               return false;
             }
 
             let tab = this.getTabForBrowser(aBrowser);
             let evt = document.createEvent("Events");
             evt.initEvent("BeforeTabRemotenessChange", true, false);
             tab.dispatchEvent(evt);
 
@@ -1760,28 +1759,18 @@
             }
 
             if (aOptions.opener) {
               // Set the opener window on the browser, such that when the frame
               // loader is created the opener is set correctly.
               aBrowser.presetOpenerWindow(aOptions.opener);
             }
 
-            // Set the freshProcess attribute so that the frameloader knows to
-            // create a new process
-            if (aOptions.freshProcess) {
-              aBrowser.setAttribute("freshProcess", "true");
-            }
-
             parent.appendChild(aBrowser);
 
-            // Remove the freshProcess attribute if we set it, as we don't
-            // want it to apply for the next time the frameloader is created
-            aBrowser.removeAttribute("freshProcess");
-
             aBrowser.userTypedValue = oldUserTypedValue;
             if (hadStartedLoad) {
               aBrowser.urlbarChangeTracker.startedLoad();
             }
 
             aBrowser.droppedLinkHandler = droppedLinkHandler;
 
             // Switching a browser's remoteness will create a new frameLoader.
@@ -1845,25 +1834,33 @@
         <parameter name="aOptions"/>
         <body>
           <![CDATA[
             aOptions = aOptions || {};
 
             if (!gMultiProcessBrowser)
               return this.updateBrowserRemoteness(aBrowser, false);
 
+            // If we're in a LargeAllocation process, we prefer switching back
+            // into a normal content process, as that way we can clean up the
+            // L-A process.
+            let preferredRemoteType = aBrowser.remoteType;
+            if (aBrowser.remoteType == E10SUtils.LARGE_ALLOCATION_REMOTE_TYPE) {
+              preferredRemoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
+            }
+            aOptions.remoteType =
+              E10SUtils.getRemoteTypeForURI(aURL,
+                                            gMultiProcessBrowser,
+                                            preferredRemoteType,
+                                            aOptions.freshProcess);
+
             // If this URL can't load in the current browser then flip it to the
             // correct type.
-            let currentRemoteType = aBrowser.remoteType;
-            aOptions.remoteType =
-              E10SUtils.getRemoteTypeForURI(aURL, gMultiProcessBrowser,
-                                            currentRemoteType);
-            if (currentRemoteType != aOptions.remoteType ||
-                aOptions.freshProcess || aOptions.newFrameloader ||
-                aBrowser.frameLoader.isFreshProcess) {
+            if (aBrowser.remoteType != aOptions.remoteType ||
+                aOptions.newFrameloader) {
               let remote = aOptions.remoteType != E10SUtils.NOT_REMOTE;
               return this.updateBrowserRemoteness(aBrowser, remote, aOptions);
             }
 
             return false;
           ]]>
         </body>
       </method>
--- a/browser/modules/E10SUtils.jsm
+++ b/browser/modules/E10SUtils.jsm
@@ -34,42 +34,51 @@ function getAboutModule(aURL) {
 }
 
 const NOT_REMOTE = null;
 
 // These must match any similar ones in ContentParent.h.
 const WEB_REMOTE_TYPE = "web";
 const FILE_REMOTE_TYPE = "file";
 const EXTENSION_REMOTE_TYPE = "extension";
+
+// This must start with the WEB_REMOTE_TYPE above.
+const LARGE_ALLOCATION_REMOTE_TYPE = "webLargeAllocation";
 const DEFAULT_REMOTE_TYPE = WEB_REMOTE_TYPE;
 
 function validatedWebRemoteType(aPreferredRemoteType) {
   return aPreferredRemoteType && aPreferredRemoteType.startsWith(WEB_REMOTE_TYPE)
          ? aPreferredRemoteType : WEB_REMOTE_TYPE;
 }
 
 this.E10SUtils = {
   DEFAULT_REMOTE_TYPE,
   NOT_REMOTE,
   WEB_REMOTE_TYPE,
   FILE_REMOTE_TYPE,
   EXTENSION_REMOTE_TYPE,
+  LARGE_ALLOCATION_REMOTE_TYPE,
 
   canLoadURIInProcess(aURL, aProcess) {
     let remoteType = aProcess == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT
                      ? DEFAULT_REMOTE_TYPE : NOT_REMOTE;
     return remoteType == this.getRemoteTypeForURI(aURL, true, remoteType);
   },
 
   getRemoteTypeForURI(aURL, aMultiProcess,
-                      aPreferredRemoteType = DEFAULT_REMOTE_TYPE) {
+                      aPreferredRemoteType = DEFAULT_REMOTE_TYPE,
+                      aLargeAllocation = false) {
     if (!aMultiProcess) {
       return NOT_REMOTE;
     }
 
+    if (aLargeAllocation) {
+      return LARGE_ALLOCATION_REMOTE_TYPE;
+    }
+
     // loadURI in browser.xml treats null as about:blank
     if (!aURL) {
       aURL = "about:blank";
     }
 
     let uri;
     try {
       uri = Services.io.newURI(aURL);
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -169,27 +169,20 @@ nsFrameLoader::nsFrameLoader(Element* aO
   , mHideCalled(false)
   , mNetworkCreated(aNetworkCreated)
   , mRemoteBrowserShown(false)
   , mRemoteFrame(false)
   , mClipSubdocument(true)
   , mClampScrollPosition(true)
   , mObservingOwnerContent(false)
   , mVisible(true)
-  , mFreshProcess(false)
 {
   mRemoteFrame = ShouldUseRemoteProcess();
   MOZ_ASSERT(!mRemoteFrame || !aOpener,
              "Cannot pass aOpener for a remote frame!");
-
-  // Check if we are supposed to load into a fresh process
-  mFreshProcess = mOwnerContent->AttrValueIs(kNameSpaceID_None,
-                                             nsGkAtoms::freshProcess,
-                                             nsGkAtoms::_true,
-                                             eCaseMatters);
 }
 
 nsFrameLoader::~nsFrameLoader()
 {
   if (mMessageManager) {
     mMessageManager->Disconnect();
   }
   MOZ_RELEASE_ASSERT(mDestroyCalled);
@@ -2933,18 +2926,17 @@ nsFrameLoader::TryRemoteBrowser()
   PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser",
     js::ProfileEntry::Category::OTHER);
 
   MutableTabContext context;
   nsresult rv = GetNewTabContext(&context);
   NS_ENSURE_SUCCESS(rv, false);
 
   nsCOMPtr<Element> ownerElement = mOwnerContent;
-  mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement, openerContentParent,
-                                                mFreshProcess);
+  mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement, openerContentParent);
   if (!mRemoteBrowser) {
     return false;
   }
   // Now that mRemoteBrowser is set, we can initialize the RenderFrameParent
   mRemoteBrowser->InitRenderFrame();
 
   MaybeUpdatePrimaryTabParent(eTabParentChanged);
 
@@ -3671,21 +3663,14 @@ nsFrameLoader::PopulateUserContextIdFrom
 
 NS_IMETHODIMP
 nsFrameLoader::GetIsDead(bool* aIsDead)
 {
   *aIsDead = mDestroyCalled;
   return NS_OK;
 }
 
-NS_IMETHODIMP
-nsFrameLoader::GetIsFreshProcess(bool* aIsFreshProcess)
-{
-  *aIsFreshProcess = mFreshProcess;
-  return NS_OK;
-}
-
 nsIMessageSender*
 nsFrameLoader::GetProcessMessageManager() const
 {
   return mRemoteBrowser ? mRemoteBrowser->Manager()->GetMessageManager()
                         : nullptr;
 };
--- a/dom/base/nsIFrameLoader.idl
+++ b/dom/base/nsIFrameLoader.idl
@@ -263,22 +263,16 @@ interface nsIFrameLoader : nsISupports
    * across root docshells.
    */
   readonly attribute nsIGroupedSHistory groupedSHistory;
 
   /**
    * Is `true` if the frameloader is dead (destroy has been called on it)
    */
   [infallible] readonly attribute boolean isDead;
-
-  /**
-   * Is `true` if the <xul:browser> which created this frameloader had the
-   * freshProcess attribute set when it was created.
-   */
-  [infallible] readonly attribute boolean isFreshProcess;
 };
 
 %{C++
 class nsFrameLoader;
 %}
 
 native alreadyAddRefed_nsFrameLoader(already_AddRefed<nsFrameLoader>);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -668,45 +668,39 @@ ContentParent::RandomSelect(const nsTArr
 
   return nullptr;
 }
 
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::GetNewOrUsedBrowserProcess(const nsAString& aRemoteType,
                                           ProcessPriority aPriority,
                                           ContentParent* aOpener,
-                                          bool aLargeAllocationProcess,
                                           bool* aNew)
 {
   if (aNew) {
     *aNew = false;
   }
-  // Decide which pool of content parents we are going to be pulling from based
-  // on the aRemoteType and aLargeAllocationProcess flag.
-  nsAutoString contentProcessType(aLargeAllocationProcess
-                                  ? NS_LITERAL_STRING(LARGE_ALLOCATION_REMOTE_TYPE)
-                                  : aRemoteType);
-
-  nsTArray<ContentParent*>& contentParents = GetOrCreatePool(contentProcessType);
-
-  uint32_t maxContentParents = GetMaxProcessCount(contentProcessType);
+
+  nsTArray<ContentParent*>& contentParents = GetOrCreatePool(aRemoteType);
+
+  uint32_t maxContentParents = GetMaxProcessCount(aRemoteType);
 
   RefPtr<ContentParent> p;
   if (contentParents.Length() >= uint32_t(maxContentParents) &&
       (p = RandomSelect(contentParents, aOpener, maxContentParents))) {
     return p.forget();
   }
 
   // Try to take the preallocated process only for the default process type.
-  if (contentProcessType.Equals(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE)) &&
+  if (aRemoteType.Equals(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE)) &&
       (p = PreallocatedProcessManager::Take())) {
     // For pre-allocated process we have not set the opener yet.
     p->mOpener = aOpener;
   } else {
-    p = new ContentParent(aOpener, contentProcessType);
+    p = new ContentParent(aOpener, aRemoteType);
 
     if (aNew) {
       *aNew = true;
     }
 
     if (!p->LaunchSubprocess(aPriority)) {
       return nullptr;
     }
@@ -976,18 +970,17 @@ ContentParent::RecvFindPlugins(const uin
 {
   *aRv = mozilla::plugins::FindPluginsForContent(aPluginEpoch, aPlugins, aNewPluginEpoch);
   return IPC_OK();
 }
 
 /*static*/ TabParent*
 ContentParent::CreateBrowser(const TabContext& aContext,
                              Element* aFrameElement,
-                             ContentParent* aOpenerContentParent,
-                             bool aFreshProcess)
+                             ContentParent* aOpenerContentParent)
 {
   PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
 
   if (!sCanLaunchSubprocesses) {
     return nullptr;
   }
 
   if (TabParent* parent = TabParent::GetNextTabParent()) {
@@ -1000,35 +993,35 @@ ContentParent::CreateBrowser(const TabCo
   TabId tabId;
 
   nsIDocShell* docShell = GetOpenerDocShellHelper(aFrameElement);
   TabId openerTabId;
   if (docShell) {
     openerTabId = TabParent::GetTabIdFrom(docShell);
   }
 
+  nsAutoString remoteType;
+  if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
+                              remoteType)) {
+    remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
+  }
+
   bool newProcess = false;
   RefPtr<nsIContentParent> constructorSender;
   if (isInContentProcess) {
     MOZ_ASSERT(aContext.IsMozBrowserElement());
     constructorSender = CreateContentBridgeParent(aContext, initialPriority,
                                                   openerTabId, &tabId);
   } else {
     if (aOpenerContentParent) {
       constructorSender = aOpenerContentParent;
     } else {
-      nsAutoString remoteType;
-      if (!aFrameElement->GetAttr(kNameSpaceID_None, nsGkAtoms::RemoteType,
-                                  remoteType)) {
-        remoteType.AssignLiteral(DEFAULT_REMOTE_TYPE);
-      }
-
       constructorSender =
         GetNewOrUsedBrowserProcess(remoteType, initialPriority, nullptr,
-                                   aFreshProcess, &newProcess);
+                                   &newProcess);
       if (!constructorSender) {
         return nullptr;
       }
     }
     tabId = AllocateTabId(openerTabId,
                           aContext.AsIPCTabContext(),
                           constructorSender->ChildID());
   }
@@ -1065,17 +1058,17 @@ ContentParent::CreateBrowser(const TabCo
     constructorSender->SendPBrowserConstructor(
       // DeallocPBrowserParent() releases this ref.
       tp.forget().take(), tabId,
       aContext.AsIPCTabContext(),
       chromeFlags,
       constructorSender->ChildID(),
       constructorSender->IsForBrowser());
 
-    if (aFreshProcess) {
+    if (remoteType.EqualsLiteral(LARGE_ALLOCATION_REMOTE_TYPE)) {
       // Tell the TabChild object that it was created due to a Large-Allocation
       // request, and whether or not that Large-Allocation request succeeded at
       // creating a new content process.
       Unused << browser->SendSetIsLargeAllocation(true, newProcess);
     }
 
     if (browser) {
       RefPtr<TabParent> constructedTabParent = TabParent::GetFrom(browser);
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -169,29 +169,27 @@ public:
    * 2. remote xul <browser>
    * 3. normal iframe
    */
   static already_AddRefed<ContentParent>
   GetNewOrUsedBrowserProcess(const nsAString& aRemoteType = NS_LITERAL_STRING(NO_REMOTE_TYPE),
                              hal::ProcessPriority aPriority =
                              hal::ProcessPriority::PROCESS_PRIORITY_FOREGROUND,
                              ContentParent* aOpener = nullptr,
-                             bool aLargeAllocationProcess = false,
                              bool* anew = nullptr);
 
   /**
    * Get or create a content process for the given TabContext.  aFrameElement
    * should be the frame/iframe element with which this process will
    * associated.
    */
   static TabParent*
   CreateBrowser(const TabContext& aContext,
                 Element* aFrameElement,
-                ContentParent* aOpenerContentParent,
-                bool aFreshProcess = false);
+                ContentParent* aOpenerContentParent);
 
   static void GetAll(nsTArray<ContentParent*>& aArray);
 
   static void GetAllEvenIfDead(nsTArray<ContentParent*>& aArray);
 
   const nsAString& GetRemoteType() const;
 
   enum CPIteratorPolicy {