Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 function CCAnalyzer() {
6 }
8 CCAnalyzer.prototype = {
9 clear: function () {
10 this.callback = null;
11 this.processingCount = 0;
12 this.graph = {};
13 this.roots = [];
14 this.garbage = [];
15 this.edges = [];
16 this.listener = null;
17 },
19 run: function (aCallback) {
20 this.clear();
21 this.callback = aCallback;
23 this.listener = Cc["@mozilla.org/cycle-collector-logger;1"].
24 createInstance(Ci.nsICycleCollectorListener);
26 this.listener.disableLog = true;
27 this.listener.wantAfterProcessing = true;
29 this.runCC(3);
30 },
32 runCC: function (aCounter) {
33 let utils = window.QueryInterface(Ci.nsIInterfaceRequestor).
34 getInterface(Ci.nsIDOMWindowUtils);
36 if (aCounter > 1) {
37 utils.garbageCollect();
38 setTimeout(this.runCC.bind(this, aCounter - 1), 0);
39 } else {
40 utils.garbageCollect(this.listener);
41 this.processLog();
42 }
43 },
45 processLog: function () {
46 // Process entire heap step by step in 5K chunks
47 for (let i = 0; i < 5000; i++) {
48 if (!this.listener.processNext(this)) {
49 this.callback();
50 this.clear();
51 return;
52 }
53 }
55 // Next chunk on timeout.
56 setTimeout(this.processLog.bind(this), 0);
57 },
59 noteRefCountedObject: function (aAddress, aRefCount, aObjectDescription) {
60 let o = this.ensureObject(aAddress);
61 o.address = aAddress;
62 o.refcount = aRefCount;
63 o.name = aObjectDescription;
64 },
66 noteGCedObject: function (aAddress, aMarked, aObjectDescription) {
67 let o = this.ensureObject(aAddress);
68 o.address = aAddress;
69 o.gcmarked = aMarked;
70 o.name = aObjectDescription;
71 },
73 noteEdge: function (aFromAddress, aToAddress, aEdgeName) {
74 let fromObject = this.ensureObject(aFromAddress);
75 let toObject = this.ensureObject(aToAddress);
76 fromObject.edges.push({name: aEdgeName, to: toObject});
77 toObject.owners.push({name: aEdgeName, from: fromObject});
79 this.edges.push({
80 name: aEdgeName,
81 from: fromObject,
82 to: toObject
83 });
84 },
86 describeRoot: function (aAddress, aKnownEdges) {
87 let o = this.ensureObject(aAddress);
88 o.root = true;
89 o.knownEdges = aKnownEdges;
90 this.roots.push(o);
91 },
93 describeGarbage: function (aAddress) {
94 let o = this.ensureObject(aAddress);
95 o.garbage = true;
96 this.garbage.push(o);
97 },
99 ensureObject: function (aAddress) {
100 if (!this.graph[aAddress])
101 this.graph[aAddress] = new CCObject();
103 return this.graph[aAddress];
104 },
106 find: function (aText) {
107 let result = [];
108 for each (let o in this.graph) {
109 if (!o.garbage && o.name.indexOf(aText) >= 0)
110 result.push(o);
111 }
112 return result;
113 }
114 };
116 function CCObject() {
117 this.name = "";
118 this.address = null;
119 this.refcount = 0;
120 this.gcmarked = false;
121 this.root = false;
122 this.garbage = false;
123 this.knownEdges = 0;
124 this.edges = [];
125 this.owners = [];
126 }