Bug 1397426 - Rename TabChild's notion of "active tabs" to "visible tabs" and move logic into renderLayers. r=billm
authorMike Conley <mconley@mozilla.com>
Fri, 03 Nov 2017 11:27:29 -0400
changeset 449801 f77d887fffcb7cef5ddb5c224639496cc77aac75
parent 449800 4dd5d1624aba5390d015023c9d836f12bf5f3d16
child 449802 44d6efb9fa693766d667adb95281edbc9954d16d
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1397426
milestone59.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1397426 - Rename TabChild's notion of "active tabs" to "visible tabs" and move logic into renderLayers. r=billm MozReview-Commit-ID: 1bBNwew7uCk
docshell/base/nsDocShell.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
ipc/glue/BackgroundChildImpl.cpp
xpcom/threads/LabeledEventQueue.cpp
xpcom/threads/LabeledEventQueue.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5819,20 +5819,16 @@ nsDocShell::SetIsActive(bool aIsActive)
   // We disallow setting active on chrome docshells.
   if (mItemType == nsIDocShellTreeItem::typeChrome) {
     return NS_ERROR_INVALID_ARG;
   }
 
   // Keep track ourselves.
   mIsActive = aIsActive;
 
-  if (TabChild* tc = TabChild::GetFrom(this)) {
-    tc->OnDocShellActivated(aIsActive);
-  }
-
   // Clear prerender flag if necessary.
   if (mIsPrerendered && aIsActive) {
     MOZ_ASSERT(mPrerenderGlobalHistory.get());
     mIsPrerendered = false;
     nsCOMPtr<IHistory> history = services::GetHistoryService();
     nsresult rv = NS_OK;
     if (history) {
       rv = mPrerenderGlobalHistory->ApplyChanges(history);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -160,17 +160,17 @@ using mozilla::layers::GeckoContentContr
 NS_IMPL_ISUPPORTS(ContentListener, nsIDOMEventListener)
 NS_IMPL_ISUPPORTS(TabChildSHistoryListener,
                   nsISHistoryListener,
                   nsIPartialSHistoryListener,
                   nsISupportsWeakReference)
 
 static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
 
-nsTHashtable<nsPtrHashKey<TabChild>>* TabChild::sActiveTabs;
+nsTHashtable<nsPtrHashKey<TabChild>>* TabChild::sVisibleTabs;
 
 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
 static TabChildMap* sTabChildren;
 StaticMutex sTabChildrenMutex;
 
 TabChildBase::TabChildBase()
   : mTabChildGlobal(nullptr)
 {
@@ -1145,21 +1145,21 @@ TabChild::ActorDestroy(ActorDestroyReaso
 
   if (GetTabId() != 0) {
     NestedTabChildMap().erase(GetTabId());
   }
 }
 
 TabChild::~TabChild()
 {
-  if (sActiveTabs) {
-    sActiveTabs->RemoveEntry(this);
-    if (sActiveTabs->IsEmpty()) {
-      delete sActiveTabs;
-      sActiveTabs = nullptr;
+  if (sVisibleTabs) {
+    sVisibleTabs->RemoveEntry(this);
+    if (sVisibleTabs->IsEmpty()) {
+      delete sVisibleTabs;
+      sVisibleTabs = nullptr;
     }
   }
 
   DestroyWindow();
 
   nsCOMPtr<nsIWebBrowser> webBrowser = do_QueryInterface(WebNavigation());
   if (webBrowser) {
     webBrowser->SetContainerWindow(nullptr);
@@ -2661,33 +2661,16 @@ TabChild::RemovePendingDocShellBlocker()
   mPendingDocShellBlockers--;
   if (!mPendingDocShellBlockers && mPendingDocShellReceivedMessage) {
     mPendingDocShellReceivedMessage = false;
     InternalSetDocShellIsActive(mPendingDocShellIsActive);
   }
 }
 
 void
-TabChild::OnDocShellActivated(bool aIsActive)
-{
-  if (aIsActive) {
-    if (!sActiveTabs) {
-      sActiveTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
-    }
-    sActiveTabs->PutEntry(this);
-  } else {
-    if (sActiveTabs) {
-      sActiveTabs->RemoveEntry(this);
-      // We don't delete sActiveTabs here when it's empty since that
-      // could cause a lot of churn. Instead, we wait until ~TabChild.
-    }
-  }
-}
-
-void
 TabChild::InternalSetDocShellIsActive(bool aIsActive)
 {
   // docshell is consider prerendered only if not active yet
   mIsPrerendered &= !aIsActive;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
 
   if (docShell) {
     docShell->SetIsActive(aIsActive);
@@ -2750,16 +2733,21 @@ TabChild::RecvRenderLayers(const bool& a
       // notification to fire in the parent (so that it knows that the child has
       // updated its epoch). ForcePaintNoOp does that.
       if (IPCOpen()) {
         Unused << SendForcePaintNoOp(mLayerObserverEpoch);
         return IPC_OK();
       }
     }
 
+    if (!sVisibleTabs) {
+      sVisibleTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
+    }
+    sVisibleTabs->PutEntry(this);
+
     MakeVisible();
 
     nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
     if (!docShell) {
       return IPC_OK();
     }
 
     // We don't use TabChildBase::GetPresShell() here because that would create
@@ -2788,16 +2776,22 @@ TabChild::RecvRenderLayers(const bool& a
         if (nsView* view = vm->GetRootView()) {
           presShell->Paint(view, view->GetBounds(),
                            nsIPresShell::PAINT_LAYERS);
         }
       }
       APZCCallbackHelper::SuppressDisplayport(false, presShell);
     }
   } else {
+    if (sVisibleTabs) {
+      sVisibleTabs->RemoveEntry(this);
+      // We don't delete sVisibleTabs here when it's empty since that
+      // could cause a lot of churn. Instead, we wait until ~TabChild.
+    }
+
     MakeHidden();
   }
 
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvNavigateByKey(const bool& aForward, const bool& aForDocumentNavigation)
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -576,18 +576,16 @@ public:
    * Signal to this TabChild that it should be made visible:
    * activated widget, retained layer tree, etc.  (Respectively,
    * made not visible.)
    */
   void MakeVisible();
   void MakeHidden();
   bool IsVisible();
 
-  void OnDocShellActivated(bool aIsActive);
-
   nsIContentChild* Manager() const { return mManager; }
 
   static inline TabChild*
   GetFrom(nsIDocShell* aDocShell)
   {
     if (!aDocShell) {
       return nullptr;
     }
@@ -773,30 +771,30 @@ public:
   // dispatching some mouse events other than mousemove.
   void FlushAllCoalescedMouseData();
   void ProcessPendingCoalescedMouseDataAndDispatchEvents();
 
   void HandleRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
                                   const ScrollableLayerGuid& aGuid,
                                   const uint64_t& aInputBlockId);
 
-  static bool HasActiveTabs()
+  static bool HasVisibleTabs()
   {
-    return sActiveTabs && !sActiveTabs->IsEmpty();
+    return sVisibleTabs && !sVisibleTabs->IsEmpty();
   }
 
-  // Returns the set of TabChilds that are currently in the foreground. There
-  // can be multiple foreground TabChilds if Firefox has multiple windows
-  // open. There can also be zero foreground TabChilds if the foreground tab is
-  // in a different content process. Note that this function should only be
-  // called if HasActiveTabs() returns true.
-  static const nsTHashtable<nsPtrHashKey<TabChild>>& GetActiveTabs()
+  // Returns the set of TabChilds that are currently rendering layers. There
+  // can be multiple TabChilds in this state if Firefox has multiple windows
+  // open or is warming tabs up. There can also be zero TabChilds in this
+  // state. Note that this function should only be called if HasVisibleTabs()
+  // returns true.
+  static const nsTHashtable<nsPtrHashKey<TabChild>>& GetVisibleTabs()
   {
-    MOZ_ASSERT(HasActiveTabs());
-    return *sActiveTabs;
+    MOZ_ASSERT(HasVisibleTabs());
+    return *sVisibleTabs;
   }
 
 protected:
   virtual ~TabChild();
 
   virtual PRenderFrameChild* AllocPRenderFrameChild() override;
 
   virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) override;
@@ -986,21 +984,21 @@ private:
   bool mCoalesceMouseMoveEvents;
 
   bool mPendingDocShellIsActive;
   bool mPendingDocShellReceivedMessage;
   uint32_t mPendingDocShellBlockers;
 
   WindowsHandle mWidgetNativeData;
 
-  // This state is used to keep track of the current active tabs (the ones in
-  // the foreground). There may be more than one if there are multiple browser
-  // windows open. There may be none if this process does not host any
-  // foreground tabs.
-  static nsTHashtable<nsPtrHashKey<TabChild>>* sActiveTabs;
+  // This state is used to keep track of the current visible tabs (the ones rendering
+  // layers). There may be more than one if there are multiple browser windows open, or
+  // tabs are being warmed up. There may be none if this process does not host any
+  // visible or warming tabs.
+  static nsTHashtable<nsPtrHashKey<TabChild>>* sVisibleTabs;
 
   DISALLOW_EVIL_CONSTRUCTORS(TabChild);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_TabChild_h
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -657,18 +657,18 @@ BackgroundChildImpl::RecvDispatchLocalSt
 }
 
 bool
 BackgroundChildImpl::GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups)
 {
   if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
     MOZ_ASSERT(NS_IsMainThread());
     aGroups.Clear();
-    if (dom::TabChild::HasActiveTabs()) {
-      for (auto iter = dom::TabChild::GetActiveTabs().ConstIter();
+    if (dom::TabChild::HasVisibleTabs()) {
+      for (auto iter = dom::TabChild::GetVisibleTabs().ConstIter();
            !iter.Done(); iter.Next()) {
         aGroups.Put(iter.Get()->GetKey()->TabGroup());
       }
     }
     return true;
   }
 
   return false;
--- a/xpcom/threads/LabeledEventQueue.cpp
+++ b/xpcom/threads/LabeledEventQueue.cpp
@@ -166,46 +166,46 @@ LabeledEventQueue::GetEvent(EventPriorit
     MOZ_ASSERT(entry.mRunnable.get());
     return entry.mRunnable.forget();
   }
 
   if (!sCurrentSchedulerGroup) {
     return nullptr;
   }
 
-  // Move active tabs to the front of the queue. The mAvoidActiveTabCount field
-  // prevents us from preferentially processing events from active tabs twice in
+  // Move visible tabs to the front of the queue. The mAvoidVisibleTabCount field
+  // prevents us from preferentially processing events from visible tabs twice in
   // a row. This scheme is designed to prevent starvation.
-  if (TabChild::HasActiveTabs() && mAvoidActiveTabCount <= 0) {
-    for (auto iter = TabChild::GetActiveTabs().ConstIter();
+  if (TabChild::HasVisibleTabs() && mAvoidVisibleTabCount <= 0) {
+    for (auto iter = TabChild::GetVisibleTabs().ConstIter();
          !iter.Done(); iter.Next()) {
       SchedulerGroup* group = iter.Get()->GetKey()->TabGroup();
       if (!group->isInList() || group == sCurrentSchedulerGroup) {
         continue;
       }
 
-      // For each active tab we move to the front of the queue, we have to
-      // process two SchedulerGroups (the active tab and another one, presumably
-      // a background group) before we prioritize active tabs again.
-      mAvoidActiveTabCount += 2;
+      // For each visible tab we move to the front of the queue, we have to
+      // process two SchedulerGroups (the visible tab and another one, presumably
+      // a background group) before we prioritize visible tabs again.
+      mAvoidVisibleTabCount += 2;
 
       // We move |group| right before sCurrentSchedulerGroup and then set
       // sCurrentSchedulerGroup to group.
       MOZ_ASSERT(group != sCurrentSchedulerGroup);
       group->removeFrom(*sSchedulerGroups);
       sCurrentSchedulerGroup->setPrevious(group);
       sCurrentSchedulerGroup = group;
     }
   }
 
   // Iterate over each SchedulerGroup once, starting at sCurrentSchedulerGroup.
   SchedulerGroup* firstGroup = sCurrentSchedulerGroup;
   SchedulerGroup* group = firstGroup;
   do {
-    mAvoidActiveTabCount--;
+    mAvoidVisibleTabCount--;
 
     RunnableEpochQueue& queue = group->GetQueue(mPriority);
 
     if (queue.IsEmpty()) {
       // This can happen if |group| is in a different LabeledEventQueue than |this|.
       group = NextSchedulerGroup(group);
       continue;
     }
--- a/xpcom/threads/LabeledEventQueue.h
+++ b/xpcom/threads/LabeledEventQueue.h
@@ -132,19 +132,19 @@ private:
   static LinkedList<SchedulerGroup>* sSchedulerGroups;
   static size_t sLabeledEventQueueCount;
   static SchedulerGroup* sCurrentSchedulerGroup;
 
   RunnableEpochQueue mUnlabeled;
   EpochQueue mEpochs;
   size_t mNumEvents = 0;
 
-  // Number of SchedulerGroups that must be processed before we prioritize an
-  // active tab. This field is designed to guarantee a 1:1 interleaving between
+  // Number of SchedulerGroups that must be processed before we prioritize a
+  // visible tab. This field is designed to guarantee a 1:1 interleaving between
   // foreground and background SchedulerGroups. For details, see its usage in
   // LabeledEventQueue.cpp.
-  int64_t mAvoidActiveTabCount = 0;
+  int64_t mAvoidVisibleTabCount = 0;
   EventPriority mPriority;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_LabeledEventQueue_h