Bug 831193 (part 1) - Remove uses of NS_MEMORY_REPORTER_IMPLEMENT from nsMemoryReporterManager.cpp. r=jlebar.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 15 Jan 2013 23:02:45 -0800
changeset 119235 2d791defc804f4f33585370876beba3591d00c8b
parent 119234 e7b94c8df70c6ee84fce581803644c021f0dccd5
child 119236 0238a6bf8f85784f264fba749c36126e8b609e07
push id21550
push usernnethercote@mozilla.com
push dateFri, 18 Jan 2013 05:46:02 +0000
treeherdermozilla-inbound@2d791defc804 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlebar
bugs831193
milestone21.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 831193 (part 1) - Remove uses of NS_MEMORY_REPORTER_IMPLEMENT from nsMemoryReporterManager.cpp. r=jlebar.
xpcom/base/nsIMemoryReporter.idl
xpcom/base/nsMemoryReporterManager.cpp
--- a/xpcom/base/nsIMemoryReporter.idl
+++ b/xpcom/base/nsIMemoryReporter.idl
@@ -425,17 +425,20 @@ void RunReporters();
   }
 
 namespace mozilla {
 
 // The following base class reduces the amount of boilerplate code required for
 // memory reporters.  You just need to provide the following.
 // - The constant values: path, kind, units, and description.  They are passed
 //   to the MemoryReporterBase constructor.
-// - An Amount() method.  It can use the MallocSizeOf method if necessary.
+// - A (private) Amount() or (public) GetAmount() method.  It can use the 
+//   MallocSizeOf method if necessary.  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:
 // - "explicit/dom/xyzzy"     --> DOMXyzzyReporter
 // - "js-compartments/system" --> JSCompartmentsSystemReporter
 //
 class MemoryReporterBase : public nsIMemoryReporter
 {
@@ -484,17 +487,22 @@ public:
 
   NS_IMETHOD GetDescription(nsACString& aDescription)
   {
     aDescription.Assign(mDescription);
     return NS_OK;
   }
 
 protected:
-  virtual int64_t Amount() = 0; 
+  virtual int64_t Amount()
+  {
+    // We only reach here if neither GetAmount() nor Amount() was overridden.
+    MOZ_ASSERT(false);
+    return 0;
+  }
 
   NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MallocSizeOf)
 
   const nsCString mPath;
   const int32_t   mKind;
   const int32_t   mUnits;
   const nsCString mDescription;
 };
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -29,46 +29,16 @@
 
 using namespace mozilla;
 
 #if defined(MOZ_MEMORY)
 #  define HAVE_JEMALLOC_STATS 1
 #  include "mozmemory.h"
 #endif  // MOZ_MEMORY
 
-#ifdef XP_UNIX
-
-#include <sys/time.h>
-#include <sys/resource.h>
-
-#define HAVE_PAGE_FAULT_REPORTERS 1
-static nsresult GetHardPageFaults(int64_t *n)
-{
-    struct rusage usage;
-    int err = getrusage(RUSAGE_SELF, &usage);
-    if (err != 0) {
-        return NS_ERROR_FAILURE;
-    }
-    *n = usage.ru_majflt;
-    return NS_OK;
-}
-
-static nsresult GetSoftPageFaults(int64_t *n)
-{
-    struct rusage usage;
-    int err = getrusage(RUSAGE_SELF, &usage);
-    if (err != 0) {
-        return NS_ERROR_FAILURE;
-    }
-    *n = usage.ru_minflt;
-    return NS_OK;
-}
-
-#endif  // HAVE_PAGE_FAULT_REPORTERS
-
 #if defined(XP_LINUX)
 
 #include <unistd.h>
 static nsresult GetProcSelfStatmField(int field, int64_t *n)
 {
     // There are more than two fields, but we're only interested in the first
     // two.
     static const int MAX_FIELD = 2;
@@ -76,17 +46,17 @@ static nsresult GetProcSelfStatmField(in
     MOZ_ASSERT(field < MAX_FIELD, "bad field number");
     FILE *f = fopen("/proc/self/statm", "r");
     if (f) {
         int nread = fscanf(f, "%zu %zu", &fields[0], &fields[1]);
         fclose(f);
         if (nread == MAX_FIELD) {
             *n = fields[field] * getpagesize();
             return NS_OK;
-        } 
+        }
     }
     return NS_ERROR_FAILURE;
 }
 
 #define HAVE_VSIZE_AND_RESIDENT_REPORTERS 1
 static nsresult GetVsize(int64_t *n)
 {
     return GetProcSelfStatmField(0, n);
@@ -351,272 +321,331 @@ static nsresult GetResident(int64_t *n)
 }
 
 static nsresult GetResidentFast(int64_t *n)
 {
     return GetResident(n);
 }
 
 #define HAVE_PRIVATE_REPORTER
