Don't retain a ref to ImageContainers in ImageBridgeChild. (bug 1325784 part 6, r=nical)
authorDavid Anderson <dvander@alliedmods.net>
Wed, 04 Jan 2017 10:19:31 -0500
changeset 327961 8a281e6c7c56a7aa2d77b556f42fedfa2baa365a
parent 327960 38cde09a9df35208d2fa0436566ea82665917c90
child 327962 3535ad342933572ba2c93f056a9cdb44a085a6cf
push id31160
push userphilringnalda@gmail.com
push dateThu, 05 Jan 2017 02:33:44 +0000
treeherdermozilla-central@f13abb8ba9f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1325784
milestone53.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
Don't retain a ref to ImageContainers in ImageBridgeChild. (bug 1325784 part 6, r=nical)
gfx/layers/ImageContainer.cpp
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -141,16 +141,21 @@ ImageContainer::ImageContainer(uint64_t 
   mAsyncContainerID(aAsyncContainerID),
   mCurrentProducerID(-1)
 {
   MOZ_ASSERT(mAsyncContainerID != sInvalidAsyncContainerId);
 }
 
 ImageContainer::~ImageContainer()
 {
+  if (mAsyncContainerID) {
+    if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) {
+      imageBridge->ForgetImageContainer(mAsyncContainerID);
+    }
+  }
 }
 
 RefPtr<PlanarYCbCrImage>
 ImageContainer::CreatePlanarYCbCrImage()
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   EnsureImageClient(false);
   if (mImageClient && mImageClient->AsImageClientSingle()) {
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -346,16 +346,17 @@ ImageBridgeChild::CreateCanvasClientSync
   AutoCompleteTask complete(aTask);
   *outResult = CreateCanvasClientNow(aType, aFlags);
 }
 
 ImageBridgeChild::ImageBridgeChild()
   : mCanSend(false)
   , mCalledClose(false)
   , mFwdTransactionId(0)
+  , mContainerMapLock("ImageBridgeChild.mContainerMapLock")
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mTxn = new CompositableTransaction();
 }
 
 ImageBridgeChild::~ImageBridgeChild()
 {
@@ -373,50 +374,65 @@ ImageBridgeChild::MarkShutDown()
 void
 ImageBridgeChild::Connect(CompositableClient* aCompositable,
                           ImageContainer* aImageContainer)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(InImageBridgeChildThread());
   MOZ_ASSERT(CanSend());
 
+  // Note: this is static, rather than per-IBC, so IDs are not re-used across
+  // ImageBridgeChild instances. This is relevant for the GPU process, where
+  // we don't want old IDs to potentially leak into a recreated ImageBridge.
   static uint64_t sNextID = 1;
   uint64_t id = sNextID++;
 
-  MOZ_ASSERT(!mImageContainers.Contains(id));
-  mImageContainers.Put(id, aImageContainer);
+  {
+    MutexAutoLock lock(mContainerMapLock);
+    MOZ_ASSERT(!mImageContainers.Contains(id));
+    mImageContainers.Put(id, aImageContainer);
+  }
 
   PCompositableChild* child =
     SendPCompositableConstructor(aCompositable->GetTextureInfo(), id);
   if (!child) {
     return;
   }
   aCompositable->InitIPDLActor(child, id);
 }
 
+void
+ImageBridgeChild::ForgetImageContainer(uint64_t aAsyncContainerID)
+{
+  MutexAutoLock lock(mContainerMapLock);
+  mImageContainers.Remove(aAsyncContainerID);
+}
+
 PCompositableChild*
 ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo, const uint64_t& aID)
 {
   MOZ_ASSERT(CanSend());
   return AsyncCompositableChild::CreateActor(aID);
 }
 
 bool
 ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
 {
   AsyncCompositableChild* actor = static_cast<AsyncCompositableChild*>(aActor);
   MOZ_ASSERT(actor->GetAsyncID());
 
-  mImageContainers.Remove(actor->GetAsyncID());
+  {
+    MutexAutoLock lock(mContainerMapLock);
+    mImageContainers.Remove(actor->GetAsyncID());
+  }
 
   AsyncCompositableChild::DestroyActor(aActor);
   return true;
 }
 
-
 Thread* ImageBridgeChild::GetThread() const
 {
   return sImageBridgeChildThread;
 }
 
 /* static */ RefPtr<ImageBridgeChild>
 ImageBridgeChild::GetSingleton()
 {
@@ -1084,17 +1100,21 @@ ImageBridgeChild::RecvParentAsyncMessage
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ImageBridgeChild::RecvDidComposite(InfallibleTArray<ImageCompositeNotification>&& aNotifications)
 {
   for (auto& n : aNotifications) {
-    RefPtr<ImageContainer> imageContainer = mImageContainers.Get(n.asyncCompositableID());
+    RefPtr<ImageContainer> imageContainer;
+    {
+      MutexAutoLock lock(mContainerMapLock);
+      imageContainer = mImageContainers.Get(n.asyncCompositableID());
+    }
     if (imageContainer) {
       imageContainer->NotifyComposite(n);
     }
   }
   return IPC_OK();
 }
 
 PTextureChild*
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -265,16 +265,18 @@ public:
   virtual void UseTextures(CompositableClient* aCompositable,
                            const nsTArray<TimedTextureClient>& aTextures) override;
   virtual void UseComponentAlphaTextures(CompositableClient* aCompositable,
                                          TextureClient* aClientOnBlack,
                                          TextureClient* aClientOnWhite) override;
 
   void Destroy(CompositableChild* aCompositable) override;
 
+  void ForgetImageContainer(uint64_t aAsyncContainerID);
+
   /**
    * Hold TextureClient ref until end of usage on host side if TextureFlags::RECYCLE is set.
    * Host side's usage is checked via CompositableRef.
    */
   void HoldUntilCompositableRefReleasedIfNecessary(TextureClient* aClient);
 
   /**
    * Notify id of Texture When host side end its use. Transaction id is used to
@@ -381,15 +383,16 @@ private:
    * Hold TextureClients refs until end of their usages on host side.
    * It defer calling of TextureClient recycle callback.
    */
   nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled;
 
   /**
    * Mapping from async compositable IDs to image containers.
    */
-  nsDataHashtable<nsUint64HashKey, RefPtr<ImageContainer>> mImageContainers;
+  Mutex mContainerMapLock;
+  nsDataHashtable<nsUint64HashKey, ImageContainer*> mImageContainers;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif