Backed out 7 changesets (bug 1298938) for mass leaks a=bustage CLOSED TREE
authorWes Kocher <wkocher@mozilla.com>
Thu, 08 Sep 2016 13:28:14 -0700
changeset 354638 1222234def49c717a85f7a0dd05806a4d5b158ff
parent 354637 061471589005c94bdd4ab3dc81cd18e3c2635ff2
child 354639 e41ac717a38f8d6518be63e0831b5eb1657a223d
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbustage
bugs1298938
milestone51.0a1
backs outd710b5ac1e138892fa1d7bcbcd37d3e67ad1506e
df832e32e7aacff4b61470edaa84e6e9b882e7d2
3f6883401be4d262e380eaecd7daba7fc60b19d2
e43fc0029b900789a6d60be92b5696e0d78121c5
6dd0b4b22b23037813023f3492ec849412190464
81e994db6b8c9e8d8d1fa5fefb1977a127b8ccfb
a757098353c69c2b25c98be3d6342241d92b3de1
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
Backed out 7 changesets (bug 1298938) for mass leaks a=bustage CLOSED TREE Backed out changeset d710b5ac1e13 (bug 1298938) Backed out changeset df832e32e7aa (bug 1298938) Backed out changeset 3f6883401be4 (bug 1298938) Backed out changeset e43fc0029b90 (bug 1298938) Backed out changeset 6dd0b4b22b23 (bug 1298938) Backed out changeset 81e994db6b8c (bug 1298938) Backed out changeset a757098353c6 (bug 1298938)
dom/canvas/OffscreenCanvas.cpp
dom/media/platforms/wmf/DXVA2Manager.cpp
dom/media/systemservices/MediaSystemResourceManager.cpp
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginModuleParent.cpp
gfx/ipc/GPUProcessManager.cpp
gfx/layers/ImageContainer.cpp
gfx/layers/ipc/CompositableForwarder.h
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/ImageBridgeChild.h
xpcom/ds/nsExpirationTracker.h
--- a/dom/canvas/OffscreenCanvas.cpp
+++ b/dom/canvas/OffscreenCanvas.cpp
@@ -142,19 +142,20 @@ OffscreenCanvas::GetContext(JSContext* a
         contextType == CanvasContextType::WebGL2) {
       WebGLContext* webGL = static_cast<WebGLContext*>(mCurrentContext.get());
       gl::GLContext* gl = webGL->GL();
       mCanvasRenderer->mContext = mCurrentContext;
       mCanvasRenderer->SetActiveThread();
       mCanvasRenderer->mGLContext = gl;
       mCanvasRenderer->SetIsAlphaPremultiplied(webGL->IsPremultAlpha() || !gl->Caps().alpha);
 
-      if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) {
+      if (ImageBridgeChild::IsCreated()) {
         TextureFlags flags = TextureFlags::ORIGIN_BOTTOM_LEFT;
-        mCanvasClient = imageBridge->CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags);
+        mCanvasClient = ImageBridgeChild::GetSingleton()->
+          CreateCanvasClient(CanvasClient::CanvasClientTypeShSurf, flags);
         mCanvasRenderer->SetCanvasClient(mCanvasClient);
 
         gl::GLScreenBuffer* screen = gl->Screen();
         gl::SurfaceCaps caps = screen->mCaps;
         auto forwarder = mCanvasClient->GetForwarder();
 
         UniquePtr<gl::SurfaceFactory> factory =
           gl::GLScreenBuffer::CreateFactory(gl, caps, forwarder, flags);
--- a/dom/media/platforms/wmf/DXVA2Manager.cpp
+++ b/dom/media/platforms/wmf/DXVA2Manager.cpp
@@ -423,17 +423,17 @@ D3D9DXVA2Manager::Init(nsACString& aFail
   mDecoderService = decoderService;
 
   mResetToken = resetToken;
   mD3D9 = d3d9Ex;
   mDevice = device;
   mDeviceManager = deviceManager;
   mSyncSurface = syncSurf;
 
-  mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
+  mTextureClientAllocator = new D3D9RecycleAllocator(layers::ImageBridgeChild::GetSingleton(),
                                                      mDevice);
   mTextureClientAllocator->SetMaxPoolSize(5);
 
   Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
                         uint32_t(media::MediaDecoderBackend::WMFDXVA2D3D9));
 
   reporter.SetSuccessful();
 
@@ -747,17 +747,17 @@ D3D11DXVA2Manager::Init(nsACString& aFai
   desc.Usage = D3D11_USAGE_STAGING;
   desc.BindFlags = 0;
   desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
   desc.MiscFlags = 0;
 
   hr = mDevice->CreateTexture2D(&desc, NULL, getter_AddRefs(mSyncSurface));
   NS_ENSURE_TRUE(SUCCEEDED(hr), hr);
 
-  mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton().get(),
+  mTextureClientAllocator = new D3D11RecycleAllocator(layers::ImageBridgeChild::GetSingleton(),
                                                       mDevice);
   mTextureClientAllocator->SetMaxPoolSize(5);
 
   Telemetry::Accumulate(Telemetry::MEDIA_DECODER_BACKEND_USED,
                         uint32_t(media::MediaDecoderBackend::WMFDXVA2D3D11));
 
   reporter.SetSuccessful();
 
--- a/dom/media/systemservices/MediaSystemResourceManager.cpp
+++ b/dom/media/systemservices/MediaSystemResourceManager.cpp
@@ -37,18 +37,17 @@ MediaSystemResourceManager::Shutdown()
     sSingleton->CloseIPC();
     sSingleton = nullptr;
   }
 }
 
 /* static */ void
 MediaSystemResourceManager::Init()
 {
-  RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
-  if (!imageBridge) {
+  if (!ImageBridgeChild::IsCreated()) {
     NS_WARNING("ImageBridge does not exist");
     return;
   }
 
   if (InImageBridgeChildThread()) {
     if (!sSingleton) {
 #ifdef DEBUG
       static int timesCreated = 0;
@@ -69,17 +68,17 @@ MediaSystemResourceManager::Init()
       if (!sSingleton) {
         sSingleton = new MediaSystemResourceManager();
       }
       ReentrantMonitorAutoEnter childThreadAutoMon(barrier);
       done = true;
       barrier.NotifyAll();
     });
 
-  imageBridge->GetMessageLoop()->PostTask(runnable.forget());
+  ImageBridgeChild::GetSingleton()->GetMessageLoop()->PostTask(runnable.forget());
 
   // should stop the thread until done.
   while (!done) {
     barrier.Wait();
   }
 }
 
 MediaSystemResourceManager::MediaSystemResourceManager()
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -672,17 +672,17 @@ PluginInstanceParent::RecvInitDXGISurfac
         return true;
     }
 
     ImageContainer *container = GetImageContainer();
     if (!container) {
         return true;
     }
 
-    RefPtr<ImageBridgeChild> forwarder = ImageBridgeChild::GetSingleton();
+    ImageBridgeChild* forwarder = ImageBridgeChild::GetSingleton();
     if (!forwarder) {
         return true;
     }
 
     RefPtr<ID3D11Device> d3d11 = DeviceManagerDx::Get()->GetContentDevice();
     if (!d3d11) {
         return true;
     }
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -3124,17 +3124,17 @@ PluginModuleParent::RecvReturnSitesWithD
     mSitesWithDataCallbacks.erase(aCallbackId);
     return true;
 }
 
 layers::TextureClientRecycleAllocator*
 PluginModuleParent::EnsureTextureAllocator()
 {
     if (!mTextureAllocator) {
-        mTextureAllocator = new TextureClientRecycleAllocator(ImageBridgeChild::GetSingleton().get());
+        mTextureAllocator = new TextureClientRecycleAllocator(ImageBridgeChild::GetSingleton());
     }
     return mTextureAllocator;
 }
 
 #ifdef MOZ_CRASHREPORTER_INJECTOR
 
 // We only add the crash reporter to subprocess which have the filename
 // FlashPlayerPlugin*