-static nsresult GetPrivate(int64_t *n)
+class PrivateReporter MOZ_FINAL : public MemoryReporterBase
 {
-    PROCESS_MEMORY_COUNTERS_EX pmcex;
-    pmcex.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
-
-    if (!GetProcessMemoryInfo(GetCurrentProcess(),
-                              (PPROCESS_MEMORY_COUNTERS) &pmcex, sizeof(pmcex)))
-    {
-        return NS_ERROR_FAILURE;
-    }
+public:
+    PrivateReporter()
+      : MemoryReporterBase("private", KIND_OTHER, UNITS_BYTES,
+"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.")
+    {}
 
-    *n = pmcex.PrivateUsage;
-    return NS_OK;
-}
+    NS_IMETHOD GetAmount(int64_t *aAmount)
+    {
+        PROCESS_MEMORY_COUNTERS_EX pmcex;
+        pmcex.cb = sizeof(PROCESS_MEMORY_COUNTERS_EX);
 
-NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Private,
-    "private",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetPrivate,
-    "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.")
+        if (!GetProcessMemoryInfo(
+                GetCurrentProcess(),
+                (PPROCESS_MEMORY_COUNTERS) &pmcex, sizeof(pmcex))) {
+            return NS_ERROR_FAILURE;
+        }
+
+        *aAmount = pmcex.PrivateUsage;
+        return NS_OK;
+    }
+};
 
 #endif  // XP_<PLATFORM>
 
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
-NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Vsize,
-    "vsize",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetVsize,
-    "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.")
+class VsizeReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    VsizeReporter()
+      : MemoryReporterBase("vsize", KIND_OTHER, UNITS_BYTES,
+"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 GetVsize(aAmount); }
+};
 
-NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Resident,
-    "resident",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetResident,
-    "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.")
+class ResidentReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    ResidentReporter()
+      : MemoryReporterBase("resident", KIND_OTHER, UNITS_BYTES,
+"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_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(ResidentFast,
-    "resident-fast",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetResidentFast,
-    "This is the same measurement as 'resident', but it tries to be as fast as "
-    "possible at the expense of accuracy.  On most platforms this is identical to "
-    "the 'resident' measurement, but on Mac it may over-count.  You should use "
-    "'resident-fast' where you care about latency of collection (e.g. in "
-    "telemetry).  Otherwise you should use 'resident'.")
+    NS_IMETHOD GetAmount(int64_t *aAmount) { return GetResident(aAmount); }
+};
+
+class ResidentFastReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    ResidentFastReporter()
+      : MemoryReporterBase("resident-fast", KIND_OTHER, UNITS_BYTES,
+"This is the same measurement as 'resident', but it tries to be as fast as "
+"possible at the expense of accuracy.  On most platforms this is identical to "
+"the 'resident' measurement, but on Mac it may over-count.  You should use "
+"'resident-fast' where you care about latency of collection (e.g. in "
+"telemetry).  Otherwise you should use 'resident'.")
+    {}
+
+    NS_IMETHOD GetAmount(int64_t *aAmount) { return GetResidentFast(aAmount); }
+};
 #endif  // HAVE_VSIZE_AND_RESIDENT_REPORTERS
 
-#ifdef HAVE_PAGE_FAULT_REPORTERS
-NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(PageFaultsSoft,
-    "page-faults-soft",
-    KIND_OTHER,
-    UNITS_COUNT_CUMULATIVE,
-    GetSoftPageFaults,
-    "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.")
+#ifdef XP_UNIX
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#define HAVE_PAGE_FAULT_REPORTERS 1
+
+class PageFaultsSoftReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    PageFaultsSoftReporter()
+      : MemoryReporterBase("page-faults-soft", KIND_OTHER,
+                           UNITS_COUNT_CUMULATIVE,
+"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_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(PageFaultsHard,
-    "page-faults-hard",
-    KIND_OTHER,
-    UNITS_COUNT_CUMULATIVE,
-    GetHardPageFaults,
-    "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)
+    {
+        struct rusage usage;
+        int err = getrusage(RUSAGE_SELF, &usage);
+        if (err != 0) {
+            return NS_ERROR_FAILURE;
+        }
+        *aAmount = usage.ru_minflt;
+        return NS_OK;
+    }
+};
+
+class PageFaultsHardReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    PageFaultsHardReporter()
+      : MemoryReporterBase("page-faults-hard", KIND_OTHER,
+                           UNITS_COUNT_CUMULATIVE,
+"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)
+    {
+        struct rusage usage;
+        int err = getrusage(RUSAGE_SELF, &usage);
+        if (err != 0) {
+            return NS_ERROR_FAILURE;
+        }
+        *aAmount = usage.ru_majflt;
+        return NS_OK;
+    }
+};
 #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).
  **/
 
