Bug 1169710 - Part 4: Test the tenuring log; r=sfink

This commit is contained in:
Nick Fitzgerald 2015-07-10 19:14:09 -07:00
parent d1a1a41f90
commit bbb9205645
6 changed files with 311 additions and 0 deletions

View File

@ -0,0 +1,43 @@
// Test basic usage of drainTenurePromotionsLog() with various objects.
const root = newGlobal();
const dbg = new Debugger();
const wrappedRoot = dbg.addDebuggee(root)
dbg.memory.trackingAllocationSites = true;
dbg.memory.trackingTenurePromotions = true;
root.eval(`
(function immediate() {
this.tests = [
{ name: "({})", cls: "Object", obj: ({}) },
{ name: "[]", cls: "Array", obj: [] },
{ name: "new Object", cls: "Object", obj: new Object() },
{ name: "new Array", cls: "Array", obj: new Array() },
{ name: "new Date", cls: "Date", obj: new Date() },
];
}());
minorgc();
`);
const promotions = dbg.memory.drainTenurePromotionsLog();
// Assert that the promotions happen in chronological order.
let lastWhen = -Infinity;
for (let p of promotions) {
assertEq(p.timestamp >= lastWhen, true);
lastWhen = p.timestamp;
}
for (let { name, cls, obj } of root.tests) {
print(name + ": " + cls);
// The promoted object's allocation site should be in the log.
let wrappedObj = wrappedRoot.makeDebuggeeValue(obj);
let allocSite = wrappedObj.allocationSite;
let idx = promotions.map(x => x.frame).indexOf(allocSite);
assertEq(idx >= 0, true);
// The promoted object's class name should be present.
assertEq(promotions.map(x => x.class).indexOf(cls) >= 0, true);
}

View File

@ -0,0 +1,72 @@
// Test usage of drainTenurePromotionsLog() with multiple debuggees.
const root1 = newGlobal();
const root2 = newGlobal();
const dbg = new Debugger();
function tenureObjectsAndDrainLog(root) {
gc();
dbg.memory.trackingAllocationSites = true;
dbg.memory.trackingTenurePromotions = true;
root.eval(
`
(function immediate() {
this.tests = [
{ name: "({})", cls: "Object", obj: ({}) },
{ name: "[]", cls: "Array", obj: [] },
{ name: "new Object", cls: "Object", obj: new Object() },
{ name: "new Array", cls: "Array", obj: new Array() },
{ name: "new Date", cls: "Date", obj: new Date() },
];
}());
minorgc();
`
);
const promotions = dbg.memory.drainTenurePromotionsLog();
dbg.memory.trackingAllocationSites = false;
dbg.memory.trackingTenurePromotions = false;
return promotions;
}
{
dbg.addDebuggee(root1);
dbg.addDebuggee(root2);
// Should get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, true);
// and logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, true);
}
{
dbg.removeAllDebuggees();
// Should *not* get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, false);
// nor logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, false);
}
{
dbg.addDebuggee(root1);
// Should get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, true);
// but *not* logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, false);
}
{
dbg.removeAllDebuggees();
dbg.addDebuggee(root2);
// Should *not* get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, false);
// but should get logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, true);
}

View File

