Bug 955942 (part 2) - Remove MemoryUniReporter. r=mccr8.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sat, 07 Dec 2013 22:09:10 -0800
changeset 162011 f33d8dee54dae96575dcddedc85328ba80de6f0d
parent 162010 9de53a0258931b7382c8edc9fa3ec193e884d9cd
child 162012 0208d8f09898e4824355c6a8845b3a9fbf8b18e7
push id38058
push usernnethercote@mozilla.com
push dateFri, 03 Jan 2014 02:10:38 +0000
treeherdermozilla-inbound@0208d8f09898 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmccr8
bugs955942
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 955942 (part 2) - Remove MemoryUniReporter. r=mccr8.
content/base/src/nsContentUtils.cpp
content/base/src/nsHostObjectProtocolHandler.cpp
content/canvas/src/CanvasRenderingContext2D.cpp
dom/base/nsScriptNameSpaceManager.cpp
dom/base/nsScriptNameSpaceManager.h
dom/base/nsWindowMemoryReporter.cpp
dom/base/nsWindowMemoryReporter.h
extensions/spellcheck/hunspell/src/mozHunspell.cpp
extensions/spellcheck/hunspell/src/mozHunspell.h
gfx/gl/GfxTexturesReporter.cpp
gfx/gl/GfxTexturesReporter.h
gfx/layers/ipc/ISurfaceAllocator.cpp
gfx/layers/ipc/ISurfaceAllocator.h
gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
gfx/thebes/gfxAndroidPlatform.cpp
gfx/thebes/gfxWindowsPlatform.cpp
image/src/SurfaceCache.cpp
ipc/glue/SharedMemory.cpp
js/xpconnect/src/XPCJSRuntime.cpp
layout/base/nsStyleSheetService.cpp
layout/base/nsStyleSheetService.h
layout/style/nsLayoutStylesheetCache.cpp
layout/style/nsLayoutStylesheetCache.h
netwerk/cookie/nsCookieService.cpp
netwerk/cookie/nsCookieService.h
netwerk/dns/nsDNSService2.cpp
netwerk/dns/nsDNSService2.h
netwerk/dns/nsEffectiveTLDService.cpp
netwerk/dns/nsEffectiveTLDService.h
toolkit/components/places/History.cpp
toolkit/components/places/History.h
toolkit/components/telemetry/Telemetry.cpp
xpcom/base/AvailableMemoryTracker.cpp
xpcom/base/nsIMemoryReporter.idl
xpcom/base/nsMemoryReporterManager.cpp
xpcom/build/nsXPComInit.cpp
xpcom/components/nsCategoryManager.cpp
xpcom/components/nsCategoryManager.h
xpcom/components/nsComponentManager.cpp
xpcom/components/nsComponentManager.h
xpcom/reflect/xptinfo/public/XPTInterfaceInfoManager.h
xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -253,39 +253,42 @@ bool nsContentUtils::sDOMWindowDumpEnabl
 
 namespace {
 
 static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
 static PLDHashTable sEventListenerManagersHash;
 
-class DOMEventListenerManagersHashReporter MOZ_FINAL : public MemoryUniReporter
-{
+class DOMEventListenerManagersHashReporter MOZ_FINAL : public nsIMemoryReporter
+{
+  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
+
 public:
-  DOMEventListenerManagersHashReporter()
-    : MemoryUniReporter(
-        "explicit/dom/event-listener-managers-hash",
-        KIND_HEAP,
-        UNITS_BYTES,
-        "Memory used by the event listener manager's hash table.")
-  {}
-
-private:
-  int64_t Amount()
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
   {
     // We don't measure the |nsEventListenerManager| objects pointed to by the
     // entries because those references are non-owning.
-    return sEventListenerManagersHash.ops
-         ? PL_DHashTableSizeOfExcludingThis(&sEventListenerManagersHash,
-                                            nullptr, MallocSizeOf)
-         : 0;
+    int64_t amount = sEventListenerManagersHash.ops
+                   ? PL_DHashTableSizeOfExcludingThis(
+                       &sEventListenerManagersHash, nullptr, MallocSizeOf)
+                   : 0;
+
+    return MOZ_COLLECT_REPORT(
+      "explicit/dom/event-listener-managers-hash", KIND_HEAP, UNITS_BYTES,
+      amount,
+      "Memory used by the event listener manager's hash table.");
   }
 };
 
+NS_IMPL_ISUPPORTS1(DOMEventListenerManagersHashReporter, nsIMemoryReporter)
+
 class EventListenerManagerMapEntry : public PLDHashEntryHdr
 {
 public:
   EventListenerManagerMapEntry(const void *aKey)
     : mKey(aKey)
   {
   }
 
--- a/content/base/src/nsHostObjectProtocolHandler.cpp
+++ b/content/base/src/nsHostObjectProtocolHandler.cpp
@@ -24,32 +24,34 @@ struct DataInfo
   nsCOMPtr<nsIPrincipal> mPrincipal;
 };
 
 static nsClassHashtable<nsCStringHashKey, DataInfo>* gDataTable;
 
 // Memory reporting for the hash table.
 namespace mozilla {
 
-class HostObjectURLsReporter MOZ_FINAL : public MemoryUniReporter
+class HostObjectURLsReporter MOZ_FINAL : public nsIMemoryReporter
 {
  public:
-  HostObjectURLsReporter()
-    : MemoryUniReporter("host-object-urls",
-                        KIND_OTHER, UNITS_COUNT,
-                        "The number of host objects stored for access via URLs "
-                        "(e.g. blobs passed to URL.createObjectURL).")
-    {}
- private:
-  int64_t Amount() MOZ_OVERRIDE
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
   {
-    return gDataTable ? gDataTable->Count() : 0;
+    return MOZ_COLLECT_REPORT(
+      "host-object-urls", KIND_OTHER, UNITS_COUNT,
+      gDataTable ? gDataTable->Count() : 0,
+      "The number of host objects stored for access via URLs "
+      "(e.g. blobs passed to URL.createObjectURL).");
   }
 };
 
+NS_IMPL_ISUPPORTS1(HostObjectURLsReporter, nsIMemoryReporter)
+
 }
 
 nsHostObjectProtocolHandler::nsHostObjectProtocolHandler()
 {
   static bool initialized = false;
 
   if (!initialized) {
     initialized = true;
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -131,27 +131,34 @@ namespace dom {
 const Float SIGMA_MAX = 100;
 
 /* Memory reporter stuff */
 static int64_t gCanvasAzureMemoryUsed = 0;
 
 // 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
 // underlying surface implementations.  See bug 655638 for details.
-class Canvas2dPixelsReporter MOZ_FINAL : public MemoryUniReporter
+class Canvas2dPixelsReporter MOZ_FINAL : public nsIMemoryReporter
 {
-  public:
-    Canvas2dPixelsReporter()
-      : MemoryUniReporter("canvas-2d-pixels", KIND_OTHER, UNITS_BYTES,
-"Memory used by 2D canvases. Each canvas requires (width * height * 4) bytes.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE { return gCanvasAzureMemoryUsed; }
+public:
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
+  {
+    return MOZ_COLLECT_REPORT(
+      "canvas-2d-pixels", KIND_OTHER, UNITS_BYTES,
+      gCanvasAzureMemoryUsed,
+      "Memory used by 2D canvases. Each canvas requires "
+      "(width * height * 4) bytes.");
+  }
 };
 
+NS_IMPL_ISUPPORTS1(Canvas2dPixelsReporter, nsIMemoryReporter)
+
 class CanvasRadialGradient : public CanvasGradient
 {
 public:
   CanvasRadialGradient(CanvasRenderingContext2D* aContext,
                        const Point &aBeginOrigin, Float aBeginRadius,
                        const Point &aEndOrigin, Float aEndRadius)
     : CanvasGradient(aContext, RADIAL)
     , mCenter1(aBeginOrigin)
--- a/dom/base/nsScriptNameSpaceManager.cpp
+++ b/dom/base/nsScriptNameSpaceManager.cpp
@@ -111,27 +111,24 @@ GlobalNameHashInitEntry(PLDHashTable *ta
   new (&e->mKey) nsString(*keyStr);
 
   // This will set e->mGlobalName.mType to
   // nsGlobalNameStruct::eTypeNotInitialized
   memset(&e->mGlobalName, 0, sizeof(nsGlobalNameStruct));
   return true;
 }
 
-NS_IMPL_ISUPPORTS_INHERITED2(
+NS_IMPL_ISUPPORTS3(
   nsScriptNameSpaceManager,
-  MemoryUniReporter,
   nsIObserver,
-  nsISupportsWeakReference)
+  nsISupportsWeakReference,
+  nsIMemoryReporter)
 
 nsScriptNameSpaceManager::nsScriptNameSpaceManager()
-  : MemoryUniReporter("explicit/script-namespace-manager",
-                      KIND_HEAP, UNITS_BYTES,
-                      "Memory used for the script namespace manager.")
-  , mIsInitialized(false)
+  : mIsInitialized(false)
 {
   MOZ_COUNT_CTOR(nsScriptNameSpaceManager);
 }
 
 nsScriptNameSpaceManager::~nsScriptNameSpaceManager()
 {
   if (mIsInitialized) {
     UnregisterWeakMemoryReporter(this);
@@ -858,24 +855,30 @@ nsScriptNameSpaceManager::EnumerateNavig
   NameClosure closure = { aEnumerator, aClosure };
   PL_DHashTableEnumerate(&mNavigatorNames, EnumerateName, &closure);
 }
 
 static size_t
 SizeOfEntryExcludingThis(PLDHashEntryHdr *aHdr, MallocSizeOf aMallocSizeOf,
                          void *aArg)
 {
-    GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
-    return entry->SizeOfExcludingThis(aMallocSizeOf);
+  GlobalNameMapEntry* entry = static_cast<GlobalNameMapEntry*>(aHdr);
+  return entry->SizeOfExcludingThis(aMallocSizeOf);
 }
 
-int64_t
-nsScriptNameSpaceManager::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(ScriptNameSpaceManagerMallocSizeOf)
+
+NS_IMETHODIMP
+nsScriptNameSpaceManager::CollectReports(
+  nsIHandleReportCallback* aHandleReport, nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/script-namespace-manager", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(ScriptNameSpaceManagerMallocSizeOf),
+    "Memory used for the script namespace manager.");
 }
 
 size_t
 nsScriptNameSpaceManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   size_t n = 0;
   n += PL_DHashTableSizeOfExcludingThis(&mGlobalNames,
          SizeOfEntryExcludingThis, aMallocSizeOf);
--- a/dom/base/nsScriptNameSpaceManager.h
+++ b/dom/base/nsScriptNameSpaceManager.h
@@ -83,23 +83,24 @@ struct nsGlobalNameStruct
 };
 
 
 class nsIScriptContext;
 class nsICategoryManager;
 class GlobalNameMapEntry;
 
 
-class nsScriptNameSpaceManager : public mozilla::MemoryUniReporter,
-                                 public nsIObserver,
-                                 public nsSupportsWeakReference
+class nsScriptNameSpaceManager : public nsIObserver,
+                                 public nsSupportsWeakReference,
+                                 public nsIMemoryReporter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
+  NS_DECL_NSIMEMORYREPORTER
 
   nsScriptNameSpaceManager();
   virtual ~nsScriptNameSpaceManager();
 
   nsresult Init();
   nsresult InitForContext(nsIScriptContext *aContext);
 
   // Returns a nsGlobalNameStruct for aName, or null if one is not
@@ -158,17 +159,16 @@ public:
   typedef PLDHashOperator
   (* NameEnumerator)(const nsAString& aGlobalName, void* aClosure);
 
   void EnumerateGlobalNames(NameEnumerator aEnumerator,
                             void* aClosure);
   void EnumerateNavigatorNames(NameEnumerator aEnumerator,
                                void* aClosure);
 
-  int64_t Amount() MOZ_OVERRIDE;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
 private:
   // Adds a new entry to the hash and returns the nsGlobalNameStruct
   // that aKey will be mapped to. If mType in the returned
   // nsGlobalNameStruct is != eTypeNotInitialized, an entry for aKey
   // already existed.
   nsGlobalNameStruct *AddToHash(PLDHashTable *aTable, const nsAString *aKey,
--- a/dom/base/nsWindowMemoryReporter.cpp
+++ b/dom/base/nsWindowMemoryReporter.cpp
@@ -795,16 +795,19 @@ nsWindowMemoryReporter::CheckForGhostWin
   // if it's not null.
   CheckForGhostWindowsEnumeratorData ghostEnumData =
     { &nonDetachedWindowDomains, aOutGhostIDs, tldService,
       GetGhostTimeout(), TimeStamp::Now() };
   mDetachedWindows.Enumerate(CheckForGhostWindowsEnumerator,
                              &ghostEnumData);
 }
 
+NS_IMPL_ISUPPORTS1(nsWindowMemoryReporter::GhostWindowsReporter,
+                   nsIMemoryReporter)
+
 /* static */ int64_t
 nsWindowMemoryReporter::GhostWindowsReporter::DistinguishedAmount()
 {
   nsTHashtable<nsUint64HashKey> ghostWindows;
   sWindowReporter->CheckForGhostWindows(&ghostWindows);
   return ghostWindows.Count();
 }
 
--- a/dom/base/nsWindowMemoryReporter.h
+++ b/dom/base/nsWindowMemoryReporter.h
@@ -146,35 +146,37 @@ public:
 
   static void Init();
 
 private:
   /**
    * nsGhostWindowReporter generates the "ghost-windows" report, which counts
    * the number of ghost windows present.
    */
-  class GhostWindowsReporter MOZ_FINAL : public mozilla::MemoryUniReporter
+  class GhostWindowsReporter MOZ_FINAL : public nsIMemoryReporter
   {
   public:
-    GhostWindowsReporter()
-      : MemoryUniReporter("ghost-windows", KIND_OTHER, UNITS_COUNT,
+    NS_DECL_ISUPPORTS
+
+    static int64_t DistinguishedAmount();
+
+    NS_IMETHOD
+    CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
+    {
+      return MOZ_COLLECT_REPORT(
+        "ghost-windows", KIND_OTHER, UNITS_COUNT, DistinguishedAmount(),
 "The number of ghost windows present (the number of nodes underneath "
 "explicit/window-objects/top(none)/ghost, modulo race conditions).  A ghost "
 "window is not shown in any tab, does not share a domain with any non-detached "
 "windows, and has met these criteria for at least "
 "memory.ghost_window_timeout_seconds, or has survived a round of "
 "about:memory's minimize memory usage button.\n\n"
 "Ghost windows can happen legitimately, but they are often indicative of "
-"leaks in the browser or add-ons.")
-    {}
-
-    static int64_t DistinguishedAmount();
-
-  private:
-    int64_t Amount() MOZ_OVERRIDE { return DistinguishedAmount(); }
+"leaks in the browser or add-ons.");
+    }
   };
 
   // Protect ctor, use Init() instead.
   nsWindowMemoryReporter();
 
   /**
    * Get the number of seconds for which a window must satisfy ghost criteria
    * (1) and (2) before we deem that it satisfies criterion (3).
--- a/extensions/spellcheck/hunspell/src/mozHunspell.cpp
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.cpp
@@ -78,20 +78,20 @@
 #include "nsIPrefBranch.h"
 
 static NS_DEFINE_CID(kUnicharUtilCID, NS_UNICHARUTIL_CID);
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(mozHunspell)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(mozHunspell)
 
 NS_INTERFACE_MAP_BEGIN(mozHunspell)
-  NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
   NS_INTERFACE_MAP_ENTRY(mozISpellCheckingEngine)
   NS_INTERFACE_MAP_ENTRY(nsIObserver)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY(nsIMemoryReporter)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozISpellCheckingEngine)
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(mozHunspell)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
                            mPersonalDictionary,
                            mEncoder,
                            mDecoder)
@@ -102,19 +102,17 @@ int64_t mozHunspell::sAmount = 0;
 void HunspellReportMemoryAllocation(void* ptr) {
   mozHunspell::OnAlloc(ptr);
 }
 void HunspellReportMemoryDeallocation(void* ptr) {
   mozHunspell::OnFree(ptr);
 }
 
 mozHunspell::mozHunspell()
-  : MemoryUniReporter("explicit/spell-check", KIND_HEAP, UNITS_BYTES,
-"Memory used by the spell-checking engine's internal data structures."),
-    mHunspell(nullptr)
+  : mHunspell(nullptr)
 {
 #ifdef DEBUG
   // There must be only one instance of this class, due to |sAmount|
   // being static.
   static bool hasRun = false;
   MOZ_ASSERT(!hasRun);
   hasRun = true;
 #endif
@@ -126,24 +124,24 @@ mozHunspell::Init()
   LoadDictionaryList();
 
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (obs) {
     obs->AddObserver(this, "profile-do-change", true);
     obs->AddObserver(this, "profile-after-change", true);
   }
 
-  RegisterWeakMemoryReporter(this);
+  mozilla::RegisterWeakMemoryReporter(this);
 
   return NS_OK;
 }
 
 mozHunspell::~mozHunspell()
 {
-  UnregisterWeakMemoryReporter(this);
+  mozilla::UnregisterWeakMemoryReporter(this);
 
   mPersonalDictionary = nullptr;
   delete mHunspell;
 }
 
 /* attribute wstring dictionary; */
 NS_IMETHODIMP mozHunspell::GetDictionary(PRUnichar **aDictionary)
 {
--- a/extensions/spellcheck/hunspell/src/mozHunspell.h
+++ b/extensions/spellcheck/hunspell/src/mozHunspell.h
@@ -75,20 +75,20 @@
 #include "nsCycleCollectionParticipant.h"
 
 #define MOZ_HUNSPELL_CONTRACTID "@mozilla.org/spellchecker/engine;1"
 #define MOZ_HUNSPELL_CID         \
 /* 56c778e4-1bee-45f3-a689-886692a97fe7 */   \
 { 0x56c778e4, 0x1bee, 0x45f3, \
   { 0xa6, 0x89, 0x88, 0x66, 0x92, 0xa9, 0x7f, 0xe7 } }
 
-class mozHunspell : public mozilla::MemoryUniReporter,
-                    public mozISpellCheckingEngine,
+class mozHunspell : public mozISpellCheckingEngine,
                     public nsIObserver,
-                    public nsSupportsWeakReference
+                    public nsSupportsWeakReference,
+                    public nsIMemoryReporter
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_MOZISPELLCHECKINGENGINE
   NS_DECL_NSIOBSERVER
   NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(mozHunspell, mozISpellCheckingEngine)
 
   mozHunspell();
@@ -96,20 +96,29 @@ public:
 
   nsresult Init();
 
   void LoadDictionaryList();
 
   // helper method for converting a word to the charset of the dictionary
   nsresult ConvertCharset(const PRUnichar* aStr, char ** aDst);
 
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
+
   static void OnAlloc(void* ptr) { sAmount += MallocSizeOfOnAlloc(ptr); }
   static void OnFree (void* ptr) { sAmount -= MallocSizeOfOnFree (ptr); }
 
-  int64_t Amount() MOZ_OVERRIDE { return sAmount; }
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
+  {
+    return MOZ_COLLECT_REPORT(
+      "explicit/spell-check", KIND_HEAP, UNITS_BYTES, sAmount,
+      "Memory used by the spell-checking engine.");
+  }
 
 protected:
 
   nsCOMPtr<mozIPersonalDictionary> mPersonalDictionary;
   nsCOMPtr<nsIUnicodeEncoder>      mEncoder;
   nsCOMPtr<nsIUnicodeDecoder>      mDecoder;
 
   // Hashtable matches dictionary name to .aff file
--- a/gfx/gl/GfxTexturesReporter.cpp
+++ b/gfx/gl/GfxTexturesReporter.cpp
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GfxTexturesReporter.h"
 #include "GLDefs.h"
 
 using namespace mozilla;
 using namespace mozilla::gl;
 
+NS_IMPL_ISUPPORTS1(GfxTexturesReporter, nsIMemoryReporter)
+
 int64_t GfxTexturesReporter::sAmount = 0;
 
 static uint32_t GetBitsPerTexel(GLenum format, GLenum type)
 {
     // If there is no defined format or type, we're not taking up any memory
     if (!format || !type) {
         return 0;
     }
--- a/gfx/gl/GfxTexturesReporter.h
+++ b/gfx/gl/GfxTexturesReporter.h
@@ -8,22 +8,22 @@
 #define GFXTEXTURESREPORTER_H_
 
 #include "nsIMemoryReporter.h"
 #include "GLTypes.h"
 
 namespace mozilla {
 namespace gl {
 
-class GfxTexturesReporter MOZ_FINAL : public MemoryUniReporter
+class GfxTexturesReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
+    NS_DECL_ISUPPORTS
+
     GfxTexturesReporter()
-      : MemoryUniReporter("gfx-textures", KIND_OTHER, UNITS_BYTES,
-                          "Memory used for storing GL textures.")
     {
 #ifdef DEBUG
         // There must be only one instance of this class, due to |sAmount|
         // being static.  Assert this.
         static bool hasRun = false;
         MOZ_ASSERT(!hasRun);
         hasRun = true;
 #endif
@@ -36,18 +36,24 @@ public:
         MemoryFreed
     };
 
     // When memory is used/freed for tile textures, call this method to update
     // the value reported by this memory reporter.
     static void UpdateAmount(MemoryUse action, GLenum format, GLenum type,
                              uint16_t tileSize);
 
+    NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                              nsISupports* aData)
+    {
+        return MOZ_COLLECT_REPORT(
+            "gfx-textures", KIND_OTHER, UNITS_BYTES, sAmount,
+            "Memory used for storing GL textures.");
+    }
+
 private:
-    int64_t Amount() MOZ_OVERRIDE { return sAmount; }
-
     static int64_t sAmount;
 };
 
 }
 }
 
 #endif // GFXTEXTURESREPORTER_H_
--- a/gfx/layers/ipc/ISurfaceAllocator.cpp
+++ b/gfx/layers/ipc/ISurfaceAllocator.cpp
@@ -23,16 +23,18 @@
 #include "prenv.h"
 #endif
 
 using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace layers {
 
+NS_IMPL_ISUPPORTS1(GfxMemoryImageReporter, nsIMemoryReporter)
+
 mozilla::Atomic<int32_t> GfxMemoryImageReporter::sAmount(0);
 
 mozilla::ipc::SharedMemory::SharedMemoryType OptimalShmemType()
 {
   return mozilla::ipc::SharedMemory::TYPE_BASIC;
 }
 
 bool
--- a/gfx/layers/ipc/ISurfaceAllocator.h
+++ b/gfx/layers/ipc/ISurfaceAllocator.h
@@ -7,17 +7,17 @@
 #define GFX_LAYERS_ISURFACEDEALLOCATOR
 
 #include <stddef.h>                     // for size_t
 #include <stdint.h>                     // for uint32_t
 #include "gfxTypes.h"
 #include "mozilla/gfx/Point.h"          // for IntSize
 #include "mozilla/ipc/SharedMemory.h"   // for SharedMemory, etc
 #include "mozilla/RefPtr.h"
-#include "nsIMemoryReporter.h"          // for MemoryUniReporter
+#include "nsIMemoryReporter.h"          // for nsIMemoryReporter
 #include "mozilla/Atomics.h"            // for Atomic
 
 /*
  * FIXME [bjacob] *** PURE CRAZYNESS WARNING ***
  *
  * This #define is actually needed here, because subclasses of ISurfaceAllocator,
  * namely ShadowLayerForwarder, will or will not override AllocGrallocBuffer
  * depending on whether MOZ_HAVE_SURFACEDESCRIPTORGRALLOC is defined.
@@ -140,44 +140,53 @@ protected:
                                               SurfaceDescriptor* aBuffer);
 
 
   virtual ~ISurfaceAllocator() {}
 
   friend class detail::RefCounted<ISurfaceAllocator, detail::AtomicRefCount>;
 };
 
-class GfxMemoryImageReporter MOZ_FINAL : public mozilla::MemoryUniReporter
+class GfxMemoryImageReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
+  NS_DECL_ISUPPORTS
+
   GfxMemoryImageReporter()
-    : MemoryUniReporter("explicit/gfx/heap-textures", KIND_HEAP, UNITS_BYTES,
-                        "Heap memory shared between threads by texture clients and hosts.")
   {
 #ifdef DEBUG
     // There must be only one instance of this class, due to |sAmount|
     // being static.
     static bool hasRun = false;
     MOZ_ASSERT(!hasRun);
     hasRun = true;
 #endif
   }
 
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
+
   static void DidAlloc(void* aPointer)
   {
     sAmount += MallocSizeOfOnAlloc(aPointer);
   }
 
   static void WillFree(void* aPointer)
   {
     sAmount -= MallocSizeOfOnFree(aPointer);
   }
 
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
+  {
+    return MOZ_COLLECT_REPORT(
+      "explicit/gfx/heap-textures", KIND_HEAP, UNITS_BYTES, sAmount,
+      "Heap memory shared between threads by texture clients and hosts.");
+  }
+
 private:
-  int64_t Amount() MOZ_OVERRIDE { return sAmount; }
-
   static mozilla::Atomic<int32_t> sAmount;
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -184,44 +184,52 @@ PixelFormatForContentType(gfxContentType
 }
 
 static gfxContentType
 ContentTypeFromPixelFormat(android::PixelFormat aFormat)
 {
   return gfxASurface::ContentFromFormat(ImageFormatForPixelFormat(aFormat));
 }
 
-class GrallocReporter MOZ_FINAL : public MemoryUniReporter
+class GrallocReporter MOZ_FINAL : public nsIMemoryReporter
 {
   friend class GrallocBufferActor;
 
 public:
+  NS_DECL_ISUPPORTS
+
   GrallocReporter()
-    : MemoryUniReporter("gralloc", KIND_OTHER, UNITS_BYTES,
-"Special RAM that can be shared between processes and directly accessed by "
-"both the CPU and GPU.  Gralloc memory is usually a relatively precious "
-"resource, with much less available than generic RAM.  When it's exhausted, "
-"graphics performance can suffer. This value can be incorrect because of race "
-"conditions.")
   {
 #ifdef DEBUG
     // There must be only one instance of this class, due to |sAmount|
     // being static.  Assert this.
     static bool hasRun = false;
     MOZ_ASSERT(!hasRun);
     hasRun = true;
 #endif
   }
 
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
+  {
+    return MOZ_COLLECT_REPORT(
+      "gralloc", KIND_OTHER, UNITS_BYTES, sAmount,
+"Special RAM that can be shared between processes and directly accessed by "
+"both the CPU and GPU. Gralloc memory is usually a relatively precious "
+"resource, with much less available than generic RAM. When it's exhausted, "
+"graphics performance can suffer. This value can be incorrect because of race "
+"conditions.");
+  }
+
 private:
-  int64_t Amount() MOZ_OVERRIDE { return sAmount; }
-
   static int64_t sAmount;
 };
 
+NS_IMPL_ISUPPORTS1(GrallocReporter, nsIMemoryReporter)
+
 int64_t GrallocReporter::sAmount = 0;
 
 GrallocBufferActor::GrallocBufferActor()
 : mAllocBytes(0)
 {
   static bool registered;
   if (!registered) {
     // We want to be sure that the first call here will always run on
--- a/gfx/thebes/gfxAndroidPlatform.cpp
+++ b/gfx/thebes/gfxAndroidPlatform.cpp
@@ -26,32 +26,35 @@
 #include FT_MODULE_H
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::gfx;
 
 static FT_Library gPlatformFTLibrary = nullptr;
 
-class FreetypeReporter MOZ_FINAL : public MemoryUniReporter
+class FreetypeReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
+    NS_DECL_ISUPPORTS
+
     FreetypeReporter()
-      : MemoryUniReporter("explicit/freetype", KIND_HEAP, UNITS_BYTES,
-                          "Memory used by Freetype.")
     {
 #ifdef DEBUG
         // There must be only one instance of this class, due to |sAmount|
         // being static.
         static bool hasRun = false;
         MOZ_ASSERT(!hasRun);
         hasRun = true;
 #endif
     }
 
+    MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
+    MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
+
     static void* CountingAlloc(FT_Memory, long size)
     {
         void *p = malloc(size);
         sAmount += MallocSizeOfOnAlloc(p);
         return p;
     }
 
     static void CountingFree(FT_Memory, void* p)
@@ -69,22 +72,30 @@ public:
             sAmount += MallocSizeOfOnAlloc(pnew);
         } else {
             // realloc failed;  undo the decrement from above
             sAmount += MallocSizeOfOnAlloc(p);
         }
         return pnew;
     }
 
+    NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                              nsISupports* aData)
+    {
+        return MOZ_COLLECT_REPORT(
+            "explicit/freetype", KIND_HEAP, UNITS_BYTES, sAmount,
+            "Memory used by Freetype.");
+    }
+
 private:
-    int64_t Amount() MOZ_OVERRIDE { return sAmount; }
-
     static int64_t sAmount;
 };
 
+NS_IMPL_ISUPPORTS1(FreetypeReporter, nsIMemoryReporter)
+
 int64_t FreetypeReporter::sAmount = 0;
 
 static FT_MemoryRec_ sFreetypeMemoryRecord;
 
 gfxAndroidPlatform::gfxAndroidPlatform()
 {
     // A custom allocator.  It counts allocations, enabling memory reporting.
     sFreetypeMemoryRecord.user    = nullptr;
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -72,30 +72,46 @@ using namespace mozilla::widget;
 #ifdef CAIRO_HAS_D2D_SURFACE
 
 static const char *kFeatureLevelPref =
   "gfx.direct3d.last_used_feature_level_idx";
 static const int kSupportedFeatureLevels[] =
   { D3D10_FEATURE_LEVEL_10_1, D3D10_FEATURE_LEVEL_10_0,
     D3D10_FEATURE_LEVEL_9_3 };
 
-class GfxD2DSurfaceCacheReporter MOZ_FINAL : public MemoryUniReporter
+class GfxD2DSurfaceReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    GfxD2DSurfaceCacheReporter()
-      : MemoryUniReporter("gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES,
-"Memory used by the Direct2D internal surface cache.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
+    NS_DECL_ISUPPORTS
+
+    NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                              nsISupports* aData)
     {
-        return cairo_d2d_get_image_surface_cache_usage();
+        nsresult rv;
+
+        int64_t amount = cairo_d2d_get_image_surface_cache_usage();
+        rv = MOZ_COLLECT_REPORT(
+            "gfx-d2d-surface-cache", KIND_OTHER, UNITS_BYTES, amount,
+            "Memory used by the Direct2D internal surface cache.");
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        cairo_device_t *device =
+            gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
+        amount = device ? cairo_d2d_get_surface_vram_usage(device) : 0;
+        rv = MOZ_COLLECT_REPORT(
+            "gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES, amount,
+            "Video memory used by D2D surfaces.");
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        return NS_OK;
     }
 };
 
+NS_IMPL_ISUPPORTS1(GfxD2DSurfaceReporter, nsIMemoryReporter)
+
 namespace
 {
 
 bool OncePreferenceDirect2DDisabled()
 {
   static int preferenceValue = -1;
   if (preferenceValue < 0) {
     preferenceValue = Preferences::GetBool("gfx.direct2d.disabled", false);
@@ -109,61 +125,45 @@ bool OncePreferenceDirect2DForceEnabled(
   if (preferenceValue < 0) {
     preferenceValue = Preferences::GetBool("gfx.direct2d.force-enabled", false);
   }
   return !!preferenceValue;
 }
 
 } // anonymous namespace
 
-class GfxD2DSurfaceVramReporter MOZ_FINAL : public MemoryUniReporter
+#endif
+
+class GfxD2DVramReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    GfxD2DSurfaceVramReporter()
-      : MemoryUniReporter("gfx-d2d-surface-vram", KIND_OTHER, UNITS_BYTES,
-                           "Video memory used by D2D surfaces.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE {
-      cairo_device_t *device =
-          gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
-      return device ? cairo_d2d_get_surface_vram_usage(device) : 0;
+    NS_DECL_ISUPPORTS
+
+    NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                              nsISupports* aData)
+    {
+        nsresult rv;
+
+        rv = MOZ_COLLECT_REPORT(
+            "gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES,
+            Factory::GetD2DVRAMUsageDrawTarget(),
+            "Video memory used by D2D DrawTargets.");
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        rv = MOZ_COLLECT_REPORT(
+            "gfx-d2d-vram-source-surface", KIND_OTHER, UNITS_BYTES,
+            Factory::GetD2DVRAMUsageSourceSurface(),
+            "Video memory used by D2D SourceSurfaces.");
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        return NS_OK;
     }
 };
 
-#endif
-
-class GfxD2DVramDrawTargetReporter MOZ_FINAL : public MemoryUniReporter
-{
-public:
-    GfxD2DVramDrawTargetReporter()
-      : MemoryUniReporter("gfx-d2d-vram-draw-target", KIND_OTHER, UNITS_BYTES,
-                           "Video memory used by D2D DrawTargets.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
-    {
-        return Factory::GetD2DVRAMUsageDrawTarget();
-    }
-};
-
-class GfxD2DVramSourceSurfaceReporter MOZ_FINAL : public MemoryUniReporter
-{
-public:
-    GfxD2DVramSourceSurfaceReporter()
-      : MemoryUniReporter("gfx-d2d-vram-source-surface",
-                           KIND_OTHER, UNITS_BYTES,
-                           "Video memory used by D2D SourceSurfaces.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
-    {
-        return Factory::GetD2DVRAMUsageSourceSurface();
-    }
-};
+NS_IMPL_ISUPPORTS1(GfxD2DVramReporter, nsIMemoryReporter)
 
 #define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
 #define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
 
 #define GFX_CLEARTYPE_PARAMS           "gfx.font_rendering.cleartype_params."
 #define GFX_CLEARTYPE_PARAMS_GAMMA     "gfx.font_rendering.cleartype_params.gamma"
 #define GFX_CLEARTYPE_PARAMS_CONTRAST  "gfx.font_rendering.cleartype_params.enhanced_contrast"
 #define GFX_CLEARTYPE_PARAMS_LEVEL     "gfx.font_rendering.cleartype_params.cleartype_level"
@@ -359,22 +359,20 @@ gfxWindowsPlatform::gfxWindowsPlatform()
     mUsingGDIFonts = false;
 
     /* 
      * Initialize COM 
      */ 
     CoInitialize(nullptr); 
 
 #ifdef CAIRO_HAS_D2D_SURFACE
-    RegisterStrongMemoryReporter(new GfxD2DSurfaceCacheReporter());
-    RegisterStrongMemoryReporter(new GfxD2DSurfaceVramReporter());
+    RegisterStrongMemoryReporter(new GfxD2DSurfaceReporter());
     mD2DDevice = nullptr;
 #endif
-    RegisterStrongMemoryReporter(new GfxD2DVramDrawTargetReporter());
-    RegisterStrongMemoryReporter(new GfxD2DVramSourceSurfaceReporter());
+    RegisterStrongMemoryReporter(new GfxD2DVramReporter());
 
     UpdateRenderMode();
 
     // This reporter is disabled because it frequently gives bogus values.  See
     // bug 917496.
     //RegisterStrongMemoryReporter(new GPUAdapterReporter());
 }
 
--- a/image/src/SurfaceCache.cpp
+++ b/image/src/SurfaceCache.cpp
@@ -192,27 +192,24 @@ private:
 
 /*
  * SurfaceCacheImpl is responsible for determining which surfaces will be cached
  * and managing the surface cache data structures. Rather than interact with
  * SurfaceCacheImpl directly, client code interacts with SurfaceCache, which
  * maintains high-level invariants and encapsulates the details of the surface
  * cache's implementation.
  */
-class SurfaceCacheImpl : public MemoryUniReporter
+class SurfaceCacheImpl : public nsIMemoryReporter
 {
 public:
   NS_DECL_ISUPPORTS
 
   SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
                    uint32_t aSurfaceCacheSize)
-    : MemoryUniReporter("imagelib-surface-cache",
-                        KIND_OTHER, UNITS_BYTES,
-                        "Memory used by the imagelib temporary surface cache.")
-    , mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
+    : mExpirationTracker(MOZ_THIS_IN_INITIALIZER_LIST(),
                          aSurfaceCacheExpirationTimeMS)
     , mMemoryPressureObserver(new MemoryPressureObserver)
     , mMaxCost(aSurfaceCacheSize)
     , mAvailableCost(aSurfaceCacheSize)
   {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os)
       os->AddObserver(mMemoryPressureObserver, "memory-pressure", false);
@@ -357,19 +354,23 @@ public:
   static PLDHashOperator DoStopTracking(const SurfaceKey&,
                                         CachedSurface*    aSurface,
                                         void*             aCache)
   {
     static_cast<SurfaceCacheImpl*>(aCache)->StopTracking(aSurface);
     return PL_DHASH_NEXT;
   }
 
-  int64_t Amount() MOZ_OVERRIDE
+  NS_IMETHOD
+  CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
   {
-    return SizeOfSurfacesEstimate();
+    return MOZ_COLLECT_REPORT(
+      "imagelib-surface-cache", KIND_OTHER, UNITS_BYTES,
+      SizeOfSurfacesEstimate(),
+      "Memory used by the imagelib temporary surface cache.");
   }
 
   // XXX(seth): This is currently only an estimate and, since we don't know
   // which surfaces are in GPU memory and which aren't, it's reported as
   // KIND_OTHER and will also show up in heap-unclassified. Bug 923302 will
   // make this nicer.
   Cost SizeOfSurfacesEstimate() const
   {
@@ -422,17 +423,17 @@ private:
   nsTArray<CostEntry>                                       mCosts;
   nsRefPtrHashtable<nsPtrHashKey<Image>, ImageSurfaceCache> mImageCaches;
   SurfaceTracker                                            mExpirationTracker;
   nsRefPtr<MemoryPressureObserver>                          mMemoryPressureObserver;
   const Cost                                                mMaxCost;
   Cost                                                      mAvailableCost;
 };
 
-NS_IMPL_ISUPPORTS_INHERITED0(SurfaceCacheImpl, MemoryUniReporter)
+NS_IMPL_ISUPPORTS1(SurfaceCacheImpl, nsIMemoryReporter)
 NS_IMPL_ISUPPORTS1(SurfaceCacheImpl::MemoryPressureObserver, nsIObserver)
 
 ///////////////////////////////////////////////////////////////////////////////
 // Public API
 ///////////////////////////////////////////////////////////////////////////////
 
 /* static */ void
 SurfaceCache::Initialize()
--- a/ipc/glue/SharedMemory.cpp
+++ b/ipc/glue/SharedMemory.cpp
@@ -12,47 +12,50 @@
 #include "mozilla/Atomics.h"
 
 namespace mozilla {
 namespace ipc {
 
 static Atomic<size_t> gShmemAllocated;
 static Atomic<size_t> gShmemMapped;
 
-class ShmemAllocatedReporter MOZ_FINAL : public MemoryUniReporter
+class ShmemReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-  ShmemAllocatedReporter()
-    : MemoryUniReporter("shmem-allocated", KIND_OTHER, UNITS_BYTES,
-"Memory shared with other processes that is accessible (but not necessarily "
-"mapped).")
-  {}
-private:
-  int64_t Amount() MOZ_OVERRIDE { return gShmemAllocated; }
+  NS_DECL_THREADSAFE_ISUPPORTS
+
+  NS_IMETHOD
+  CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
+  {
+    nsresult rv;
+    rv = MOZ_COLLECT_REPORT(
+      "shmem-allocated", KIND_OTHER, UNITS_BYTES, gShmemAllocated,
+      "Memory shared with other processes that is accessible (but not "
+      "necessarily mapped).");
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = MOZ_COLLECT_REPORT(
+      "shmem-mapped", KIND_OTHER, UNITS_BYTES, gShmemMapped,
+      "Memory shared with other processes that is mapped into the address "
+      "space.");
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return NS_OK;
+  }
 };
 
-class ShmemMappedReporter MOZ_FINAL : public MemoryUniReporter
-{
-public:
-  ShmemMappedReporter()
-    : MemoryUniReporter("shmem-mapped", KIND_OTHER, UNITS_BYTES,
-"Memory shared with other processes that is mapped into the address space.")
-  {}
-private:
-  int64_t Amount() MOZ_OVERRIDE { return gShmemMapped; }
-};
+NS_IMPL_ISUPPORTS1(ShmemReporter, nsIMemoryReporter)
 
 SharedMemory::SharedMemory()
   : mAllocSize(0)
   , mMappedSize(0)
 {
   static Atomic<uint32_t> registered;
   if (registered.compareExchange(0, 1)) {
-    RegisterStrongMemoryReporter(new ShmemAllocatedReporter());
-    RegisterStrongMemoryReporter(new ShmemMappedReporter());
+    RegisterStrongMemoryReporter(new ShmemReporter());
   }
 }
 
 /*static*/ size_t
 SharedMemory::PageAlignedSize(size_t aSize)
 {
   size_t pageSize = SystemPageSize();
   size_t nPagesNeeded = size_t(ceil(double(aSize) / double(pageSize)));
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1624,32 +1624,35 @@ JSMainRuntimeCompartmentsSystemDistingui
 
 static int64_t
 JSMainRuntimeCompartmentsUserDistinguishedAmount()
 {
     JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->Runtime();
     return JS::UserCompartmentCount(rt);
 }
 
-class JSMainRuntimeTemporaryPeakReporter MOZ_FINAL : public MemoryUniReporter
+class JSMainRuntimeTemporaryPeakReporter MOZ_FINAL : public nsIMemoryReporter
 {
-public:
-    JSMainRuntimeTemporaryPeakReporter()
-      : MemoryUniReporter("js-main-runtime-temporary-peak",
-                           KIND_OTHER, UNITS_BYTES,
-"The peak size of the transient storage in the main JSRuntime (the current "
-"size of which is reported as 'explicit/js-non-window/runtime/temporary').")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
+  public:
+    NS_DECL_ISUPPORTS
+
+    NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                              nsISupports* aData)
     {
-        return JSMainRuntimeTemporaryPeakDistinguishedAmount();
+        return MOZ_COLLECT_REPORT(
+            "js-main-runtime-temporary-peak", KIND_OTHER, UNITS_BYTES,
+            JSMainRuntimeTemporaryPeakDistinguishedAmount(),
+            "The peak size of the transient storage in the main JSRuntime "
+            "(the current size of which is reported as "
+            "'explicit/js-non-window/runtime/temporary').");
     }
 };
 
+NS_IMPL_ISUPPORTS1(JSMainRuntimeTemporaryPeakReporter, nsIMemoryReporter)
+
 // The REPORT* macros do an unconditional report.  The ZCREPORT* macros are for
 // compartments and zones; they aggregate any entries smaller than
 // SUNDRIES_THRESHOLD into the "sundries/gc-heap" and "sundries/malloc-heap"
 // entries for the compartment.
 
 #define SUNDRIES_THRESHOLD js::MemoryReportingSundriesThreshold()
 
 #define REPORT(_path, _kind, _units, _amount, _desc)                          \
--- a/layout/base/nsStyleSheetService.cpp
+++ b/layout/base/nsStyleSheetService.cpp
@@ -22,36 +22,33 @@
 #include "nsIObserverService.h"
 #include "nsLayoutStatics.h"
 
 using namespace mozilla;
 
 nsStyleSheetService *nsStyleSheetService::gInstance = nullptr;
 
 nsStyleSheetService::nsStyleSheetService()
-  : MemoryUniReporter("explicit/layout/style-sheet-service",
-                       KIND_HEAP, UNITS_BYTES,
-"Memory used for style sheets held by the style sheet service.")
 {
   PR_STATIC_ASSERT(0 == AGENT_SHEET && 1 == USER_SHEET && 2 == AUTHOR_SHEET);
   NS_ASSERTION(!gInstance, "Someone is using CreateInstance instead of GetService");
   gInstance = this;
   nsLayoutStatics::AddRef();
 }
 
 nsStyleSheetService::~nsStyleSheetService()
 {
   UnregisterWeakMemoryReporter(this);
 
   gInstance = nullptr;
   nsLayoutStatics::Release();
 }
 
-NS_IMPL_ISUPPORTS_INHERITED1(
-  nsStyleSheetService, MemoryUniReporter, nsIStyleSheetService)
+NS_IMPL_ISUPPORTS2(
+  nsStyleSheetService, nsIStyleSheetService, nsIMemoryReporter)
 
 void
 nsStyleSheetService::RegisterFromEnumerator(nsICategoryManager  *aManager,
                                             const char          *aCategory,
                                             nsISimpleEnumerator *aEnumerator,
                                             uint32_t             aSheetType)
 {
   if (!aEnumerator)
@@ -277,23 +274,29 @@ nsStyleSheetService::GetInstance()
 
   return gInstance;
 }
 
 static size_t
 SizeOfElementIncludingThis(nsIStyleSheet* aElement,
                            MallocSizeOf aMallocSizeOf, void *aData)
 {
-    return aElement->SizeOfIncludingThis(aMallocSizeOf);
+  return aElement->SizeOfIncludingThis(aMallocSizeOf);
 }
 
-int64_t
-nsStyleSheetService::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(StyleSheetServiceMallocSizeOf)
+
+NS_IMETHODIMP
+nsStyleSheetService::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                    nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/layout/style-sheet-service", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(StyleSheetServiceMallocSizeOf),
+    "Memory used for style sheets held by the style sheet service.");
 }
 
 size_t
 nsStyleSheetService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
   n += mSheets[AGENT_SHEET].SizeOfExcludingThis(SizeOfElementIncludingThis,
                                                 aMallocSizeOf);
--- a/layout/base/nsStyleSheetService.h
+++ b/layout/base/nsStyleSheetService.h
@@ -23,39 +23,38 @@ class nsIStyleSheet;
 
 #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 nsStyleSheetService MOZ_FINAL
-  : public mozilla::MemoryUniReporter
-  , public nsIStyleSheetService
+  : public nsIStyleSheetService
+  , public nsIMemoryReporter
 {
  public:
   nsStyleSheetService() NS_HIDDEN;
   ~nsStyleSheetService() NS_HIDDEN;
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSISTYLESHEETSERVICE
+  NS_DECL_NSIMEMORYREPORTER
 
   NS_HIDDEN_(nsresult) Init();
 
   nsCOMArray<nsIStyleSheet>* AgentStyleSheets() { return &mSheets[AGENT_SHEET]; }
   nsCOMArray<nsIStyleSheet>* UserStyleSheets() { return &mSheets[USER_SHEET]; }
   nsCOMArray<nsIStyleSheet>* AuthorStyleSheets() { return &mSheets[AUTHOR_SHEET]; }
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   static nsStyleSheetService *GetInstance();
   static nsStyleSheetService *gInstance;
 
-  int64_t Amount() MOZ_OVERRIDE;
-
  private:
 
   NS_HIDDEN_(void) RegisterFromEnumerator(nsICategoryManager  *aManager,
                                           const char          *aCategory,
                                           nsISimpleEnumerator *aEnumerator,
                                           uint32_t             aSheetType);
 
   NS_HIDDEN_(int32_t) FindSheetByURI(const nsCOMArray<nsIStyleSheet> &sheets,
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -11,18 +11,18 @@
 #include "mozilla/css/Loader.h"
 #include "nsIFile.h"
 #include "nsNetUtil.h"
 #include "nsIObserverService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIXULRuntime.h"
 #include "nsCSSStyleSheet.h"
 
-NS_IMPL_ISUPPORTS_INHERITED1(
-  nsLayoutStylesheetCache, MemoryUniReporter, nsIObserver)
+NS_IMPL_ISUPPORTS2(
+  nsLayoutStylesheetCache, nsIObserver, nsIMemoryReporter)
 
 nsresult
 nsLayoutStylesheetCache::Observe(nsISupports* aSubject,
                             const char* aTopic,
                             const PRUnichar* aData)
 {
   if (!strcmp(aTopic, "profile-before-change")) {
     mUserContentSheet = nullptr;
@@ -137,22 +137,29 @@ nsLayoutStylesheetCache::FullScreenOverr
 
 void
 nsLayoutStylesheetCache::Shutdown()
 {
   NS_IF_RELEASE(gCSSLoader);
   NS_IF_RELEASE(gStyleCache);
 }
 
-int64_t
-nsLayoutStylesheetCache::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(LayoutStylesheetCacheMallocSizeOf)
+
+NS_IMETHODIMP
+nsLayoutStylesheetCache::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                        nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/layout/style-sheet-cache", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(LayoutStylesheetCacheMallocSizeOf),
+    "Memory used for some built-in style sheets.");
 }
 
+
 size_t
 nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
   #define MEASURE(s) n += s ? s->SizeOfIncludingThis(aMallocSizeOf) : 0;
 
   MEASURE(mScrollbarsSheet);
@@ -166,19 +173,16 @@ nsLayoutStylesheetCache::SizeOfIncluding
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - gCSSLoader
 
   return n;
 }
 
 nsLayoutStylesheetCache::nsLayoutStylesheetCache()
-  : MemoryUniReporter("explicit/layout/style-sheet-cache",
-                      KIND_HEAP, UNITS_BYTES,
-                      "Memory used for some built-in style sheets.")
 {
   nsCOMPtr<nsIObserverService> obsSvc =
     mozilla::services::GetObserverService();
   NS_ASSERTION(obsSvc, "No global observer service?");
 
   if (obsSvc) {
     obsSvc->AddObserver(this, "profile-before-change", false);
     obsSvc->AddObserver(this, "profile-do-change", false);
@@ -207,24 +211,24 @@ nsLayoutStylesheetCache::nsLayoutStylesh
   if (uri) {
     LoadSheet(uri, mFullScreenOverrideSheet, true);
   }
   NS_ASSERTION(mFullScreenOverrideSheet, "Could not load full-screen-override.css");
 }
 
 nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
 {
-  UnregisterWeakMemoryReporter(this);
+  mozilla::UnregisterWeakMemoryReporter(this);
   gStyleCache = nullptr;
 }
 
 void
 nsLayoutStylesheetCache::InitMemoryReporter()
 {
-  RegisterWeakMemoryReporter(this);
+  mozilla::RegisterWeakMemoryReporter(this);
 }
 
 void
 nsLayoutStylesheetCache::EnsureGlobal()
 {
   if (gStyleCache) return;
 
   gStyleCache = new nsLayoutStylesheetCache();
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -19,33 +19,33 @@ class nsIURI;
 
 namespace mozilla {
 namespace css {
 class Loader;
 }
 }
 
 class nsLayoutStylesheetCache MOZ_FINAL
- : public mozilla::MemoryUniReporter
- , public nsIObserver
+ : public nsIObserver
+ , public nsIMemoryReporter
 {
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
+  NS_DECL_NSIMEMORYREPORTER
 
   static nsCSSStyleSheet* ScrollbarsSheet();
   static nsCSSStyleSheet* FormsSheet();
   static nsCSSStyleSheet* UserContentSheet();
   static nsCSSStyleSheet* UserChromeSheet();
   static nsCSSStyleSheet* UASheet();
   static nsCSSStyleSheet* QuirkSheet();
   static nsCSSStyleSheet* FullScreenOverrideSheet();
 
   static void Shutdown();
 
-  int64_t Amount() MOZ_OVERRIDE;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
   nsLayoutStylesheetCache();
   ~nsLayoutStylesheetCache();
 
   static void EnsureGlobal();
   void InitFromProfile();
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -712,27 +712,26 @@ nsCookieService::AppClearDataObserverIni
                                /* holdsWeak= */ false);
 }
 
 /******************************************************************************
  * nsCookieService impl:
  * public methods
  ******************************************************************************/
 
-NS_IMPL_ISUPPORTS_INHERITED5(nsCookieService, MemoryUniReporter,
-                             nsICookieService,
-                             nsICookieManager,
-                             nsICookieManager2,
-                             nsIObserver,
-                             nsISupportsWeakReference)
+NS_IMPL_ISUPPORTS6(nsCookieService,
+                   nsICookieService,
+                   nsICookieManager,
+                   nsICookieManager2,
+                   nsIObserver,
+                   nsISupportsWeakReference,
+                   nsIMemoryReporter)
 
 nsCookieService::nsCookieService()
- : MemoryUniReporter("explicit/cookie-service", KIND_HEAP, UNITS_BYTES,
-                     "Memory used by the cookie service.")
- , mDBState(nullptr)
+ : mDBState(nullptr)
  , mCookieBehavior(BEHAVIOR_ACCEPT)
  , mThirdPartySession(false)
  , mMaxNumberOfCookies(kMaxNumberOfCookies)
  , mMaxCookiesPerHost(kMaxCookiesPerHost)
  , mCookiePurgeAge(kCookiePurgeAge)
 {
 }
 
@@ -4349,13 +4348,19 @@ nsCookieService::SizeOfIncludingThis(moz
   }
   if (mPrivateDBState) {
     n += mPrivateDBState->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   return n;
 }
 
-int64_t
-nsCookieService::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(CookieServiceMallocSizeOf)
+
+NS_IMETHODIMP
+nsCookieService::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/cookie-service", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(CookieServiceMallocSizeOf),
+    "Memory used by the cookie service.");
 }
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -226,33 +226,32 @@ enum OpenDBResult
   RESULT_FAILURE
 };
 
 /******************************************************************************
  * nsCookieService:
  * class declaration
  ******************************************************************************/
 
-class nsCookieService : public mozilla::MemoryUniReporter
-                      , public nsICookieService
+class nsCookieService : public nsICookieService
                       , public nsICookieManager2
                       , public nsIObserver
                       , public nsSupportsWeakReference
+                      , public nsIMemoryReporter
 {
   private:
-    int64_t Amount() MOZ_OVERRIDE;
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   public:
-    // nsISupports
-    NS_DECL_ISUPPORTS_INHERITED
+    NS_DECL_ISUPPORTS
     NS_DECL_NSIOBSERVER
     NS_DECL_NSICOOKIESERVICE
     NS_DECL_NSICOOKIEMANAGER
     NS_DECL_NSICOOKIEMANAGER2
+    NS_DECL_NSIMEMORYREPORTER
 
     nsCookieService();
     virtual ~nsCookieService();
     static nsICookieService*      GetXPCOMSingleton();
     nsresult                      Init();
 
   /**
    * Start watching the observer service for messages indicating that an app has
--- a/netwerk/dns/nsDNSService2.cpp
+++ b/netwerk/dns/nsDNSService2.cpp
@@ -393,31 +393,28 @@ nsDNSSyncRequest::SizeOfIncludingThis(Ma
     // - mMonitor
 
     return n;
 }
 
 //-----------------------------------------------------------------------------
 
 nsDNSService::nsDNSService()
-    : MemoryUniReporter("explicit/network/dns-service",
-                        KIND_HEAP, UNITS_BYTES,
-                        "Memory used for the DNS service.")
-    , mLock("nsDNSServer.mLock")
+    : mLock("nsDNSServer.mLock")
     , mFirstTime(true)
     , mOffline(false)
 {
 }
 
 nsDNSService::~nsDNSService()
 {
 }
 
-NS_IMPL_ISUPPORTS_INHERITED3(nsDNSService, MemoryUniReporter, nsIDNSService,
-                             nsPIDNSService, nsIObserver)
+NS_IMPL_ISUPPORTS4(nsDNSService, nsIDNSService, nsPIDNSService, nsIObserver,
+                   nsIMemoryReporter)
 
 /******************************************************************************
  * nsDNSService impl:
  * singleton instance ctor/dtor methods
  ******************************************************************************/
 static nsDNSService *gDNSService;
 
 nsIDNSService*
@@ -908,8 +905,21 @@ nsDNSService::SizeOfIncludingThis(mozill
 
     size_t n = mallocSizeOf(this);
     n += mResolver->SizeOfIncludingThis(mallocSizeOf);
     n += mIPv4OnlyDomains.SizeOfExcludingThisMustBeUnshared(mallocSizeOf);
     n += mLocalDomains.SizeOfExcludingThis(SizeOfLocalDomainsEntryExcludingThis,
                                            mallocSizeOf);
     return n;
 }
+
+MOZ_DEFINE_MALLOC_SIZE_OF(DNSServiceMallocSizeOf)
+
+NS_IMETHODIMP
+nsDNSService::CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+{
+    return MOZ_COLLECT_REPORT(
+        "explicit/network/dns-service", KIND_HEAP, UNITS_BYTES,
+        SizeOfIncludingThis(DNSServiceMallocSizeOf),
+        "Memory used for the DNS service.");
+}
+
--- a/netwerk/dns/nsDNSService2.h
+++ b/netwerk/dns/nsDNSService2.h
@@ -14,35 +14,32 @@
 #include "nsHostResolver.h"
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/Attributes.h"
 
-class nsDNSService MOZ_FINAL : public mozilla::MemoryUniReporter
-                             , public nsPIDNSService
+class nsDNSService MOZ_FINAL : public nsPIDNSService
                              , public nsIObserver
+                             , public nsIMemoryReporter
 {
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSPIDNSSERVICE
     NS_DECL_NSIDNSSERVICE
     NS_DECL_NSIOBSERVER
+    NS_DECL_NSIMEMORYREPORTER
 
     nsDNSService();
     ~nsDNSService();
 
     static nsIDNSService* GetXPCOMSingleton();
 
-    int64_t Amount() MOZ_OVERRIDE
-    {
-        return SizeOfIncludingThis(MallocSizeOf);
-    }
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
 
 private:
     static nsDNSService* GetSingleton();
 
     uint16_t GetAFForLookup(const nsACString &host, uint32_t flags);
 
     nsRefPtr<nsHostResolver>  mResolver;
--- a/netwerk/dns/nsEffectiveTLDService.cpp
+++ b/netwerk/dns/nsEffectiveTLDService.cpp
@@ -13,18 +13,18 @@
 
 #include "nsEffectiveTLDService.h"
 #include "nsIIDNService.h"
 #include "nsNetUtil.h"
 #include "prnetdb.h"
 
 using namespace mozilla;
 
-NS_IMPL_ISUPPORTS_INHERITED1(nsEffectiveTLDService, MemoryUniReporter,
-                             nsIEffectiveTLDService)
+NS_IMPL_ISUPPORTS2(nsEffectiveTLDService, nsIEffectiveTLDService,
+                   nsIMemoryReporter)
 
 // ----------------------------------------------------------------------
 
 #define ETLD_STR_NUM_1(line) str##line
 #define ETLD_STR_NUM(line) ETLD_STR_NUM_1(line)
 #define ETLD_ENTRY_OFFSET(name) offsetof(struct etld_string_list, ETLD_STR_NUM(__LINE__))
 
 const ETLDEntry nsDomainEntry::entries[] = {
@@ -61,20 +61,17 @@ nsDomainEntry::FuncForStaticAsserts(void
 
 static nsEffectiveTLDService *gService = nullptr;
 
 nsEffectiveTLDService::nsEffectiveTLDService()
   // We'll probably have to rehash at least once, since nsTHashtable doesn't
   // use a perfect hash, but at least we'll save a few rehashes along the way.
   // Next optimization here is to precompute the hash using something like
   // gperf, but one step at a time.  :-)
-  : MemoryUniReporter("explicit/xpcom/effective-TLD-service",
-                       KIND_HEAP, UNITS_BYTES,
-                       "Memory used by the effective TLD service.")
-  , mHash(ArrayLength(nsDomainEntry::entries))
+  : mHash(ArrayLength(nsDomainEntry::entries))
 {
 }
 
 nsresult
 nsEffectiveTLDService::Init()
 {
   const ETLDEntry *entries = nsDomainEntry::entries;
 
@@ -105,20 +102,26 @@ nsEffectiveTLDService::Init()
 }
 
 nsEffectiveTLDService::~nsEffectiveTLDService()
 {
   UnregisterWeakMemoryReporter(this);
   gService = nullptr;
 }
 
-int64_t
-nsEffectiveTLDService::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(EffectiveTLDServiceMallocSizeOf)
+
+NS_IMETHODIMP
+nsEffectiveTLDService::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                      nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/xpcom/effective-TLD-service", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(EffectiveTLDServiceMallocSizeOf),
+    "Memory used by the effective TLD service.");
 }
 
 size_t
 nsEffectiveTLDService::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   size_t n = aMallocSizeOf(this);
   n += mHash.SizeOfExcludingThis(nullptr, aMallocSizeOf);
 
--- a/netwerk/dns/nsEffectiveTLDService.h
+++ b/netwerk/dns/nsEffectiveTLDService.h
@@ -101,27 +101,27 @@ private:
   } strings;
   static const ETLDEntry entries[];
   void FuncForStaticAsserts(void);
 #undef ETLD_STR_NUM
 #undef ETLD_STR_NUM1
 };
 
 class nsEffectiveTLDService MOZ_FINAL
-  : public mozilla::MemoryUniReporter
-  , public nsIEffectiveTLDService
+  : public nsIEffectiveTLDService
+  , public nsIMemoryReporter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIEFFECTIVETLDSERVICE
+  NS_DECL_NSIMEMORYREPORTER
 
   nsEffectiveTLDService();
   nsresult Init();
 
-  int64_t Amount() MOZ_OVERRIDE;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
 private:
   nsresult GetBaseDomainInternal(nsCString &aHostname, int32_t aAdditionalParts, nsACString &aBaseDomain);
   nsresult NormalizeHostname(nsCString &aHostname);
   ~nsEffectiveTLDService();
 
   nsTHashtable<nsDomainEntry> mHash;
--- a/toolkit/components/places/History.cpp
+++ b/toolkit/components/places/History.cpp
@@ -1910,21 +1910,17 @@ StoreAndNotifyEmbedVisit(VisitData& aPla
 } // anonymous namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 //// History
 
 History* History::gService = nullptr;
 
 History::History()
-  : MemoryUniReporter("explicit/history-links-hashtable",
-                      KIND_HEAP, UNITS_BYTES,
-"Memory used by the hashtable that records changes to the visited state of "
-"links.")
-  , mShuttingDown(false)
+  : mShuttingDown(false)
   , mShutdownMutex("History::mShutdownMutex")
   , mObservers(VISIT_OBSERVERS_INITIAL_CACHE_SIZE)
   , mRecentlyVisitedURIsNextIndex(0)
 {
   NS_ASSERTION(!gService, "Ruh-roh!  This service has already been created!");
   gService = this;
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
@@ -2216,20 +2212,27 @@ History::FetchPageInfo(VisitData& _place
 }
 
 /* static */ size_t
 History::SizeOfEntryExcludingThis(KeyClass* aEntry, mozilla::MallocSizeOf aMallocSizeOf, void *)
 {
   return aEntry->array.SizeOfExcludingThis(aMallocSizeOf);
 }
 
-int64_t
-History::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(HistoryMallocSizeOf)
+
+NS_IMETHODIMP
+History::CollectReports(nsIHandleReportCallback* aHandleReport,
+                        nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/history-links-hashtable", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(HistoryMallocSizeOf),
+    "Memory used by the hashtable that records changes to the visited state "
+    "of links.");
 }
 
 size_t
 History::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOfThis)
 {
   return aMallocSizeOfThis(this) +
          mObservers.SizeOfExcludingThis(SizeOfEntryExcludingThis, aMallocSizeOfThis);
 }
@@ -2909,19 +2912,19 @@ History::Observe(nsISupports* aSubject, 
   }
 
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsISupports
 
-NS_IMPL_ISUPPORTS_INHERITED4(
+NS_IMPL_ISUPPORTS5(
   History
-, MemoryUniReporter
 , IHistory
 , nsIDownloadHistory
 , mozIAsyncHistory
 , nsIObserver
+, nsIMemoryReporter
 )
 
 } // namespace places
 } // namespace mozilla
--- a/toolkit/components/places/History.h
+++ b/toolkit/components/places/History.h
@@ -30,28 +30,29 @@ namespace places {
 struct VisitData;
 
 #define NS_HISTORYSERVICE_CID \
   {0x0937a705, 0x91a6, 0x417a, {0x82, 0x92, 0xb2, 0x2e, 0xb1, 0x0d, 0xa8, 0x6c}}
 
 // Max size of History::mRecentlyVisitedURIs
 #define RECENTLY_VISITED_URI_SIZE 8
 
-class History : mozilla::MemoryUniReporter
-              , public IHistory
+class History : public IHistory
               , public nsIDownloadHistory
               , public mozIAsyncHistory
               , public nsIObserver
+              , public nsIMemoryReporter
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_IHISTORY
   NS_DECL_NSIDOWNLOADHISTORY
   NS_DECL_MOZIASYNCHISTORY
   NS_DECL_NSIOBSERVER
+  NS_DECL_NSIMEMORYREPORTER
 
   History();
 
   /**
    * Obtains the statement to use to check if a URI is visited or not.
    */
   mozIStorageAsyncStatement* GetIsVisitedStatement();
 
@@ -80,17 +81,16 @@ public:
    *        Whether or the page was recorded in moz_places, false otherwise.
    */
   nsresult FetchPageInfo(VisitData& _place, bool* _exists);
 
   /**
    * Get the number of bytes of memory this History object is using,
    * including sizeof(*this))
    */
-  int64_t Amount() MOZ_OVERRIDE;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
   /**
    * Obtains a pointer to this service.
    */
   static History* GetService();
 
   /**
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -228,21 +228,22 @@ HangReports::GetStacks() const {
 }
 
 uint32_t
 HangReports::GetDuration(unsigned aIndex) const {
   return mDurations[aIndex];
 }
 
 class TelemetryImpl MOZ_FINAL
-  : public MemoryUniReporter
-  , public nsITelemetry
+  : public nsITelemetry
+  , public nsIMemoryReporter
 {
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSITELEMETRY
+  NS_DECL_NSIMEMORYREPORTER
 
 public:
   ~TelemetryImpl();
 
   void InitMemoryReporter();
 
   static bool CanRecord();
   static already_AddRefed<nsITelemetry> CreateTelemetryInstance();
@@ -250,17 +251,16 @@ public:
   static void RecordSlowStatement(const nsACString &sql, const nsACString &dbName,
                                   uint32_t delay);
 #if defined(MOZ_ENABLE_PROFILER_SPS)
   static void RecordChromeHang(uint32_t duration,
                                Telemetry::ProcessedStack &aStack);
 #endif
   static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats);
   static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
-  int64_t Amount() MOZ_OVERRIDE;
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
   struct Stat {
     uint32_t hitCount;
     uint32_t totalTime;
   };
   struct StmtStats {
     struct Stat mainThread;
     struct Stat otherThreads;
@@ -336,20 +336,26 @@ private:
   uint32_t mLastShutdownTime;
   uint32_t mFailedLockCount;
   nsCOMArray<nsIFetchTelemetryDataCallback> mCallbacks;
   friend class nsFetchTelemetryData;
 };
 
 TelemetryImpl*  TelemetryImpl::sTelemetry = nullptr;
 
-int64_t
-TelemetryImpl::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(TelemetryMallocSizeOf)
+
+NS_IMETHODIMP
+TelemetryImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
+                              nsISupports* aData)
 {
-  return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/telemetry", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(TelemetryMallocSizeOf),
+    "Memory used by the telemetry system.");
 }
 
 size_t
 TelemetryImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
   size_t n = aMallocSizeOf(this);
   // Ignore the hashtables in mAddonMap; they are not significant.
   n += mAddonMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);
@@ -918,18 +924,16 @@ TelemetryImpl::AsyncFetchTelemetryData(n
                                                          failedProfileLockFile,
                                                          profileDir);
 
   targetThread->Dispatch(event, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 TelemetryImpl::TelemetryImpl():
-MemoryUniReporter("explicit/telemetry", KIND_HEAP, UNITS_BYTES,
-                  "Memory used by the telemetry system."),
 mHistogramMap(Telemetry::HistogramCount),
 mCanRecord(XRE_GetProcessType() == GeckoProcessType_Default),
 mHashMutex("Telemetry::mHashMutex"),
 mHangReportsMutex("Telemetry::mHangReportsMutex"),
 mThreadHangStatsMutex("Telemetry::mThreadHangStatsMutex"),
 mCachedTelemetryData(false),
 mLastShutdownTime(0),
 mFailedLockCount(0)
@@ -2228,17 +2232,17 @@ TelemetryImpl::RecordThreadHangStats(Tel
   if (!sTelemetry || !sTelemetry->mCanRecord)
     return;
 
   MutexAutoLock autoLock(sTelemetry->mThreadHangStatsMutex);
 
   sTelemetry->mThreadHangStats.append(Move(aStats));
 }
 
-NS_IMPL_ISUPPORTS_INHERITED1(TelemetryImpl, MemoryUniReporter, nsITelemetry)
+NS_IMPL_ISUPPORTS2(TelemetryImpl, nsITelemetry, nsIMemoryReporter)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsITelemetry, TelemetryImpl::CreateTelemetryInstance)
 
 #define NS_TELEMETRY_CID \
   {0xaea477f2, 0xb3a2, 0x469c, {0xaa, 0x29, 0x0a, 0x82, 0xd1, 0x32, 0xb8, 0x29}}
 NS_DEFINE_NAMED_CID(NS_TELEMETRY_CID);
 
 const Module::CIDEntry kTelemetryCIDs[] = {
   { &kNS_TELEMETRY_CID, false, nullptr, nsITelemetryConstructor },
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -326,79 +326,69 @@ CreateDIBSectionHook(HDC aDC,
 }
 
 static int64_t
 LowMemoryEventsVirtualDistinguishedAmount()
 {
   return sNumLowVirtualMemEvents;
 }
 
-class LowMemoryEventsVirtualReporter MOZ_FINAL : public MemoryUniReporter
-{
-public:
-  LowMemoryEventsVirtualReporter()
-    : MemoryUniReporter("low-memory-events/virtual",
-                         KIND_OTHER, UNITS_COUNT_CUMULATIVE,
-"Number of low-virtual-memory events fired since startup. We fire such an "
-"event if we notice there is less than memory.low_virtual_mem_threshold_mb of "
-"virtual address space available (if zero, this behavior is disabled).  The "
-"process will probably crash if it runs out of virtual address space, so "
-"this event is dire.")
-  {}
-
-private:
-  int64_t Amount() MOZ_OVERRIDE
-  {
-    // This memory reporter shouldn't be installed on 64-bit machines, since we
-    // force-disable virtual-memory tracking there.
-    MOZ_ASSERT(sizeof(void*) == 4);
-
-    return LowMemoryEventsVirtualDistinguishedAmount();
-  }
-};
-
-class LowCommitSpaceEventsReporter MOZ_FINAL : public MemoryUniReporter
-{
-public:
-  LowCommitSpaceEventsReporter()
-    : MemoryUniReporter("low-commit-space-events",
-                         KIND_OTHER, UNITS_COUNT_CUMULATIVE,
-"Number of low-commit-space events fired since startup. We fire such an "
-"event if we notice there is less than memory.low_commit_space_threshold_mb of "
-"commit space available (if zero, this behavior is disabled).  Windows will "
-"likely kill the process if it runs out of commit space, so this event is "
-"dire.")
-  {}
-
-private:
-  int64_t Amount() MOZ_OVERRIDE { return sNumLowCommitSpaceEvents; }
-};
-
 static int64_t
 LowMemoryEventsPhysicalDistinguishedAmount()
 {
   return sNumLowPhysicalMemEvents;
 }
 
-class LowMemoryEventsPhysicalReporter MOZ_FINAL : public MemoryUniReporter
+class LowEventsReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-  LowMemoryEventsPhysicalReporter()
-    : MemoryUniReporter("low-memory-events/physical",
-                         KIND_OTHER, UNITS_COUNT_CUMULATIVE,
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                            nsISupports* aData)
+  {
+    nsresult rv;
+
+    // We only do virtual-memory tracking on 32-bit builds.
+    if (sizeof(void*) == 4) {
+      rv = MOZ_COLLECT_REPORT(
+        "low-memory-events/virtual", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
+        LowMemoryEventsVirtualDistinguishedAmount(),
+"Number of low-virtual-memory events fired since startup. We fire such an "
+"event if we notice there is less than memory.low_virtual_mem_threshold_mb of "
+"virtual address space available (if zero, this behavior is disabled). The "
+"process will probably crash if it runs out of virtual address space, so "
+"this event is dire.");
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+
+    rv = MOZ_COLLECT_REPORT(
+      "low-commit-space-events", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
+      sNumLowCommitSpaceEvents,
+"Number of low-commit-space events fired since startup. We fire such an "
+"event if we notice there is less than memory.low_commit_space_threshold_mb of "
+"commit space available (if zero, this behavior is disabled). Windows will "
+"likely kill the process if it runs out of commit space, so this event is "
+"dire.");
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = MOZ_COLLECT_REPORT(
+      "low-memory-events/physical", KIND_OTHER, UNITS_COUNT_CUMULATIVE,
+      LowMemoryEventsPhysicalDistinguishedAmount(),
 "Number of low-physical-memory events fired since startup. We fire such an "
 "event if we notice there is less than memory.low_physical_memory_threshold_mb "
 "of physical memory available (if zero, this behavior is disabled).  The "
 "machine will start to page if it runs out of physical memory.  This may "
-"cause it to run slowly, but it shouldn't cause it to crash.")
-  {}
+"cause it to run slowly, but it shouldn't cause it to crash.");
+    NS_ENSURE_SUCCESS(rv, rv);
 
-private:
-  int64_t Amount() MOZ_OVERRIDE { return LowMemoryEventsPhysicalDistinguishedAmount(); }
+    return NS_OK;
+  }
 };
+NS_IMPL_ISUPPORTS1(LowEventsReporter, nsIMemoryReporter)
 
 #endif // defined(XP_WIN)
 
 /**
  * This runnable is executed in response to a memory-pressure event; we spin
  * the event-loop when receiving the memory-pressure event in the hope that
  * other observers will synchronously free some memory that we'll be able to
  * purge here.
@@ -505,21 +495,17 @@ 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);
 
-  RegisterStrongMemoryReporter(new LowCommitSpaceEventsReporter());
-  RegisterStrongMemoryReporter(new LowMemoryEventsPhysicalReporter());
-  if (sizeof(void*) == 4) {
-    RegisterStrongMemoryReporter(new LowMemoryEventsVirtualReporter());
-  }
+  RegisterStrongMemoryReporter(new LowEventsReporter());
   RegisterLowMemoryEventsVirtualDistinguishedAmount(LowMemoryEventsVirtualDistinguishedAmount);
   RegisterLowMemoryEventsPhysicalDistinguishedAmount(LowMemoryEventsPhysicalDistinguishedAmount);
   sHooksActive = true;
 #endif
 
   // This object is held alive by the observer service.
   nsRefPtr<nsMemoryPressureWatcher> watcher = new nsMemoryPressureWatcher();
   watcher->Init();
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -501,80 +501,16 @@ void RunReportersForThisProcess();
       return moz_malloc_size_of(aPtr);                                        \
   }
 #define MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(fn)                                 \
   static size_t fn(const void* aPtr)                                          \
   {                                                                           \
       return moz_malloc_size_of(aPtr);                                        \
   }
 
-namespace mozilla {
-
-// The following base class reduces the amount of boilerplate code required for
-// memory uni-reporters.  You just need to provide the following.
-// - The constant values: path, kind, units, and description.  They are
-//   arguments to the MemoryUniReporter constructor.
-// - A private Amount() or public GetAmount() method.  It can use the
-//   MallocSizeOf method if necessary.  (There is also
-//   MallocSizeOfOn{Alloc,Free}, which can be useful.)  Use Amount() if the
-//   reporter is infallible, and GetAmount() otherwise.  (If you fail to
-//   provide one or the other, you'll get assertion failures when the memory
-//   reporter runs.)
-//
-// The class name of subclasses should match the path, minus the "explicit" (if
-// present), and with "Reporter" at the end.  For example:
-// - path == "explicit/dom/xyzzy"     --> DOMXyzzyReporter
-// - path == "js-compartments/system" --> JSCompartmentsSystemReporter
-//
-class MemoryUniReporter : public nsIMemoryReporter
-{
-public:
-  MemoryUniReporter(const char* aPath, int32_t aKind, int32_t aUnits,
-                    const char* aDescription)
-    : mPath(aPath)
-    , mKind(aKind)
-    , mUnits(aUnits)
-    , mDescription(aDescription)
-  {}
-
-  virtual ~MemoryUniReporter() {}
-
-  NS_DECL_THREADSAFE_ISUPPORTS
-
-  NS_IMETHOD CollectReports(nsIMemoryReporterCallback* aCallback,
-                            nsISupports* aData)
-  {
-    int64_t amount;
-    nsresult rv = GetAmount(&amount);
-    if (NS_WARN_IF(NS_FAILED(rv)))
-      return rv;
-
-    return aCallback->Callback(EmptyCString(), mPath, mKind, mUnits,
-                               amount, mDescription, aData);
-  }
-
-protected:
-  NS_IMETHOD GetAmount(int64_t* aAmount)
-  {
-    *aAmount = Amount();
-    return NS_OK;
-  }
-
-  virtual int64_t Amount()
-  {
-    // We only reach here if neither GetAmount() nor Amount() was overridden.
-    MOZ_ASSERT(false);
-    return 0;
-  }
-
-  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
-  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
-  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
-
-  const nsCString mPath;
-  const int32_t   mKind;
-  const int32_t   mUnits;
-  const nsCString mDescription;
-};
-
-} // namespace mozilla
+// This macro assumes the presence of appropriate |aHandleReport| and |aData|
+// variables.
+#define MOZ_COLLECT_REPORT(path, kind, units, amount, description)            \
+  aHandleReport->Callback(EmptyCString(), NS_LITERAL_CSTRING(path),           \
+                          kind, units, amount,                                \
+                          NS_LITERAL_CSTRING(description), aData)
 
 %}
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -74,58 +74,56 @@ ResidentDistinguishedAmount(int64_t* aN)
 
 static nsresult
 ResidentFastDistinguishedAmount(int64_t* aN)
 {
     return ResidentDistinguishedAmount(aN);
 }
 
 #define HAVE_RESIDENT_UNIQUE_REPORTER
-class ResidentUniqueReporter MOZ_FINAL : public MemoryUniReporter
+class ResidentUniqueReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-  ResidentUniqueReporter()
-    : MemoryUniReporter("resident-unique", KIND_OTHER, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        // You might be tempted to calculate USS by subtracting the "shared"
+        // value from the "resident" value in /proc/<pid>/statm. But at least
+        // on Linux, statm's "shared" value actually counts pages backed by
+        // files, which has little to do with whether the pages are actually
+        // shared. /proc/self/smaps on the other hand appears to give us the
+        // correct information.
+
+        FILE *f = fopen("/proc/self/smaps", "r");
+        if (NS_WARN_IF(!f))
+            return NS_ERROR_UNEXPECTED;
+
+        int64_t amount = 0;
+        char line[256];
+        while (fgets(line, sizeof(line), f)) {
+            long long val = 0;
+            if (sscanf(line, "Private_Dirty: %lld kB", &val) == 1 ||
+                sscanf(line, "Private_Clean: %lld kB", &val) == 1) {
+                amount += val * 1024; // convert from kB to bytes
+            }
+        }
+
+        fclose(f);
+
+        return MOZ_COLLECT_REPORT(
+            "resident-unique", KIND_OTHER, UNITS_BYTES, amount,
 "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.")
-  {}
-
-private:
-  NS_IMETHOD GetAmount(int64_t *aAmount)
-  {
-    // You might be tempted to calculate USS by subtracting the "shared" value
-    // from the "resident" value in /proc/<pid>/statm.  But at least on Linux,
-    // statm's "shared" value actually counts pages backed by files, which has
-    // little to do with whether the pages are actually shared.
-    // /proc/self/smaps on the other hand appears to give us the correct
-    // information.
-
-    *aAmount = 0;
-
-    FILE *f = fopen("/proc/self/smaps", "r");
-    if (NS_WARN_IF(!f))
-        return NS_ERROR_UNEXPECTED;
-
-    int64_t total = 0;
-    char line[256];
-    while (fgets(line, sizeof(line), f)) {
-      long long val = 0;
-      if (sscanf(line, "Private_Dirty: %lld kB", &val) == 1 ||
-          sscanf(line, "Private_Clean: %lld kB", &val) == 1) {
-        total += val * 1024; // convert from kB to bytes
-      }
+"closed this process.");
     }
-    *aAmount = total;
-
-    fclose(f);
-    return NS_OK;
-  }
 };
+NS_IMPL_ISUPPORTS1(ResidentUniqueReporter, nsIMemoryReporter)
 
 #elif defined(__DragonFly__) || defined(__FreeBSD__) \
     || defined(__NetBSD__) || defined(__OpenBSD__)
 
 #include <sys/param.h>
 #include <sys/sysctl.h>
 #if defined(__DragonFly__) || defined(__FreeBSD__)
 #include <sys/user.h>
@@ -236,19 +234,18 @@ GetKinfoVmentrySelf(int64_t* prss, uint6
 }
 
 #define HAVE_PRIVATE_REPORTER
 static nsresult
 PrivateDistinguishedAmount(int64_t* aN)
 {
     int64_t priv;
     nsresult rv = GetKinfoVmentrySelf(&priv, NULL);
-    if (NS_SUCCEEDED(rv))
-        *aN = priv * getpagesize();
-
+    NS_ENSURE_SUCCESS(rv, rv);
+    *aN = priv * getpagesize();
     return NS_OK;
 }
 
 #define HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER 1
 static nsresult
 VsizeMaxContiguousDistinguishedAmount(int64_t* aN)
 {
     uint64_t biggestRegion;
@@ -486,159 +483,186 @@ PrivateDistinguishedAmount(int64_t* aN)
     }
 
     *aN = pmcex.PrivateUsage;
     return NS_OK;
 }
 #endif  // XP_<PLATFORM>
 
 #ifdef HAVE_VSIZE_MAX_CONTIGUOUS_REPORTER
-class VsizeMaxContiguousReporter MOZ_FINAL : public MemoryUniReporter
+class VsizeMaxContiguousReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    VsizeMaxContiguousReporter()
-      : MemoryUniReporter("vsize-max-contiguous", KIND_OTHER, UNITS_BYTES,
-"Size of the maximum contiguous block of available virtual memory.")
-    {}
+    NS_DECL_ISUPPORTS
 
-    NS_IMETHOD GetAmount(int64_t* aAmount)
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
     {
-        return VsizeMaxContiguousDistinguishedAmount(aAmount);
+        int64_t amount;
+        nsresult rv = VsizeMaxContiguousDistinguishedAmount(&amount);
+        NS_ENSURE_SUCCESS(rv, rv);
+        return MOZ_COLLECT_REPORT(
+            "vsize-max-contiguous", KIND_OTHER, UNITS_BYTES, amount,
+            "Size of the maximum contiguous block of available virtual "
+            "memory.");
     }
 };
+NS_IMPL_ISUPPORTS1(VsizeMaxContiguousReporter, nsIMemoryReporter)
 #endif
 
 #ifdef HAVE_PRIVATE_REPORTER
-class PrivateReporter MOZ_FINAL : public MemoryUniReporter
+class PrivateReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    PrivateReporter()
-      : MemoryUniReporter("private", KIND_OTHER, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        int64_t amount;
+        nsresult rv = PrivateDistinguishedAmount(&amount);
+        NS_ENSURE_SUCCESS(rv, rv);
+        return MOZ_COLLECT_REPORT(
+            "private", KIND_OTHER, UNITS_BYTES, amount,
 "Memory that cannot be shared with other processes, including memory that is "
 "committed and marked MEM_PRIVATE, data that is not mapped, and executable "
-"pages that have been written to.")
-    {}
-
-    NS_IMETHOD GetAmount(int64_t* aAmount)
-    {
-        return PrivateDistinguishedAmount(aAmount);
+"pages that have been written to.");
     }
 };
+NS_IMPL_ISUPPORTS1(PrivateReporter, nsIMemoryReporter)
 #endif
 
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
-class VsizeReporter MOZ_FINAL : public MemoryUniReporter
+class VsizeReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    VsizeReporter()
-      : MemoryUniReporter("vsize", KIND_OTHER, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        int64_t amount;
+        nsresult rv = VsizeDistinguishedAmount(&amount);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        return MOZ_COLLECT_REPORT(
+            "vsize", KIND_OTHER, UNITS_BYTES, amount,
 "Memory mapped by the process, including code and data segments, the heap, "
 "thread stacks, memory explicitly mapped by the process via mmap and similar "
 "operations, and memory shared with other processes. This is the vsize figure "
 "as reported by 'top' and 'ps'.  This figure is of limited use on Mac, where "
 "processes share huge amounts of memory with one another.  But even on other "
 "operating systems, 'resident' is a much better measure of the memory "
-"resources used by the process.")
-    {}
-
-    NS_IMETHOD GetAmount(int64_t* aAmount)
-    {
-        return VsizeDistinguishedAmount(aAmount);
+"resources used by the process.");
     }
 };
+NS_IMPL_ISUPPORTS1(VsizeReporter, nsIMemoryReporter)
 
-class ResidentReporter MOZ_FINAL : public MemoryUniReporter
+class ResidentReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    ResidentReporter()
-      : MemoryUniReporter("resident", KIND_OTHER, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        int64_t amount;
+        nsresult rv = ResidentDistinguishedAmount(&amount);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        return MOZ_COLLECT_REPORT(
+            "resident", KIND_OTHER, UNITS_BYTES, amount,
 "Memory mapped by the process that is present in physical memory, also known "
 "as the resident set size (RSS).  This is the best single figure to use when "
 "considering the memory resources used by the process, but it depends both on "
 "other processes being run and details of the OS kernel and so is best used "
 "for comparing the memory usage of a single process at different points in "
-"time.")
-    {}
-
-    NS_IMETHOD GetAmount(int64_t* aAmount)
-    {
-        return ResidentDistinguishedAmount(aAmount);
+"time.");
     }
 };
+NS_IMPL_ISUPPORTS1(ResidentReporter, nsIMemoryReporter)
+
 #endif  // HAVE_VSIZE_AND_RESIDENT_REPORTERS
 
 #ifdef XP_UNIX
 
 #include <sys/resource.h>
 
 #define HAVE_PAGE_FAULT_REPORTERS 1
 
-class PageFaultsSoftReporter MOZ_FINAL : public MemoryUniReporter
+class PageFaultsSoftReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    PageFaultsSoftReporter()
-      : MemoryUniReporter("page-faults-soft", KIND_OTHER,
-                           UNITS_COUNT_CUMULATIVE,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        struct rusage usage;
+        int err = getrusage(RUSAGE_SELF, &usage);
+        if (err != 0) {
+            return NS_ERROR_FAILURE;
+        }
+        int64_t amount = usage.ru_minflt;
+
+        return MOZ_COLLECT_REPORT(
+            "page-faults-soft", KIND_OTHER, UNITS_COUNT_CUMULATIVE, amount,
 "The number of soft page faults (also known as 'minor page faults') that "
 "have occurred since the process started.  A soft page fault occurs when the "
 "process tries to access a page which is present in physical memory but is "
 "not mapped into the process's address space.  For instance, a process might "
 "observe soft page faults when it loads a shared library which is already "
 "present in physical memory. A process may experience many thousands of soft "
 "page faults even when the machine has plenty of available physical memory, "
 "and because the OS services a soft page fault without accessing the disk, "
-"they impact performance much less than hard page faults.")
-    {}
-
-    NS_IMETHOD GetAmount(int64_t* aAmount)
-    {
-        struct rusage usage;
-        int err = getrusage(RUSAGE_SELF, &usage);
-        if (err != 0) {
-            return NS_ERROR_FAILURE;
-        }
-        *aAmount = usage.ru_minflt;
-        return NS_OK;
+"they impact performance much less than hard page faults.");
     }
 };
+NS_IMPL_ISUPPORTS1(PageFaultsSoftReporter, nsIMemoryReporter)
 
 static nsresult
 PageFaultsHardDistinguishedAmount(int64_t* aAmount)
 {
     struct rusage usage;
     int err = getrusage(RUSAGE_SELF, &usage);
     if (err != 0) {
         return NS_ERROR_FAILURE;
     }
     *aAmount = usage.ru_majflt;
     return NS_OK;
 }
 
-class PageFaultsHardReporter MOZ_FINAL : public MemoryUniReporter
+class PageFaultsHardReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    PageFaultsHardReporter()
-      : MemoryUniReporter("page-faults-hard", KIND_OTHER,
-                           UNITS_COUNT_CUMULATIVE,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        int64_t amount;
+        nsresult rv = PageFaultsHardDistinguishedAmount(&amount);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        return MOZ_COLLECT_REPORT(
+            "page-faults-hard", KIND_OTHER, UNITS_COUNT_CUMULATIVE, amount,
 "The number of hard page faults (also known as 'major page faults') that have "
 "occurred since the process started.  A hard page fault occurs when a process "
 "tries to access a page which is not present in physical memory. The "
 "operating system must access the disk in order to fulfill a hard page fault. "
 "When memory is plentiful, you should see very few hard page faults. But if "
 "the process tries to use more memory than your machine has available, you "
 "may see many thousands of hard page faults. Because accessing the disk is up "
 "to a million times slower than accessing RAM, the program may run very "
-"slowly when it is experiencing more than 100 or so hard page faults a second.")
-    {}
-
-    NS_IMETHOD GetAmount(int64_t* aAmount)
-    {
-        return PageFaultsHardDistinguishedAmount(aAmount);
+"slowly when it is experiencing more than 100 or so hard page faults a "
+"second.");
     }
 };
+NS_IMPL_ISUPPORTS1(PageFaultsHardReporter, nsIMemoryReporter)
+
 #endif  // HAVE_PAGE_FAULT_REPORTERS
 
 /**
  ** memory reporter implementation for jemalloc and OSX malloc,
  ** to obtain info on total memory in use (that we know about,
  ** at least -- on OSX, there are sometimes other zones in use).
  **/
 
@@ -658,145 +682,169 @@ HeapOverheadRatio()
 {
     jemalloc_stats_t stats;
     jemalloc_stats(&stats);
     return (int64_t) 10000 *
       (stats.waste + stats.bookkeeping + stats.page_cache) /
       ((double)stats.allocated);
 }
 
-class HeapAllocatedReporter MOZ_FINAL : public MemoryUniReporter
+class HeapAllocatedReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    HeapAllocatedReporter()
-      : MemoryUniReporter("heap-allocated", KIND_OTHER, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        return MOZ_COLLECT_REPORT(
+            "heap-allocated", KIND_OTHER, UNITS_BYTES, HeapAllocated(),
 "Memory mapped by the heap allocator that is currently allocated to the "
 "application.  This may exceed the amount of memory requested by the "
 "application because the allocator regularly rounds up request sizes. (The "
-"exact amount requested is not recorded.)")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE { return HeapAllocated(); }
+"exact amount requested is not recorded.)");
+    }
 };
+NS_IMPL_ISUPPORTS1(HeapAllocatedReporter, nsIMemoryReporter)
 
-class HeapOverheadWasteReporter MOZ_FINAL : public MemoryUniReporter
+class HeapOverheadWasteReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    // We mark this and the other heap-overhead reporters as KIND_NONHEAP
-    // because KIND_HEAP memory means "counted in heap-allocated", which this
-    // is not.
-    HeapOverheadWasteReporter()
-      : MemoryUniReporter("explicit/heap-overhead/waste",
-                           KIND_NONHEAP, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        int64_t amount = stats.waste;
+
+        // We mark this and the other heap-overhead reporters as KIND_NONHEAP
+        // because KIND_HEAP memory means "counted in heap-allocated", which
+        // this is not.
+        return MOZ_COLLECT_REPORT(
+            "explicit/heap-overhead/waste", KIND_NONHEAP, UNITS_BYTES, amount,
 "Committed bytes which do not correspond to an active allocation and which the "
 "allocator is not intentionally keeping alive (i.e., not 'heap-bookkeeping' or "
 "'heap-page-cache').  Although the allocator will waste some space under any "
 "circumstances, a large value here may indicate that the heap is highly "
-"fragmented, or that allocator is performing poorly for some other reason.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
-    {
-        jemalloc_stats_t stats;
-        jemalloc_stats(&stats);
-        return stats.waste;
+"fragmented, or that allocator is performing poorly for some other reason.");
     }
 };
+NS_IMPL_ISUPPORTS1(HeapOverheadWasteReporter, nsIMemoryReporter)
 
-class HeapOverheadBookkeepingReporter MOZ_FINAL : public MemoryUniReporter
+class HeapOverheadBookkeepingReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    HeapOverheadBookkeepingReporter()
-      : MemoryUniReporter("explicit/heap-overhead/bookkeeping",
-                           KIND_NONHEAP, UNITS_BYTES,
-"Committed bytes which the heap allocator uses for internal data structures.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
     {
         jemalloc_stats_t stats;
         jemalloc_stats(&stats);
-        return stats.bookkeeping;
+        int64_t amount = stats.bookkeeping;
+
+        return MOZ_COLLECT_REPORT(
+            "explicit/heap-overhead/bookkeeping", KIND_NONHEAP, UNITS_BYTES,
+            amount,
+            "Committed bytes which the heap allocator uses for internal data "
+            "structures.");
     }
 };
+NS_IMPL_ISUPPORTS1(HeapOverheadBookkeepingReporter, nsIMemoryReporter)
 
-class HeapOverheadPageCacheReporter MOZ_FINAL : public MemoryUniReporter
+class HeapOverheadPageCacheReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    HeapOverheadPageCacheReporter()
-      : MemoryUniReporter("explicit/heap-overhead/page-cache",
-                           KIND_NONHEAP, UNITS_BYTES,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        int64_t amount = stats.page_cache;
+
+        return MOZ_COLLECT_REPORT(
+            "explicit/heap-overhead/page-cache", KIND_NONHEAP, UNITS_BYTES,
+            amount,
 "Memory which the allocator could return to the operating system, but hasn't. "
 "The allocator keeps this memory around as an optimization, so it doesn't "
 "have to ask the OS the next time it needs to fulfill a request. This value "
-"is typically not larger than a few megabytes.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
+"is typically not larger than a few megabytes.");
+    }
+};
+NS_IMPL_ISUPPORTS1(HeapOverheadPageCacheReporter, nsIMemoryReporter)
+
+class HeapCommittedReporter MOZ_FINAL : public nsIMemoryReporter
+{
+public:
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
     {
         jemalloc_stats_t stats;
         jemalloc_stats(&stats);
-        return (int64_t) stats.page_cache;
-    }
-};
+        int64_t amount = stats.allocated + stats.waste +
+                         stats.bookkeeping + stats.page_cache;
 
