Fix up handling of nsIMemoryReporter pointers

RESOLVED WONTFIX

Status

()

Core
DOM
RESOLVED WONTFIX
6 years ago
5 years ago

People

(Reporter: njn, Assigned: njn)

Tracking

Trunk
Points:
---

Firefox Tracking Flags

(blocking-basecamp:-)

Details

Attachments

(1 obsolete attachment)

(Assignee)

Description

6 years ago
We should use nsCOMPtr more for nsIMemoryReporter objects.  See bug 803684 comment 9 and onwards.
Jonas suggests not blocking on this unless it causes actual problems.  Feel free to re-nom if you disagree :)
blocking-basecamp: ? → -
(Assignee)

Comment 2

6 years ago
> Jonas suggests not blocking on this unless it causes actual problems.  Feel
> free to re-nom if you disagree :)

Was this bug nominated for basecamp?  It's possible that I nominated it by mistake, but I'm also wondering if you set the flag in the wrong bug.
> blocking-basecamp: ? → -

Perhaps it was marked blocking-basecamp when you created it.
(Assignee)

Comment 4

6 years ago
Created attachment 698948 [details] [diff] [review]
Convert |nsIMemoryReporter*| to |nsCOMPtr<nsIMemoryReporter>| where appropriate.

This patch is mostly boring.  I've added assertions so that people
won't be able to make this mistake in the future.

I checked all the cases where we register and unregister, and a few were
failing to null after unregistration, so I added that.

Also, image/src/imgLoader.cpp was a bit strange.  It was doing addref/release
on the reporter when imgLoader was constructed/destructed.  But the reporter is
only registered, never unregistered, so converting the static pointer to it to
nsCOMPtr is sufficient.  So I removed the addref/release pair.

I also fixed up a few mode lines, and the odd bit of whitespace.
Attachment #698948 - Flags: review?(justin.lebar+bug)
Comment on attachment 698948 [details] [diff] [review]
Convert |nsIMemoryReporter*| to |nsCOMPtr<nsIMemoryReporter>| where appropriate.

I think I might have sent you on a snipe hunt; sorry, Nick.

>diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl
>--- a/xpcom/base/nsIMemoryReporter.idl
>+++ b/xpcom/base/nsIMemoryReporter.idl

>@@ -343,25 +343,24 @@ interface nsIMemoryReporterManager : nsI
>         NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _THREADSAFE_)
> #define NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \
>         NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _)
> #define NS_FALLIBLE_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \
>         NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _THREADSAFE_)
> 
> #define NS_MEMORY_REPORTER_NAME(_classname)  MemoryReporter_##_classname
> 
>-// Note that the memory reporters are held in an nsCOMArray, which means
>-// that individual reporters should be referenced with |nsIMemoryReporter *|
>-// instead of nsCOMPtr<nsIMemoryReporter>.
>+// The |aReporter| passed in to these register/unregister functions must have a
>+// refcount of at least one.
> 
>-nsresult NS_RegisterMemoryReporter(nsIMemoryReporter *reporter);
>-nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
>+nsresult NS_RegisterMemoryReporter(nsIMemoryReporter *aReporter);
>+nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *aReporter);
> 
>-nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *reporter);
>-nsresult NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
>+nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *aReporter);
>+nsresult NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *aReporter);
> 
> #if defined(MOZ_DMD)
> namespace mozilla {
> namespace dmd {
> // This runs all the memory reporters but does nothing with the results;  i.e.
> // it does the minimal amount of work possible for DMD to do its thing.
> void RunReporters();
> }


>diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp
>--- a/content/canvas/src/CanvasRenderingContext2D.cpp
>+++ b/content/canvas/src/CanvasRenderingContext2D.cpp

>@@ -1,10 +1,11 @@
>-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
>- * This Source Code Form is subject to the terms of the Mozilla Public
>+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
>+/* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> #include "base/basictypes.h"
> #include "CanvasRenderingContext2D.h"
> 
> #include "nsIDOMXULElement.h"
> 

>@@ -125,17 +126,17 @@ namespace dom {
> static float kDefaultFontSize = 10.0;
> static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
> static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
> 
> // Cap sigma to avoid overly large temp surfaces.
> const Float SIGMA_MAX = 100;
> 
> /* Memory reporter stuff */
>-static nsIMemoryReporter *gCanvasAzureMemoryReporter = nullptr;
>+static nsCOMPtr<nsIMemoryReporter> gCanvasAzureMemoryReporter = nullptr;
> static int64_t gCanvasAzureMemoryUsed = 0;

static nsCOMPtr / nsRefPtr is bad because it generates static constructors.

Instead we use static StaticRefPtr.  There's no StaticCOMPtr, though.

> static int64_t GetCanvasAzureMemoryUsed() {
>   return gCanvasAzureMemoryUsed;
> }
> 
> // This is KIND_OTHER because it's not always clear where in memory the pixels
> // of a canvas are stored.  Furthermore, this memory will be tracked by the

>@@ -788,17 +789,17 @@ CanvasRenderingContext2D::EnsureTarget()
>        mTarget = layerManager->CreateDrawTarget(size, format);
>      } else {
>        mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format);
>      }
>   }
> 
>   if (mTarget) {
>     if (gCanvasAzureMemoryReporter == nullptr) {
>-        gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
>+      gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
>       NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter);
>     }
> 
>     gCanvasAzureMemoryUsed += mWidth * mHeight * 4;
>     JSContext* context = nsContentUtils::GetCurrentJSContext();
>     if (context) {
>       JS_updateMallocCounter(context, mWidth * mHeight * 4);
>     }

This leaks gCanvasAzureMemoryReporter, and if we ever touch this code, it will
turn tree orange.  This is the problem that ClearOnShutdown fixes.

TBH, it seems to me that it would be easier if we just ensured that
NS_RegisterMemoryReporter worked properly when passed an object with refcount
0.  This is easy, because when the function ends its input arg has a larger
refcount than when the function begins; therefore we can safely addref the arg
at the beginning of the function and release it at the end.

>diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
>--- a/dom/base/nsJSEnvironment.cpp
>+++ b/dom/base/nsJSEnvironment.cpp

>@@ -170,17 +170,17 @@ static uint32_t sRemovedPurples = 0;
> static uint32_t sForgetSkippableBeforeCC = 0;
> static uint32_t sPreviousSuspectedCount = 0;
> static uint32_t sCompartmentGCCount = NS_MAX_COMPARTMENT_GC_COUNT;
> static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
> static bool sNeedsFullCC = false;
> static nsJSContext *sContextList = nullptr;
> 
> static nsScriptNameSpaceManager *gNameSpaceManager;
>-static nsIMemoryReporter *gReporter;
>+static nsCOMPtr<nsIMemoryReporter> gReporter;

ibid

>diff --git a/extensions/spellcheck/hunspell/src/mozHunspell.cpp b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
>--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
>+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp

>@@ -139,16 +139,17 @@ mozHunspell::Init()
> }
> 
> mozHunspell::~mozHunspell()
> {
>   mPersonalDictionary = nullptr;
>   delete mHunspell;
> 
>   NS_UnregisterMemoryReporter(mHunspellReporter);
>+  mHunspellReporter = nullptr;
> }

This isn't necessary; when the destructor finishes, it runs the destructors of
all its members, which ends up releasing mHunspellReporter.

Unless mHunspellReporter references the mozHunspell object, in which case you
probably need some cc action.  (Breaking cycles in the destructor doesn't work
for somewhat obvious reasons.)

>diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
>--- a/gfx/thebes/gfxWindowsPlatform.cpp
>+++ b/gfx/thebes/gfxWindowsPlatform.cpp

>@@ -349,36 +349,42 @@ gfxWindowsPlatform::gfxWindowsPlatform()
> 
>     /* 
>      * Initialize COM 
>      */ 
>     CoInitialize(NULL); 
> 
>     mScreenDC = GetDC(NULL);
> 
>+    nsCOMPtr<nsMemoryReporter> r;
> #ifdef CAIRO_HAS_D2D_SURFACE
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DCache));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVram));
>+    r = new NS_MEMORY_REPORTER_NAME(D2DCache);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(D2DVram);
>+    NS_RegisterMemoryReporter(r);
>     mD2DDevice = nullptr;
> #endif
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMDT));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMSS));
>+    r = new NS_MEMORY_REPORTER_NAME(D2DVRAMDT);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(D2DVRAMSS);
>+    NS_RegisterMemoryReporter(r);

Re-using the nsCOMPtr like this is non-canonical.

> gfxWindowsPlatform::~gfxWindowsPlatform()
> {
> #ifdef ENABLE_GPU_MEM_REPORTER
>     NS_UnregisterMemoryMultiReporter(mGPUAdapterMultiReporter);
>+    mGPUAdapterMultiReporter = nullptr;

(Probably) not necessary.

>diff --git a/image/src/imgLoader.h b/image/src/imgLoader.h
>--- a/image/src/imgLoader.h
>+++ b/image/src/imgLoader.h

>-  static imgMemoryReporter* sMemReporter;
>+  static nsCOMPtr<imgMemoryReporter> sMemReporter;

See above.

>@@ -37,18 +37,21 @@ NS_MEMORY_REPORTER_IMPLEMENT(ShmemMapped
> SharedMemory::SharedMemory()
>   : mAllocSize(0)
>   , mMappedSize(0)
> {
>   // NB: SharedMemory is main-thread-only at the moment, but that may
>   // change soon
>   static bool registered;
>   if (!registered) {
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ShmemAllocated));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ShmemMapped));
>+    nsCOMPtr<nsIMemoryReporter> r;
>+    r = new NS_MEMORY_REPORTER_NAME(ShmemAllocated);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(ShmemMapped);
>+    NS_RegisterMemoryReporter(r);
>     registered = true;
>   }
> }

See above.

>diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
>--- a/js/xpconnect/src/XPCJSRuntime.cpp
>+++ b/js/xpconnect/src/XPCJSRuntime.cpp

>@@ -2500,20 +2500,26 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
>     // function compiled with LAZY_SOURCE, it calls SourceHook to load it.
>     ///
>     // Note we do have to retain the source code in memory for scripts compiled in
>     // compileAndGo mode and compiled function bodies (from
>     // JS_CompileFunction*). In practice, this means content scripts and event
>     // handlers.
>     JS_SetSourceHook(mJSRuntime, SourceHook);
> 
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
>-    NS_RegisterMemoryMultiReporter(new JSCompartmentsMultiReporter);
>+    nsCOMPtr<nsIMemoryReporter> r;
>+    r = new NS_MEMORY_REPORTER_NAME(JSGCHeap);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(JSSystemCompartmentCount);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(JSUserCompartmentCount);
>+    NS_RegisterMemoryReporter(r);

See above.

>diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp
>--- a/xpcom/base/nsCycleCollector.cpp
>+++ b/xpcom/base/nsCycleCollector.cpp

> static nsCycleCollector *sCollector = nullptr;
>-static nsIMemoryMultiReporter *sCollectorReporter = nullptr;
>+static nsCOMPtr<nsIMemoryMultiReporter> sCollectorReporter = nullptr;

See above.
Attachment #698948 - Flags: review?(justin.lebar+bug) → review-
(Assignee)

Comment 6

5 years ago
> static nsCOMPtr / nsRefPtr is bad because it generates static constructors.
> 
> Instead we use static StaticRefPtr.  There's no StaticCOMPtr, though.

And adding one would be difficult, I assume?


> >     if (gCanvasAzureMemoryReporter == nullptr) {
> >-        gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
> >+      gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
> >       NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter);
> >     }
> 
> This leaks gCanvasAzureMemoryReporter, and if we ever touch this code, it
> will
> turn tree orange.  This is the problem that ClearOnShutdown fixes.

Is this because nsCOMPtr does some kind of leak logging?
(Assignee)

Comment 7

5 years ago
> Is this because nsCOMPtr does some kind of leak logging?

Oh, it's because the nsCOMPtr will keep the refcount at 1.  Whereas with a raw pointer the reporter will be freed as soon as its unregistered.
> And adding one would be difficult, I assume?

Not very, I don't think.  But there's some trickiness with nsCOMPtr wrt keeping nsISupports*'s instead of T*'s.  I just never bothered to figure it out.

> Oh, it's because the nsCOMPtr will keep the refcount at 1.

Yes, exactly.
(Assignee)

Updated

5 years ago
Depends on: 829439
(Assignee)

Comment 9

5 years ago
Comment on attachment 698948 [details] [diff] [review]
Convert |nsIMemoryReporter*| to |nsCOMPtr<nsIMemoryReporter>| where appropriate.