--- a/gfx/ipc/GPUProcessManager.cpp
+++ b/gfx/ipc/GPUProcessManager.cpp
@@ -146,17 +146,17 @@ GPUProcessManager::EnsureGPUReady()
   if (mGPUChild) {
     mGPUChild->EnsureGPUReady();
   }
 }
 
 void
 GPUProcessManager::EnsureImageBridgeChild()
 {
-  if (ImageBridgeChild::GetSingleton()) {
+  if (ImageBridgeChild::IsCreated()) {
     return;
   }
 
   EnsureGPUReady();
 
   if (!mGPUChild) {
     ImageBridgeChild::InitSameProcess();
     return;
--- a/gfx/layers/ImageContainer.cpp
+++ b/gfx/layers/ImageContainer.cpp
@@ -145,19 +145,17 @@ ImageContainer::ImageContainer(uint64_t 
 {
   MOZ_ASSERT(mAsyncContainerID != sInvalidAsyncContainerId);
 }
 
 ImageContainer::~ImageContainer()
 {
   if (mIPDLChild) {
     mIPDLChild->ForgetImageContainer();
-    if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) {
-      imageBridge->ReleaseImageContainer(mIPDLChild);
-    }
+    ImageBridgeChild::DispatchReleaseImageContainer(mIPDLChild);
   }
 }
 
 RefPtr<PlanarYCbCrImage>
 ImageContainer::CreatePlanarYCbCrImage()
 {
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   if (mImageClient && mImageClient->AsImageClientSingle()) {
@@ -266,32 +264,28 @@ ImageContainer::ClearImagesFromImageBrid
 }
 
 void
 ImageContainer::SetCurrentImages(const nsTArray<NonOwningImage>& aImages)
 {
   MOZ_ASSERT(!aImages.IsEmpty());
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   if (mImageClient) {
-    if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) {
-      imageBridge->UpdateImageClient(mImageClient, this);
-    }
+    ImageBridgeChild::DispatchImageClientUpdate(mImageClient, this);
   }
   SetCurrentImageInternal(aImages);
 }
 
 void
 ImageContainer::ClearAllImages()
 {
   if (mImageClient) {
     // Let ImageClient release all TextureClients. This doesn't return
     // until ImageBridge has called ClearCurrentImageFromImageBridge.
-    if (RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton()) {
-      imageBridge->FlushAllImages(mImageClient, this);
-    }
+    ImageBridgeChild::FlushAllImages(mImageClient, this);
     return;
   }
 
   ReentrantMonitorAutoEnter mon(mReentrantMonitor);
   SetCurrentImageInternal(nsTArray<NonOwningImage>());
 }
 
 void
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_LAYERS_COMPOSITABLEFORWARDER
 #define MOZILLA_LAYERS_COMPOSITABLEFORWARDER
 
 #include <stdint.h>                     // for int32_t, uint64_t
 #include "gfxTypes.h"
 #include "mozilla/Attributes.h"         // for override
-#include "mozilla/UniquePtr.h"
 #include "mozilla/layers/CompositableClient.h"  // for CompositableClient
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "mozilla/layers/TextureClient.h"  // for TextureClient
 #include "mozilla/layers/TextureForwarder.h"  // for TextureForwarder
 #include "nsRegion.h"                   // for nsIntRegion
 #include "mozilla/gfx/Rect.h"
@@ -75,20 +74,19 @@ public:
  * additionally forward modifications of the Layer tree).
  * ImageBridgeChild is another CompositableForwarder.
  */
 class CompositableForwarder : public TextureForwarder
 {
 public:
 
   CompositableForwarder()
-    : mSerial(++sSerialCounter)
-  {
-    mActiveResourceTracker = MakeUnique<ActiveResourceTracker>(1000, "CompositableForwarder");
-  }
+    : mActiveResourceTracker(1000, "CompositableForwarder")
+    , mSerial(++sSerialCounter)
+  {}
 
   /**
    * Setup the IPDL actor for aCompositable to be part of layers
    * transactions.
    */
   virtual void Connect(CompositableClient* aCompositable,
                        ImageContainer* aImageContainer = nullptr) = 0;
 
@@ -204,26 +202,26 @@ public:
     return mTextureFactoryIdentifier.mSupportsPartialUploads;
   }
 
   const TextureFactoryIdentifier& GetTextureFactoryIdentifier() const
   {
     return mTextureFactoryIdentifier;
   }
 
-  ActiveResourceTracker& GetActiveResourceTracker() { return *mActiveResourceTracker.get(); }
+  ActiveResourceTracker& GetActiveResourceTracker() { return mActiveResourceTracker; }
 
 protected:
   TextureFactoryIdentifier mTextureFactoryIdentifier;
 
   nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
   nsTArray<RefPtr<CompositableClient>> mCompositableClientsToRemove;
   RefPtr<SyncObject> mSyncObject;
 
-  UniquePtr<ActiveResourceTracker> mActiveResourceTracker;
+  ActiveResourceTracker mActiveResourceTracker;
 
   const int32_t mSerial;
   static mozilla::Atomic<int32_t> sSerialCounter;
 };
 
 } // namespace layers
 } // namespace mozilla
 
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -28,24 +28,21 @@
 #include "mozilla/layers/CompositorThread.h"
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/ImageClient.h"  // for ImageClient
 #include "mozilla/layers/ImageContainerChild.h"
 #include "mozilla/layers/LayersMessages.h"  // for CompositableOperation
 #include "mozilla/layers/PCompositableChild.h"  // for PCompositableChild
 #include "mozilla/layers/TextureClient.h"  // for TextureClient
 #include "mozilla/mozalloc.h"           // for operator new, etc
-#include "mtransport/runnable_utils.h"
-#include "nsContentUtils.h"
 #include "nsISupportsImpl.h"            // for ImageContainer::AddRef, etc
 #include "nsTArray.h"                   // for AutoTArray, nsTArray, etc
 #include "nsTArrayForwardDeclare.h"     // for AutoTArray
 #include "nsThreadUtils.h"              // for NS_IsMainThread
 #include "nsXULAppAPI.h"                // for XRE_GetIOMessageLoop
-#include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"          // for StaticRefPtr
 #include "mozilla/layers/TextureClient.h"
 
 namespace mozilla {
 namespace ipc {
 class Shmem;
 } // namespace ipc
 
@@ -164,16 +161,19 @@ struct CompositableTransaction
 };
 
 struct AutoEndTransaction {
   explicit AutoEndTransaction(CompositableTransaction* aTxn) : mTxn(aTxn) {}
   ~AutoEndTransaction() { mTxn->End(); }
   CompositableTransaction* mTxn;
 };
 
+/* static */
+Atomic<bool> ImageBridgeChild::sIsShutDown(false);
+
 void
 ImageBridgeChild::UseTextures(CompositableClient* aCompositable,
                               const nsTArray<TimedTextureClient>& aTextures)
 {
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aCompositable->IsConnected());
 
@@ -386,17 +386,16 @@ ImageBridgeChild::CancelWaitForRecycle(u
   RefPtr<TextureClient> client = mTexturesWaitingRecycled.Get(aTextureId);
   if (!client) {
     return;
   }
   mTexturesWaitingRecycled.Remove(aTextureId);
 }
 
 // Singleton
-static StaticMutex sImageBridgeSingletonLock;
 static StaticRefPtr<ImageBridgeChild> sImageBridgeChildSingleton;
 static Thread *sImageBridgeChildThread = nullptr;
 
 void
 ImageBridgeChild::FallbackDestroyActors() {
   if (mTxn && !mTxn->mDestroyedActors.IsEmpty()) {
     mTxn->FallbackDestroyActors();
   }
@@ -446,138 +445,127 @@ public:
   }
 
 private:
   SynchronousTask* mTask;
   ReentrantMonitorAutoEnter mAutoEnter;
 };
 
 // dispatched function