-class HeapCommittedReporter MOZ_FINAL : public MemoryUniReporter
-{
-public:
-    HeapCommittedReporter()
-      : MemoryUniReporter("heap-committed", KIND_OTHER, UNITS_BYTES,
+        return MOZ_COLLECT_REPORT(
+            "heap-committed", KIND_OTHER, UNITS_BYTES, amount,
 "Memory mapped by the heap allocator that is committed, i.e. in physical "
 "memory or paged to disk.  This value corresponds to 'heap-allocated' + "
 "'heap-waste' + 'heap-bookkeeping' + 'heap-page-cache', but because "
 "these values are read at different times, the result probably won't match "
-"exactly.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
-    {
-        jemalloc_stats_t stats;
-        jemalloc_stats(&stats);
-        return (int64_t) (stats.allocated + stats.waste +
-                          stats.bookkeeping + stats.page_cache);
+"exactly.");
     }
 };
+NS_IMPL_ISUPPORTS1(HeapCommittedReporter, nsIMemoryReporter)
 
-class HeapOverheadRatioReporter MOZ_FINAL : public MemoryUniReporter
+class HeapOverheadRatioReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
-    HeapOverheadRatioReporter()
-      : MemoryUniReporter("heap-overhead-ratio", KIND_OTHER,
-                           UNITS_PERCENTAGE,
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
+    {
+        return MOZ_COLLECT_REPORT(
+            "heap-overhead-ratio", KIND_OTHER, UNITS_PERCENTAGE,
+            HeapOverheadRatio(),
 "Ratio of committed, unused bytes to allocated bytes; i.e., "
 "'heap-overhead' / 'heap-allocated'.  This measures the overhead of "
-"the heap allocator relative to amount of memory allocated.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE { return HeapOverheadRatio(); }
+"the heap allocator relative to amount of memory allocated.");
+    }
 };
+NS_IMPL_ISUPPORTS1(HeapOverheadRatioReporter, nsIMemoryReporter)
 #endif  // HAVE_JEMALLOC_STATS
 
 // Why is this here?  At first glance, you'd think it could be defined and
 // registered with nsMemoryReporterManager entirely within nsAtomTable.cpp.
 // However, the obvious time to register it is when the table is initialized,
 // and that happens before XPCOM components are initialized, which means the
 // RegisterStrongMemoryReporter call fails.  So instead we do it here.
-class AtomTablesReporter MOZ_FINAL : public MemoryUniReporter
+class AtomTablesReporter MOZ_FINAL : public nsIMemoryReporter
 {
+    MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
+
 public:
-    AtomTablesReporter()
-      : MemoryUniReporter("explicit/atom-tables", KIND_HEAP, UNITS_BYTES,
-"Memory used by the dynamic and static atoms tables.")
-    {}
-private:
-    int64_t Amount() MOZ_OVERRIDE
+    NS_DECL_ISUPPORTS
+
+    NS_METHOD CollectReports(nsIHandleReportCallback* aHandleReport,
+                             nsISupports* aData)
     {
-        return NS_SizeOfAtomTablesIncludingThis(MallocSizeOf);
+        return MOZ_COLLECT_REPORT(
+            "explicit/atom-tables", KIND_HEAP, UNITS_BYTES,
+            NS_SizeOfAtomTablesIncludingThis(MallocSizeOf),
+            "Memory used by the dynamic and static atoms tables.");
     }
 };
+NS_IMPL_ISUPPORTS1(AtomTablesReporter, nsIMemoryReporter)
 
 #ifdef MOZ_DMD
 
 namespace mozilla {
 namespace dmd {
 
 class DMDReporter MOZ_FINAL : public nsIMemoryReporter
 {
@@ -837,17 +885,16 @@ public:
            sizes.mBlockTable,
            "Memory used by DMD's live block table.");
 
 #undef REPORT
 
     return NS_OK;
   }
 };
-
 NS_IMPL_ISUPPORTS1(DMDReporter, nsIMemoryReporter)
 
 } // namespace dmd
 } // namespace mozilla
 
 #endif  // MOZ_DMD
 
 /**
@@ -1754,21 +1801,16 @@ nsMemoryReporterManager::SizeOfTab(nsIDO
     #undef DO
 
     *aJSMilliseconds    = (t2 - t1).ToMilliseconds();
     *aNonJSMilliseconds = (t3 - t2).ToMilliseconds();
 
     return NS_OK;
 }
 
-// Most memory reporters don't need thread safety, but some do.  Make them all
-// thread-safe just to be safe.  Memory reporters are created and destroyed
-// infrequently enough that the performance cost should be negligible.
-NS_IMPL_ISUPPORTS1(MemoryUniReporter, nsIMemoryReporter)
-
 namespace mozilla {
 
 nsresult
 RegisterStrongMemoryReporter(nsIMemoryReporter* aReporter)
 {
     nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
     if (!mgr) {
         return NS_ERROR_FAILURE;
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -332,22 +332,22 @@ NS_GetTraceRefcnt(nsITraceRefcnt** resul
 
 EXPORT_XPCOM_API(nsresult)
 NS_InitXPCOM(nsIServiceManager* *result,
                              nsIFile* binDirectory)
 {
     return NS_InitXPCOM2(result, binDirectory, nullptr);
 }
 
-class ICUReporter MOZ_FINAL : public MemoryUniReporter
+class ICUReporter MOZ_FINAL : public nsIMemoryReporter
 {
 public:
+    NS_DECL_ISUPPORTS
+
     ICUReporter()
-      : MemoryUniReporter("explicit/icu", KIND_HEAP, UNITS_BYTES,
-"Memory used by ICU, a Unicode and globalization support library.")
     {
 #ifdef DEBUG
         // There must be only one instance of this class, due to |sAmount|
         // being static.
         static bool hasRun = false;
         MOZ_ASSERT(!hasRun);
         hasRun = true;
 #endif
@@ -380,19 +380,31 @@ public:
         free(p);
     }
 
 private:
     // |sAmount| can be (implicitly) accessed by multiple JSRuntimes, so it
     // must be thread-safe.
     static Atomic<size_t> sAmount;
 
-    int64_t Amount() MOZ_OVERRIDE { return sAmount; }
+    MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
+    MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
+    MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
+
+    NS_IMETHODIMP
+    CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
+    {
+        return MOZ_COLLECT_REPORT(
+            "explicit/icu", KIND_HEAP, UNITS_BYTES, sAmount,
+            "Memory used by ICU, a Unicode and globalization support library.");
+    }
 };
 
+NS_IMPL_ISUPPORTS1(ICUReporter, nsIMemoryReporter)
+
 /* static */ Atomic<size_t> ICUReporter::sAmount;
 
 EXPORT_XPCOM_API(nsresult)
 NS_InitXPCOM2(nsIServiceManager* *result,
               nsIFile* binDirectory,
               nsIDirectoryServiceProvider* appFileLocationProvider)
 {
     mozPoisonValueInit();
--- a/xpcom/components/nsCategoryManager.cpp
+++ b/xpcom/components/nsCategoryManager.cpp
@@ -395,17 +395,17 @@ CategoryEnumerator::enumfunc_createenume
   return PL_DHASH_NEXT;
 }
 
 
 //
 // nsCategoryManager implementations
 //
 