># HG changeset patch
># User Nicholas Nethercote <nnethercote@mozilla.com>
># Date 1357603659 28800
># Node ID 7d0a7aeee0584e70c28712d01b298e38ec4741d3
># Parent  6abeaaa94f24fc7c168c718074f7f9a2801f5f59
>Bug 803785 - Convert |nsIMemoryReporter*| to |nsCOMPtr<nsIMemoryReporter>| where appropriate.
>
>diff --git a/content/canvas/src/CanvasRenderingContext2D.cpp b/content/canvas/src/CanvasRenderingContext2D.cpp
>--- a/content/canvas/src/CanvasRenderingContext2D.cpp
>+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
>@@ -1,10 +1,11 @@
>-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
>- * This Source Code Form is subject to the terms of the Mozilla Public
>+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
>+/* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> #include "base/basictypes.h"
> #include "CanvasRenderingContext2D.h"
> 
> #include "nsIDOMXULElement.h"
> 
>@@ -125,17 +126,17 @@ namespace dom {
> static float kDefaultFontSize = 10.0;
> static NS_NAMED_LITERAL_STRING(kDefaultFontName, "sans-serif");
> static NS_NAMED_LITERAL_STRING(kDefaultFontStyle, "10px sans-serif");
> 
> // Cap sigma to avoid overly large temp surfaces.
> const Float SIGMA_MAX = 100;
> 
> /* Memory reporter stuff */
>-static nsIMemoryReporter *gCanvasAzureMemoryReporter = nullptr;
>+static nsCOMPtr<nsIMemoryReporter> gCanvasAzureMemoryReporter = nullptr;
> static int64_t gCanvasAzureMemoryUsed = 0;
> 
> static int64_t GetCanvasAzureMemoryUsed() {
>   return gCanvasAzureMemoryUsed;
> }
> 
> // This is KIND_OTHER because it's not always clear where in memory the pixels
> // of a canvas are stored.  Furthermore, this memory will be tracked by the
>@@ -788,17 +789,17 @@ CanvasRenderingContext2D::EnsureTarget()
>        mTarget = layerManager->CreateDrawTarget(size, format);
>      } else {
>        mTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(size, format);
>      }
>   }
> 
>   if (mTarget) {
>     if (gCanvasAzureMemoryReporter == nullptr) {
>-        gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
>+      gCanvasAzureMemoryReporter = new NS_MEMORY_REPORTER_NAME(CanvasAzureMemory);
>       NS_RegisterMemoryReporter(gCanvasAzureMemoryReporter);
>     }
> 
>     gCanvasAzureMemoryUsed += mWidth * mHeight * 4;
>     JSContext* context = nsContentUtils::GetCurrentJSContext();
>     if (context) {
>       JS_updateMallocCounter(context, mWidth * mHeight * 4);
>     }
>diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
>--- a/dom/base/nsJSEnvironment.cpp
>+++ b/dom/base/nsJSEnvironment.cpp
>@@ -1,10 +1,10 @@
>-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>-/* vim: set ts=2 sw=2 et tw=78: */
>+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>+/* vim: set ts=8 sts=2 sw=2 et tw=80: */
> /* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> #include "nsError.h"
> #include "nsJSEnvironment.h"
> #include "nsIScriptGlobalObject.h"
> #include "nsIScriptObjectPrincipal.h"
>@@ -170,17 +170,17 @@ static uint32_t sRemovedPurples = 0;
> static uint32_t sForgetSkippableBeforeCC = 0;
> static uint32_t sPreviousSuspectedCount = 0;
> static uint32_t sCompartmentGCCount = NS_MAX_COMPARTMENT_GC_COUNT;
> static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
> static bool sNeedsFullCC = false;
> static nsJSContext *sContextList = nullptr;
> 
> static nsScriptNameSpaceManager *gNameSpaceManager;
>-static nsIMemoryReporter *gReporter;
>+static nsCOMPtr<nsIMemoryReporter> gReporter;
> 
> NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(ScriptNameSpaceManagerMallocSizeOf)
> 
> static int64_t
> GetScriptNameSpaceManagerSize()
> {
>   MOZ_ASSERT(gNameSpaceManager);
>   return gNameSpaceManager->SizeOfIncludingThis(
>diff --git a/extensions/spellcheck/hunspell/src/mozHunspell.cpp b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
>--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
>+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
>@@ -139,16 +139,17 @@ mozHunspell::Init()
> }
> 
> mozHunspell::~mozHunspell()
> {
>   mPersonalDictionary = nullptr;
>   delete mHunspell;
> 
>   NS_UnregisterMemoryReporter(mHunspellReporter);
>+  mHunspellReporter = nullptr;
> }
> 
> /* attribute wstring dictionary; */
> NS_IMETHODIMP mozHunspell::GetDictionary(PRUnichar **aDictionary)
> {
>   NS_ENSURE_ARG_POINTER(aDictionary);
> 
>   *aDictionary = ToNewUnicode(mDictionary);
>diff --git a/extensions/spellcheck/hunspell/src/mozHunspell.h b/extensions/spellcheck/hunspell/src/mozHunspell.h
>--- a/extensions/spellcheck/hunspell/src/mozHunspell.h
>+++ b/extensions/spellcheck/hunspell/src/mozHunspell.h
>@@ -97,28 +97,27 @@ public:
>   nsresult Init();
> 
>   void LoadDictionaryList();
> 
>   // helper method for converting a word to the charset of the dictionary
>   nsresult ConvertCharset(const PRUnichar* aStr, char ** aDst);
> 
> protected:
>- 
>   nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
>-  nsCOMPtr<nsIUnicodeEncoder>      mEncoder; 
>-  nsCOMPtr<nsIUnicodeDecoder>      mDecoder; 
>+  nsCOMPtr<nsIUnicodeEncoder>      mEncoder;
>+  nsCOMPtr<nsIUnicodeDecoder>      mDecoder;
> 
>   // Hashtable matches dictionary name to .aff file
>   nsInterfaceHashtable<nsStringHashKey, nsIFile> mDictionaries;
>   nsString  mDictionary;
>   nsString  mLanguage;
>   nsCString mAffixFileName;
> 
>   // dynamic dirs used to search for dictionaries
>   nsCOMArray<nsIFile> mDynamicDirectories;
> 
>   Hunspell  *mHunspell;
> 
>-  nsIMemoryReporter* mHunspellReporter;
>+  nsCOMPtr<nsIMemoryReporter> mHunspellReporter;
> };
> 
> #endif
>diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp
>--- a/gfx/gl/GLContext.cpp
>+++ b/gfx/gl/GLContext.cpp
>@@ -1,9 +1,10 @@
>-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
>+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
>+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
> /* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> #include <algorithm>
> #include <stdio.h>
> #include <string.h>
> 
>@@ -678,18 +679,20 @@ GLContext::CanUploadSubTextures()
> }
> 
> bool GLContext::sPowerOfTwoForced = false;
> bool GLContext::sPowerOfTwoPrefCached = false;
> 
> void
> GLContext::PlatformStartup()
> {
>-  CacheCanUploadNPOT();
>-  NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(TextureMemoryUsage));
>+    CacheCanUploadNPOT();
>+    nsCOMPtr<nsIMemoryReporter> r =
>+        new NS_MEMORY_REPORTER_NAME(TextureMemoryUsage);
>+    NS_RegisterMemoryReporter(r);
> }
> 
> void
> GLContext::CacheCanUploadNPOT()
> {
>     MOZ_ASSERT(NS_IsMainThread(), "Can't cache prefs off the main thread.");
>     MOZ_ASSERT(!sPowerOfTwoPrefCached, "Must only call this function once!");
> 
>diff --git a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
>--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
>+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
>@@ -175,17 +175,19 @@ GrallocBufferActor::GrallocBufferActor()
> : mAllocBytes(0)
> {
>   static bool registered;
>   if (!registered) {
>     // We want to be sure that the first call here will always run on
>     // the main thread.
>     NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
> 
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(GrallocBufferActor));
>+    nsCOMPtr<nsIMemoryReporter> r =
>+      new NS_MEMORY_REPORTER_NAME(GrallocBufferActor)
>+    NS_RegisterMemoryReporter(r);
>     registered = true;
>   }
> }
> 
> GrallocBufferActor::~GrallocBufferActor()
> {
>   if (mAllocBytes > 0) {
>     sCurrentAlloc -= mAllocBytes;
>diff --git a/gfx/thebes/gfxASurface.cpp b/gfx/thebes/gfxASurface.cpp
>--- a/gfx/thebes/gfxASurface.cpp
>+++ b/gfx/thebes/gfxASurface.cpp
>@@ -620,17 +620,18 @@ gfxASurface::RecordMemoryUsedForSurfaceT
> {
>     if (aType < 0 || aType >= SurfaceTypeMax) {
>         NS_WARNING("Invalid type to RecordMemoryUsedForSurfaceType!");
>         return;
>     }
> 
>     static bool registered = false;
>     if (!registered) {
>-        NS_RegisterMemoryMultiReporter(new SurfaceMemoryReporter());
>+        nsCOMPtr<nsIMemoryMultiReporter> mr = new SurfaceMemoryReporter();
>+        NS_RegisterMemoryMultiReporter(mr);
>         registered = true;
>     }
> 
>     gSurfaceMemoryUsed[aType] += aBytes;
> }
> 
> void
> gfxASurface::RecordMemoryUsed(int32_t aBytes)
>diff --git a/gfx/thebes/gfxAndroidPlatform.cpp b/gfx/thebes/gfxAndroidPlatform.cpp
>--- a/gfx/thebes/gfxAndroidPlatform.cpp
>+++ b/gfx/thebes/gfxAndroidPlatform.cpp
>@@ -86,17 +86,18 @@ gfxAndroidPlatform::gfxAndroidPlatform()
>     sFreetypeMemoryRecord.free    = CountingFree;
>     sFreetypeMemoryRecord.realloc = CountingRealloc;
> 
>     // These two calls are equivalent to FT_Init_FreeType(), but allow us to
>     // provide a custom memory allocator.
>     FT_New_Library(&sFreetypeMemoryRecord, &gPlatformFTLibrary);
>     FT_Add_Default_Modules(gPlatformFTLibrary);
> 
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(Freetype));
>+    nsCOMPtr<nsIMemoryReporter> r = new NS_MEMORY_REPORTER_NAME(Freetype);
>+    NS_RegisterMemoryReporter(r);
> 
>     nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
>     nsCOMPtr<nsIScreen> screen;
>     screenMgr->GetPrimaryScreen(getter_AddRefs(screen));
>     mScreenDepth = 24;
>     screen->GetColorDepth(&mScreenDepth);
> 
>     mOffscreenFormat = mScreenDepth == 16
>diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp
>--- a/gfx/thebes/gfxFont.cpp
>+++ b/gfx/thebes/gfxFont.cpp
>@@ -1202,17 +1202,18 @@ MemoryPressureObserver::Observe(nsISuppo
> nsresult
> gfxFontCache::Init()
> {
>     NS_ASSERTION(!gGlobalCache, "Where did this come from?");
>     gGlobalCache = new gfxFontCache();
>     if (!gGlobalCache) {
>         return NS_ERROR_OUT_OF_MEMORY;
>     }
>-    NS_RegisterMemoryMultiReporter(new MemoryReporter);
>+    nsCOMPtr<nsIMemoryMultiReporter> mr = new MemoryReporter;
>+    NS_RegisterMemoryMultiReporter(mr);
>     return NS_OK;
> }
> 
> void
> gfxFontCache::Shutdown()
> {
>     delete gGlobalCache;
>     gGlobalCache = nullptr;
>diff --git a/gfx/thebes/gfxPlatformFontList.cpp b/gfx/thebes/gfxPlatformFontList.cpp
>--- a/gfx/thebes/gfxPlatformFontList.cpp
>+++ b/gfx/thebes/gfxPlatformFontList.cpp
>@@ -151,17 +151,18 @@ gfxPlatformFontList::gfxPlatformFontList
>     NS_ASSERTION(!gFontListPrefObserver,
>                  "There has been font list pref observer already");
>     gFontListPrefObserver = new gfxFontListPrefObserver();
>     NS_ADDREF(gFontListPrefObserver);
>     Preferences::AddStrongObservers(gFontListPrefObserver, kObservedPrefs);
> 
>     mSharedCmaps.Init(16);
> 
>-    NS_RegisterMemoryMultiReporter(new MemoryReporter);
>+    nsCOMPtr<nsIMemoryMultiReporter> mr = new MemoryReporter;
>+    NS_RegisterMemoryMultiReporter(mr);
> }
> 
> gfxPlatformFontList::~gfxPlatformFontList()
> {
>     mSharedCmaps.Clear();
>     NS_ASSERTION(gFontListPrefObserver, "There is no font list pref observer");
>     Preferences::RemoveObservers(gFontListPrefObserver, kObservedPrefs);
>     NS_RELEASE(gFontListPrefObserver);
>diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp
>--- a/gfx/thebes/gfxWindowsPlatform.cpp
>+++ b/gfx/thebes/gfxWindowsPlatform.cpp
>@@ -349,36 +349,42 @@ gfxWindowsPlatform::gfxWindowsPlatform()
> 
>     /* 
>      * Initialize COM 
>      */ 
>     CoInitialize(NULL); 
> 
>     mScreenDC = GetDC(NULL);
> 
>+    nsCOMPtr<nsMemoryReporter> r;
> #ifdef CAIRO_HAS_D2D_SURFACE
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DCache));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVram));
>+    r = new NS_MEMORY_REPORTER_NAME(D2DCache);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(D2DVram);
>+    NS_RegisterMemoryReporter(r);
>     mD2DDevice = nullptr;
> #endif
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMDT));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(D2DVRAMSS));
>+    r = new NS_MEMORY_REPORTER_NAME(D2DVRAMDT);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(D2DVRAMSS);
>+    NS_RegisterMemoryReporter(r);
> 
>     UpdateRenderMode();
> 
> #ifdef ENABLE_GPU_MEM_REPORTER
>     mGPUAdapterMultiReporter = new GPUAdapterMultiReporter();
>     NS_RegisterMemoryMultiReporter(mGPUAdapterMultiReporter);
> #endif
> }
> 
> gfxWindowsPlatform::~gfxWindowsPlatform()
> {
> #ifdef ENABLE_GPU_MEM_REPORTER
>     NS_UnregisterMemoryMultiReporter(mGPUAdapterMultiReporter);
>+    mGPUAdapterMultiReporter = nullptr;
> #endif
>     
>     ::ReleaseDC(NULL, mScreenDC);
>     // not calling FT_Done_FreeType because cairo may still hold references to
>     // these FT_Faces.  See bug 458169.
> #ifdef CAIRO_HAS_D2D_SURFACE
>     if (mD2DDevice) {
>         cairo_release_device(mD2DDevice);
>diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h
>--- a/gfx/thebes/gfxWindowsPlatform.h
>+++ b/gfx/thebes/gfxWindowsPlatform.h
>@@ -18,23 +18,23 @@
> #include "gfxFont.h"
> #ifdef CAIRO_HAS_DWRITE_FONT
> #include "gfxDWriteFonts.h"
> #endif
> #include "gfxPlatform.h"
> #include "gfxContext.h"
> 
> #include "nsTArray.h"
>+#include "nsCOMPtr.h"
> #include "nsDataHashtable.h"
>+#include "nsIMemoryReporter.h"
> 
> #include <windows.h>
> #include <objbase.h>
> 
>-class nsIMemoryMultiReporter;
>-
> // Utility to get a Windows HDC from a thebes context,
> // used by both GDI and Uniscribe font shapers
> struct DCFromContext {
>     DCFromContext(gfxContext *aContext) {
>         dc = NULL;
>         nsRefPtr<gfxASurface> aSurface = aContext->CurrentSurface();
>         NS_ASSERTION(aSurface, "DCFromContext: null surface");
>         if (aSurface &&
>@@ -265,12 +265,12 @@ private:
>     cairo_device_t *mD2DDevice;
> #endif
> 
>     virtual qcms_profile* GetPlatformCMSOutputProfile();
> 
>     // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
>     nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
> 
>-    nsIMemoryMultiReporter* mGPUAdapterMultiReporter;
>+    nsCOMPtr<nsIMemoryMultiReporter> mGPUAdapterMultiReporter;
> };
> 
> #endif /* GFX_WINDOWS_PLATFORM_H */
>diff --git a/image/src/imgLoader.cpp b/image/src/imgLoader.cpp
>--- a/image/src/imgLoader.cpp
>+++ b/image/src/imgLoader.cpp
>@@ -777,24 +777,23 @@ void imgCacheExpirationTracker::NotifyEx
> 
>   entry->Loader()->VerifyCacheSizes();
> }
> 
> imgCacheObserver *gCacheObserver;
> 
> double imgLoader::sCacheTimeWeight;
> uint32_t imgLoader::sCacheMaxSize;
>-imgMemoryReporter* imgLoader::sMemReporter;
>+nsCOMPtr<imgMemoryReporter> imgLoader::sMemReporter;
> 
> NS_IMPL_ISUPPORTS5(imgLoader, imgILoader, nsIContentSniffer, imgICache, nsISupportsWeakReference, nsIObserver)
> 
> imgLoader::imgLoader()
> : mRespectPrivacy(false)
> {
>-  sMemReporter->AddRef();
>   sMemReporter->RegisterLoader(this);
> }
> 
> already_AddRefed<imgLoader>
> imgLoader::GetInstance()
> {
>   static StaticRefPtr<imgLoader> singleton;
>   if (!singleton) {
>@@ -807,17 +806,16 @@ imgLoader::GetInstance()
>   return loader.forget();
> }
> 
> imgLoader::~imgLoader()
> {
>   ClearChromeImageCache();
>   ClearImageCache();
>   sMemReporter->UnregisterLoader(this);
>-  sMemReporter->Release();
> }
> 
> void imgLoader::VerifyCacheSizes()
> {
> #ifdef DEBUG
>   if (!mCacheTracker)
>     return;
> 
>@@ -871,17 +869,20 @@ void imgLoader::GlobalInit()
>   rv = Preferences::GetInt("image.cache.size", &cachesize);
>   if (NS_SUCCEEDED(rv))
>     sCacheMaxSize = cachesize;
>   else
>     sCacheMaxSize = 5 * 1024 * 1024;
> 
>   sMemReporter = new imgMemoryReporter();
>   NS_RegisterMemoryMultiReporter(sMemReporter);
>-  NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ImagesContentUsedUncompressed));
>+
>+  nsCOMPtr<nsIMemoryReporter> r =
>+    new NS_MEMORY_REPORTER_NAME(ImagesContentUsedUncompressed);
>+  NS_RegisterMemoryReporter(r);
> }
> 
> nsresult imgLoader::InitCache()
> {
>   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
>   if (!os)
>     return NS_ERROR_FAILURE;
> 
>diff --git a/image/src/imgLoader.h b/image/src/imgLoader.h
>--- a/image/src/imgLoader.h
>+++ b/image/src/imgLoader.h
>@@ -363,17 +363,17 @@ private: // data
>   imgCacheTable mCache;
>   imgCacheQueue mCacheQueue;
> 
>   imgCacheTable mChromeCache;
>   imgCacheQueue mChromeCacheQueue;
> 
>   static double sCacheTimeWeight;
>   static uint32_t sCacheMaxSize;
>-  static imgMemoryReporter* sMemReporter;
>+  static nsCOMPtr<imgMemoryReporter> sMemReporter;
> 
>   nsCString mAcceptHeader;
> 
>   nsAutoPtr<imgCacheExpirationTracker> mCacheTracker;
>   bool mRespectPrivacy;
> };
> 
> 
>diff --git a/ipc/glue/SharedMemory.cpp b/ipc/glue/SharedMemory.cpp
>--- a/ipc/glue/SharedMemory.cpp
>+++ b/ipc/glue/SharedMemory.cpp
>@@ -1,17 +1,17 @@
>-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
>- * vim: sw=2 ts=8 et :
>- */
>+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
>+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
> /* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> #include <math.h>
> 
>+#include "nsCOMPtr.h"
> #include "nsString.h"
> #include "nsIMemoryReporter.h"
> #include "mozilla/ipc/SharedMemory.h"
> 
> namespace mozilla {
> namespace ipc {
> 
> static int64_t gShmemAllocated;
>@@ -37,18 +37,21 @@ NS_MEMORY_REPORTER_IMPLEMENT(ShmemMapped
> SharedMemory::SharedMemory()
>   : mAllocSize(0)
>   , mMappedSize(0)
> {
>   // NB: SharedMemory is main-thread-only at the moment, but that may
>   // change soon
>   static bool registered;
>   if (!registered) {
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ShmemAllocated));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(ShmemMapped));
>+    nsCOMPtr<nsIMemoryReporter> r;
>+    r = new NS_MEMORY_REPORTER_NAME(ShmemAllocated);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(ShmemMapped);
>+    NS_RegisterMemoryReporter(r);
>     registered = true;
>   }
> }
> 
> /*static*/ size_t
> SharedMemory::PageAlignedSize(size_t aSize)
> {
>   size_t pageSize = SystemPageSize();
>diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp
>--- a/js/xpconnect/src/XPCJSRuntime.cpp
>+++ b/js/xpconnect/src/XPCJSRuntime.cpp
>@@ -1345,17 +1345,17 @@ GetGCChunkTotalBytes()
> {
>     JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
>     return int64_t(JS_GetGCParameter(rt, JSGC_TOTAL_CHUNKS)) * js::gc::ChunkSize;
> }
> 
> // Telemetry relies on this memory reporter being a single-reporter (rather
> // than part of the "js" multi-reporter, which is too slow to run during a
> // telemetry ping).
>-NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSGCHeap,
>+NS_MEMORY_REPORTER_IMPLEMENT(JSGCHeap,
>                              "js-gc-heap",
>                              KIND_OTHER,
>                              nsIMemoryReporter::UNITS_BYTES,
>                              GetGCChunkTotalBytes,
>                              "Memory used by the garbage-collected JavaScript heap.")
> static int64_t
> GetJSSystemCompartmentCount()
> {
>@@ -1370,27 +1370,27 @@ GetJSUserCompartmentCount()
> 
> // Nb: js-system-compartment-count + js-user-compartment-count could be
> // different to the number of compartments reported by
> // JSMemoryMultiReporter if a garbage collection occurred
> // between them being consulted.  We could move these reporters into
> // XPConnectJSCompartmentCount to avoid that problem, but then we couldn't
> // easily report them via telemetry, so we live with the small risk of
> // inconsistencies.
>-NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSSystemCompartmentCount,
>+NS_MEMORY_REPORTER_IMPLEMENT(JSSystemCompartmentCount,
>     "js-compartments/system",
>     KIND_OTHER,
>     nsIMemoryReporter::UNITS_COUNT,
>     GetJSSystemCompartmentCount,
>     "The number of JavaScript compartments for system code.  The sum of this "
>     "and 'js-compartments-user' might not match the number of compartments "
>     "listed under 'js' if a garbage collection occurs at an inopportune time, "
>     "but such cases should be rare.")
> 
>-NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSUserCompartmentCount,
>+NS_MEMORY_REPORTER_IMPLEMENT(JSUserCompartmentCount,
>     "js-compartments/user",
>     KIND_OTHER,
>     nsIMemoryReporter::UNITS_COUNT,
>     GetJSUserCompartmentCount,
>     "The number of JavaScript compartments for user code.  The sum of this "
>     "and 'js-compartments-system' might not match the number of compartments "
>     "listed under 'js' if a garbage collection occurs at an inopportune time, "
>     "but such cases should be rare.")
>@@ -2500,20 +2500,26 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
>     // function compiled with LAZY_SOURCE, it calls SourceHook to load it.
>     ///
>     // Note we do have to retain the source code in memory for scripts compiled in
>     // compileAndGo mode and compiled function bodies (from
>     // JS_CompileFunction*). In practice, this means content scripts and event
>     // handlers.
>     JS_SetSourceHook(mJSRuntime, SourceHook);
> 
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
>-    NS_RegisterMemoryMultiReporter(new JSCompartmentsMultiReporter);
>+    nsCOMPtr<nsIMemoryReporter> r;
>+    r = new NS_MEMORY_REPORTER_NAME(JSGCHeap);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(JSSystemCompartmentCount);
>+    NS_RegisterMemoryReporter(r);
>+    r = new NS_MEMORY_REPORTER_NAME(JSUserCompartmentCount);
>+    NS_RegisterMemoryReporter(r);
>+
>+    nsCOMPtr<nsIMemoryMultiReporter> mr = new JSCompartmentsMultiReporter;
>+    NS_RegisterMemoryMultiReporter(mr);
> 
>     mJSHolders.Init(512);
> 
>     // Install a JavaScript 'debugger' keyword handler in debug builds only
> #ifdef DEBUG
>     if (!JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler)
>         xpc_InstallJSDebuggerKeywordHandler(mJSRuntime);
> #endif
>diff --git a/layout/base/nsStyleSheetService.h b/layout/base/nsStyleSheetService.h
>--- a/layout/base/nsStyleSheetService.h
>+++ b/layout/base/nsStyleSheetService.h
>@@ -4,31 +4,31 @@
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> /* implementation of interface for managing user and user-agent style sheets */
> 
> #ifndef nsStyleSheetService_h_
> #define nsStyleSheetService_h_
> 
> #include "nsIStyleSheetService.h"
>+#include "nsCOMPtr.h"
> #include "nsCOMArray.h"
>+#include "nsIMemoryReporter.h"
> #include "nsIStyleSheet.h"
> #include "mozilla/Attributes.h"
> 
> class nsISimpleEnumerator;
> class nsICategoryManager;
> 
> #define NS_STYLESHEETSERVICE_CID \
> {0xfcca6f83, 0x9f7d, 0x44e4, {0xa7, 0x4b, 0xb5, 0x94, 0x33, 0xe6, 0xc8, 0xc3}}
> 
> #define NS_STYLESHEETSERVICE_CONTRACTID \
>   "@mozilla.org/content/style-sheet-service;1"
> 
>-class nsIMemoryReporter;
>-
> class nsStyleSheetService MOZ_FINAL : public nsIStyleSheetService
> {
>  public:
>   nsStyleSheetService() NS_HIDDEN;
>   ~nsStyleSheetService() NS_HIDDEN;
> 
>   NS_DECL_ISUPPORTS
>   NS_DECL_NSISTYLESHEETSERVICE
>@@ -58,12 +58,12 @@ class nsStyleSheetService MOZ_FINAL : pu
>   // new sheet will be the last sheet in mSheets[aSheetType].
>   NS_HIDDEN_(nsresult) LoadAndRegisterSheetInternal(nsIURI *aSheetURI,
>                                                     uint32_t aSheetType);
> 
>   size_t SizeOfIncludingThisHelper(nsMallocSizeOfFun aMallocSizeOf) const;
> 
>   nsCOMArray<nsIStyleSheet> mSheets[3];
> 
>-  nsIMemoryReporter* mReporter;
>+  nsCOMPtr<nsIMemoryReporter> mReporter;
> };
> 
> #endif
>diff --git a/layout/style/nsLayoutStylesheetCache.h b/layout/style/nsLayoutStylesheetCache.h
>--- a/layout/style/nsLayoutStylesheetCache.h
>+++ b/layout/style/nsLayoutStylesheetCache.h
>@@ -58,12 +58,12 @@ private:
>   nsRefPtr<nsCSSStyleSheet> mScrollbarsSheet;
>   nsRefPtr<nsCSSStyleSheet> mFormsSheet;
>   nsRefPtr<nsCSSStyleSheet> mUserContentSheet;
>   nsRefPtr<nsCSSStyleSheet> mUserChromeSheet;
>   nsRefPtr<nsCSSStyleSheet> mUASheet;
>   nsRefPtr<nsCSSStyleSheet> mQuirkSheet;
>   nsRefPtr<nsCSSStyleSheet> mFullScreenOverrideSheet;
> 
>-  nsIMemoryReporter* mReporter;
>+  nsCOMPtr<nsIMemoryReporter> mReporter;
> };
> 
> #endif
>diff --git a/netwerk/dns/nsEffectiveTLDService.h b/netwerk/dns/nsEffectiveTLDService.h
>--- a/netwerk/dns/nsEffectiveTLDService.h
>+++ b/netwerk/dns/nsEffectiveTLDService.h
>@@ -1,22 +1,22 @@
> //* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
> /* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> #include "nsIEffectiveTLDService.h"
> 
>+#include "nsIMemoryReporter.h"
> #include "nsTHashtable.h"
> #include "nsString.h"
> #include "nsCOMPtr.h"
> #include "mozilla/Attributes.h"
> 
> class nsIIDNService;
>-class nsIMemoryReporter;
> 
> #define ETLD_ENTRY_N_INDEX_BITS 30
> 
> // struct for static data generated from effective_tld_names.dat
> struct ETLDEntry {
>   uint32_t strtab_index : ETLD_ENTRY_N_INDEX_BITS;
>   uint32_t exception : 1;
>   uint32_t wild : 1;
>@@ -112,12 +112,12 @@ public:
> 
>   size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
> 
> private:
>   nsresult GetBaseDomainInternal(nsCString &aHostname, uint32_t aAdditionalParts, nsACString &aBaseDomain);
>   nsresult NormalizeHostname(nsCString &aHostname);
>   ~nsEffectiveTLDService();
> 
>-  nsIMemoryReporter*          mReporter;
>+  nsCOMPtr<nsIMemoryReporter> mReporter;
>   nsTHashtable<nsDomainEntry> mHash;
>   nsCOMPtr<nsIIDNService>     mIDNService;
> };
>diff --git a/startupcache/StartupCache.h b/startupcache/StartupCache.h
>--- a/startupcache/StartupCache.h
>+++ b/startupcache/StartupCache.h
>@@ -177,18 +177,18 @@ private:
>   static StartupCache *gStartupCache;
>   static bool gShutdownInitiated;
>   static bool gIgnoreDiskCache;
>   PRThread *mWriteThread;
> #ifdef DEBUG
>   nsTHashtable<nsISupportsHashKey> mWriteObjectMap;
> #endif
> 
>-  nsIMemoryReporter* mMappingMemoryReporter;
>-  nsIMemoryReporter* mDataMemoryReporter;
>+  nsCOMPtr<nsIMemoryReporter> mMappingMemoryReporter;
>+  nsCOMPtr<nsIMemoryReporter> mDataMemoryReporter;
> };
> 
> // This debug outputstream attempts to detect if clients are writing multiple
> // references to the same object. We only support that if that object
> // is a singleton.
> #ifdef DEBUG
> class StartupCacheDebugOutputStream MOZ_FINAL
>   : public nsIObjectOutputStream
>diff --git a/toolkit/components/places/History.cpp b/toolkit/components/places/History.cpp
>--- a/toolkit/components/places/History.cpp
>+++ b/toolkit/components/places/History.cpp
>@@ -1435,17 +1435,18 @@ History::History()
>   gService = this;
> 
>   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
>   NS_WARN_IF_FALSE(os, "Observer service was not found!");
>   if (os) {
>     (void)os->AddObserver(this, TOPIC_PLACES_SHUTDOWN, false);
>   }
> 
>-  NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(HistoryService));
>+  nsCOMPtr<nsIMemoryReporter> r = new NS_MEMORY_REPORTER_NAME(HistoryService);
>+  NS_RegisterMemoryReporter(r);
> }
> 
> History::~History()
> {
>   gService = NULL;
> 
> #ifdef DEBUG
>   if (mObservers.IsInitialized()) {
>diff --git a/toolkit/components/telemetry/Telemetry.cpp b/toolkit/components/telemetry/Telemetry.cpp
>--- a/toolkit/components/telemetry/Telemetry.cpp
>+++ b/toolkit/components/telemetry/Telemetry.cpp
>@@ -314,17 +314,17 @@ private:
>   AutoHashtable<SlowSQLEntryType> mPrivateSQL;
>   AutoHashtable<SlowSQLEntryType> mSanitizedSQL;
>   // This gets marked immutable in debug builds, so we can't use
>   // AutoHashtable here.
>   nsTHashtable<nsCStringHashKey> mTrackedDBs;
>   Mutex mHashMutex;
>   HangReports mHangReports;
>   Mutex mHangReportsMutex;
>-  nsIMemoryReporter *mMemoryReporter;
>+  nsCOMPtr<nsIMemoryReporter> mMemoryReporter;
> 
>   bool mCachedTelemetryData;
>   uint32_t mLastShutdownTime;
>   std::vector<nsCOMPtr<nsIFetchTelemetryDataCallback> > mCallbacks;
>   friend class nsFetchTelemetryData;
> };
> 
> TelemetryImpl*  TelemetryImpl::sTelemetry = NULL;
>diff --git a/xpcom/base/AvailableMemoryTracker.cpp b/xpcom/base/AvailableMemoryTracker.cpp
>--- a/xpcom/base/AvailableMemoryTracker.cpp
>+++ b/xpcom/base/AvailableMemoryTracker.cpp
>@@ -577,20 +577,24 @@ void Activate()
> 
>   Preferences::AddUintVarCache(&sLowPhysicalMemoryThreshold,
>       "memory.low_physical_memory_threshold_mb", 0);
>   Preferences::AddUintVarCache(&sLowCommitSpaceThreshold,
>       "memory.low_commit_space_threshold_mb", 128);
>   Preferences::AddUintVarCache(&sLowMemoryNotificationIntervalMS,
>       "memory.low_memory_notification_interval_ms", 10000);
> 
>-  NS_RegisterMemoryReporter(new NumLowCommitSpaceEventsMemoryReporter());
>-  NS_RegisterMemoryReporter(new NumLowPhysicalMemoryEventsMemoryReporter());
>+  nsCOMPtr<nsIMemoryReporter> r;
>+  r = new NumLowCommitSpaceEventsMemoryReporter();
>+  NS_RegisterMemoryReporter(r);
>+  r = new NumLowPhysicalMemoryEventsMemoryReporter();
>+  NS_RegisterMemoryReporter(r);
>   if (sizeof(void*) == 4) {
>-    NS_RegisterMemoryReporter(new NumLowVirtualMemoryEventsMemoryReporter());
>+    r = new NumLowVirtualMemoryEventsMemoryReporter();
>+    NS_RegisterMemoryReporter(r);
>   }
>   sHooksActive = true;
> #endif
> 
>   if (Preferences::GetBool("memory.free_dirty_pages", false)) {
>     // This object is held alive by the observer service.
>     nsRefPtr<nsMemoryPressureWatcher> watcher = new nsMemoryPressureWatcher();
>     watcher->Init();
>diff --git a/xpcom/base/MapsMemoryReporter.cpp b/xpcom/base/MapsMemoryReporter.cpp
>--- a/xpcom/base/MapsMemoryReporter.cpp
>+++ b/xpcom/base/MapsMemoryReporter.cpp
>@@ -554,16 +554,17 @@ NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(US
>     GetUSS,
>     "Memory mapped by the process that is present in physical memory and not "
>     "shared with any other processes.  This is also known as the process's "
>     "unique set size (USS).  This is the amount of RAM we'd expect to be freed "
>     "if we closed this process.")
> 
> void Init()
> {
>-  nsCOMPtr<nsIMemoryMultiReporter> reporter = new MapsReporter();
>-  NS_RegisterMemoryMultiReporter(reporter);
>+  nsCOMPtr<nsIMemoryMultiReporter> mr = new MapsReporter();
>+  NS_RegisterMemoryMultiReporter(mr);
> 
>-  NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(USS));
>+  nsCOMPtr<nsIMemoryReporter> r = new NS_MEMORY_REPORTER_NAME(USS);
>+  NS_RegisterMemoryReporter(r);
> }
> 
> } // namespace MapsMemoryReporter
> } // namespace mozilla
>diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp
>--- a/xpcom/base/nsCycleCollector.cpp
>+++ b/xpcom/base/nsCycleCollector.cpp
>@@ -1134,17 +1134,17 @@ public:
> 
> 
> ////////////////////////////////////////////////////////////////////////
> // The static collector object
> ////////////////////////////////////////////////////////////////////////
> 
> 
> static nsCycleCollector *sCollector = nullptr;
>-static nsIMemoryMultiReporter *sCollectorReporter = nullptr;
>+static nsCOMPtr<nsIMemoryMultiReporter> sCollectorReporter = nullptr;
> 
> 
> ////////////////////////////////////////////////////////////////////////
> // Utility functions
> ////////////////////////////////////////////////////////////////////////
> 
> MOZ_NEVER_INLINE static void
> Fault(const char *msg, const void *ptr=nullptr)
>diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl
>--- a/xpcom/base/nsIMemoryReporter.idl
>+++ b/xpcom/base/nsIMemoryReporter.idl
>@@ -343,25 +343,24 @@ interface nsIMemoryReporterManager : nsI
>         NS_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _THREADSAFE_)
> #define NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \
>         NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _)
> #define NS_FALLIBLE_THREADSAFE_MEMORY_REPORTER_IMPLEMENT(_c, _p, _k, _u, _a, _d) \
>         NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT_HELPER(_c, _p, _k, _u, _a, _d, _THREADSAFE_)
> 
> #define NS_MEMORY_REPORTER_NAME(_classname)  MemoryReporter_##_classname
> 
>-// Note that the memory reporters are held in an nsCOMArray, which means
>-// that individual reporters should be referenced with |nsIMemoryReporter *|
>-// instead of nsCOMPtr<nsIMemoryReporter>.
>+// The |aReporter| passed in to these register/unregister functions must have a
>+// refcount of at least one.
> 
>-nsresult NS_RegisterMemoryReporter(nsIMemoryReporter *reporter);
>-nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
>+nsresult NS_RegisterMemoryReporter(nsIMemoryReporter *aReporter);
>+nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *aReporter);
> 
>-nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *reporter);
>-nsresult NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
>+nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *aReporter);
>+nsresult NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *aReporter);
> 
> #if defined(MOZ_DMD)
> namespace mozilla {
> namespace dmd {
> // This runs all the memory reporters but does nothing with the results;  i.e.
> // it does the minimal amount of work possible for DMD to do its thing.
> void RunReporters();
> }
>diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp
>--- a/xpcom/base/nsMemoryReporterManager.cpp
>+++ b/xpcom/base/nsMemoryReporterManager.cpp
>@@ -711,52 +711,52 @@ nsMemoryReporterManager::EnumerateMultiR
> {
>     nsresult rv;
>     mozilla::MutexAutoLock autoLock(mMutex);
>     rv = NS_NewArrayEnumerator(result, mMultiReporters);
>     return rv;
> }
> 
> NS_IMETHODIMP
>-nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter *reporter)
>+nsMemoryReporterManager::RegisterReporter(nsIMemoryReporter *aReporter)
> {
>     mozilla::MutexAutoLock autoLock(mMutex);
>-    if (mReporters.IndexOf(reporter) != -1)
>+    if (mReporters.IndexOf(aReporter) != -1)
>         return NS_ERROR_FAILURE;
> 
>-    mReporters.AppendObject(reporter);
>+    mReporters.AppendObject(aReporter);
>     return NS_OK;
> }
> 
> NS_IMETHODIMP
>-nsMemoryReporterManager::RegisterMultiReporter(nsIMemoryMultiReporter *reporter)
>+nsMemoryReporterManager::RegisterMultiReporter(nsIMemoryMultiReporter *aReporter)
> {
>     mozilla::MutexAutoLock autoLock(mMutex);
>-    if (mMultiReporters.IndexOf(reporter) != -1)
>+    if (mMultiReporters.IndexOf(aReporter) != -1)
>         return NS_ERROR_FAILURE;
> 
>-    mMultiReporters.AppendObject(reporter);
>+    mMultiReporters.AppendObject(aReporter);
>     return NS_OK;
> }
> 
> NS_IMETHODIMP
>-nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter *reporter)
>+nsMemoryReporterManager::UnregisterReporter(nsIMemoryReporter *aReporter)
> {
>     mozilla::MutexAutoLock autoLock(mMutex);
>-    if (!mReporters.RemoveObject(reporter))
>+    if (!mReporters.RemoveObject(aReporter))
>         return NS_ERROR_FAILURE;
> 
>     return NS_OK;
> }
> 
> NS_IMETHODIMP
>-nsMemoryReporterManager::UnregisterMultiReporter(nsIMemoryMultiReporter *reporter)
>+nsMemoryReporterManager::UnregisterMultiReporter(nsIMemoryMultiReporter *aReporter)
> {
>     mozilla::MutexAutoLock autoLock(mMutex);
>-    if (!mMultiReporters.RemoveObject(reporter))
>+    if (!mMultiReporters.RemoveObject(aReporter))
>         return NS_ERROR_FAILURE;
> 
>     return NS_OK;
> }
> 
> NS_IMETHODIMP
> nsMemoryReporterManager::GetResident(int64_t *aResident)
> {
>@@ -1077,50 +1077,66 @@ NS_IMETHODIMP nsMemoryReporter::GetAmoun
> }
> 
> NS_IMETHODIMP nsMemoryReporter::GetDescription(nsACString &aDescription)
> {
>     aDescription.Assign(mDesc);
>     return NS_OK;
> }
> 
>+static void
>+CheckRefCountIsNonZero(nsISupports *aSupports)
>+{
>+#ifdef DEBUG
>+    // There's no way to get the refcount without adding to it, hence this
>+    // clunkiness.
>+    nsrefcnt n = aSupports->AddRef();
>+    MOZ_ASSERT(n >= 2);
>+    aSupports->Release();
>+#endif
>+}
>+
> nsresult
>-NS_RegisterMemoryReporter (nsIMemoryReporter *reporter)
>+NS_RegisterMemoryReporter(nsIMemoryReporter *aReporter)
> {
>+    CheckRefCountIsNonZero(aReporter);
>     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
>     if (mgr == nullptr)
>         return NS_ERROR_FAILURE;
>-    return mgr->RegisterReporter(reporter);
>+    return mgr->RegisterReporter(aReporter);
> }
> 
> nsresult
>-NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
>+NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *aReporter)
> {
>+    CheckRefCountIsNonZero(aReporter);
>     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
>     if (mgr == nullptr)
>         return NS_ERROR_FAILURE;
>-    return mgr->RegisterMultiReporter(reporter);
>+    return mgr->RegisterMultiReporter(aReporter);
> }
> 
> nsresult
>-NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter)
>+NS_UnregisterMemoryReporter(nsIMemoryReporter *aReporter)
> {
>+    CheckRefCountIsNonZero(aReporter);
>     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
>     if (mgr == nullptr)
>         return NS_ERROR_FAILURE;
>-    return mgr->UnregisterReporter(reporter);
>+    return mgr->UnregisterReporter(aReporter);
> }
> 
> nsresult
>-NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
>+NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *aReporter)
> {
>+    CheckRefCountIsNonZero(aReporter);
>     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
>     if (mgr == nullptr)
>         return NS_ERROR_FAILURE;
>-    return mgr->UnregisterMultiReporter(reporter);
>+    return mgr->UnregisterMultiReporter(aReporter);
> }
> 
> #if defined(MOZ_DMD)
> 
> namespace mozilla {
> namespace dmd {
> 
> class NullMultiReporterCallback : public nsIMemoryMultiReporterCallback
>diff --git a/xpcom/components/nsCategoryManager.h b/xpcom/components/nsCategoryManager.h
>--- a/xpcom/components/nsCategoryManager.h
>+++ b/xpcom/components/nsCategoryManager.h
>@@ -135,12 +135,12 @@ private:
>                        const char* aCategoryName, // must be a static string
>                        const char* aEntryName);
> 
>   PLArenaPool mArena;
>   nsClassHashtable<nsDepCharHashKey, CategoryNode> mTable;
>   mozilla::Mutex mLock;
>   bool mSuppressNotifications;
> 
>-  nsIMemoryReporter* mReporter;
>+  nsCOMPtr<nsIMemoryReporter> mReporter;
> };
> 
> #endif
>diff --git a/xpcom/components/nsComponentManager.h b/xpcom/components/nsComponentManager.h
>--- a/xpcom/components/nsComponentManager.h
>+++ b/xpcom/components/nsComponentManager.h
>@@ -253,17 +253,17 @@ public:
> 
>     nsTArray<PendingServiceInfo> mPendingServices;
> 
>     size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf);
> 
> private:
>     ~nsComponentManagerImpl();
> 
>-    nsIMemoryReporter* mReporter;
>+    nsCOMPtr<nsIMemoryReporter> mReporter;
> };
> 
> 
> #define NS_MAX_FILENAME_LEN     1024
> 
> #define NS_ERROR_IS_DIR NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_XPCOM, 24)
> 
> struct nsFactoryEntry
>diff --git a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
>--- a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
>+++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
>@@ -1,9 +1,10 @@
> /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
>+/* vim: set ts=8 sts=4 et sw=4 tw=80: */
> /* This Source Code Form is subject to the terms of the Mozilla Public
>  * License, v. 2.0. If a copy of the MPL was not distributed with this
>  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
> 
> /* Implementation of xptiInterfaceInfoManager. */
> 
> #include "xptiprivate.h"
> #include "nsDependentString.h"
>@@ -78,17 +79,18 @@ xptiInterfaceInfoManager::FreeInterfaceI
> }
> 
> xptiInterfaceInfoManager::xptiInterfaceInfoManager()
>     :   mWorkingSet(),
>         mResolveLock("xptiInterfaceInfoManager.mResolveLock"),
>         mAdditionalManagersLock(
>             "xptiInterfaceInfoManager.mAdditionalManagersLock")
> {
>-    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(xptiWorkingSet));
>+    nsCOMPtr<nsIMemoryReporter> r = new NS_MEMORY_REPORTER_NAME(xptiWorkingSet);
>+    NS_RegisterMemoryReporter(r);
> }
> 
> xptiInterfaceInfoManager::~xptiInterfaceInfoManager()
> {
>     // We only do this on shutdown of the service.
>     mWorkingSet.InvalidateInterfaceInfos();
> 
>     gInterfaceInfoManager = nullptr;
Attachment #698948 - Attachment is obsolete: true
(Assignee)

Comment 10

5 years ago
Um, not sure what happened in comment 9.  Sorry.  My kingdom for a bugzilla comment delete feature.
(Assignee)

Updated

5 years ago
Status: NEW → RESOLVED
Last Resolved: 5 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.