Bug 820566 - DMD: Improve testing by using a script to filter out platform-specific stuff in the output. r=jlebar.
authorNicholas Nethercote <nnethercote@mozilla.com>
Sun, 06 Jan 2013 19:18:13 -0800
changeset 117851 fdfc52d62d5262b1c3ef48471c7880ab6751ef54
parent 117850 d86f67959794702f4fa90cea6bbb54731029a2e3
child 117852 13cf1c8cceab1bba587c4a123b1bb7957dd7f3e4
push id20712
push usernnethercote@mozilla.com
push dateMon, 07 Jan 2013 03:54:49 +0000
treeherdermozilla-inbound@fdfc52d62d52 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlebar
bugs820566
milestone20.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 820566 - DMD: Improve testing by using a script to filter out platform-specific stuff in the output. r=jlebar.
memory/replace/dmd/DMD.cpp
memory/replace/dmd/check_test_output.py
memory/replace/dmd/test-expected.dmd
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -777,22 +777,16 @@ static StackTraceTable* gStackTraceTable
 void
 StackTrace::Print(const Writer& aWriter, LocationService* aLocService) const
 {
   if (mLength == 0) {
     W("   (empty)\n");
     return;
   }
 
-  if (gMode == Test) {
-    // Don't print anything because there's too much variation.
-    W("   (stack omitted due to test mode)\n");
-    return;
-  }
-
   for (uint32_t i = 0; i < mLength; i++) {
     aLocService->WriteLocation(aWriter, Pc(i));
   }
 }
 
 /* static */ const StackTrace*
 StackTrace::Get(Thread* aT)
 {
@@ -807,17 +801,17 @@ StackTrace::Get(Thread* aT)
   // On Linux, something similar can happen;  see bug 824340.
   // So let's just release it on all platforms.
   StackTrace tmp;
   {
     AutoUnlockState unlock;
     // In normal operation, skip=3 gets us past various malloc wrappers into
     // more interesting stuff.  But in test mode we need to skip a bit less to
     // sufficiently differentiate some similar stacks.
-    uint32_t skip = (gMode == Test) ? 2 : 3;
+    uint32_t skip = 2;
     nsresult rv = NS_StackWalk(StackWalkCallback, skip, &tmp, 0, nullptr);
     if (NS_FAILED(rv) || tmp.mLength == 0) {
       tmp.mLength = 0;
     }
   }
 
   StackTraceTable::AddPtr p = gStackTraceTable->lookupForAdd(&tmp);
   if (!p) {
@@ -1574,17 +1568,17 @@ BadArg(const char* aArg)
 static void
 NopStackWalkCallback(void* aPc, void* aSp, void* aClosure)
 {
 }
 #endif
 
 // Note that fopen() can allocate.
 static FILE*
-OpenTestOrStressFile(const char* aFilename)
+OpenOutputFile(const char* aFilename)
 {
   FILE* fp = fopen(aFilename, "w");
   if (!fp) {
     StatusMsg("can't create %s file: %s\n", aFilename, strerror(errno));
     exit(1);
   }
   return fp;
 }
@@ -1687,31 +1681,31 @@ Init(const malloc_table_t* aMallocTable)
 
   gStackTraceTable = InfallibleAllocPolicy::new_<StackTraceTable>();
   gStackTraceTable->init(8192);
 
   gBlockTable = InfallibleAllocPolicy::new_<BlockTable>();
   gBlockTable->init(8192);
 
   if (gMode == Test) {
-    // OpenTestOrStressFile() can allocate.  So do this before setting
+    // OpenOutputFile() can allocate.  So do this before setting
     // gIsDMDRunning so those allocations don't show up in our results.  Once
     // gIsDMDRunning is set we are intercepting malloc et al. in earnest.
-    FILE* fp = OpenTestOrStressFile("test.dmd");
+    FILE* fp = OpenOutputFile("test.dmd");
     gIsDMDRunning = true;
 
     StatusMsg("running test mode...\n");
     RunTestMode(fp);
     StatusMsg("finished test mode\n");
     fclose(fp);
     exit(0);
   }
 
   if (gMode == Stress) {
-    FILE* fp = OpenTestOrStressFile("stress.dmd");
+    FILE* fp = OpenOutputFile("stress.dmd");
     gIsDMDRunning = true;
 
     StatusMsg("running stress mode...\n");
     RunStressMode(fp);
     StatusMsg("finished stress mode\n");
     fclose(fp);
     exit(0);
   }
@@ -1822,22 +1816,16 @@ PrintSortedTraceAndFrameRecords(const Wr
                                 const char* aStr, const char* astr,
                                 const TraceRecordTable& aTraceRecordTable,
                                 size_t aCategoryUsableSize,
                                 size_t aTotalUsableSize)
 {
   PrintSortedRecords(aWriter, aLocService, aStr, astr, aTraceRecordTable,
                      aCategoryUsableSize, aTotalUsableSize);
 
-  // Frame records are totally dependent on vagaries of stack traces, so we
-  // can't show them in test mode.
-  if (gMode == Test) {
-    return;
-  }
-
   FrameRecordTable frameRecordTable;
   (void)frameRecordTable.init(2048);
   for (TraceRecordTable::Range r = aTraceRecordTable.all();
        !r.empty();
        r.popFront()) {
     const TraceRecord& tr = r.front();
     const StackTrace* st = tr.mAllocStackTrace;
 
new file mode 100755
--- /dev/null
+++ b/memory/replace/dmd/check_test_output.py
@@ -0,0 +1,139 @@
+#! /usr/bin/python
+
+"""This script takes the file produced by DMD's test mode and checks its
+correctness.
+
+It produces the following output files: $TMP/test-{fixed,filtered,diff}.dmd.
+
+It runs the appropriate fix* script to get nice stack traces.  It also
+filters out platform-specific details from the test output file.
+
+Note: you must run this from the same directory that you invoked DMD's test
+mode, otherwise the fix* script will not work properly, because some of the
+paths in the test output are relative.
+
+"""
+
+from __future__ import print_function
+
+import os
+import platform
+import re
+import subprocess
+import sys
+import tempfile
+
+
+def main():
+
+    # Arguments
+
+    if (len(sys.argv) != 3):
+        print("usage:", sys.argv[0], "<srcdir> <test-output>")
+        sys.exit(1)
+
+    srcdir = sys.argv[1]
+
+    # Filenames
+
+    tempdir = tempfile.gettempdir()
+    in_name       = sys.argv[2]
+    fixed_name    = tempdir + os.sep + "test-fixed.dmd"
+    filtered_name = tempdir + os.sep + "test-filtered.dmd"
+    diff_name     = tempdir + os.sep + "test-diff.dmd"
+    expected_name = srcdir + os.sep + \
+                    "memory/replace/dmd/test-expected.dmd"
+
+    # Fix stack traces
+
+    print("fixing output to", fixed_name)
+
+    sysname = platform.system()
+    if sysname == "Linux":
+        fix = srcdir + os.sep + "tools/rb/fix-linux-stack.pl"
+    elif sysname == "Darwin":
+        fix = srcdir + os.sep + "tools/rb/fix_macosx_stack.py"
+    else:
+        print("unhandled platform: " + sysname, file=sys.stderr)
+        sys.exit(1)
+
+    subprocess.call(fix, stdin=open(in_name, "r"),
+                         stdout=open(fixed_name, "w"))
+
+    # Filter output
+
+    # In stack trace records we filter out all stack frames that contain a
+    # function whose name doesn't begin with "RunTestMode".  And the remaining
+    # ones have their line numbers omitted, unfortunately, because they are
+    # often off by one or two and this can vary between builds (e.g. debug vs
+    # non-debug).
+    #
+    # As for stack frame records, we complete eliminate all those that contain
+    # a function whose name doesn't begin with "RunTestMode", because such
+    # stack frame records are highly dependent on the exact forms of stack
+    # traces.
+
+    print("filtering output to", filtered_name)
+
+    with open(fixed_name, "r") as fin, \
+         open(filtered_name, "w") as fout:
+
+        test_frame_re = re.compile(r".*(RunTestMode\w*).*(DMD.cpp)")
+
+        for line in fin:
+            if re.match(r" (Allocated at|Reported( again)? at)", line):
+                # It's a stack trace record.
+                print(line, end='', file=fout)
+
+                # Filter the stack trace -- only show RunTestMode* frames.
+                for frame in fin:
+                    if re.match(r"   ", frame):
+                        m = test_frame_re.match(frame)
+                        if m:
+                            print("   ...", m.group(1), "...", m.group(2),
+                                  file=fout)
+                    else:
+                        # We're past the stack trace.
+                        print(frame, end='', file=fout)
+                        break
+
+            elif re.search("in stack frame record", line):
+                # Stack frame record.  Get the whole thing (we know how many
+                # lines it has).
+                line2 = fin.next()
+                line3 = fin.next()
+                line4 = fin.next()
+                frame = fin.next()
+                line6 = fin.next()
+                m = test_frame_re.match(frame)
+                if m:
+                    # This is a stack frame record from RunTestMode* -- print
+                    # it, obscuring record numbers (which vary unpredictably).
+                    print(re.sub(r"record \d+ of \d+", "record M of N", line),
+                          end='', file=fout)
+                    print(line2, end='', file=fout)
+                    print(line3, end='', file=fout)
+                    print(line4, end='', file=fout)
+                    print("   ...", m.group(1), "...", m.group(2), file=fout)
+                    print(line6, end='', file=fout)
+
+            else:
+                # Some line that needs no special handling.  Copy it through.
+                print(line, end='', file=fout)
+
+    # Compare with expected output
+
+    print("diffing output to", diff_name)
+
+    ret = subprocess.call(["diff", "-u", filtered_name, expected_name],
+                          stdout=open(diff_name, "w"))
+
+    if ret == 0:
+        print("test PASSED")
+    else:
+        print("test FAILED (did you remember to run this script and Firefox "
+              "in the same directory?)")
+
+
+if __name__ == "__main__":
+    main()
--- a/memory/replace/dmd/test-expected.dmd
+++ b/memory/replace/dmd/test-expected.dmd
@@ -13,22 +13,34 @@ Twice-reported stack trace records
 
 ------------------------------------------------------------------
 Unreported stack trace records
 ------------------------------------------------------------------
 
 (none)
 
 ------------------------------------------------------------------
+Unreported stack frame records
+------------------------------------------------------------------
+
+(none)
+
+------------------------------------------------------------------
 Once-reported stack trace records
 ------------------------------------------------------------------
 
 (none)
 
 ------------------------------------------------------------------
+Once-reported stack frame records
+------------------------------------------------------------------
+
+(none)
+
+------------------------------------------------------------------
 Summary
 ------------------------------------------------------------------
 
 Total:                     0 bytes (100.00%) in       0 blocks (100.00%)
 Unreported:                0 bytes (  0.00%) in       0 blocks (  0.00%)
 Once-reported:             0 bytes (  0.00%) in       0 blocks (  0.00%)
 Twice-reported:            0 bytes (  0.00%) in       0 blocks (  0.00%)
 
@@ -42,190 +54,264 @@ Sample-below size = 1
 ------------------------------------------------------------------
 Twice-reported stack trace records
 ------------------------------------------------------------------
 
 Twice-reported: 1 block in stack trace record 1 of 4
  80 bytes (79 requested / 1 slop)
  0.53% of the heap (0.53% cumulative);  29.41% of twice-reported (29.41% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported again at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Twice-reported: 1 block in stack trace record 2 of 4
  80 bytes (78 requested / 2 slop)
  0.53% of the heap (1.05% cumulative);  29.41% of twice-reported (58.82% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported again at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Twice-reported: 1 block in stack trace record 3 of 4
  80 bytes (77 requested / 3 slop)
  0.53% of the heap (1.58% cumulative);  29.41% of twice-reported (88.24% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported again at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Twice-reported: 1 block in stack trace record 4 of 4
  32 bytes (30 requested / 2 slop)
  0.21% of the heap (1.79% cumulative);  11.76% of twice-reported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported again at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Unreported stack trace records
 ------------------------------------------------------------------
 
 Unreported: 1 block in stack trace record 1 of 4
  4,096 bytes (1 requested / 4,095 slop)
  27.00% of the heap (27.00% cumulative);  76.88% of unreported (76.88% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 9 blocks in stack trace record 2 of 4
  1,008 bytes (900 requested / 108 slop)
  6.65% of the heap (33.65% cumulative);  18.92% of unreported (95.80% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 2 blocks in stack trace record 3 of 4
  112 bytes (112 requested / 0 slop)
  0.74% of the heap (34.39% cumulative);  2.10% of unreported (97.90% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 2 blocks in stack trace record 4 of 4
  112 bytes (112 requested / 0 slop)
  0.74% of the heap (35.13% cumulative);  2.10% of unreported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
+
+------------------------------------------------------------------
+Unreported stack frame records
+------------------------------------------------------------------
+
+Unreported: 1 block from 1 stack trace record in stack frame record M of N
+ 4,096 bytes (1 requested / 4,095 slop)
+ 27.00% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 9 blocks from 1 stack trace record in stack frame record M of N
+ 1,008 bytes (900 requested / 108 slop)
+ 6.65% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 2 blocks from 1 stack trace record in stack frame record M of N
+ 112 bytes (112 requested / 0 slop)
+ 0.74% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 2 blocks from 1 stack trace record in stack frame record M of N
+ 112 bytes (112 requested / 0 slop)
+ 0.74% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Once-reported stack trace records
 ------------------------------------------------------------------
 
 Once-reported: 1 block in stack trace record 1 of 11
  8,192 bytes (4,097 requested / 4,095 slop)
  54.01% of the heap (54.01% cumulative);  85.62% of once-reported (85.62% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 2 of 11
  512 bytes (512 requested / 0 slop)
  3.38% of the heap (57.38% cumulative);  5.35% of once-reported (90.97% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 2 blocks in stack trace record 3 of 11
  240 bytes (240 requested / 0 slop)
  1.58% of the heap (58.97% cumulative);  2.51% of once-reported (93.48% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 2 blocks in stack trace record 4 of 11
  240 bytes (240 requested / 0 slop)
  1.58% of the heap (60.55% cumulative);  2.51% of once-reported (95.99% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 5 of 11
  96 bytes (96 requested / 0 slop)
  0.63% of the heap (61.18% cumulative);  1.00% of once-reported (96.99% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 6 of 11
  96 bytes (96 requested / 0 slop)
  0.63% of the heap (61.81% cumulative);  1.00% of once-reported (97.99% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 7 of 11
  80 bytes (80 requested / 0 slop)
  0.53% of the heap (62.34% cumulative);  0.84% of once-reported (98.83% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 8 of 11
  80 bytes (80 requested / 0 slop)
  0.53% of the heap (62.87% cumulative);  0.84% of once-reported (99.67% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 9 of 11
  16 bytes (10 requested / 6 slop)
  0.11% of the heap (62.97% cumulative);  0.17% of once-reported (99.83% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 10 of 11
  8 bytes (0 requested / 8 slop)
  0.05% of the heap (63.03% cumulative);  0.08% of once-reported (99.92% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 11 of 11
  8 bytes (0 requested / 8 slop)
  0.05% of the heap (63.08% cumulative);  0.08% of once-reported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
+
+------------------------------------------------------------------
+Once-reported stack frame records
+------------------------------------------------------------------
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 8,192 bytes (4,097 requested / 4,095 slop)
+ 54.01% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 512 bytes (512 requested / 0 slop)
+ 3.38% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 4 blocks from 3 stack trace records in stack frame record M of N
+ 416 bytes (416 requested / 0 slop)
+ 2.74% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 4 blocks from 3 stack trace records in stack frame record M of N
+ 416 bytes (416 requested / 0 slop)
+ 2.74% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 16 bytes (10 requested / 6 slop)
+ 0.11% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 8 bytes (0 requested / 8 slop)
+ 0.05% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 8 bytes (0 requested / 8 slop)
+ 0.05% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Summary
 ------------------------------------------------------------------
 
 Total:                15,168 bytes (100.00%) in      31 blocks (100.00%)
 Unreported:            5,328 bytes ( 35.13%) in      14 blocks ( 45.16%)
 Once-reported:         9,568 bytes ( 63.08%) in      13 blocks ( 41.94%)
@@ -241,97 +327,147 @@ Sample-below size = 1
 ------------------------------------------------------------------
 Twice-reported stack trace records
 ------------------------------------------------------------------
 
 Twice-reported: 1 block in stack trace record 1 of 2
  80 bytes (77 requested / 3 slop)
  2.82% of the heap (2.82% cumulative);  90.91% of twice-reported (90.91% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported again at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Twice-reported: 1 block in stack trace record 2 of 2
  8 bytes (0 requested / 8 slop)
  0.28% of the heap (3.10% cumulative);  9.09% of twice-reported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported again at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Unreported stack trace records
 ------------------------------------------------------------------
 
 Unreported: 9 blocks in stack trace record 1 of 3
  1,008 bytes (900 requested / 108 slop)
  35.49% of the heap (35.49% cumulative);  48.84% of unreported (48.84% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 6 blocks in stack trace record 2 of 3
  528 bytes (528 requested / 0 slop)
  18.59% of the heap (54.08% cumulative);  25.58% of unreported (74.42% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 6 blocks in stack trace record 3 of 3
  528 bytes (528 requested / 0 slop)
  18.59% of the heap (72.68% cumulative);  25.58% of unreported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
+
+------------------------------------------------------------------
+Unreported stack frame records
+------------------------------------------------------------------
+
+Unreported: 9 blocks from 1 stack trace record in stack frame record M of N
+ 1,008 bytes (900 requested / 108 slop)
+ 35.49% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 6 blocks from 1 stack trace record in stack frame record M of N
+ 528 bytes (528 requested / 0 slop)
+ 18.59% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 6 blocks from 1 stack trace record in stack frame record M of N
+ 528 bytes (528 requested / 0 slop)
+ 18.59% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Once-reported stack trace records
 ------------------------------------------------------------------
 
 Once-reported: 1 block in stack trace record 1 of 4
  512 bytes (512 requested / 0 slop)
  18.03% of the heap (18.03% cumulative);  74.42% of once-reported (74.42% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 2 of 4
  80 bytes (79 requested / 1 slop)
  2.82% of the heap (20.85% cumulative);  11.63% of once-reported (86.05% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 3 of 4
  80 bytes (78 requested / 2 slop)
  2.82% of the heap (23.66% cumulative);  11.63% of once-reported (97.67% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Once-reported: 1 block in stack trace record 4 of 4
  16 bytes (10 requested / 6 slop)
  0.56% of the heap (24.23% cumulative);  2.33% of once-reported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
  Reported at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
+
+------------------------------------------------------------------
+Once-reported stack frame records
+------------------------------------------------------------------
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 512 bytes (512 requested / 0 slop)
+ 18.03% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 80 bytes (79 requested / 1 slop)
+ 2.82% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 80 bytes (78 requested / 2 slop)
+ 2.82% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Once-reported: 1 block from 1 stack trace record in stack frame record M of N
+ 16 bytes (10 requested / 6 slop)
+ 0.56% of the heap;  0.00% of once-reported
+ PC is
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Summary
 ------------------------------------------------------------------
 
 Total:                 2,840 bytes (100.00%) in      27 blocks (100.00%)
 Unreported:            2,064 bytes ( 72.68%) in      21 blocks ( 77.78%)
 Once-reported:           688 bytes ( 24.23%) in       4 blocks ( 14.81%)
@@ -353,61 +489,113 @@ Twice-reported stack trace records
 ------------------------------------------------------------------
 Unreported stack trace records
 ------------------------------------------------------------------
 
 Unreported: ~4 blocks in stack trace record 1 of 7
  ~512 bytes (~512 requested / ~0 slop)
  35.96% of the heap (35.96% cumulative);  35.96% of unreported (35.96% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 1 block in stack trace record 2 of 7
  256 bytes (256 requested / 0 slop)
  17.98% of the heap (53.93% cumulative);  17.98% of unreported (53.93% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 1 block in stack trace record 3 of 7
  144 bytes (144 requested / 0 slop)
  10.11% of the heap (64.04% cumulative);  10.11% of unreported (64.04% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: 1 block in stack trace record 4 of 7
  128 bytes (128 requested / 0 slop)
  8.99% of the heap (73.03% cumulative);  8.99% of unreported (73.03% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: ~1 block in stack trace record 5 of 7
  ~128 bytes (~128 requested / ~0 slop)
  8.99% of the heap (82.02% cumulative);  8.99% of unreported (82.02% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: ~1 block in stack trace record 6 of 7
  ~128 bytes (~128 requested / ~0 slop)
  8.99% of the heap (91.01% cumulative);  8.99% of unreported (91.01% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
 
 Unreported: ~1 block in stack trace record 7 of 7
  ~128 bytes (~128 requested / ~0 slop)
  8.99% of the heap (100.00% cumulative);  8.99% of unreported (100.00% cumulative)
  Allocated at
-   (stack omitted due to test mode)
+   ... RunTestMode ... DMD.cpp
+
+------------------------------------------------------------------
+Unreported stack frame records
+------------------------------------------------------------------
+
+Unreported: ~4 blocks from ~1 stack trace record in stack frame record M of N
+ ~512 bytes (~512 requested / ~0 slop)
+ 35.96% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 1 block from 1 stack trace record in stack frame record M of N
+ 256 bytes (256 requested / 0 slop)
+ 17.98% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 1 block from 1 stack trace record in stack frame record M of N
+ 144 bytes (144 requested / 0 slop)
+ 10.11% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: 1 block from 1 stack trace record in stack frame record M of N
+ 128 bytes (128 requested / 0 slop)
+ 8.99% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: ~1 block from ~1 stack trace record in stack frame record M of N
+ ~128 bytes (~128 requested / ~0 slop)
+ 8.99% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: ~1 block from ~1 stack trace record in stack frame record M of N
+ ~128 bytes (~128 requested / ~0 slop)
+ 8.99% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
+
+Unreported: ~1 block from ~1 stack trace record in stack frame record M of N
+ ~128 bytes (~128 requested / ~0 slop)
+ 8.99% of the heap;  0.00% of unreported
+ PC is
+   ... RunTestMode ... DMD.cpp
 
 ------------------------------------------------------------------
 Once-reported stack trace records
 ------------------------------------------------------------------
 
 (none)
 
 ------------------------------------------------------------------
+Once-reported stack frame records
+------------------------------------------------------------------
+
+(none)
+
+------------------------------------------------------------------
 Summary
 ------------------------------------------------------------------
 
 Total:                ~1,424 bytes (100.00%) in     ~10 blocks (100.00%)
 Unreported:           ~1,424 bytes (100.00%) in     ~10 blocks (100.00%)
 Once-reported:            ~0 bytes (  0.00%) in      ~0 blocks (  0.00%)
 Twice-reported:           ~0 bytes (  0.00%) in      ~0 blocks (  0.00%)