1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/lib/sdk/deprecated/memory.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,129 @@ 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 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +"use strict"; 1.8 + 1.9 +module.metadata = { 1.10 + "stability": "deprecated" 1.11 +}; 1.12 + 1.13 +const { Cc, Ci, Cu, components } = require("chrome"); 1.14 +const { when: unload } = require("../system/unload") 1.15 + 1.16 +var trackedObjects = {}; 1.17 +const Compacter = { 1.18 + notify: function() { 1.19 + var newTrackedObjects = {}; 1.20 + 1.21 + for (let name in trackedObjects) { 1.22 + let oldBin = trackedObjects[name]; 1.23 + let newBin = []; 1.24 + let strongRefs = []; 1.25 + 1.26 + for (let i = 0, l = oldBin.length; i < l; i++) { 1.27 + let strongRef = oldBin[i].weakref.get(); 1.28 + 1.29 + if (strongRef && strongRefs.indexOf(strongRef) == -1) { 1.30 + strongRefs.push(strongRef); 1.31 + newBin.push(oldBin[i]); 1.32 + } 1.33 + } 1.34 + 1.35 + if (newBin.length) 1.36 + newTrackedObjects[name] = newBin; 1.37 + } 1.38 + 1.39 + trackedObjects = newTrackedObjects; 1.40 + } 1.41 +}; 1.42 + 1.43 +var timer = Cc["@mozilla.org/timer;1"] 1.44 + .createInstance(Ci.nsITimer); 1.45 +timer.initWithCallback(Compacter, 1.46 + 5000, 1.47 + Ci.nsITimer.TYPE_REPEATING_SLACK); 1.48 + 1.49 +function track(object, bin, stackFrameNumber) { 1.50 + var frame = components.stack.caller; 1.51 + var weakref = Cu.getWeakReference(object); 1.52 + 1.53 + if (!bin && 'constructor' in object) 1.54 + bin = object.constructor.name; 1.55 + if (bin == "Object") 1.56 + bin = frame.name; 1.57 + if (!bin) 1.58 + bin = "generic"; 1.59 + if (!(bin in trackedObjects)) 1.60 + trackedObjects[bin] = []; 1.61 + 1.62 + if (stackFrameNumber > 0) 1.63 + for (var i = 0; i < stackFrameNumber; i++) 1.64 + frame = frame.caller; 1.65 + 1.66 + trackedObjects[bin].push({weakref: weakref, 1.67 + created: new Date(), 1.68 + filename: frame.filename, 1.69 + lineNo: frame.lineNumber, 1.70 + bin: bin}); 1.71 +} 1.72 +exports.track = track; 1.73 + 1.74 +var getBins = exports.getBins = function getBins() { 1.75 + var names = []; 1.76 + for (let name in trackedObjects) 1.77 + names.push(name); 1.78 + return names; 1.79 +}; 1.80 + 1.81 +function getObjects(bin) { 1.82 + var results = []; 1.83 + 1.84 + function getLiveObjectsInBin(bin) { 1.85 + for (let i = 0, l = bin.length; i < l; i++) { 1.86 + let object = bin[i].weakref.get(); 1.87 + 1.88 + if (object) { 1.89 + results.push(bin[i]); 1.90 + } 1.91 + } 1.92 + } 1.93 + 1.94 + if (bin) { 1.95 + if (bin in trackedObjects) 1.96 + getLiveObjectsInBin(trackedObjects[bin]); 1.97 + } 1.98 + else { 1.99 + for (let name in trackedObjects) 1.100 + getLiveObjectsInBin(trackedObjects[name]); 1.101 + } 1.102 + 1.103 + return results; 1.104 +} 1.105 +exports.getObjects = getObjects; 1.106 + 1.107 +function gc() { 1.108 + // Components.utils.forceGC() doesn't currently perform 1.109 + // cycle collection, which means that e.g. DOM elements 1.110 + // won't be collected by it. Fortunately, there are 1.111 + // other ways... 1.112 + var test_utils = Cc["@mozilla.org/appshell/appShellService;1"] 1.113 + .getService(Ci.nsIAppShellService) 1.114 + .hiddenDOMWindow 1.115 + .QueryInterface(Ci.nsIInterfaceRequestor) 1.116 + .getInterface(Ci.nsIDOMWindowUtils); 1.117 + test_utils.garbageCollect(); 1.118 + // Clean metadata for dead objects 1.119 + Compacter.notify(); 1.120 + // Not sure why, but sometimes it appears that we don't get 1.121 + // them all with just one CC, so let's do it again. 1.122 + test_utils.garbageCollect(); 1.123 +}; 1.124 +exports.gc = gc; 1.125 + 1.126 +unload(_ => { 1.127 + trackedObjects = {}; 1.128 + if (timer) { 1.129 + timer.cancel(); 1.130 + timer = null; 1.131 + } 1.132 +});