-void
-ImageBridgeChild::ShutdownStep1(SynchronousTask* aTask)
+static void ImageBridgeShutdownStep1(SynchronousTask* aTask)
 {
   AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(InImageBridgeChildThread(),
              "Should be in ImageBridgeChild thread.");
 
   MediaSystemResourceManager::Shutdown();
 
-  // Force all managed protocols to shut themselves down cleanly
-  InfallibleTArray<PCompositableChild*> compositables;
-  ManagedPCompositableChild(compositables);
-  for (int i = compositables.Length() - 1; i >= 0; --i) {
-    auto compositable = CompositableClient::FromIPDLActor(compositables[i]);
-    if (compositable) {
-      compositable->Destroy();
+  if (sImageBridgeChildSingleton) {
+    // Force all managed protocols to shut themselves down cleanly
+    InfallibleTArray<PCompositableChild*> compositables;
+    sImageBridgeChildSingleton->ManagedPCompositableChild(compositables);
+    for (int i = compositables.Length() - 1; i >= 0; --i) {
+      auto compositable = CompositableClient::FromIPDLActor(compositables[i]);
+      if (compositable) {
+        compositable->Destroy();
+      }
     }
+    InfallibleTArray<PTextureChild*> textures;
+    sImageBridgeChildSingleton->ManagedPTextureChild(textures);
+    for (int i = textures.Length() - 1; i >= 0; --i) {
+      RefPtr<TextureClient> client = TextureClient::AsTextureClient(textures[i]);
+      if (client) {
+        client->Destroy();
+      }
+    }
+    sImageBridgeChildSingleton->FallbackDestroyActors();
+
+    sImageBridgeChildSingleton->SendWillClose();
+    sImageBridgeChildSingleton->MarkShutDown();
+    // From now on, no message can be sent through the image bridge from the
+    // client side except the final Stop message.
   }
-  InfallibleTArray<PTextureChild*> textures;
-  ManagedPTextureChild(textures);
-  for (int i = textures.Length() - 1; i >= 0; --i) {
-    RefPtr<TextureClient> client = TextureClient::AsTextureClient(textures[i]);
-    if (client) {
-      client->Destroy();
-    }
-  }
-  FallbackDestroyActors();
-
-  SendWillClose();
-  MarkShutDown();
-
-  // From now on, no message can be sent through the image bridge from the
-  // client side except the final Stop message.
 }
 
 // dispatched function
-void
-ImageBridgeChild::ShutdownStep2(SynchronousTask* aTask)
+static void
+ImageBridgeShutdownStep2(SynchronousTask* aTask)
 {
   AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(InImageBridgeChildThread(),
              "Should be in ImageBridgeChild thread.");
 
-  if (mCanSend) {
-    Close();
-  }
-}
-
-void
-ImageBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
-{
-  mCanSend = false;
+  sImageBridgeChildSingleton->Close();
 }
 
-void
-ImageBridgeChild::DeallocPImageBridgeChild()
-{
-  this->Release();
-}
-
-void
-ImageBridgeChild::CreateImageClientSync(SynchronousTask* aTask,
-                                        RefPtr<ImageClient>* result,
-                                        CompositableType aType,
-                                        ImageContainer* aImageContainer,
-                                        ImageContainerChild* aContainerChild)
+/* static */ void
+CreateImageClientSync(SynchronousTask* aTask,
+                      RefPtr<ImageBridgeChild> aChild,
+                      RefPtr<ImageClient>* result,
+                      CompositableType aType,
+                      ImageContainer* aImageContainer,
+                      ImageContainerChild* aContainerChild)
 {
   AutoCompleteTask complete(aTask);
-  *result = CreateImageClientNow(aType, aImageContainer, aContainerChild);
+  *result = aChild->CreateImageClientNow(aType, aImageContainer, aContainerChild);
 }
 
 // dispatched function
-void
-ImageBridgeChild::CreateCanvasClientSync(SynchronousTask* aTask,
-                                         CanvasClient::CanvasClientType aType,
-                                         TextureFlags aFlags,
-                                         RefPtr<CanvasClient>* const outResult)
+static void CreateCanvasClientSync(SynchronousTask* aTask,
+                                   CanvasClient::CanvasClientType aType,
+                                   TextureFlags aFlags,
+                                   RefPtr<CanvasClient>* const outResult)
 {
   AutoCompleteTask complete(aTask);
-  *outResult = CreateCanvasClientNow(aType, aFlags);
+  *outResult = sImageBridgeChildSingleton->CreateCanvasClientNow(aType, aFlags);
+}
+
+static void ConnectImageBridge(ImageBridgeChild * child, ImageBridgeParent * parent)
+{
+  MessageLoop *parentMsgLoop = parent->GetMessageLoop();
+  ipc::MessageChannel *parentChannel = parent->GetIPCChannel();
+  child->Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
 }
 
 ImageBridgeChild::ImageBridgeChild()
-  : mCanSend(false)
+  : mShuttingDown(false)
   , mFwdTransactionId(0)
 #ifdef MOZ_WIDGET_GONK
   , mWaitingFenceHandleMutex("ImageBridgeChild::mWaitingFenceHandleMutex")
 #endif
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   mTxn = new CompositableTransaction();
-  mShutdownObserver = new ShutdownObserver(this);
 }
 
 ImageBridgeChild::~ImageBridgeChild()
 {
-  // We should have already removed this in WillShutdown, since it must be
-  // removed on the main thread.
-  MOZ_ASSERT(!mShutdownObserver);
-
   delete mTxn;
 }
 
 void
 ImageBridgeChild::MarkShutDown()
 {
+  MOZ_ASSERT(!mShuttingDown);
   mTexturesWaitingRecycled.Clear();
   mTrackersHolder.DestroyAsyncTransactionTrackersHolder();
 
-  mCanSend = false;
+  mShuttingDown = true;
 }
 
 void
 ImageBridgeChild::Connect(CompositableClient* aCompositable,
                           ImageContainer* aImageContainer)
 {
   MOZ_ASSERT(aCompositable);
+  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(InImageBridgeChildThread());
-  MOZ_ASSERT(CanSend());
 
   uint64_t id = 0;
 
   PImageContainerChild* imageContainerChild = nullptr;
   if (aImageContainer)
     imageContainerChild = aImageContainer->GetPImageContainerChild();
 
   PCompositableChild* child =
@@ -586,255 +574,265 @@ ImageBridgeChild::Connect(CompositableCl
   MOZ_ASSERT(child);
   aCompositable->InitIPDLActor(child, id);
 }
 
 PCompositableChild*
 ImageBridgeChild::AllocPCompositableChild(const TextureInfo& aInfo,
                                           PImageContainerChild* aChild, uint64_t* aID)
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   return AsyncCompositableChild::CreateActor();
 }
 
 bool
 ImageBridgeChild::DeallocPCompositableChild(PCompositableChild* aActor)
 {
   AsyncCompositableChild::DestroyActor(aActor);
   return true;
 }
 
 
 Thread* ImageBridgeChild::GetThread() const
 {
   return sImageBridgeChildThread;
 }
 
-/* static */ RefPtr<ImageBridgeChild>
-ImageBridgeChild::GetSingleton()
+ImageBridgeChild* ImageBridgeChild::GetSingleton()
 {
-  StaticMutexAutoLock lock(sImageBridgeSingletonLock);
   return sImageBridgeChildSingleton;
 }
 
-void
-ImageBridgeChild::ReleaseImageContainer(RefPtr<ImageContainerChild> aChild)
+bool ImageBridgeChild::IsCreated()
+{
+  return GetSingleton() != nullptr;
+}
+
+static void
+ReleaseImageContainerNow(RefPtr<ImageBridgeChild> aBridge, RefPtr<ImageContainerChild> aChild)
+{
+  MOZ_ASSERT(InImageBridgeChildThread());
+
+  aChild->SendAsyncDelete();
+}
+
+// static
+void ImageBridgeChild::DispatchReleaseImageContainer(ImageContainerChild* aChild)
 {
   if (!aChild) {
     return;
   }
 
-  if (!InImageBridgeChildThread()) {
-    RefPtr<Runnable> runnable = WrapRunnable(
-      RefPtr<ImageBridgeChild>(this),
-      &ImageBridgeChild::ReleaseImageContainer,
-      aChild);
-    GetMessageLoop()->PostTask(runnable.forget());
+  RefPtr<ImageBridgeChild> bridge = GetSingleton();
+  if (!bridge) {
     return;
   }
 
-  aChild->SendAsyncDelete();
+  RefPtr<ImageContainerChild> child(aChild);
+  bridge->GetMessageLoop()->PostTask(
+    NewRunnableFunction(&ReleaseImageContainerNow, bridge, child));
 }
 
-void
-ImageBridgeChild::ReleaseTextureClientNow(TextureClient* aClient)
+static void ReleaseTextureClientNow(TextureClient* aClient)
 {
   MOZ_ASSERT(InImageBridgeChildThread());
   RELEASE_MANUALLY(aClient);
 }
 
-/* static */ void
-ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
+// static
+void ImageBridgeChild::DispatchReleaseTextureClient(TextureClient* aClient)
 {
   if (!aClient) {
     return;
   }
 
-  RefPtr<ImageBridgeChild> imageBridge = ImageBridgeChild::GetSingleton();
-  if (!imageBridge) {
+  if (!IsCreated()) {
     // TextureClient::Release should normally happen in the ImageBridgeChild
     // thread because it usually generate some IPDL messages.
     // However, if we take this branch it means that the ImageBridgeChild
     // has already shut down, along with the TextureChild, which means no
     // message will be sent and it is safe to run this code from any thread.
     MOZ_ASSERT(aClient->GetIPDLActor() == nullptr);
     RELEASE_MANUALLY(aClient);
     return;
   }
 
-  RefPtr<Runnable> runnable = WrapRunnable(
-    imageBridge,
-    &ImageBridgeChild::ReleaseTextureClientNow,
-    aClient);
-  imageBridge->GetMessageLoop()->PostTask(runnable.forget());
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    NewRunnableFunction(&ReleaseTextureClientNow, aClient));
 }
 
-void
-ImageBridgeChild::UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageContainer> aContainer)
+static void
+UpdateImageClientNow(RefPtr<ImageClient> aClient, RefPtr<ImageContainer>&& aContainer)
 {
-  if (!aClient || !aContainer) {
+  if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
+    NS_WARNING("Something is holding on to graphics resources after the shutdown"
+               "of the graphics subsystem!");
     return;
   }
-
-  if (!InImageBridgeChildThread()) {
-    RefPtr<Runnable> runnable = WrapRunnable(
-      RefPtr<ImageBridgeChild>(this),
-      &ImageBridgeChild::UpdateImageClient,
-      aClient,
-      aContainer);
-    GetMessageLoop()->PostTask(runnable.forget());
-    return;
-  }
-
-  if (!CanSend()) {
-    return;
-  }
+  MOZ_ASSERT(aClient);
+  MOZ_ASSERT(aContainer);
 
   // If the client has become disconnected before this event was dispatched,
   // early return now.
   if (!aClient->IsConnected()) {
     return;
   }
 
-  BeginTransaction();
+  sImageBridgeChildSingleton->BeginTransaction();
   aClient->UpdateImage(aContainer, Layer::CONTENT_OPAQUE);
-  EndTransaction();
+  sImageBridgeChildSingleton->EndTransaction();
 }
 
-void
-ImageBridgeChild::UpdateAsyncCanvasRendererSync(SynchronousTask* aTask, AsyncCanvasRenderer* aWrapper)
+// static
+void ImageBridgeChild::DispatchImageClientUpdate(ImageClient* aClient,
+                                                 ImageContainer* aContainer)
+{
+  if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
+    NS_WARNING("Something is holding on to graphics resources after the shutdown"
+               "of the graphics subsystem!");
+    return;
+  }
+  if (!aClient || !aContainer || !IsCreated()) {
+    return;
+  }
+
+  if (InImageBridgeChildThread()) {
+    UpdateImageClientNow(aClient, aContainer);
+    return;
+  }
+
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    NewRunnableFunction(&UpdateImageClientNow,
+      RefPtr<ImageClient>(aClient), RefPtr<ImageContainer>(aContainer)));
+}
+
+static void
+UpdateAsyncCanvasRendererSync(SynchronousTask* aTask, AsyncCanvasRenderer* aWrapper)
 {
   AutoCompleteTask complete(aTask);
 
-  UpdateAsyncCanvasRendererNow(aWrapper);
+  ImageBridgeChild::UpdateAsyncCanvasRendererNow(aWrapper);
 }
 
-void
-ImageBridgeChild::UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aWrapper)
+// static
+void ImageBridgeChild::UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aWrapper)
 {
   aWrapper->GetCanvasClient()->UpdateAsync(aWrapper);
 
   if (InImageBridgeChildThread()) {
     UpdateAsyncCanvasRendererNow(aWrapper);
     return;
   }
 
   SynchronousTask task("UpdateAsyncCanvasRenderer Lock");
 
-  RefPtr<Runnable> runnable = WrapRunnable(
-    RefPtr<ImageBridgeChild>(this),
-    &ImageBridgeChild::UpdateAsyncCanvasRendererSync,
-    &task,
-    aWrapper);
-  GetMessageLoop()->PostTask(runnable.forget());
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    NewRunnableFunction(&UpdateAsyncCanvasRendererSync, &task, aWrapper));
 
   task.Wait();
 }
 
-void
-ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
+// static
+void ImageBridgeChild::UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aWrapper)
 {
   MOZ_ASSERT(aWrapper);
-
-  if (!CanSend()) {
-    return;
-  }
-
-  BeginTransaction();
+  sImageBridgeChildSingleton->BeginTransaction();
   aWrapper->GetCanvasClient()->Updated();
-  EndTransaction();
+  sImageBridgeChildSingleton->EndTransaction();
 }
 
-void
-ImageBridgeChild::FlushAllImagesSync(SynchronousTask* aTask,
-                                     ImageClient* aClient,
-                                     ImageContainer* aContainer,
-                                     RefPtr<AsyncTransactionWaiter> aWaiter)
+static void
+FlushAllImagesSync(SynchronousTask* aTask,
+                   ImageClient* aClient,
+                   ImageContainer* aContainer,
+                   RefPtr<AsyncTransactionWaiter>&& aWaiter)
 {
 #ifdef MOZ_WIDGET_GONK
   MOZ_ASSERT(aWaiter);
 #else
   MOZ_ASSERT(!aWaiter);
 #endif
 
   AutoCompleteTask complete(aTask);
 
-  if (!CanSend()) {
+  if (!ImageBridgeChild::IsCreated() || ImageBridgeChild::IsShutDown()) {
+    // How sad. If we get into this branch it means that the ImageBridge
+    // got destroyed between the time we ImageBridgeChild::FlushAllImage
+    // was called on some thread, and the time this function was proxied
+    // to the ImageBridge thread. ImageBridge gets destroyed way to late
+    // in the shutdown of gecko for this to be happening for a good reason.
+    NS_WARNING("Something is holding on to graphics resources after the shutdown"
+               "of the graphics subsystem!");
 #ifdef MOZ_WIDGET_GONK
     aWaiter->DecrementWaitCount();
 #endif
     return;
   }
-
   MOZ_ASSERT(aClient);
-  BeginTransaction();
+  sImageBridgeChildSingleton->BeginTransaction();
   if (aContainer) {
     aContainer->ClearImagesFromImageBridge();
   }
   aClient->FlushAllImages(aWaiter);
-  EndTransaction();
+  sImageBridgeChildSingleton->EndTransaction();
   // This decrement is balanced by the increment in FlushAllImages.
   // If any AsyncTransactionTrackers were created by FlushAllImages and attached
   // to aWaiter, aWaiter will not complete until those trackers all complete.
   // Otherwise, aWaiter will be ready to complete now.
 #ifdef MOZ_WIDGET_GONK
   aWaiter->DecrementWaitCount();
 #endif
 }
 
-void
-ImageBridgeChild::FlushAllImages(ImageClient* aClient, ImageContainer* aContainer)
+// static
+void ImageBridgeChild::FlushAllImages(ImageClient* aClient,
+                                      ImageContainer* aContainer)
 {
+  if (!IsCreated() || IsShutDown()) {
+    return;
+  }
   MOZ_ASSERT(aClient);
+  MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
   MOZ_ASSERT(!InImageBridgeChildThread());
-
   if (InImageBridgeChildThread()) {
     NS_ERROR("ImageBridgeChild::FlushAllImages() is called on ImageBridge thread.");
     return;
   }
 
   SynchronousTask task("FlushAllImages Lock");
 
   RefPtr<AsyncTransactionWaiter> waiter;
 #ifdef MOZ_WIDGET_GONK
   waiter = new AsyncTransactionWaiter();
   // This increment is balanced by the decrement in FlushAllImagesSync
   waiter->IncrementWaitCount();
 #endif
-
-  // RefPtrs on arguments are not needed since this dispatches synchronously.
-  RefPtr<Runnable> runnable = WrapRunnable(
-    RefPtr<ImageBridgeChild>(this),
-    &ImageBridgeChild::FlushAllImagesSync,
-    &task,
-    aClient,
-    aContainer,
-    waiter);
-  GetMessageLoop()->PostTask(runnable.forget());
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    NewRunnableFunction(&FlushAllImagesSync, &task, aClient, aContainer, waiter));
 
   task.Wait();
 
 #ifdef MOZ_WIDGET_GONK
   waiter->WaitComplete();
 #endif
 }
 
 void
 ImageBridgeChild::BeginTransaction()
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
   UpdateFwdTransactionId();
   mTxn->Begin();
 }
 
 void
 ImageBridgeChild::EndTransaction()
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
 
   AutoEndTransaction _(mTxn);
 
   if (mTxn->IsEmpty()) {
     return;
   }
 
@@ -869,231 +867,183 @@ ImageBridgeChild::EndTransaction()
     NS_RUNTIMEABORT("not reached");
   }
 }
 
 void
 ImageBridgeChild::SendImageBridgeThreadId()
 {
 #ifdef MOZ_WIDGET_GONK
-  PImageBridgeChild::SendImageBridgeThreadId(gettid());
+  SendImageBridgeThreadId(gettid());
 #endif
 }
 
+static void CallSendImageBridgeThreadId(ImageBridgeChild* aImageBridgeChild)
+{
+  MOZ_ASSERT(InImageBridgeChildThread());
+  aImageBridgeChild->SendImageBridgeThreadId();
+}
+
 bool
 ImageBridgeChild::InitForContent(Endpoint<PImageBridgeChild>&& aEndpoint)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   gfxPlatform::GetPlatform();
 
   sImageBridgeChildThread = new ImageBridgeThread();
   if (!sImageBridgeChildThread->Start()) {
     return false;
   }
 
-  RefPtr<ImageBridgeChild> child = new ImageBridgeChild();
+  sImageBridgeChildSingleton = new ImageBridgeChild();
 
-  RefPtr<Runnable> runnable = NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
-    child,
-    &ImageBridgeChild::Bind,
-    Move(aEndpoint));
-  child->GetMessageLoop()->PostTask(runnable.forget());
+  MessageLoop* loop = sImageBridgeChildSingleton->GetMessageLoop();
 
-  // Assign this after so other threads can't post messages before we connect to IPDL.
-  {
-    StaticMutexAutoLock lock(sImageBridgeSingletonLock);
-    sImageBridgeChildSingleton = child;
-  }
+  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
+    sImageBridgeChildSingleton, &ImageBridgeChild::Bind, Move(aEndpoint)));
+  loop->PostTask(NewRunnableFunction(
+    CallSendImageBridgeThreadId, sImageBridgeChildSingleton.get()));
 
-  return true;
+  return sImageBridgeChildSingleton;
 }
 
 void
 ImageBridgeChild::Bind(Endpoint<PImageBridgeChild>&& aEndpoint)
 {
-  if (!aEndpoint.Bind(this)) {
-    return;
-  }
-
-  // This reference is dropped in DeallocPImageBridgeChild.
-  this->AddRef();
-
-  mCanSend = true;
-  SendImageBridgeThreadId();
-}
-
-void
-ImageBridgeChild::BindSameProcess(RefPtr<ImageBridgeParent> aParent)
-{
-  MessageLoop *parentMsgLoop = aParent->GetMessageLoop();
-  ipc::MessageChannel *parentChannel = aParent->GetIPCChannel();
-  Open(parentChannel, parentMsgLoop, mozilla::ipc::ChildSide);
-
-  // This reference is dropped in DeallocPImageBridgeChild.
-  this->AddRef();
-
-  mCanSend = true;
-  SendImageBridgeThreadId();
+  aEndpoint.Bind(this);
 }
 
 void ImageBridgeChild::ShutDown()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (RefPtr<ImageBridgeChild> child = GetSingleton()) {
-    child->WillShutdown();
+  sIsShutDown = true;
 
-    StaticMutexAutoLock lock(sImageBridgeSingletonLock);
-    sImageBridgeChildSingleton = nullptr;
-  }
+  if (ImageBridgeChild::IsCreated()) {
+    MOZ_ASSERT(!sImageBridgeChildSingleton->mShuttingDown);
 
-  delete sImageBridgeChildThread;
-  sImageBridgeChildThread = nullptr;
-}
+    {
+      SynchronousTask task("ImageBridge ShutdownStep1 lock");
 
-void
-ImageBridgeChild::WillShutdown()
-{
-  {
-    SynchronousTask task("ImageBridge ShutdownStep1 lock");
+      sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+                      NewRunnableFunction(&ImageBridgeShutdownStep1, &task));
+
+      task.Wait();
+    }
 
-    RefPtr<Runnable> runnable = WrapRunnable(
-      RefPtr<ImageBridgeChild>(this),
-      &ImageBridgeChild::ShutdownStep1,
-      &task);
-    GetMessageLoop()->PostTask(runnable.forget());
+    {
+      SynchronousTask task("ImageBridge ShutdownStep2 lock");
 
-    task.Wait();
-  }
-
-  {
-    SynchronousTask task("ImageBridge ShutdownStep2 lock");
+      sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+                      NewRunnableFunction(&ImageBridgeShutdownStep2, &task));
 
-    RefPtr<Runnable> runnable = WrapRunnable(
-      RefPtr<ImageBridgeChild>(this),
-      &ImageBridgeChild::ShutdownStep2,
-      &task);
-    GetMessageLoop()->PostTask(runnable.forget());
+      task.Wait();
+    }
 
-    task.Wait();
-  }
+    sImageBridgeChildSingleton = nullptr;
 
-  if (mShutdownObserver) {
-    mShutdownObserver->Unregister();
-    mShutdownObserver = nullptr;
+    delete sImageBridgeChildThread;
+    sImageBridgeChildThread = nullptr;
   }
 }
 
 void
 ImageBridgeChild::InitSameProcess()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on the main Thread!");
 
   MOZ_ASSERT(!sImageBridgeChildSingleton);
   MOZ_ASSERT(!sImageBridgeChildThread);
 
   sImageBridgeChildThread = new ImageBridgeThread();
   if (!sImageBridgeChildThread->IsRunning()) {
     sImageBridgeChildThread->Start();
   }
 
-  RefPtr<ImageBridgeChild> child = new ImageBridgeChild();
+  sImageBridgeChildSingleton = new ImageBridgeChild();
   RefPtr<ImageBridgeParent> parent = ImageBridgeParent::CreateSameProcess();
 
-  RefPtr<Runnable> runnable = WrapRunnable(
-    child,
-    &ImageBridgeChild::BindSameProcess,
-    parent);
-  child->GetMessageLoop()->PostTask(runnable.forget());
-
-  // Assign this after so other threads can't post messages before we connect to IPDL.
-  {
-    StaticMutexAutoLock lock(sImageBridgeSingletonLock);
-    sImageBridgeChildSingleton = child;
-  }
+  sImageBridgeChildSingleton->ConnectAsync(parent);
+  sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
+    NewRunnableFunction(CallSendImageBridgeThreadId,
+                        sImageBridgeChildSingleton.get()));
 }
 
 /* static */ void
 ImageBridgeChild::InitWithGPUProcess(Endpoint<PImageBridgeChild>&& aEndpoint)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(!sImageBridgeChildSingleton);
   MOZ_ASSERT(!sImageBridgeChildThread);
 
   sImageBridgeChildThread = new ImageBridgeThread();
   if (!sImageBridgeChildThread->IsRunning()) {
     sImageBridgeChildThread->Start();
   }
 
