зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1405824 - Recycle a Shmem for IpcResourceUpdateQueue to avoid allocation overhead. r=jrmuizel
This commit is contained in:
Родитель
36aaaf44e8
Коммит
a98ed42cd6
|
@ -92,11 +92,12 @@ bool
|
|||
ShmSegmentsWriter::AllocChunk()
|
||||
{
|
||||
RefCountedShmem shm;
|
||||
if (!RefCountedShm::Alloc(mShmAllocator, mChunkSize, shm)) {
|
||||
if (!mShmAllocator->AllocResourceShmem(mChunkSize, shm)) {
|
||||
gfxCriticalNote << "ShmSegmentsWriter failed to allocate chunk #" << mSmallAllocs.Length();
|
||||
MOZ_ASSERT(false, "ShmSegmentsWriter fails to allocate chunk");
|
||||
return false;
|
||||
}
|
||||
RefCountedShm::AddRef(shm);
|
||||
mSmallAllocs.AppendElement(shm);
|
||||
return true;
|
||||
}
|
||||
|
@ -119,8 +120,8 @@ ShmSegmentsWriter::AllocLargeChunk(size_t aSize)
|
|||
void
|
||||
ShmSegmentsWriter::Flush(nsTArray<RefCountedShmem>& aSmallAllocs, nsTArray<ipc::Shmem>& aLargeAllocs)
|
||||
{
|
||||
aSmallAllocs.Clear();
|
||||
aLargeAllocs.Clear();
|
||||
MOZ_ASSERT(aSmallAllocs.IsEmpty());
|
||||
MOZ_ASSERT(aLargeAllocs.IsEmpty());
|
||||
mSmallAllocs.SwapElements(aSmallAllocs);
|
||||
mLargeAllocs.SwapElements(aLargeAllocs);
|
||||
}
|
||||
|
@ -129,15 +130,9 @@ void
|
|||
ShmSegmentsWriter::Clear()
|
||||
{
|
||||
if (mShmAllocator) {
|
||||
for (auto& shm : mSmallAllocs) {
|
||||
RefCountedShm::Dealloc(mShmAllocator, shm);
|
||||
}
|
||||
for (auto& shm : mLargeAllocs) {
|
||||
mShmAllocator->DeallocShmem(shm);
|
||||
}
|
||||
IpcResourceUpdateQueue::ReleaseShmems(mShmAllocator, mSmallAllocs);
|
||||
IpcResourceUpdateQueue::ReleaseShmems(mShmAllocator, mLargeAllocs);
|
||||
}
|
||||
mSmallAllocs.Clear();
|
||||
mLargeAllocs.Clear();
|
||||
mCursor = 0;
|
||||
}
|
||||
|
||||
|
@ -354,7 +349,7 @@ IpcResourceUpdateQueue::DeleteFontInstance(wr::FontInstanceKey aKey)
|
|||
|
||||
void
|
||||
IpcResourceUpdateQueue::Flush(nsTArray<layers::OpUpdateResource>& aUpdates,
|
||||
nsTArray<RefCountedShmem>& aSmallAllocs,
|
||||
nsTArray<layers::RefCountedShmem>& aSmallAllocs,
|
||||
nsTArray<ipc::Shmem>& aLargeAllocs)
|
||||
{
|
||||
aUpdates.Clear();
|
||||
|
@ -369,5 +364,27 @@ IpcResourceUpdateQueue::Clear()
|
|||
mUpdates.Clear();
|
||||
}
|
||||
|
||||
//static
|
||||
void
|
||||
IpcResourceUpdateQueue::ReleaseShmems(ipc::IProtocol* aShmAllocator, nsTArray<layers::RefCountedShmem>& aShms)
|
||||
{
|
||||
for (auto& shm : aShms) {
|
||||
if (RefCountedShm::IsValid(shm) && RefCountedShm::Release(shm) == 0) {
|
||||
RefCountedShm::Dealloc(aShmAllocator, shm);
|
||||
}
|
||||
}
|
||||
aShms.Clear();
|
||||
}
|
||||
|
||||
//static
|
||||
void
|
||||
IpcResourceUpdateQueue::ReleaseShmems(ipc::IProtocol* aShmAllocator, nsTArray<ipc::Shmem>& aShms)
|
||||
{
|
||||
for (auto& shm : aShms) {
|
||||
aShmAllocator->DeallocShmem(shm);
|
||||
}
|
||||
aShms.Clear();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
|
|
@ -118,6 +118,8 @@ public:
|
|||
nsTArray<layers::RefCountedShmem>& aSmallAllocs,
|
||||
nsTArray<ipc::Shmem>& aLargeAllocs);
|
||||
|
||||
static void ReleaseShmems(ipc::IProtocol*, nsTArray<layers::RefCountedShmem>& aShmems);
|
||||
static void ReleaseShmems(ipc::IProtocol*, nsTArray<ipc::Shmem>& aShmems);
|
||||
protected:
|
||||
ShmSegmentsWriter mWriter;
|
||||
nsTArray<layers::OpUpdateResource> mUpdates;
|
||||
|
|
|
@ -68,6 +68,11 @@ WebRenderBridgeChild::ActorDestroy(ActorDestroyReason why)
|
|||
void
|
||||
WebRenderBridgeChild::DoDestroy()
|
||||
{
|
||||
if (RefCountedShm::IsValid(mResourceShm) && RefCountedShm::Release(mResourceShm) == 0) {
|
||||
RefCountedShm::Dealloc(this, mResourceShm);
|
||||
mResourceShm = RefCountedShmem();
|
||||
}
|
||||
|
||||
// mDestroyed is used to prevent calling Send__delete__() twice.
|
||||
// When this function is called from CompositorBridgeChild::Destroy().
|
||||
// mActiveResourceTracker is not cleared here, since it is
|
||||
|
@ -637,5 +642,49 @@ WebRenderBridgeChild::GetForMedia()
|
|||
return MakeAndAddRef<KnowsCompositorMediaProxy>(GetTextureFactoryIdentifier());
|
||||
}
|
||||
|
||||
bool
|
||||
WebRenderBridgeChild::AllocResourceShmem(size_t aSize, RefCountedShmem& aShm)
|
||||
{
|
||||
// We keep a single shmem around to reuse later if it is reference count has
|
||||
// dropped back to 1 (the reference held by the WebRenderBridgeChild).
|
||||
|
||||
// If the cached shmem exists, has the correct size and isn't held by anything
|
||||
// other than us, recycle it.
|
||||
bool alreadyAllocated = RefCountedShm::IsValid(mResourceShm);
|
||||
if (alreadyAllocated) {
|
||||
if (RefCountedShm::GetSize(mResourceShm) == aSize
|
||||
&& RefCountedShm::GetReferenceCount(mResourceShm) <= 1) {
|
||||
MOZ_ASSERT(RefCountedShm::GetReferenceCount(mResourceShm) == 1);
|
||||
aShm = mResourceShm;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If there was no cached shmem or we couldn't recycle it, alloc a new one.
|
||||
if (!RefCountedShm::Alloc(this, aSize, aShm)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now that we have a valid shmem, put it in the cache if we don't have one
|
||||
// yet.
|
||||
if (!alreadyAllocated) {
|
||||
mResourceShm = aShm;
|
||||
RefCountedShm::AddRef(aShm);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeChild::DeallocResourceShmem(RefCountedShmem& aShm)
|
||||
{
|
||||
if (!RefCountedShm::IsValid(aShm)) {
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(RefCountedShm::GetReferenceCount(aShm) == 0);
|
||||
|
||||
RefCountedShm::Dealloc(this, aShm);
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -154,6 +154,17 @@ public:
|
|||
|
||||
virtual RefPtr<KnowsCompositor> GetForMedia() override;
|
||||
|
||||
/// Alloc a specific type of shmem that is intended for use in
|
||||
/// IpcResourceUpdateQueue only, and cache at most one of them,
|
||||
/// when called multiple times.
|
||||
///
|
||||
/// Do not use this for anything else.
|
||||
bool AllocResourceShmem(size_t aSize, RefCountedShmem& aShm);
|
||||
/// Dealloc shared memory that was allocated with AllocResourceShmem.
|
||||
///
|
||||
/// Do not use this for anything else.
|
||||
void DeallocResourceShmem(RefCountedShmem& aShm);
|
||||
|
||||
private:
|
||||
friend class CompositorBridgeChild;
|
||||
|
||||
|
@ -224,6 +235,8 @@ private:
|
|||
nsDataHashtable<ScaledFontHashKey, wr::FontInstanceKey> mFontInstanceKeys;
|
||||
|
||||
UniquePtr<ActiveResourceTracker> mActiveResourceTracker;
|
||||
|
||||
RefCountedShmem mResourceShm;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
|
|
@ -266,28 +266,6 @@ WebRenderBridgeParent::Destroy()
|
|||
ClearResources();
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeParent::DeallocShmems(nsTArray<ipc::Shmem>& aShmems)
|
||||
{
|
||||
if (IPCOpen()) {
|
||||
for (auto& shm : aShmems) {
|
||||
DeallocShmem(shm);
|
||||
}
|
||||
}
|
||||
aShmems.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
WebRenderBridgeParent::DeallocShmems(nsTArray<RefCountedShmem>& aShmems)
|
||||
{
|
||||
if (IPCOpen()) {
|
||||
for (auto& shm : aShmems) {
|
||||
RefCountedShm::Dealloc(this, shm);
|
||||
}
|
||||
}
|
||||
aShmems.Clear();
|
||||
}
|
||||
|
||||
bool
|
||||
WebRenderBridgeParent::UpdateResources(const nsTArray<OpUpdateResource>& aResourceUpdates,
|
||||
const nsTArray<RefCountedShmem>& aSmallShmems,
|
||||
|
@ -465,16 +443,14 @@ WebRenderBridgeParent::RecvUpdateResources(nsTArray<OpUpdateResource>&& aResourc
|
|||
nsTArray<ipc::Shmem>&& aLargeShmems)
|
||||
{
|
||||
if (mDestroyed) {
|
||||
DeallocShmems(aSmallShmems);
|
||||
DeallocShmems(aLargeShmems);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
wr::ResourceUpdateQueue updates;
|
||||
|
||||
if (!UpdateResources(aResourceUpdates, aSmallShmems, aLargeShmems, updates)) {
|
||||
DeallocShmems(aSmallShmems);
|
||||
DeallocShmems(aLargeShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
|
||||
IPC_FAIL(this, "Invalid WebRender resource data shmem or address.");
|
||||
}
|
||||
|
||||
|
@ -482,8 +458,8 @@ WebRenderBridgeParent::RecvUpdateResources(nsTArray<OpUpdateResource>&& aResourc
|
|||
txn.UpdateResources(updates);
|
||||
mApi->SendTransaction(txn);
|
||||
|
||||
DeallocShmems(aSmallShmems);
|
||||
DeallocShmems(aLargeShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -601,8 +577,6 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
|
|||
for (const auto& op : aToDestroy) {
|
||||
DestroyActor(op);
|
||||
}
|
||||
DeallocShmems(aSmallShmems);
|
||||
DeallocShmems(aLargeShmems);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -664,8 +638,8 @@ WebRenderBridgeParent::RecvSetDisplayList(const gfx::IntSize& aSize,
|
|||
mCompositorBridge->DidComposite(wr::AsUint64(mPipelineId), now, now);
|
||||
}
|
||||
|
||||
DeallocShmems(aSmallShmems);
|
||||
DeallocShmems(aLargeShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aSmallShmems);
|
||||
wr::IpcResourceUpdateQueue::ReleaseShmems(this, aLargeShmems);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
|
@ -192,9 +192,6 @@ public:
|
|||
CompositorAnimationStorage* aAnimStorage);
|
||||
|
||||
private:
|
||||
void DeallocShmems(nsTArray<ipc::Shmem>& aShmems);
|
||||
void DeallocShmems(nsTArray<RefCountedShmem>& aShmems);
|
||||
|
||||
explicit WebRenderBridgeParent(const wr::PipelineId& aPipelineId);
|
||||
virtual ~WebRenderBridgeParent();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче