Bug 1082128 - Make id to string conversion in DMD use a class. r=njn
authorAndrew McCreight <continuation@gmail.com>
Fri, 24 Oct 2014 13:44:33 -0700
changeset 212301 37e6b0283f65dd04aa9de3bdd1cb15b51661ace1
parent 212300 ca03ec2697992a17bc28354d4e0fba64a26553c1
child 212302 1b4e8921ba1659f3233e24b856cf6f51c85a095f
push id27704
push userkwierso@gmail.com
push dateSat, 25 Oct 2014 01:25:30 +0000
treeherdermozilla-central@e37231060eb4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1082128
milestone36.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 1082128 - Make id to string conversion in DMD use a class. r=njn
memory/replace/dmd/DMD.cpp
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -1590,65 +1590,81 @@ ClearReports()
 }
 
 MOZ_EXPORT bool
 IsRunning()
 {
   return gIsDMDRunning;
 }
 
-// This function converts an integer to base-32. |aBuf| must have space for at
-// least eight chars, which is the space needed to hold 'Dffffff' (including
-// the terminating null char), which is the base-32 representation of
-// 0xffffffff.
-//
-// We use base-32 values for indexing into the traceTable and the frameTable,
-// for the following reasons.
-//
-// - Base-32 gives more compact indices than base-16.
-//
-// - 32 is a power-of-two, which makes the necessary div/mod calculations fast.
-//
-// - We can (and do) choose non-numeric digits for base-32. When
-//   inspecting/debugging the JSON output, non-numeric indices are easier to
-//   search for than numeric indices.
-//
-char* Base32(uint32_t aN, char* aBuf, size_t aBufLen)
+class ToIdStringConverter MOZ_FINAL
 {
-  static const char digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef";
+public:
+  ToIdStringConverter() : mNextId(0) { mIdMap.init(512); }
+
+  // Converts a pointer to a unique ID. Reuses the existing ID for the pointer if
+  // it's been seen before.
+  const char* ToIdString(const void* aPtr)
+  {
+    uint32_t id;
+    PointerIdMap::AddPtr p = mIdMap.lookupForAdd(aPtr);
+    if (!p) {
+      id = mNextId++;
+      (void)mIdMap.add(p, aPtr, id);
+    } else {
+      id = p->value();
+    }
+    return Base32(id);
+  }
+
+  size_t sizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+  {
+    return mIdMap.sizeOfExcludingThis(aMallocSizeOf);
+  }
 
-  char* b = aBuf + aBufLen - 1;
-  *b = '\0';
-  do {
-    b--;
-    if (b == aBuf) {
-      MOZ_CRASH("Base32 buffer too small");
-    }
-    *b = digits[aN % 32];
-    aN /= 32;
-  } while (aN);
-
-  return b;
-}
+private:
+  // This function converts an integer to base-32. |aBuf| must have space for at
+  // least eight chars, which is the space needed to hold 'Dffffff' (including
+  // the terminating null char), which is the base-32 representation of
+  // 0xffffffff.
+  //
+  // We use base-32 values for indexing into the traceTable and the frameTable,
+  // for the following reasons.
+  //
+  // - Base-32 gives more compact indices than base-16.
+  //
+  // - 32 is a power-of-two, which makes the necessary div/mod calculations fast.
+  //
+  // - We can (and do) choose non-numeric digits for base-32. When
+  //   inspecting/debugging the JSON output, non-numeric indices are easier to
+  //   search for than numeric indices.
+  //
+  char* Base32(uint32_t aN)
+  {
+    static const char digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdef";
 
-// Converts a pointer to a unique ID. Reuses the existing ID for the pointer if
-// it's been seen before.
-static const char* Id(PointerIdMap& aIdMap, uint32_t& aNextId,
-                      const void* aPtr, char* aBuf, size_t aBufLen)
-{
-  uint32_t id;
-  PointerIdMap::AddPtr p = aIdMap.lookupForAdd(aPtr);
-  if (!p) {
-    id = aNextId++;
-    (void)aIdMap.add(p, aPtr, id);
-  } else {
-    id = p->value();
+    char* b = mIdBuf + kIdBufLen - 1;
+    *b = '\0';
+    do {
+      b--;
+      if (b == mIdBuf) {
+        MOZ_CRASH("Base32 buffer too small");
+      }
+      *b = digits[aN % 32];
+      aN /= 32;
+    } while (aN);
+
+    return b;
   }
-  return Base32(id, aBuf, aBufLen);
-}
+
+  PointerIdMap mIdMap;
+  uint32_t mNextId;
+  static const size_t kIdBufLen = 16;
+  char mIdBuf[kIdBufLen];
+};
 
 static void
 AnalyzeReportsImpl(JSONWriter& aWriter)
 {
   if (!gIsDMDRunning) {
     return;
   }
 
@@ -1659,85 +1675,80 @@ AnalyzeReportsImpl(JSONWriter& aWriter)
   auto locService = InfallibleAllocPolicy::new_<CodeAddressService>();
 
   StackTraceSet usedStackTraces;
   usedStackTraces.init(512);
 
   PointerSet usedPcs;
   usedPcs.init(512);
 
-  PointerIdMap idMap;
-  idMap.init(512);
+  size_t iscSize;
 
   static int analysisCount = 1;
   StatusMsg("Dump %d {\n", analysisCount++);
 
   aWriter.Start();
   {
-    #define ID(p) Id(idMap, id, p, idBuf, idBufLen)
-
     aWriter.IntProperty("version", kOutputVersionNumber);
 
     aWriter.StartObjectProperty("invocation");
     {
       aWriter.StringProperty("dmdEnvVar", gOptions->DMDEnvVar());
       aWriter.IntProperty("sampleBelowSize", gOptions->SampleBelowSize());
     }
     aWriter.EndObject();
 
     StatusMsg("  Constructing the heap block list...\n");
 
-    static const size_t idBufLen = 16;
-    char idBuf[idBufLen];
-    uint32_t id = 0;
+    ToIdStringConverter isc;
 
     aWriter.StartArrayProperty("blockList");
     {
       for (BlockTable::Range r = gBlockTable->all(); !r.empty(); r.popFront()) {
         const Block& b = r.front();
         b.AddStackTracesToTable(usedStackTraces);
 
         aWriter.StartObjectElement(aWriter.SingleLineStyle);
         {
           if (!b.IsSampled()) {
             aWriter.IntProperty("req", b.ReqSize());
             if (b.SlopSize() > 0) {
               aWriter.IntProperty("slop", b.SlopSize());
             }
           }
-          aWriter.StringProperty("alloc", ID(b.AllocStackTrace()));
+          aWriter.StringProperty("alloc", isc.ToIdString(b.AllocStackTrace()));
           if (b.NumReports() > 0) {
             aWriter.StartArrayProperty("reps");
             {
               if (b.ReportStackTrace1()) {
-                aWriter.StringElement(ID(b.ReportStackTrace1()));
+                aWriter.StringElement(isc.ToIdString(b.ReportStackTrace1()));
               }
               if (b.ReportStackTrace2()) {
-                aWriter.StringElement(ID(b.ReportStackTrace2()));
+                aWriter.StringElement(isc.ToIdString(b.ReportStackTrace2()));
               }
             }
             aWriter.EndArray();
           }
         }
         aWriter.EndObject();
       }
     }
     aWriter.EndArray();
 
     StatusMsg("  Constructing the stack trace table...\n");
 
     aWriter.StartObjectProperty("traceTable");
     {
       for (StackTraceSet::Enum e(usedStackTraces); !e.empty(); e.popFront()) {
         const StackTrace* const st = e.front();
-        aWriter.StartArrayProperty(ID(st), aWriter.SingleLineStyle);
+        aWriter.StartArrayProperty(isc.ToIdString(st), aWriter.SingleLineStyle);
         {
           for (uint32_t i = 0; i < st->Length(); i++) {
             const void* pc = st->Pc(i);
-            aWriter.StringElement(ID(pc));
+            aWriter.StringElement(isc.ToIdString(pc));
             usedPcs.put(pc);
           }
         }
         aWriter.EndArray();
       }
     }
     aWriter.EndObject();
 
@@ -1749,22 +1760,22 @@ AnalyzeReportsImpl(JSONWriter& aWriter)
       char locBuf[locBufLen];
 
       for (PointerSet::Enum e(usedPcs); !e.empty(); e.popFront()) {
         const void* const pc = e.front();
 
         // Use 0 for the frame number. See the JSON format description comment
         // in DMD.h to understand why.
         locService->GetLocation(0, pc, locBuf, locBufLen);
-        aWriter.StringProperty(ID(pc), locBuf);
+        aWriter.StringProperty(isc.ToIdString(pc), locBuf);
       }
     }
     aWriter.EndObject();
 
-    #undef ID
+    iscSize = isc.sizeOfExcludingThis(MallocSizeOf);
   }
   aWriter.End();
 
   if (gOptions->ShowDumpStats()) {
     Sizes sizes;
     SizeOfInternal(&sizes);
 
     static const size_t kBufLen = 64;
@@ -1797,17 +1808,17 @@ AnalyzeReportsImpl(JSONWriter& aWriter)
 
     StatusMsg("      Location service:      %10s bytes\n",
       Show(locService->SizeOfIncludingThis(MallocSizeOf), buf1, kBufLen));
     StatusMsg("      Used stack traces set: %10s bytes\n",
       Show(usedStackTraces.sizeOfExcludingThis(MallocSizeOf), buf1, kBufLen));
     StatusMsg("      Used PCs set:          %10s bytes\n",
       Show(usedPcs.sizeOfExcludingThis(MallocSizeOf), buf1, kBufLen));
     StatusMsg("      Pointer ID map:        %10s bytes\n",
-      Show(idMap.sizeOfExcludingThis(MallocSizeOf), buf1, kBufLen));
+      Show(iscSize, buf1, kBufLen));
 
     StatusMsg("    }\n");
     StatusMsg("    Counts {\n");
 
     size_t hits   = locService->NumCacheHits();
     size_t misses = locService->NumCacheMisses();
     size_t requests = hits + misses;
     StatusMsg("      Location service:    %10s requests\n",