Bug 1397426 - Rename TabChild's notion of "active tabs" to "visible tabs" and move logic into renderLayers. r=billm

MozReview-Commit-ID: 1bBNwew7uCk

--HG--
extra : rebase_source : 0e59b548c6c01d7feaf9f40c282ab2f55e47bab7
extra : source : 4643e46ff8d3e84d10ff178e15a1be7f734b020f
This commit is contained in:
Mike Conley 2017-11-03 11:27:29 -04:00
Родитель 26b5553c8a
Коммит 921cb8735c
6 изменённых файлов: 46 добавлений и 58 удалений

Просмотреть файл

@ -5824,10 +5824,6 @@ nsDocShell::SetIsActive(bool aIsActive)
// 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());

Просмотреть файл

@ -165,7 +165,7 @@ NS_IMPL_ISUPPORTS(TabChildSHistoryListener,
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;
@ -1150,11 +1150,11 @@ TabChild::ActorDestroy(ActorDestroyReason why)
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;
}
}
@ -2665,23 +2665,6 @@ TabChild::RemovePendingDocShellBlocker()
}
}
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)
{
@ -2755,6 +2738,11 @@ TabChild::RecvRenderLayers(const bool& aEnabled, const uint64_t& aLayerObserverE
}
}
if (!sVisibleTabs) {
sVisibleTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
}
sVisibleTabs->PutEntry(this);
MakeVisible();
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
@ -2793,6 +2781,12 @@ TabChild::RecvRenderLayers(const bool& aEnabled, const uint64_t& aLayerObserverE
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();
}

Просмотреть файл

@ -581,8 +581,6 @@ public:
void MakeHidden();
bool IsVisible();
void OnDocShellActivated(bool aIsActive);
nsIContentChild* Manager() const { return mManager; }
static inline TabChild*
@ -778,20 +776,20 @@ public:
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:
@ -991,11 +989,11 @@ private:
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);
};

Просмотреть файл

@ -662,8 +662,8 @@ BackgroundChildImpl::GetMessageSchedulerGroups(const Message& aMsg, SchedulerGro
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());
}

Просмотреть файл

@ -171,21 +171,21 @@ LabeledEventQueue::GetEvent(EventPriority* aPriority,
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.
@ -200,7 +200,7 @@ LabeledEventQueue::GetEvent(EventPriority* aPriority,
SchedulerGroup* firstGroup = sCurrentSchedulerGroup;
SchedulerGroup* group = firstGroup;
do {
mAvoidActiveTabCount--;
mAvoidVisibleTabCount--;
RunnableEpochQueue& queue = group->GetQueue(mPriority);

Просмотреть файл

@ -137,11 +137,11 @@ private:
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;
};