-  RefPtr<ImageBridgeChild> child = new ImageBridgeChild();
-
-  MessageLoop* loop = child->GetMessageLoop();
-  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
-    child, &ImageBridgeChild::Bind, Move(aEndpoint)));
+  sImageBridgeChildSingleton = new ImageBridgeChild();
 
-  // Assign this after so other threads can't post messages before we connect to IPDL.
-  {
-    StaticMutexAutoLock lock(sImageBridgeSingletonLock);
-    sImageBridgeChildSingleton = child;
-  }
+  MessageLoop* loop = sImageBridgeChildSingleton->GetMessageLoop();
+  loop->PostTask(NewRunnableMethod<Endpoint<PImageBridgeChild>&&>(
+    sImageBridgeChildSingleton, &ImageBridgeChild::Bind, Move(aEndpoint)));
 }
 
 bool InImageBridgeChildThread()
 {
-  return sImageBridgeChildThread &&
+  return ImageBridgeChild::IsCreated() &&
     sImageBridgeChildThread->thread_id() == PlatformThread::CurrentId();
 }
 
 MessageLoop * ImageBridgeChild::GetMessageLoop() const
 {
   return sImageBridgeChildThread ? sImageBridgeChildThread->message_loop() : nullptr;
 }
 
-/* static */ void
+void ImageBridgeChild::ConnectAsync(ImageBridgeParent* aParent)
+{
+  GetMessageLoop()->PostTask(NewRunnableFunction(&ConnectImageBridge,
+                                                 this, aParent));
+}
+
+void
 ImageBridgeChild::IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier)
 {
-  if (RefPtr<ImageBridgeChild> child = GetSingleton()) {
-    child->IdentifyTextureHost(aIdentifier);
+  if (sImageBridgeChildSingleton) {
+    sImageBridgeChildSingleton->IdentifyTextureHost(aIdentifier);
   }
 }
 
 RefPtr<ImageClient>
 ImageBridgeChild::CreateImageClient(CompositableType aType,
                                     ImageContainer* aImageContainer,
                                     ImageContainerChild* aContainerChild)
 {
   if (InImageBridgeChildThread()) {
     return CreateImageClientNow(aType, aImageContainer, aContainerChild);
   }
 
   SynchronousTask task("CreateImageClient Lock");
 
   RefPtr<ImageClient> result = nullptr;
-
-  RefPtr<Runnable> runnable = WrapRunnable(
-    RefPtr<ImageBridgeChild>(this),
-    &ImageBridgeChild::CreateImageClientSync,
-    &task,
-    &result,
-    aType,
-    aImageContainer,
-    aContainerChild);
-  GetMessageLoop()->PostTask(runnable.forget());
+  GetMessageLoop()->PostTask(
+      NewRunnableFunction(&CreateImageClientSync, &task, this, &result, aType,
+                          aImageContainer, aContainerChild));
 
   task.Wait();
 
   return result;
 }
 
 RefPtr<ImageClient>
 ImageBridgeChild::CreateImageClientNow(CompositableType aType,
                                        ImageContainer* aImageContainer,
                                        ImageContainerChild* aContainerChild)
 {
+  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(InImageBridgeChildThread());
 
   if (aImageContainer) {
     SendPImageContainerConstructor(aContainerChild);
     aContainerChild->RegisterWithIPDL();
   }
 
   RefPtr<ImageClient> client = ImageClient::CreateImageClient(aType, this, TextureFlags::NO_FLAGS);
@@ -1109,26 +1059,19 @@ ImageBridgeChild::CreateCanvasClient(Can
                                      TextureFlags aFlag)
 {
   if (InImageBridgeChildThread()) {
     return CreateCanvasClientNow(aType, aFlag);
   }
 
   SynchronousTask task("CreateCanvasClient Lock");
 
-  // RefPtrs on arguments are not needed since this dispatches synchronously.
   RefPtr<CanvasClient> result = nullptr;
-  RefPtr<Runnable> runnable = WrapRunnable(
-    RefPtr<ImageBridgeChild>(this),
-    &ImageBridgeChild::CreateCanvasClientSync,
-    &task,
-    aType,
-    aFlag,
-    &result);
-  GetMessageLoop()->PostTask(runnable.forget());
+  GetMessageLoop()->PostTask(NewRunnableFunction(&CreateCanvasClientSync,
+                                 &task, aType, aFlag, &result));
 
   task.Wait();
 
   return result.forget();
 }
 
 already_AddRefed<CanvasClient>
 ImageBridgeChild::CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
@@ -1143,50 +1086,51 @@ ImageBridgeChild::CreateCanvasClientNow(
   return client.forget();
 }
 
 bool
 ImageBridgeChild::AllocUnsafeShmem(size_t aSize,
                                    ipc::SharedMemory::SharedMemoryType aType,
                                    ipc::Shmem* aShmem)
 {
-  if (!InImageBridgeChildThread()) {
+  MOZ_ASSERT(!mShuttingDown);
+  if (InImageBridgeChildThread()) {
+    return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
+  } else {
     return DispatchAllocShmemInternal(aSize, aType, aShmem, true); // true: unsafe
   }
-
-  MOZ_ASSERT(CanSend());
-  return PImageBridgeChild::AllocUnsafeShmem(aSize, aType, aShmem);
 }
 
 bool
 ImageBridgeChild::AllocShmem(size_t aSize,
                              ipc::SharedMemory::SharedMemoryType aType,
                              ipc::Shmem* aShmem)
 {
-  if (!InImageBridgeChildThread()) {
+  MOZ_ASSERT(!mShuttingDown);
+  if (InImageBridgeChildThread()) {
+    return PImageBridgeChild::AllocShmem(aSize, aType,
+                                         aShmem);
+  } else {
     return DispatchAllocShmemInternal(aSize, aType, aShmem, false); // false: unsafe
   }
-
-  MOZ_ASSERT(CanSend());
-  return PImageBridgeChild::AllocShmem(aSize, aType, aShmem);
 }
 
 // NewRunnableFunction accepts a limited number of parameters so we need a
 // struct here
 struct AllocShmemParams {
   RefPtr<ISurfaceAllocator> mAllocator;
   size_t mSize;
   ipc::SharedMemory::SharedMemoryType mType;
   ipc::Shmem* mShmem;
   bool mUnsafe;
   bool mSuccess;
 };
 
-void
-ImageBridgeChild::ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams)
+static void
+ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams)
 {
   AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(aParams);
 
   auto shmAllocator = aParams->mAllocator->AsShmemAllocator();
   if (aParams->mUnsafe) {
     aParams->mSuccess = shmAllocator->AllocUnsafeShmem(aParams->mSize,
@@ -1206,81 +1150,72 @@ ImageBridgeChild::DispatchAllocShmemInte
                                              bool aUnsafe)
 {
   SynchronousTask task("AllocatorProxy alloc");
 
   AllocShmemParams params = {
     this, aSize, aType, aShmem, aUnsafe, true
   };
 
-  RefPtr<Runnable> runnable = WrapRunnable(
-    RefPtr<ImageBridgeChild>(this),
-    &ImageBridgeChild::ProxyAllocShmemNow,
-    &task,
-    &params);
-  GetMessageLoop()->PostTask(runnable.forget());
+  GetMessageLoop()->PostTask(NewRunnableFunction(&ProxyAllocShmemNow,
+                                                 &task, &params));
 
   task.Wait();
 
   return params.mSuccess;
 }
 
-void
-ImageBridgeChild::ProxyDeallocShmemNow(SynchronousTask* aTask,
-                                       ISurfaceAllocator* aAllocator,
-                                       ipc::Shmem* aShmem)
+static void ProxyDeallocShmemNow(SynchronousTask* aTask,
+                                 ISurfaceAllocator* aAllocator,
+                                 ipc::Shmem* aShmem)
 {
   AutoCompleteTask complete(aTask);
 
   MOZ_ASSERT(aShmem);
 
   aAllocator->AsShmemAllocator()->DeallocShmem(*aShmem);
 }
 
 void
 ImageBridgeChild::DeallocShmem(ipc::Shmem& aShmem)
 {
   if (InImageBridgeChildThread()) {
     PImageBridgeChild::DeallocShmem(aShmem);
-    return;
-  }
-
-  SynchronousTask task("AllocatorProxy Dealloc");
+  } else {
+    SynchronousTask task("AllocatorProxy Dealloc");
 
-  RefPtr<Runnable> runnable = WrapRunnable(
-    RefPtr<ImageBridgeChild>(this),
-    &ImageBridgeChild::ProxyDeallocShmemNow,
-    &task,
-    this,
-    &aShmem);
-  GetMessageLoop()->PostTask(runnable.forget());
+    GetMessageLoop()->PostTask(NewRunnableFunction(&ProxyDeallocShmemNow,
+                                                   &task,
+                                                   this,
+                                                   &aShmem));
 
-  task.Wait();
+    task.Wait();
+  }
 }
 
 PTextureChild*
 ImageBridgeChild::AllocPTextureChild(const SurfaceDescriptor&,
                                      const LayersBackend&,
                                      const TextureFlags&,
                                      const uint64_t& aSerial)
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   return TextureClient::CreateIPDLActor();
 }
 
 bool
 ImageBridgeChild::DeallocPTextureChild(PTextureChild* actor)
 {
   return TextureClient::DestroyIPDLActor(actor);
 }
 
 PMediaSystemResourceManagerChild*
 ImageBridgeChild::AllocPMediaSystemResourceManagerChild()
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   return new mozilla::media::MediaSystemResourceManagerChild();
 }
 
 bool
 ImageBridgeChild::DeallocPMediaSystemResourceManagerChild(PMediaSystemResourceManagerChild* aActor)
 {
   MOZ_ASSERT(aActor);
   delete static_cast<mozilla::media::MediaSystemResourceManagerChild*>(aActor);
@@ -1370,17 +1305,17 @@ ImageBridgeChild::RecvDidComposite(Infal
 }
 
 PTextureChild*
 ImageBridgeChild::CreateTexture(const SurfaceDescriptor& aSharedData,
                                 LayersBackend aLayersBackend,
                                 TextureFlags aFlags,
                                 uint64_t aSerial)
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   return SendPTextureConstructor(aSharedData, aLayersBackend, aFlags, aSerial);
 }
 
 static bool
 IBCAddOpDestroy(CompositableTransaction* aTxn, const OpDestroy& op, bool synchronously)
 {
   if (aTxn->Finished()) {
     return false;
@@ -1407,17 +1342,17 @@ ImageBridgeChild::DestroyInTransaction(P
   return IBCAddOpDestroy(mTxn, OpDestroy(aCompositable), synchronously);
 }
 
 
 void
 ImageBridgeChild::RemoveTextureFromCompositable(CompositableClient* aCompositable,
                                                 TextureClient* aTexture)
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aTexture->IsSharedWithCompositor());
   MOZ_ASSERT(aCompositable->IsConnected());
   if (!aTexture || !aTexture->IsSharedWithCompositor() || !aCompositable->IsConnected()) {
     return;
   }
 
   CompositableOperation op(
@@ -1431,17 +1366,17 @@ ImageBridgeChild::RemoveTextureFromCompo
   }
 }
 
 void
 ImageBridgeChild::RemoveTextureFromCompositableAsync(AsyncTransactionTracker* aAsyncTransactionTracker,
                                                      CompositableClient* aCompositable,
                                                      TextureClient* aTexture)
 {
-  MOZ_ASSERT(CanSend());
+  MOZ_ASSERT(!mShuttingDown);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aTexture->IsSharedWithCompositor());
   MOZ_ASSERT(aCompositable->IsConnected());
   if (!aTexture || !aTexture->IsSharedWithCompositor() || !aCompositable->IsConnected()) {
     return;
   }
 
   CompositableOperation op(
@@ -1457,66 +1392,30 @@ ImageBridgeChild::RemoveTextureFromCompo
   mTrackersHolder.HoldUntilComplete(aAsyncTransactionTracker);
 }
 
 bool ImageBridgeChild::IsSameProcess() const
 {
   return OtherPid() == base::GetCurrentProcId();
 }
 
+static void
+DestroyCompositableNow(RefPtr<ImageBridgeChild> aImageBridge,
+                       RefPtr<CompositableChild> aCompositable)
+{
+  aImageBridge->Destroy(aCompositable);
+}
+
 void
 ImageBridgeChild::Destroy(CompositableChild* aCompositable)
 {
   if (!InImageBridgeChildThread()) {
-    RefPtr<Runnable> runnable = WrapRunnable(
-      RefPtr<ImageBridgeChild>(this),
-      &ImageBridgeChild::Destroy,
-      RefPtr<CompositableChild>(aCompositable));
-    GetMessageLoop()->PostTask(runnable.forget());
+    RefPtr<ImageBridgeChild> self = this;
+    RefPtr<CompositableChild> compositable = aCompositable;
+    GetMessageLoop()->PostTask(
+      NewRunnableFunction(&DestroyCompositableNow, self, compositable));
     return;
   }
   CompositableForwarder::Destroy(aCompositable);
 }
 
-bool
-ImageBridgeChild::CanSend() const
-{
-  MOZ_ASSERT(InImageBridgeChildThread());
-  return mCanSend;
-}
-
-void
-ImageBridgeChild::OnXPCOMShutdown()
-{
-  // This uses nsIObserverService, so it must be cleaned up. Other threads may
-  // hold references to ImageBridgeChild and we may actually be destroyed well
-  // after XPCOM shutdown.
-  mActiveResourceTracker = nullptr;
-}
-
-NS_IMPL_ISUPPORTS(ImageBridgeChild::ShutdownObserver, nsIObserver);
-
-ImageBridgeChild::ShutdownObserver::ShutdownObserver(ImageBridgeChild* aImageBridge)
- : mImageBridge(aImageBridge)
-{
-  nsContentUtils::RegisterShutdownObserver(this);
-}
-
-void
-ImageBridgeChild::ShutdownObserver::Unregister()
-{
-  nsContentUtils::UnregisterShutdownObserver(this);
-  mImageBridge = nullptr;
-}
-
-NS_IMETHODIMP
-ImageBridgeChild::ShutdownObserver::Observe(nsISupports* aSubject,
-                                            const char* aTopic,
-                                            const char16_t* aData)
-{
-  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
-    mImageBridge->OnXPCOMShutdown();
-  }
-  return NS_OK;
-}
-
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/ImageBridgeChild.h
+++ b/gfx/layers/ipc/ImageBridgeChild.h
@@ -14,17 +14,16 @@
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/layers/AsyncTransactionTracker.h" // for AsyncTransactionTrackerHolder
 #include "mozilla/layers/CanvasClient.h"
 #include "mozilla/layers/CompositableForwarder.h"
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/PImageBridgeChild.h"
 #include "mozilla/Mutex.h"
 #include "nsDebug.h"                    // for NS_RUNTIMEABORT