-NS_IMPL_QUERY_INTERFACE_INHERITED1(nsCategoryManager, MemoryUniReporter, nsICategoryManager)
+NS_IMPL_QUERY_INTERFACE2(nsCategoryManager, nsICategoryManager, nsIMemoryReporter)
 
 NS_IMETHODIMP_(nsrefcnt)
 nsCategoryManager::AddRef()
 {
   return 2;
 }
 
 NS_IMETHODIMP_(nsrefcnt)
@@ -436,20 +436,17 @@ nsCategoryManager::Create(nsISupports* a
 {
   if (aOuter)
     return NS_ERROR_NO_AGGREGATION;
 
   return GetSingleton()->QueryInterface(aIID, aResult);
 }
 
 nsCategoryManager::nsCategoryManager()
-  : MemoryUniReporter("explicit/xpcom/category-manager",
-                       KIND_HEAP, UNITS_BYTES,
-                       "Memory used for the XPCOM category manager.")
-  , mLock("nsCategoryManager")
+  : mLock("nsCategoryManager")
   , mSuppressNotifications(false)
 {
   PL_INIT_ARENA_POOL(&mArena, "CategoryManagerArena",
                      NS_CATEGORYMANAGER_ARENA_SIZE);
 }
 
 void
 nsCategoryManager::InitMemoryReporter()
@@ -473,20 +470,26 @@ inline CategoryNode*
 nsCategoryManager::get_category(const char* aName) {
   CategoryNode* node;
   if (!mTable.Get(aName, &node)) {
     return nullptr;
   }
   return node;
 }
 
-int64_t
-nsCategoryManager::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(CategoryManagerMallocSizeOf)
+
+NS_IMETHODIMP
+nsCategoryManager::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                  nsISupports* aData)
 {
-    return SizeOfIncludingThis(MallocSizeOf);
+  return MOZ_COLLECT_REPORT(
+    "explicit/xpcom/category-manager", KIND_HEAP, UNITS_BYTES,
+    SizeOfIncludingThis(CategoryManagerMallocSizeOf),
+    "Memory used for the XPCOM category manager.");
 }
 
 static size_t
 SizeOfCategoryManagerTableEntryExcludingThis(nsDepCharHashKey::KeyType aKey,
                                              const nsAutoPtr<CategoryNode> &aData,
                                              MallocSizeOf aMallocSizeOf,
                                              void* aUserArg)
 {
--- a/xpcom/components/nsCategoryManager.h
+++ b/xpcom/components/nsCategoryManager.h
@@ -93,22 +93,23 @@ private:
 
 
 /**
  * The main implementation of nsICategoryManager.
  *
  * This implementation is thread-safe.
  */
 class nsCategoryManager MOZ_FINAL
-  : public mozilla::MemoryUniReporter
-  , public nsICategoryManager
+  : public nsICategoryManager
+  , public nsIMemoryReporter
 {
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICATEGORYMANAGER
+  NS_DECL_NSIMEMORYREPORTER
 
   /**
    * Suppress or unsuppress notifications of category changes to the
    * observer service. This is to be used by nsComponentManagerImpl
    * on startup while reading the stored category list.
    */
   NS_METHOD SuppressNotifications(bool aSuppress);
 
@@ -119,18 +120,16 @@ public:
                         char** aOldValue = nullptr);
 
   static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
   void InitMemoryReporter();
 
   static nsCategoryManager* GetSingleton();
   static void Destroy();
 
-  int64_t Amount() MOZ_OVERRIDE;
-
 private:
   static nsCategoryManager* gCategoryManager;
 
   nsCategoryManager();
   ~nsCategoryManager();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
--- a/xpcom/components/nsComponentManager.cpp
+++ b/xpcom/components/nsComponentManager.cpp
@@ -292,20 +292,17 @@ nsComponentManagerImpl::Create(nsISuppor
         return NS_ERROR_FAILURE;
 
     return gComponentManager->QueryInterface(aIID, aResult);
 }
 
 static const int CONTRACTID_HASHTABLE_INITIAL_SIZE = 2048;
 
 nsComponentManagerImpl::nsComponentManagerImpl()
-    : MemoryUniReporter("explicit/xpcom/component-manager",
-                        KIND_HEAP, UNITS_BYTES,
-                        "Memory used for the XPCOM component manager.")
-    , mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE)
+    : mFactories(CONTRACTID_HASHTABLE_INITIAL_SIZE)
     , mContractIDs(CONTRACTID_HASHTABLE_INITIAL_SIZE)
     , mLock("nsComponentManagerImpl.mLock")
     , mStatus(NOT_INITIALIZED)
 {
 }
 
 nsTArray<const mozilla::Module*>* nsComponentManagerImpl::sStaticModules;
 