-#if HAVE_JEMALLOC_STATS
-
-static int64_t GetHeapUnused()
-{
-    jemalloc_stats_t stats;
-    jemalloc_stats(&stats);
-    return (int64_t) (stats.mapped - stats.allocated);
-}
+#ifdef HAVE_JEMALLOC_STATS
 
-static int64_t GetHeapAllocated()
-{
-    jemalloc_stats_t stats;
-    jemalloc_stats(&stats);
-    return (int64_t) stats.allocated;
-}
-
-static int64_t GetHeapCommitted()
+class HeapCommittedReporter MOZ_FINAL : public MemoryReporterBase
 {
-    jemalloc_stats_t stats;
-    jemalloc_stats(&stats);
-    return (int64_t) stats.committed;
-}
-
-static int64_t GetHeapCommittedUnused()
-{
-    jemalloc_stats_t stats;
-    jemalloc_stats(&stats);
-    return stats.committed - stats.allocated;
-}
+public:
+    HeapCommittedReporter()
+      : MemoryReporterBase("heap-committed", KIND_OTHER, UNITS_BYTES,
+"Memory mapped by the heap allocator that is committed, i.e. in physical "
+"memory or paged to disk.  When 'heap-committed' is larger than "
+"'heap-allocated', the difference between the two values is likely due to "
+"external fragmentation; that is, the allocator allocated a large block of "
+"memory and is unable to decommit it because a small part of that block is "
+"currently in use.")
+    {}
+private:
+    int64_t Amount()
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        return (int64_t) stats.committed;
+    }
+};
 
-static int64_t GetHeapCommittedUnusedRatio()
+class HeapCommittedUnusedReporter MOZ_FINAL : public MemoryReporterBase
 {
-    jemalloc_stats_t stats;
-    jemalloc_stats(&stats);
-    return (int64_t) 10000 * (stats.committed - stats.allocated) /
-                              ((double)stats.allocated);
-}
-
-static int64_t GetHeapDirty()
-{
-    jemalloc_stats_t stats;
-    jemalloc_stats(&stats);
-    return (int64_t) stats.dirty;
-}
+public:
+    HeapCommittedUnusedReporter()
+      : MemoryReporterBase("heap-committed-unused", KIND_OTHER, UNITS_BYTES,
+"Committed bytes which do not correspond to an active allocation; i.e., "
+"'heap-committed' - 'heap-allocated'.  Although the allocator will waste some "
+"space under any circumstances, a large value here may indicate that the "
+"heap is highly fragmented.")
+    {}
+private:
+    int64_t Amount()
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        return stats.committed - stats.allocated;
+    }
+};
 
-NS_MEMORY_REPORTER_IMPLEMENT(HeapCommitted,
-    "heap-committed",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetHeapCommitted,
-    "Memory mapped by the heap allocator that is committed, i.e. in physical "
-    "memory or paged to disk.  When heap-committed is larger than "
-    "heap-allocated, the difference between the two values is likely due to "
-    "external fragmentation; that is, the allocator allocated a large block of "
-    "memory and is unable to decommit it because a small part of that block is "
-    "currently in use.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(HeapCommittedUnused,
-    "heap-committed-unused",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetHeapCommittedUnused,
-    "Committed bytes which do not correspond to an active allocation; i.e., "
-    "'heap-committed' - 'heap-allocated'.  Although the allocator will waste some "
-    "space under any circumstances, a large value here may indicate that the "
-    "heap is highly fragmented.")
+class HeapCommittedUnusedRatioReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    HeapCommittedUnusedRatioReporter()
+      : MemoryReporterBase("heap-committed-unused-ratio", KIND_OTHER,
+                           UNITS_PERCENTAGE,
+"Ratio of committed, unused bytes to allocated bytes; i.e., "
+"'heap-committed-unused' / 'heap-allocated'.  This measures the overhead of "
+"the heap allocator relative to amount of memory allocated.")
+    {}
+private:
+    int64_t Amount()
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        return (int64_t) 10000 * (stats.committed - stats.allocated) /
+                                  ((double)stats.allocated);
+    }
+};
 
