mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1124754: Use approximate object counts when testing takeCensus, to avoid being flummoxed by SpiderMonkey implementation details. r=shu
--HG-- extra : rebase_source : 21d82c9b552c2e2f72e35e3c74f660c7a99341a6
This commit is contained in:
parent
670653d955
commit
fb57bc6ba1
@ -106,12 +106,12 @@ const Census = {};
|
||||
};
|
||||
}
|
||||
|
||||
function missingProp() {
|
||||
throw "Census mismatch: subject lacks property present in basis";
|
||||
function missingProp(prop) {
|
||||
throw "Census mismatch: subject lacks property present in basis: " + uneval(prop);
|
||||
}
|
||||
|
||||
function extraProp() {
|
||||
throw "Census mismatch: subject has property not present in basis";
|
||||
function extraProp(prop) {
|
||||
throw "Census mismatch: subject has property not present in basis: " + uneval(prop);
|
||||
}
|
||||
|
||||
// Return a walker that checks that the subject census has counts all equal to
|
||||
@ -130,4 +130,22 @@ const Census = {};
|
||||
extra: () => Census.walkAnything
|
||||
});
|
||||
|
||||
// Return a walker that checks that the subject census has at most as many
|
||||
// items of each category as |basis|.
|
||||
Census.assertAllNotMoreThan = makeBasisChecker({
|
||||
compare: (subject, basis) => assertEq(subject <= basis, true),
|
||||
missing: missingProp,
|
||||
extra: () => Census.walkAnything
|
||||
});
|
||||
|
||||
// Return a walker that checks that the subject census has within |fudge|
|
||||
// items of each category of the count in |basis|.
|
||||
Census.assertAllWithin = function (fudge, basis) {
|
||||
return makeBasisChecker({
|
||||
compare: (subject, basis) => assertEq(Math.abs(subject - basis) <= fudge, true),
|
||||
missing: missingProp,
|
||||
extra: () => Census.walkAnything
|
||||
})(basis);
|
||||
}
|
||||
|
||||
})();
|
||||
|
@ -1,70 +1,49 @@
|
||||
// Debugger.Memory.prototype.takeCensus behaves plausibly as we allocate and drop objects.
|
||||
// Debugger.Memory.prototype.takeCensus behaves plausibly as we allocate objects.
|
||||
|
||||
// Exact object counts vary in ways we can't predict. For example,
|
||||
// BaselineScripts can hold onto "template objects", which exist only to hold
|
||||
// the shape and type for newly created objects. When BaselineScripts are
|
||||
// discarded, these template objects go with them.
|
||||
//
|
||||
// So instead of expecting precise counts, we expect counts that are at least as
|
||||
// many as we would expect given the object graph we've built.
|
||||
|
||||
load(libdir + 'census.js');
|
||||
|
||||
// A Debugger with no debuggees had better not find anything.
|
||||
var dbg = new Debugger;
|
||||
var census0 = dbg.memory.takeCensus();
|
||||
Census.walkCensus(census0, "census0", Census.assertAllZeros);
|
||||
|
||||
var g1 = newGlobal();
|
||||
g1.eval('var a = [];');
|
||||
g1.eval('function add(f) { a.push({}); a.push(f ? (() => undefined) : null); }');
|
||||
g1.eval('function remove() { a.pop(); a.pop(); }');
|
||||
g1.add();
|
||||
g1.remove();
|
||||
|
||||
// Adding a global shouldn't cause any counts to *decrease*.
|
||||
dbg.addDebuggee(g1);
|
||||
var census1 = dbg.memory.takeCensus();
|
||||
Census.walkCensus(census1, "census1", Census.assertAllNotLessThan(census0));
|
||||
|
||||
function pointCheck(label, lhs, rhs, objComp, funComp) {
|
||||
print(label);
|
||||
try {
|
||||
assertEq(objComp(lhs.objects.Object.count, rhs.objects.Object.count), true);
|
||||
assertEq(funComp(lhs.objects.Function.count, rhs.objects.Function.count), true);
|
||||
} catch (ex) {
|
||||
print("pointCheck failed: " + ex);
|
||||
print("lhs: " + JSON.stringify(lhs, undefined, 2));
|
||||
print("rhs: " + JSON.stringify(rhs, undefined, 2));
|
||||
|
||||
// Do it again, and put the result where Mozilla's continuous integration
|
||||
// code will find it.
|
||||
var upload_dir = os.getenv("MOZ_UPLOAD_DIR") || ".";
|
||||
redirect(upload_dir + "/Memory-takeCensus-02.txt");
|
||||
print("pointCheck failed: " + ex);
|
||||
print("lhs: " + JSON.stringify(lhs, undefined, 2));
|
||||
print("rhs: " + JSON.stringify(rhs, undefined, 2));
|
||||
|
||||
throw ex;
|
||||
}
|
||||
function newGlobalWithDefs() {
|
||||
var g = newGlobal();
|
||||
g.eval(`
|
||||
function times(n, fn) {
|
||||
var a=[];
|
||||
for (var i = 0; i<n; i++)
|
||||
a.push(fn());
|
||||
return a;
|
||||
}`);
|
||||
return g;
|
||||
}
|
||||
|
||||
function eq(lhs, rhs) { return lhs === rhs; }
|
||||
function lt(lhs, rhs) { return lhs < rhs; }
|
||||
function gt(lhs, rhs) { return lhs > rhs; }
|
||||
// Allocate a large number of various types of objects, and check that census
|
||||
// finds them.
|
||||
var g = newGlobalWithDefs();
|
||||
dbg.addDebuggee(g);
|
||||
|
||||
// As we increase the number of reachable objects, the census should
|
||||
// reflect that.
|
||||
g1.add(false);
|
||||
var census2 = dbg.memory.takeCensus();
|
||||
pointCheck("census2", census2, census1, gt, eq);
|
||||
g.eval('var objs = times(100, () => ({}));');
|
||||
g.eval('var rxs = times(200, () => /foo/);');
|
||||
g.eval('var ars = times(400, () => []);');
|
||||
g.eval('var fns = times(800, () => () => {});');
|
||||
|
||||
g1.add(true);
|
||||
var census3 = dbg.memory.takeCensus();
|
||||
pointCheck("census3", census3, census2, gt, gt);
|
||||
|
||||
g1.add(false);
|
||||
var census4 = dbg.memory.takeCensus();
|
||||
pointCheck("census4", census4, census3, gt, eq);
|
||||
|
||||
// As we decrease the number of reachable objects, the census counts should go
|
||||
// down. Note that since the census does its own reachability analysis, we don't
|
||||
// need to GC here to see the counts drop.
|
||||
g1.remove();
|
||||
var census5 = dbg.memory.takeCensus();
|
||||
pointCheck("census5", census5, census4, lt, eq);
|
||||
|
||||
g1.remove();
|
||||
var census6 = dbg.memory.takeCensus();
|
||||
pointCheck("census6", census6, census5, lt, lt);
|
||||
var census1 = dbg.memory.takeCensus();
|
||||
Census.walkCensus(census1, "census1",
|
||||
Census.assertAllNotLessThan(
|
||||
{ 'objects':
|
||||
{ 'Object': { count: 100 },
|
||||
'RegExp': { count: 200 },
|
||||
'Array': { count: 400 },
|
||||
'Function': { count: 800 }
|
||||
}
|
||||
}));
|
||||
|
Loading…
Reference in New Issue
Block a user