-#include "nsIObserver.h"
 #include "nsRegion.h"                   // for nsIntRegion
 #include "mozilla/gfx/Rect.h"
 
 class MessageLoop;
 
 namespace base {
 class Thread;
 } // namespace base
@@ -41,18 +40,16 @@ class AsyncTransactionTracker;
 class ImageClient;
 class ImageContainer;
 class ImageContainerChild;
 class ImageBridgeParent;
 class CompositableClient;
 struct CompositableTransaction;
 class Image;
 class TextureClient;
-class SynchronousTask;
-struct AllocShmemParams;
 
 /**
  * Returns true if the current thread is the ImageBrdigeChild's thread.
  *
  * Can be called from any thread.
  */
 bool InImageBridgeChildThread();
 
@@ -107,17 +104,16 @@ bool InImageBridgeChildThread();
  * not used at all (except for the very first transaction that provides the
  * CompositableHost with an AsyncID).
  */
 class ImageBridgeChild final : public PImageBridgeChild
                              , public CompositableForwarder
                              , public ShmemAllocator
 {
   friend class ImageContainer;
-
   typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
 public:
 
   virtual ShmemAllocator* AsShmemAllocator() override { return this; }
 
   /**
    * Creates the image bridge with a dedicated thread for ImageBridgeChild.
    *
@@ -134,22 +130,46 @@ public:
    * ImageBridge's thread.
    *
    * If you don't want to destroy the thread, call DestroyBridge directly
    * instead.
    */
   static void ShutDown();
 
   /**
+   * Returns true if the singleton has been created.
+   *
+   * Can be called from any thread.
+   */
+  static bool IsCreated();
+  /**
+   * Returns true if the singleton's ShutDown() was called.
+   *
+   * Can be called from any thread.
+   */
+  static bool IsShutDown()
+  {
+    return sIsShutDown;
+  }
+
+  /**
    * returns the singleton instance.
    *
    * can be called from any thread.
    */
-  static RefPtr<ImageBridgeChild> GetSingleton();
+  static ImageBridgeChild* GetSingleton();
+
 
+  /**
+   * Dispatches a task to the ImageBridgeChild thread to do the connection
+   */
+  void ConnectAsync(ImageBridgeParent* aParent);
+
+  using PImageBridgeChild::SendImageBridgeThreadId;
+  void SendImageBridgeThreadId();
 
   static void IdentifyCompositorTextureHost(const TextureFactoryIdentifier& aIdentifier);
 
   void BeginTransaction();
   void EndTransaction();
 
   /**
    * Returns the ImageBridgeChild's thread.
@@ -208,64 +228,31 @@ public:
   // Create an ImageClient from the ImageBridge thread.
   RefPtr<ImageClient> CreateImageClientNow(
     CompositableType aType,
     ImageContainer* aImageContainer,
     ImageContainerChild* aContainerChild);
 
   already_AddRefed<CanvasClient> CreateCanvasClient(CanvasClient::CanvasClientType aType,
                                                     TextureFlags aFlag);
-  void ReleaseImageContainer(RefPtr<ImageContainerChild> aChild);
-  void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient);
-  void UpdateImageClient(RefPtr<ImageClient> aClient, RefPtr<ImageContainer> aContainer);
+  already_AddRefed<CanvasClient> CreateCanvasClientNow(CanvasClient::CanvasClientType aType,
+                                                       TextureFlags aFlag);
+
+  static void DispatchReleaseImageContainer(ImageContainerChild* aChild);
   static void DispatchReleaseTextureClient(TextureClient* aClient);
+  static void DispatchImageClientUpdate(ImageClient* aClient, ImageContainer* aContainer);
+
+  static void UpdateAsyncCanvasRenderer(AsyncCanvasRenderer* aClient);
+  static void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient);
 
   /**
    * Flush all Images sent to CompositableHost.
    */
-  void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer);
-
-private:
-  // Helpers for dispatching.
-  already_AddRefed<CanvasClient> CreateCanvasClientNow(
-    CanvasClient::CanvasClientType aType,
-    TextureFlags aFlags);
-  void CreateCanvasClientSync(
-    SynchronousTask* aTask,
-    CanvasClient::CanvasClientType aType,
-    TextureFlags aFlags,
-    RefPtr<CanvasClient>* const outResult);
-
-  void CreateImageClientSync(
-    SynchronousTask* aTask,
-    RefPtr<ImageClient>* result,
-    CompositableType aType,
-    ImageContainer* aImageContainer,
-    ImageContainerChild* aContainerChild);
+  static void FlushAllImages(ImageClient* aClient, ImageContainer* aContainer);
 
