testing/mochitest/cc-analyzer.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/testing/mochitest/cc-analyzer.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,126 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +function CCAnalyzer() {
     1.9 +}
    1.10 +
    1.11 +CCAnalyzer.prototype = {
    1.12 +  clear: function () {
    1.13 +    this.callback = null;
    1.14 +    this.processingCount = 0;
    1.15 +    this.graph = {};
    1.16 +    this.roots = [];
    1.17 +    this.garbage = [];
    1.18 +    this.edges = [];
    1.19 +    this.listener = null;
    1.20 +  },
    1.21 +
    1.22 +  run: function (aCallback) {
    1.23 +    this.clear();
    1.24 +    this.callback = aCallback;
    1.25 +
    1.26 +    this.listener = Cc["@mozilla.org/cycle-collector-logger;1"].
    1.27 +      createInstance(Ci.nsICycleCollectorListener);
    1.28 +
    1.29 +    this.listener.disableLog = true;
    1.30 +    this.listener.wantAfterProcessing = true;
    1.31 +
    1.32 +    this.runCC(3);
    1.33 +  },
    1.34 +
    1.35 +  runCC: function (aCounter) {
    1.36 +    let utils = window.QueryInterface(Ci.nsIInterfaceRequestor).
    1.37 +        getInterface(Ci.nsIDOMWindowUtils);
    1.38 +
    1.39 +    if (aCounter > 1) {
    1.40 +      utils.garbageCollect();
    1.41 +      setTimeout(this.runCC.bind(this, aCounter - 1), 0);
    1.42 +    } else {
    1.43 +      utils.garbageCollect(this.listener);
    1.44 +      this.processLog();
    1.45 +    }
    1.46 +  },
    1.47 +
    1.48 +  processLog: function () {
    1.49 +    // Process entire heap step by step in 5K chunks
    1.50 +    for (let i = 0; i < 5000; i++) {
    1.51 +      if (!this.listener.processNext(this)) {
    1.52 +        this.callback();
    1.53 +        this.clear();
    1.54 +        return;
    1.55 +      }
    1.56 +    }
    1.57 +
    1.58 +    // Next chunk on timeout.
    1.59 +    setTimeout(this.processLog.bind(this), 0);
    1.60 +  },
    1.61 +
    1.62 +  noteRefCountedObject: function (aAddress, aRefCount, aObjectDescription) {
    1.63 +    let o = this.ensureObject(aAddress);
    1.64 +    o.address = aAddress;
    1.65 +    o.refcount = aRefCount;
    1.66 +    o.name = aObjectDescription;
    1.67 +  },
    1.68 +
    1.69 +  noteGCedObject: function (aAddress, aMarked, aObjectDescription) {
    1.70 +    let o = this.ensureObject(aAddress);
    1.71 +    o.address = aAddress;
    1.72 +    o.gcmarked = aMarked;
    1.73 +    o.name = aObjectDescription;
    1.74 +  },
    1.75 +
    1.76 +  noteEdge: function (aFromAddress, aToAddress, aEdgeName) {
    1.77 +    let fromObject = this.ensureObject(aFromAddress);
    1.78 +    let toObject = this.ensureObject(aToAddress);
    1.79 +    fromObject.edges.push({name: aEdgeName, to: toObject});
    1.80 +    toObject.owners.push({name: aEdgeName, from: fromObject});
    1.81 +
    1.82 +    this.edges.push({
    1.83 +      name: aEdgeName,
    1.84 +      from: fromObject,
    1.85 +      to: toObject
    1.86 +    });
    1.87 +  },
    1.88 +
    1.89 +  describeRoot: function (aAddress, aKnownEdges) {
    1.90 +    let o = this.ensureObject(aAddress);
    1.91 +    o.root = true;
    1.92 +    o.knownEdges = aKnownEdges;
    1.93 +    this.roots.push(o);
    1.94 +  },
    1.95 +
    1.96 +  describeGarbage: function (aAddress) {
    1.97 +    let o = this.ensureObject(aAddress);
    1.98 +    o.garbage = true;
    1.99 +    this.garbage.push(o);
   1.100 +  },
   1.101 +
   1.102 +  ensureObject: function (aAddress) {
   1.103 +    if (!this.graph[aAddress])
   1.104 +      this.graph[aAddress] = new CCObject();
   1.105 +
   1.106 +    return this.graph[aAddress];
   1.107 +  },
   1.108 +
   1.109 +  find: function (aText) {
   1.110 +    let result = [];
   1.111 +    for each (let o in this.graph) {
   1.112 +      if (!o.garbage && o.name.indexOf(aText) >= 0)
   1.113 +        result.push(o);
   1.114 +    }
   1.115 +    return result;
   1.116 +  }
   1.117 +};
   1.118 +
   1.119 +function CCObject() {
   1.120 +  this.name = "";
   1.121 +  this.address = null;
   1.122 +  this.refcount = 0;
   1.123 +  this.gcmarked = false;
   1.124 +  this.root = false;
   1.125 +  this.garbage = false;
   1.126 +  this.knownEdges = 0;
   1.127 +  this.edges = [];
   1.128 +  this.owners = [];
   1.129 +}

mercurial