Bug 955942 (part 2) - Remove MemoryUniReporter. r=mccr8.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sat, 07 Dec 2013 22:09:10 -0800
changeset 167225 f33d8dee54dae96575dcddedc85328ba80de6f0d
parent 167224 9de53a0258931b7382c8edc9fa3ec193e884d9cd
child 167226 0208d8f09898e4824355c6a8845b3a9fbf8b18e7
push idunknown
push userunknown
push dateunknown
reviewersmccr8
bugs955942
milestone29.0a1
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();