-NS_MEMORY_REPORTER_IMPLEMENT(HeapCommittedUnusedRatio,
-    "heap-committed-unused-ratio",
-    KIND_OTHER,
-    UNITS_PERCENTAGE,
-    GetHeapCommittedUnusedRatio,
-    "Ratio of committed, unused bytes to allocated bytes; i.e., "
-    "'heap-committed-unused' / 'heap-allocated'.  This measures the overhead "
-    "of the heap allocator relative to amount of memory allocated.")
-
-NS_MEMORY_REPORTER_IMPLEMENT(HeapDirty,
-    "heap-dirty",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetHeapDirty,
-    "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.")
+class HeapDirtyReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    HeapDirtyReporter()
+      : MemoryReporterBase("heap-dirty", KIND_OTHER, UNITS_BYTES,
+"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()
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        return (int64_t) stats.dirty;
+    }
+};
 
-NS_MEMORY_REPORTER_IMPLEMENT(HeapUnused,
-    "heap-unused",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetHeapUnused,
-    "Memory mapped by the heap allocator that is not part of an active "
-    "allocation. Much of this memory may be uncommitted -- that is, it does not "
-    "take up space in physical memory or in the swap file.")
+class HeapUnusedReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    HeapUnusedReporter()
+      : MemoryReporterBase("heap-unused", KIND_OTHER, UNITS_BYTES,
+"Memory mapped by the heap allocator that is not part of an active "
+"allocation. Much of this memory may be uncommitted -- that is, it does not "
+"take up space in physical memory or in the swap file.")
+    {}
+private:
+    int64_t Amount()
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        return (int64_t) (stats.mapped - stats.allocated);
+    }
+};
 
-NS_MEMORY_REPORTER_IMPLEMENT(HeapAllocated,
-    "heap-allocated",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetHeapAllocated,
-    "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.)")
+class HeapAllocatedReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    HeapAllocatedReporter()
+      : MemoryReporterBase("heap-allocated", KIND_OTHER, UNITS_BYTES,
+"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()
+    {
+        jemalloc_stats_t stats;
+        jemalloc_stats(&stats);
+        return (int64_t) stats.allocated;
+    }
+};
 
 // The computation of "explicit" fails if "heap-allocated" isn't available,
 // which is why this is depends on HAVE_JEMALLOC_STATS.
-static nsresult GetExplicit(int64_t *n)
+class ExplicitReporter MOZ_FINAL : public MemoryReporterBase
 {
-    nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
-    if (mgr == nullptr)
-        return NS_ERROR_FAILURE;
-
-    return mgr->GetExplicit(n);
-}
+public:
+    ExplicitReporter()
+      : MemoryReporterBase("explicit", KIND_OTHER, UNITS_BYTES,
+"This is the same measurement as the root of the 'explicit' tree.  However, "
+"it is measured at a different time and so gives slightly different results.")
+    {}
 
-NS_FALLIBLE_MEMORY_REPORTER_IMPLEMENT(Explicit,
-    "explicit",
-    KIND_OTHER,
-    UNITS_BYTES,
-    GetExplicit,
-    "This is the same measurement as the root of the 'explicit' tree.  "
-    "However, it is measured at a different time and so gives slightly "
-    "different results.")
+    NS_IMETHOD GetAmount(int64_t *aAmount)
+    {
+        nsCOMPtr<nsIMemoryReporterManager> mgr = do_GetService("@mozilla.org/memory-reporter-manager;1");
+        if (mgr == nullptr)
+            return NS_ERROR_FAILURE;
+
+        return mgr->GetExplicit(aAmount);
+    }
+};
 #endif  // HAVE_JEMALLOC_STATS
 
-NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(AtomTableMallocSizeOf)
-
-static int64_t GetAtomTableSize() {
-  return NS_SizeOfAtomTablesIncludingThis(AtomTableMallocSizeOf);
-}
-
 // 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
 // NS_RegisterMemoryReporter call fails.  So instead we do it here.