@@ -813,24 +810,24 @@ nsComponentManagerImpl::~nsComponentMana
     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Beginning destruction."));
 
     if (SHUTDOWN_COMPLETE != mStatus)
         Shutdown();
 
     PR_LOG(nsComponentManagerLog, PR_LOG_DEBUG, ("nsComponentManager: Destroyed."));
 }
 
-NS_IMPL_ISUPPORTS_INHERITED5(
+NS_IMPL_ISUPPORTS6(
     nsComponentManagerImpl,
-    MemoryUniReporter,
     nsIComponentManager,
     nsIServiceManager,
     nsIComponentRegistrar,
     nsISupportsWeakReference,
-    nsIInterfaceRequestor)
+    nsIInterfaceRequestor,
+    nsIMemoryReporter)
 
 nsresult
 nsComponentManagerImpl::GetInterface(const nsIID & uuid, void **result)
 {
     NS_WARNING("This isn't supported");
     // fall through to QI as anything QIable is a superset of what can be
     // got via the GetInterface()
     return  QueryInterface(uuid, result);
@@ -1685,20 +1682,26 @@ SizeOfContractIDsEntryExcludingThis(nsCS
                                     MallocSizeOf aMallocSizeOf,
                                     void* aUserArg)
 {
     // We don't measure the nsFactoryEntry data because its owned by mFactories
     // (which measures them in SizeOfFactoriesEntryExcludingThis).
     return aKey.SizeOfExcludingThisMustBeUnshared(aMallocSizeOf);
 }
 
-int64_t
-nsComponentManagerImpl::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(ComponentManagerMallocSizeOf)
+
+NS_IMETHODIMP
+nsComponentManagerImpl::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                       nsISupports* aData)
 {
-    return SizeOfIncludingThis(MallocSizeOf);
+    return MOZ_COLLECT_REPORT(
+        "explicit/xpcom/component-manager", KIND_HEAP, UNITS_BYTES,
+        SizeOfIncludingThis(ComponentManagerMallocSizeOf),
+        "Memory used for the XPCOM component manager.");
 }
 
 size_t
 nsComponentManagerImpl::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
     size_t n = aMallocSizeOf(this);
     n += mLoaderMap.SizeOfExcludingThis(nullptr, aMallocSizeOf);
     n += mFactories.SizeOfExcludingThis(SizeOfFactoriesEntryExcludingThis, aMallocSizeOf);
