tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_HeapSnapshot_takeCensus_11.js (4105B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 "use strict";
      4 
      5 // Test that Debugger.Memory.prototype.takeCensus and
      6 // HeapSnapshot.prototype.takeCensus return the same data for the same heap
      7 // graph.
      8 
      9 function doLiveAndOfflineCensus(g, dbg, opts) {
     10  dbg.memory.allocationSamplingProbability = 1;
     11  dbg.memory.trackingAllocationSites = true;
     12  g.eval(`                                          // 1
     13         (function unsafeAtAnySpeed() {             // 2
     14           for (var i = 0; i < 100; i++) {          // 3
     15             this.markers.push(allocationMarker()); // 4
     16           }                                        // 5
     17         }());                                      // 6
     18         `);
     19  dbg.memory.trackingAllocationSites = false;
     20 
     21  return {
     22    live: dbg.memory.takeCensus(opts),
     23    offline: saveHeapSnapshotAndTakeCensus(dbg, opts),
     24  };
     25 }
     26 
     27 function getMarkerSize(g, dbg) {
     28  dbg.memory.allocationSamplingProbability = 1;
     29  dbg.memory.trackingAllocationSites = true;
     30  g.eval("var hold = allocationMarker();");
     31  dbg.memory.trackingAllocationSites = false;
     32  const live = dbg.memory.takeCensus({
     33    breakdown: { by: "objectClass", then: { by: "count" } },
     34  });
     35  g.hold = null;
     36  equal(live.AllocationMarker.count, 1);
     37  return live.AllocationMarker.bytes;
     38 }
     39 
     40 function run_test() {
     41  const g = newGlobal();
     42  const dbg = new Debugger(g);
     43 
     44  g.eval("this.markers = []");
     45  const markerSize = getMarkerSize(g, dbg);
     46 
     47  // First, test that we get the same counts and sizes as we allocate and retain
     48  // more things.
     49 
     50  let prevCount = 0;
     51  let prevBytes = 0;
     52 
     53  for (let i = 0; i < 10; i++) {
     54    const { live, offline } = doLiveAndOfflineCensus(g, dbg, {
     55      breakdown: { by: "objectClass", then: { by: "count" } },
     56    });
     57 
     58    equal(live.AllocationMarker.count, offline.AllocationMarker.count);
     59    equal(live.AllocationMarker.bytes, offline.AllocationMarker.bytes);
     60    equal(live.AllocationMarker.count, prevCount + 100);
     61    equal(live.AllocationMarker.bytes, prevBytes + 100 * markerSize);
     62 
     63    prevCount = live.AllocationMarker.count;
     64    prevBytes = live.AllocationMarker.bytes;
     65  }
     66 
     67  // Second, test that the reported allocation stacks and counts and sizes at
     68  // those allocation stacks match up.
     69 
     70  const { live, offline } = doLiveAndOfflineCensus(g, dbg, {
     71    breakdown: { by: "objectClass", then: { by: "allocationStack" } },
     72  });
     73 
     74  equal(live.AllocationMarker.size, offline.AllocationMarker.size);
     75  // One stack with the loop further above, and another stack featuring the call
     76  // right above.
     77  equal(live.AllocationMarker.size, 2);
     78 
     79  // Note that because SavedFrame stacks reconstructed from an offline heap
     80  // snapshot don't have the same principals as SavedFrame stacks captured from
     81  // a live stack, the live and offline allocation stacks won't be identity
     82  // equal, but should be structurally the same.
     83 
     84  const liveEntries = [];
     85  live.AllocationMarker.forEach((v, k) => {
     86    dumpn("Allocation stack:");
     87    k.toString()
     88      .split(/\n/g)
     89      .forEach(s => dumpn(s));
     90 
     91    equal(k.functionDisplayName, "unsafeAtAnySpeed");
     92    equal(k.line, 4);
     93 
     94    liveEntries.push([k.toString(), v]);
     95  });
     96 
     97  const offlineEntries = [];
     98  offline.AllocationMarker.forEach((v, k) => {
     99    dumpn("Allocation stack:");
    100    k.toString()
    101      .split(/\n/g)
    102      .forEach(s => dumpn(s));
    103 
    104    equal(k.functionDisplayName, "unsafeAtAnySpeed");
    105    equal(k.line, 4);
    106 
    107    offlineEntries.push([k.toString(), v]);
    108  });
    109 
    110  const sortEntries = (a, b) => {
    111    if (a[0] < b[0]) {
    112      return -1;
    113    } else if (a[0] > b[0]) {
    114      return 1;
    115    }
    116    return 0;
    117  };
    118  liveEntries.sort(sortEntries);
    119  offlineEntries.sort(sortEntries);
    120 
    121  equal(liveEntries.length, live.AllocationMarker.size);
    122  equal(liveEntries.length, offlineEntries.length);
    123 
    124  for (let i = 0; i < liveEntries.length; i++) {
    125    equal(liveEntries[i][0], offlineEntries[i][0]);
    126    equal(liveEntries[i][1].count, offlineEntries[i][1].count);
    127    equal(liveEntries[i][1].bytes, offlineEntries[i][1].bytes);
    128  }
    129 
    130  do_test_finished();
    131 }