Bug 1454594 - Avoid running unordered_map static initializers. r=botond

We wrap the std::unordered_map in a StaticAutoPtr so that there's no
initialization cost, and also so that we have a smaller memory footprint
in processes that aren't using WebRender+APZ.

MozReview-Commit-ID: 9QCKiv0IzB8

--HG--
extra : rebase_source : 102d034478513f45da689bacffbc893370677ff7
This commit is contained in:
Kartikaya Gupta 2018-04-18 17:32:38 -04:00
parent 5164ff5681
commit 34876c4821
4 changed files with 38 additions and 17 deletions

View File

@ -12,6 +12,7 @@
#include "base/platform_thread.h" // for PlatformThreadId
#include "mozilla/layers/AsyncCompositionManager.h" // for AsyncTransform
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "nsTArray.h"
#include "Units.h"
@ -110,9 +111,12 @@ private:
// Used to manage the mapping from a WR window id to APZSampler. These are only
// used if WebRender is enabled. Both sWindowIdMap and mWindowId should only
// be used while holding the sWindowIdLock.
// be used while holding the sWindowIdLock. Note that we use a StaticAutoPtr
// wrapper on sWindowIdMap to avoid a static initializer for the unordered_map.
// This also avoids the initializer/memory allocation in cases where we're
// not using WebRender.
static StaticMutex sWindowIdLock;
static std::unordered_map<uint64_t, APZSampler*> sWindowIdMap;
static StaticAutoPtr<std::unordered_map<uint64_t, APZSampler*>> sWindowIdMap;
Maybe<wr::WrWindowId> mWindowId;
// If WebRender is enabled, this holds the thread id of the render backend

View File

@ -15,6 +15,7 @@
#include "mozilla/layers/APZTestData.h"
#include "mozilla/layers/WebRenderScrollData.h"
#include "mozilla/StaticMutex.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsThreadUtils.h"
#include "Units.h"
@ -184,9 +185,12 @@ private:
// Used to manage the mapping from a WR window id to APZUpdater. These are only
// used if WebRender is enabled. Both sWindowIdMap and mWindowId should only
// be used while holding the sWindowIdLock.
// be used while holding the sWindowIdLock. Note that we use a StaticAutoPtr
// wrapper on sWindowIdMap to avoid a static initializer for the unordered_map.
// This also avoids the initializer/memory allocation in cases where we're
// not using WebRender.
static StaticMutex sWindowIdLock;
static std::unordered_map<uint64_t, APZUpdater*> sWindowIdMap;
static StaticAutoPtr<std::unordered_map<uint64_t, APZUpdater*>> sWindowIdMap;
Maybe<wr::WrWindowId> mWindowId;
// If WebRender and async scene building are enabled, this holds the thread id

View File

@ -19,7 +19,7 @@ namespace mozilla {
namespace layers {
StaticMutex APZSampler::sWindowIdLock;
std::unordered_map<uint64_t, APZSampler*> APZSampler::sWindowIdMap;
StaticAutoPtr<std::unordered_map<uint64_t, APZSampler*>> APZSampler::sWindowIdMap;
APZSampler::APZSampler(const RefPtr<APZCTreeManager>& aApz)
@ -39,7 +39,8 @@ APZSampler::~APZSampler()
StaticMutexAutoLock lock(sWindowIdLock);
if (mWindowId) {
sWindowIdMap.erase(wr::AsUint64(*mWindowId));
MOZ_ASSERT(sWindowIdMap);
sWindowIdMap->erase(wr::AsUint64(*mWindowId));
}
}
@ -49,7 +50,10 @@ APZSampler::SetWebRenderWindowId(const wr::WindowId& aWindowId)
StaticMutexAutoLock lock(sWindowIdLock);
MOZ_ASSERT(!mWindowId);
mWindowId = Some(aWindowId);
sWindowIdMap[wr::AsUint64(aWindowId)] = this;
if (!sWindowIdMap) {
sWindowIdMap = new std::unordered_map<uint64_t, APZSampler*>();
}
(*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
}
/*static*/ void
@ -242,9 +246,11 @@ APZSampler::GetSampler(const wr::WrWindowId& aWindowId)
{
RefPtr<APZSampler> sampler;
StaticMutexAutoLock lock(sWindowIdLock);
auto it = sWindowIdMap.find(wr::AsUint64(aWindowId));
if (it != sWindowIdMap.end()) {
sampler = it->second;
if (sWindowIdMap) {
auto it = sWindowIdMap->find(wr::AsUint64(aWindowId));
if (it != sWindowIdMap->end()) {
sampler = it->second;
}
}
return sampler.forget();
}

View File

@ -19,7 +19,7 @@ namespace mozilla {
namespace layers {
StaticMutex APZUpdater::sWindowIdLock;
std::unordered_map<uint64_t, APZUpdater*> APZUpdater::sWindowIdMap;
StaticAutoPtr<std::unordered_map<uint64_t, APZUpdater*>> APZUpdater::sWindowIdMap;
APZUpdater::APZUpdater(const RefPtr<APZCTreeManager>& aApz)
@ -39,8 +39,9 @@ APZUpdater::~APZUpdater()
StaticMutexAutoLock lock(sWindowIdLock);
if (mWindowId) {
MOZ_ASSERT(sWindowIdMap);
// Ensure that ClearTree was called and the task got run
MOZ_ASSERT(sWindowIdMap.find(wr::AsUint64(*mWindowId)) == sWindowIdMap.end());
MOZ_ASSERT(sWindowIdMap->find(wr::AsUint64(*mWindowId)) == sWindowIdMap->end());
}
}
@ -56,7 +57,10 @@ APZUpdater::SetWebRenderWindowId(const wr::WindowId& aWindowId)
StaticMutexAutoLock lock(sWindowIdLock);
MOZ_ASSERT(!mWindowId);
mWindowId = Some(aWindowId);
sWindowIdMap[wr::AsUint64(aWindowId)] = this;
if (!sWindowIdMap) {
sWindowIdMap = new std::unordered_map<uint64_t, APZUpdater*>();
}
(*sWindowIdMap)[wr::AsUint64(aWindowId)] = this;
}
/*static*/ void
@ -147,7 +151,8 @@ APZUpdater::ClearTree(LayersId aRootLayersId)
// and avoid leaving a dangling pointer to this object.
StaticMutexAutoLock lock(sWindowIdLock);
if (self->mWindowId) {
sWindowIdMap.erase(wr::AsUint64(*(self->mWindowId)));
MOZ_ASSERT(sWindowIdMap);
sWindowIdMap->erase(wr::AsUint64(*(self->mWindowId)));
}
}
));
@ -416,9 +421,11 @@ APZUpdater::GetUpdater(const wr::WrWindowId& aWindowId)
{
RefPtr<APZUpdater> updater;
StaticMutexAutoLock lock(sWindowIdLock);
auto it = sWindowIdMap.find(wr::AsUint64(aWindowId));
if (it != sWindowIdMap.end()) {
updater = it->second;
if (sWindowIdMap) {
auto it = sWindowIdMap->find(wr::AsUint64(aWindowId));
if (it != sWindowIdMap->end()) {
updater = it->second;
}
}
return updater.forget();
}