--- a/xpcom/components/nsComponentManager.h
+++ b/xpcom/components/nsComponentManager.h
@@ -114,28 +114,29 @@ private:
     mozilla::Mutex mMutex;
     volatile PRThread* mOwnerThread;
 };
 
 typedef mozilla::BaseAutoLock<SafeMutex> SafeMutexAutoLock;
 typedef mozilla::BaseAutoUnlock<SafeMutex> SafeMutexAutoUnlock;
 
 class nsComponentManagerImpl MOZ_FINAL
-    : public mozilla::MemoryUniReporter
-    , public nsIComponentManager
+    : public nsIComponentManager
     , public nsIServiceManager
     , public nsSupportsWeakReference
     , public nsIComponentRegistrar
     , public nsIInterfaceRequestor
+    , public nsIMemoryReporter
 {
 public:
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINTERFACEREQUESTOR
     NS_DECL_NSICOMPONENTMANAGER
     NS_DECL_NSICOMPONENTREGISTRAR
+    NS_DECL_NSIMEMORYREPORTER
 
     static nsresult Create(nsISupports* aOuter, REFNSIID aIID, void** aResult);
 
     nsresult RegistryLocationForFile(nsIFile* aFile,
                                      nsCString& aResult);
     nsresult FileForRegistryLocation(const nsCString &aLocation,
                                      nsIFile **aSpec);
 
@@ -308,17 +309,16 @@ public:
 
     inline PendingServiceInfo* AddPendingService(const nsCID& aServiceCID,
                                                  PRThread* aThread);
     inline void RemovePendingService(const nsCID& aServiceCID);
     inline PRThread* GetPendingServiceThread(const nsCID& aServiceCID) const;
 
     nsTArray<PendingServiceInfo> mPendingServices;
 
-    int64_t Amount() MOZ_OVERRIDE;
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
 
 private:
     ~nsComponentManagerImpl();
 };
 
 
 #define NS_MAX_FILENAME_LEN     1024
