If a Debug.Object’s existence is somehow observable, keep it alive. This means it is alive if it has expandos or is a key of a live WeakMap. Since we have no way of telling when those things are true, simply mark as if each referent had a strong reference back to each corresponding Debug.Object.

This commit is contained in:
Jason Orendorff 2011-05-06 11:51:43 -05:00
parent 8fde8c4bbc
commit 68b3652a25
3 changed files with 62 additions and 2 deletions

View File

@ -0,0 +1,27 @@
// |jit-test| debug
// Storing a property on a Debug.Object protects it from GC as long as the
// referent is alive.
var g = newGlobal('new-compartment');
var N = g.N = 3;
var dbg = Debug(g);
var i = 0;
dbg.hooks = {
debuggerHandler: function (frame) {
frame.arguments[0].id = i++;
}
};
g.eval("function f(x) { debugger; }");
g.eval("var arr = [], j; for (j = 0; j < N; j++) arr[j] = {};");
g.eval("for (j = 0; j < N; j++) f(arr[j]);");
assertEq(i, N);
gc(); gc();
i = 0;
dbg.hooks.debuggerHandler = function (frame) {
assertEq(frame.arguments[0].id, i++)
}
g.eval("for (j = 0; j < N; j++) f(arr[j]);");
assertEq(i, N);

View File

@ -0,0 +1,28 @@
// |jit-test| debug
// Storing a Debug.Object as a key in a WeakMap protects it from GC as long as
// the referent is alive.
var g = newGlobal('new-compartment');
var N = g.N = 10;
var dbg = Debug(g);
var cache = new WeakMap;
var i = 0;
dbg.hooks = {
debuggerHandler: function (frame) {
cache.set(frame.arguments[0], i++);
}
};
g.eval("function f(x) { debugger; }");
g.eval("var arr = [], j; for (j = 0; j < N; j++) arr[j] = {};");
g.eval("for (j = 0; j < N; j++) f(arr[j]);");
assertEq(i, N);
gc(); gc();
i = 0;
dbg.hooks.debuggerHandler = function (frame) {
assertEq(cache.get(frame.arguments[0]), i++)
};
g.eval("for (j = 0; j < N; j++) f(arr[j]);");
assertEq(i, N);

View File

@ -483,8 +483,13 @@ Debug::mark(GCMarker *trc, JSCompartment *comp, JSGCInvocationKind gckind)
// //
if (!comp || obj->compartment() == comp) { if (!comp || obj->compartment() == comp) {
for (ObjectMap::Range r = dbg->objects.all(); !r.empty(); r.popFront()) { for (ObjectMap::Range r = dbg->objects.all(); !r.empty(); r.popFront()) {
if (!r.front().value->isMarked() && (comp || r.front().key->isMarked())) { // The unwrap() call below has the following effect: we
MarkObject(trc, *r.front().key, "Debug.Object with live referent"); // mark the Debug.Object if the *referent* is alive,
// even if the CCW of the referent seems unreachable.
if (!r.front().value->isMarked() &&
(comp || r.front().key->unwrap()->isMarked()))
{
MarkObject(trc, *r.front().value, "Debug.Object with live referent");
markedAny = true; markedAny = true;
} }
} }