Fix JS_TraceChildren crash triggered by findReferences. Bug 708261, r=jimb.

--HG--
extra : rebase_source : 336ebf499834345d364955000977a952014ea2bb
This commit is contained in:
Jason Orendorff 2011-12-08 14:23:31 -06:00
parent 92b99889d2
commit 579d99f332
3 changed files with 15 additions and 54 deletions

View File

@ -184,16 +184,6 @@ MarkObjectUnbarriered(JSTracer *trc, JSObject *obj, const char *name)
Mark(trc, obj);
}
void
MarkObjectWithPrinterUnbarriered(JSTracer *trc, JSObject *obj, JSTraceNamePrinter printer,
const void *arg, size_t index)
{
JS_ASSERT(trc);
JS_ASSERT(obj);
JS_SET_TRACING_DETAILS(trc, printer, arg, index);
Mark(trc, obj);
}
void
MarkObject(JSTracer *trc, const MarkablePtr<JSObject> &obj, const char *name)
{
@ -675,30 +665,6 @@ MarkRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
MarkIdRangeUnbarriered(trc, len, vec, name);
}
static void
PrintPropertyId(char *buf, size_t bufsize, jsid propid, const char *label)
{
JS_ASSERT(!JSID_IS_VOID(propid));
if (JSID_IS_ATOM(propid)) {
size_t n = PutEscapedString(buf, bufsize, JSID_TO_ATOM(propid), 0);
if (n < bufsize)
JS_snprintf(buf + n, bufsize - n, " %s", label);
} else if (JSID_IS_INT(propid)) {
JS_snprintf(buf, bufsize, "%d %s", JSID_TO_INT(propid), label);
} else {
JS_snprintf(buf, bufsize, "<object> %s", label);
}
}
static void
PrintPropertyGetterOrSetter(JSTracer *trc, char *buf, size_t bufsize)
{
JS_ASSERT(trc->debugPrinter == PrintPropertyGetterOrSetter);
Shape *shape = (Shape *)trc->debugPrintArg;
PrintPropertyId(buf, bufsize, shape->propid(),
trc->debugPrintIndex ? js_setter_str : js_getter_str);
}
static inline void
ScanValue(GCMarker *gcmarker, const Value &v)
{
@ -999,15 +965,10 @@ MarkChildren(JSTracer *trc, const Shape *shape)
void
MarkChildren(JSTracer *trc, BaseShape *base)
{
if (base->hasGetterObject()) {
MarkObjectWithPrinterUnbarriered(trc, base->getterObject(),
PrintPropertyGetterOrSetter, base, 0);
}
if (base->hasSetterObject()) {
MarkObjectWithPrinterUnbarriered(trc, base->setterObject(),
PrintPropertyGetterOrSetter, base, 0);
}
if (base->hasGetterObject())
MarkObjectUnbarriered(trc, base->getterObject(), "getter");
if (base->hasSetterObject())
MarkObjectUnbarriered(trc, base->setterObject(), "setter");
if (base->isOwned())
MarkBaseShapeUnbarriered(trc, base->baseUnowned(), "base");

View File

@ -11,7 +11,7 @@ if (typeof findReferences == "function") {
o.alsoMyself = o; // multiple self-references should all be reported
assertEq(referencesVia(o, 'type; type_proto', C.prototype), true);
assertEq(referencesVia(o, 'parent', this), true);
assertEq(referencesVia(o, 'shape; base; parent', this), true);
assertEq(referencesVia(o, 'x', o.x), true);
assertEq(referencesVia(o, '42', o[42]), true);
assertEq(referencesVia(o, 'myself', o), true);
@ -20,22 +20,22 @@ if (typeof findReferences == "function") {
function g() { return 42; }
function s(v) { }
var p = Object.defineProperty({}, 'a', { get:g, set:s });
assertEq(referencesVia(p, 'shape; a getter', g), true);
assertEq(referencesVia(p, 'shape; a setter', s), true);
assertEq(referencesVia(p, 'shape; base; getter', g), true);
assertEq(referencesVia(p, 'shape; base; setter', s), true);
// If there are multiple objects with the same shape referring to a getter
// or setter, findReferences should get all of them, even though the shape
// gets 'marked' the first time we visit it.
var q = Object.defineProperty({}, 'a', { get:g, set:s });
assertEq(referencesVia(p, 'shape; a getter', g), true);
assertEq(referencesVia(q, 'shape; a getter', g), true);
assertEq(referencesVia(p, 'shape; base; getter', g), true);
assertEq(referencesVia(q, 'shape; base; getter', g), true);
// If we extend each object's shape chain, both should still be able to
// reach the getter, even though the two shapes are each traversed twice.
p.b = 9;
q.b = 9;
assertEq(referencesVia(p, 'shape; a getter', g), true);
assertEq(referencesVia(q, 'shape; a getter', g), true);
assertEq(referencesVia(p, 'shape; parent; base; getter', g), true);
assertEq(referencesVia(q, 'shape; parent; base; getter', g), true);
// These are really just ordinary own property references.
assertEq(referencesVia(C, 'prototype', Object.getPrototypeOf(o)), true);

View File

@ -13,14 +13,14 @@ if (typeof findReferences == "function") {
assertEq(referencesVia(returnFlat(o), 'upvars[0]', o), true);
function returnHeavy(y) { eval(''); return function heavy() { return y; }; }
assertEq(referencesVia(returnHeavy(o), 'parent; y', o), true);
assertEq(referencesVia(returnHeavy(o), 'parent; parent', this), true);
assertEq(referencesVia(returnHeavy(o), 'fun_callscope; y', o), true);
assertEq(referencesVia(returnHeavy(o), 'fun_callscope; shape; base; parent', this), true);
function returnBlock(z) { eval(''); let(w = z) { return function block() { return w; }; }; }
assertEq(referencesVia(returnBlock(o), 'parent; w', o), true);
assertEq(referencesVia(returnBlock(o), 'fun_callscope; w', o), true);
function returnWithObj(v) { with(v) return function withObj() { return u; }; }
assertEq(referencesVia(returnWithObj(o), 'parent; type; type_proto', o), true);
assertEq(referencesVia(returnWithObj(o), 'fun_callscope; type; type_proto', o), true);
reportCompare(true, true);
} else {