-  void ReleaseTextureClientNow(TextureClient* aClient);
-
-  void UpdateAsyncCanvasRendererNow(AsyncCanvasRenderer* aClient);
-  void UpdateAsyncCanvasRendererSync(
-    SynchronousTask* aTask,
-    AsyncCanvasRenderer* aWrapper);
-
-  void FlushAllImagesSync(
-    SynchronousTask* aTask,
-    ImageClient* aClient,
-    ImageContainer* aContainer,
-    RefPtr<AsyncTransactionWaiter> aWaiter);
-
-  void ProxyAllocShmemNow(SynchronousTask* aTask, AllocShmemParams* aParams);
-  void ProxyDeallocShmemNow(
-    SynchronousTask* aTask,
-    ISurfaceAllocator* aAllocator,
-    Shmem* aShmem);
-
-public:
   // CompositableForwarder
 
   virtual void Connect(CompositableClient* aCompositable,
                        ImageContainer* aImageContainer) override;
 
   virtual bool UsesImageBridge() const override { return true; }
 
   /**
@@ -362,62 +349,34 @@ public:
 
   virtual void UpdateFwdTransactionId() override { ++mFwdTransactionId; }
   virtual uint64_t GetFwdTransactionId() override { return mFwdTransactionId; }
 
   bool InForwarderThread() override {
     return InImageBridgeChildThread();
   }
 
+
+  void MarkShutDown();
+
+  void FallbackDestroyActors();
+
 protected:
   ImageBridgeChild();
   bool DispatchAllocShmemInternal(size_t aSize,
                                   SharedMemory::SharedMemoryType aType,
                                   Shmem* aShmem,
                                   bool aUnsafe);
 
   void Bind(Endpoint<PImageBridgeChild>&& aEndpoint);
-  void BindSameProcess(RefPtr<ImageBridgeParent> aParent);
-
-  void SendImageBridgeThreadId();
-
-  void WillShutdown();
-  void ShutdownStep1(SynchronousTask* aTask);
-  void ShutdownStep2(SynchronousTask* aTask);
-  void MarkShutDown();
-  void FallbackDestroyActors();
-
-  void ActorDestroy(ActorDestroyReason aWhy) override;
-  void DeallocPImageBridgeChild() override;
-
-  bool CanSend() const;
-
-private:
-  class ShutdownObserver final : public nsIObserver
-  {
-  public:
-    NS_DECL_ISUPPORTS
-    NS_DECL_NSIOBSERVER
-
-    explicit ShutdownObserver(ImageBridgeChild* aImageBridge);
-    void Unregister();
-
-  private:
-    ~ShutdownObserver() {};
-
-    ImageBridgeChild* mImageBridge;
-  };
-  friend class ShutdownObserver;
-
-  void OnXPCOMShutdown();
 
 private:
   CompositableTransaction* mTxn;
-
-  bool mCanSend;
+  Atomic<bool> mShuttingDown;
+  static Atomic<bool> sIsShutDown;
 
   /**
    * Transaction id of CompositableForwarder.
    * It is incrementaed by UpdateFwdTransactionId() in each BeginTransaction() call.
    */
   uint64_t mFwdTransactionId;
 
   /**
@@ -427,16 +386,14 @@ private:
   nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingRecycled;
 
   AsyncTransactionTrackersHolder mTrackersHolder;
 
 #ifdef MOZ_WIDGET_GONK
   Mutex mWaitingFenceHandleMutex;
   nsDataHashtable<nsUint64HashKey, RefPtr<TextureClient> > mTexturesWaitingFenceHandle;
 #endif
-
-  RefPtr<ShutdownObserver> mShutdownObserver;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif
--- a/xpcom/ds/nsExpirationTracker.h
+++ b/xpcom/ds/nsExpirationTracker.h
@@ -88,17 +88,17 @@ public:
     , mInAgeOneGeneration(false)
     , mName(aName)
   {
     static_assert(K >= 2 && K <= nsExpirationState::NOT_TRACKED,
                   "Unsupported number of generations (must be 2 <= K <= 15)");
     mObserver = new ExpirationTrackerObserver();
     mObserver->Init(this);
   }
-  virtual ~nsExpirationTracker()
+  ~nsExpirationTracker()
   {
     if (mTimer) {
       mTimer->Cancel();
     }
     mObserver->Destroy();
   }
 
   /**