@ -0,0 +1,81 @@
// Test usage of drainTenurePromotionsLog() with multiple debuggers.
const root = newGlobal();
const dbg1 = new Debugger(root);
const dbg2 = new Debugger(root);
function setTracking(dbg, bool) {
dbg.memory.trackingAllocationSites = bool;
dbg.memory.trackingTenurePromotions = bool;
}
function tenureObjectsAndDrainLog() {
gc();
root.eval(
`
(function immediate() {
this.tests = [
{ name: "({})", cls: "Object", obj: ({}) },
{ name: "[]", cls: "Array", obj: [] },
{ name: "new Object", cls: "Object", obj: new Object() },
{ name: "new Array", cls: "Array", obj: new Array() },
{ name: "new Date", cls: "Date", obj: new Date() },
];
}());
minorgc();
`
);
const promotions2 = dbg2.memory.trackingTenurePromotions ? dbg2.memory.drainTenurePromotionsLog() : [];
const promotions1 = dbg1.memory.trackingTenurePromotions ? dbg1.memory.drainTenurePromotionsLog() : [];
setTracking(dbg1, false);
setTracking(dbg2, false);
return { promotions1, promotions2 };
}
{
setTracking(dbg1, true);
setTracking(dbg2, true);
const { promotions1, promotions2 } = tenureObjectsAndDrainLog();
// Should get logs in dbg1,
assertEq(!!promotions1.length, true);
// and logs in dbg2.
assertEq(!!promotions2.length, true);
}
{
setTracking(dbg1, false);
setTracking(dbg2, false);
const { promotions1, promotions2 } = tenureObjectsAndDrainLog();
// Should *not* get logs in dbg1,
assertEq(!!promotions1.length, false);
// nor logs in dbg2.
assertEq(!!promotions2.length, false);
}
{
setTracking(dbg1, true);
setTracking(dbg2, false);
const { promotions1, promotions2 } = tenureObjectsAndDrainLog();
// Should get logs in dbg1,
assertEq(!!promotions1.length, true);
// but *not* logs in dbg2.
assertEq(!!promotions2.length, false);
}
{
setTracking(dbg1, false);
setTracking(dbg2, true);
const { promotions1, promotions2 } = tenureObjectsAndDrainLog();
// Should *not* get logs in dbg1,
assertEq(!!promotions1.length, false);
// but *should* get logs in dbg2.
assertEq(!!promotions2.length, true);
}

View File

@ -0,0 +1,12 @@
// Test draining tenure log without tracking tenures.
const root = newGlobal();
const dbg = new Debugger(root);
let threw = false;
try {
dbg.drainTenurePromotionsLog();
} catch (e) {
threw = true;
}
assertEq(threw, true);

View File

@ -0,0 +1,30 @@
// Test that objects that do not get tenured do not go in the log.
// Can't let gc zeal mess with our assumptions about gc behavior here.
gczeal(0);
const root = newGlobal();
const dbg = root.dbg = new Debugger(root);
root.eval(
`
this.forceLazyInstantiation = new Date;
gc();
this.allocTemp = function allocTemp() {
gc();
this.dbg.memory.trackingTenurePromotions = true;
// Create an object, remove references to it, and then do a minor gc. It
// should not be in the tenure promotions log because it should have died in
// the nursery. We use a Date object so it is easier to find when asserting.
var d = new Date;
d = null;
minorgc();
};
`
);
root.allocTemp();
const promotions = dbg.memory.drainTenurePromotionsLog();
assertEq(promotions.some(e => e.class === "Date"), false);

View File

@ -0,0 +1,73 @@
// Test usage of drainTenurePromotionsLog() with multiple debuggees in the same
// zone.
const root1 = newGlobal();
const root2 = newGlobal({ sameZoneAs: root1 });
const dbg = new Debugger();
function tenureObjectsAndDrainLog(root) {
gc();
dbg.memory.trackingAllocationSites = true;
dbg.memory.trackingTenurePromotions = true;
root.eval(
`
(function immediate() {
this.tests = [
{ name: "({})", cls: "Object", obj: ({}) },
{ name: "[]", cls: "Array", obj: [] },
{ name: "new Object", cls: "Object", obj: new Object() },
{ name: "new Array", cls: "Array", obj: new Array() },
{ name: "new Date", cls: "Date", obj: new Date() },
];
}());
minorgc();
`
);
const promotions = dbg.memory.drainTenurePromotionsLog();
dbg.memory.trackingAllocationSites = false;
dbg.memory.trackingTenurePromotions = false;
return promotions;
}
{
dbg.addDebuggee(root1);
dbg.addDebuggee(root2);
// Should get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, true);
// and logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, true);
}
{
dbg.removeAllDebuggees();
// Should *not* get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, false);
// nor logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, false);
}
{
dbg.addDebuggee(root1);
// Should get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, true);
// but *not* logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, false);
}
{
dbg.removeAllDebuggees();
dbg.addDebuggee(root2);
// Should *not* get logs from root1,
assertEq(!!tenureObjectsAndDrainLog(root1).length, false);
// but should get logs from root2.
assertEq(!!tenureObjectsAndDrainLog(root2).length, true);
}