-NS_MEMORY_REPORTER_IMPLEMENT(AtomTable,
-    "explicit/atom-tables",
-    KIND_HEAP,
-    UNITS_BYTES,
-    GetAtomTableSize,
-    "Memory used by the dynamic and static atoms tables.")
+class AtomTablesReporter MOZ_FINAL : public MemoryReporterBase
+{
+public:
+    AtomTablesReporter()
+      : MemoryReporterBase("explicit/atom-tables", KIND_HEAP, UNITS_BYTES,
+"Memory used by the dynamic and static atoms tables.")
+    {}
+private:
+    int64_t Amount() { return NS_SizeOfAtomTablesIncludingThis(MallocSizeOf); }
+};
 
 #ifdef MOZ_DMD
 
 namespace mozilla {
 namespace dmd {
 
-class MemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter
+class DMDMultiReporter MOZ_FINAL : public nsIMemoryMultiReporter
 {
 public:
-  MemoryReporter()
+  DMDMultiReporter()
   {}
 
   NS_DECL_ISUPPORTS
 
   NS_IMETHOD GetName(nsACString &name)
   {
     name.Assign("dmd");
     return NS_OK;
@@ -662,71 +691,68 @@ public:
   }
 
   NS_IMETHOD GetExplicitNonHeap(int64_t *n)
   {
     // No non-heap allocations.
     *n = 0;
     return NS_OK;
   }
-
 };
 
-NS_IMPL_ISUPPORTS1(MemoryReporter, nsIMemoryMultiReporter)
+NS_IMPL_ISUPPORTS1(DMDMultiReporter, nsIMemoryMultiReporter)
 
 } // namespace dmd
 } // namespace mozilla
 
 #endif  // MOZ_DMD
 
 /**
  ** nsMemoryReporterManager implementation
  **/
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryReporterManager, nsIMemoryReporterManager)
 
 NS_IMETHODIMP
 nsMemoryReporterManager::Init()
 {
-#if HAVE_JEMALLOC_STATS && defined(XP_LINUX)
+#if defined(HAVE_JEMALLOC_STATS) && defined(XP_LINUX)
     if (!jemalloc_stats)
         return NS_ERROR_FAILURE;
 #endif
 
-#define REGISTER(_x)  RegisterReporter(new NS_MEMORY_REPORTER_NAME(_x))
-
 #ifdef HAVE_JEMALLOC_STATS
-    REGISTER(HeapAllocated);
-    REGISTER(HeapUnused);
-    REGISTER(HeapCommitted);
-    REGISTER(HeapCommittedUnused);
-    REGISTER(HeapCommittedUnusedRatio);
-    REGISTER(HeapDirty);
-    REGISTER(Explicit);
+    RegisterReporter(new HeapAllocatedReporter);
+    RegisterReporter(new HeapUnusedReporter);
+    RegisterReporter(new HeapCommittedReporter);
+    RegisterReporter(new HeapCommittedUnusedReporter);
+    RegisterReporter(new HeapCommittedUnusedRatioReporter);
+    RegisterReporter(new HeapDirtyReporter);
+    RegisterReporter(new ExplicitReporter);
 #endif
 
 #ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
-    REGISTER(Vsize);
-    REGISTER(Resident);
-    REGISTER(ResidentFast);
+    RegisterReporter(new VsizeReporter);
+    RegisterReporter(new ResidentReporter);
+    RegisterReporter(new ResidentFastReporter);
 #endif
 
 #ifdef HAVE_PAGE_FAULT_REPORTERS
-    REGISTER(PageFaultsSoft);
-    REGISTER(PageFaultsHard);
+    RegisterReporter(new PageFaultsSoftReporter);
+    RegisterReporter(new PageFaultsHardReporter);
 #endif
 
 #ifdef HAVE_PRIVATE_REPORTER
-    REGISTER(Private);
+    RegisterReporter(new PrivateReporter);
 #endif
 
-    REGISTER(AtomTable);
+    RegisterReporter(new AtomTablesReporter);
 
 #ifdef MOZ_DMD
-    RegisterMultiReporter(new mozilla::dmd::MemoryReporter);
+    RegisterMultiReporter(new mozilla::dmd::DMDMultiReporter);
 #endif
 
 #if defined(XP_LINUX)
     nsMemoryInfoDumper::Initialize();
 #endif
 
     return NS_OK;
 }
@@ -798,17 +824,17 @@ nsMemoryReporterManager::UnregisterMulti
         return NS_ERROR_FAILURE;
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMemoryReporterManager::GetResident(int64_t *aResident)
 {
-#if HAVE_VSIZE_AND_RESIDENT_REPORTERS
+#ifdef HAVE_VSIZE_AND_RESIDENT_REPORTERS
     return ::GetResident(aResident);
 #else
     *aResident = 0;
     return NS_ERROR_NOT_AVAILABLE;
 #endif
 }
 
 #if defined(DEBUG) && !defined(MOZ_DMD)