--- a/xpcom/reflect/xptinfo/public/XPTInterfaceInfoManager.h
+++ b/xpcom/reflect/xptinfo/public/XPTInterfaceInfoManager.h
@@ -21,21 +21,22 @@ class XPTHeader;
 class XPTInterfaceDirectoryEntry;
 class xptiInterfaceEntry;
 class xptiInterfaceInfo;
 class xptiTypelibGuts;
 
 namespace mozilla {
 
 class XPTInterfaceInfoManager MOZ_FINAL
-    : public mozilla::MemoryUniReporter
-    , public nsIInterfaceInfoManager
+    : public nsIInterfaceInfoManager
+    , public nsIMemoryReporter
 {
     NS_DECL_THREADSAFE_ISUPPORTS
     NS_DECL_NSIINTERFACEINFOMANAGER
+    NS_DECL_NSIMEMORYREPORTER
 
 public:
     // GetSingleton() is infallible
     static XPTInterfaceInfoManager* GetSingleton();
     static void FreeInterfaceInfoManager();
 
     void GetScriptableInterfaces(nsCOMArray<nsIInterfaceInfo>& aInterfaces);
 
@@ -44,17 +45,16 @@ public:
     static Mutex& GetResolveLock()
     {
         return GetSingleton()->mResolveLock;
     }
 
     xptiInterfaceEntry* GetInterfaceEntryForIID(const nsIID *iid);
 
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf);
-    int64_t Amount() MOZ_OVERRIDE;
 
 private:
     XPTInterfaceInfoManager();
     ~XPTInterfaceInfoManager();
 
     void InitMemoryReporter();
 
     void RegisterXPTHeader(XPTHeader* aHeader);
--- a/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
+++ b/xpcom/reflect/xptinfo/src/xptiInterfaceInfoManager.cpp
@@ -17,46 +17,51 @@
 #include "nsString.h"
 #include "nsISupportsArray.h"
 #include "nsArrayEnumerator.h"
 #include "nsDirectoryService.h"
 #include "nsIMemoryReporter.h"
 
 using namespace mozilla;
 
-NS_IMPL_ISUPPORTS_INHERITED1(
+NS_IMPL_ISUPPORTS2(
   XPTInterfaceInfoManager,
-  MemoryUniReporter,
-  nsIInterfaceInfoManager)
+  nsIInterfaceInfoManager,
+  nsIMemoryReporter)
 
 static StaticRefPtr<XPTInterfaceInfoManager> gInterfaceInfoManager;
 
 size_t
 XPTInterfaceInfoManager::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
 {
     size_t n = aMallocSizeOf(this);
     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     // The entries themselves are allocated out of an arena accounted
     // for elsewhere, so don't measure them
     n += mWorkingSet.mIIDTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
     n += mWorkingSet.mNameTable.SizeOfExcludingThis(nullptr, aMallocSizeOf);
     return n;
 }
 
-int64_t
-XPTInterfaceInfoManager::Amount()
+MOZ_DEFINE_MALLOC_SIZE_OF(XPTIMallocSizeOf)
+
+NS_IMETHODIMP
+XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
+                                        nsISupports* aData)
 {
-    size_t n = SizeOfIncludingThis(MallocSizeOf);
+    size_t amount = SizeOfIncludingThis(XPTIMallocSizeOf);
 
     // Measure gXPTIStructArena here, too.  This is a bit grotty because it
     // doesn't belong to the XPTIInterfaceInfoManager, but there's no
     // obviously better place to measure it.
-    n += XPT_SizeOfArena(gXPTIStructArena, MallocSizeOf);
+    amount += XPT_SizeOfArena(gXPTIStructArena, XPTIMallocSizeOf);
 
-    return n;
+    return MOZ_COLLECT_REPORT(
+        "explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
+        "Memory used by the XPCOM typelib system.");
 }
 
 // static
 XPTInterfaceInfoManager*
 XPTInterfaceInfoManager::GetSingleton()
 {
     if (!gInterfaceInfoManager) {
         gInterfaceInfoManager = new XPTInterfaceInfoManager();
@@ -67,19 +72,17 @@ XPTInterfaceInfoManager::GetSingleton()
 
 void
 XPTInterfaceInfoManager::FreeInterfaceInfoManager()
 {
     gInterfaceInfoManager = nullptr;
 }
 
 XPTInterfaceInfoManager::XPTInterfaceInfoManager()
-    :   MemoryUniReporter("explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES,
-                          "Memory used by the XPCOM typelib system."),
-        mWorkingSet(),
+    :   mWorkingSet(),
         mResolveLock("XPTInterfaceInfoManager.mResolveLock")
 {
 }
 
 XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
 {
     // We only do this on shutdown of the service.
     mWorkingSet.InvalidateInterfaceInfos();