From f952c6179e8b54dfa9c4d87bf959c644ef81e82a Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 8 Dec 2011 14:23:31 -0600 Subject: [PATCH] Fix JS_TraceChildren crash triggered by findReferences. Bug 708261, r=jimb. --HG-- extra : rebase_source : 336ebf499834345d364955000977a952014ea2bb --- js/src/jsgcmark.cpp | 47 ++----------------- .../js1_8_5/extensions/findReferences-01.js | 14 +++--- .../js1_8_5/extensions/findReferences-02.js | 8 ++-- 3 files changed, 15 insertions(+), 54 deletions(-) diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index 83bfb8dc1aa..77bac1d4514 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -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 &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, " %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"); diff --git a/js/src/tests/js1_8_5/extensions/findReferences-01.js b/js/src/tests/js1_8_5/extensions/findReferences-01.js index f90f7d9126b..9af6744e32a 100644 --- a/js/src/tests/js1_8_5/extensions/findReferences-01.js +++ b/js/src/tests/js1_8_5/extensions/findReferences-01.js @@ -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); diff --git a/js/src/tests/js1_8_5/extensions/findReferences-02.js b/js/src/tests/js1_8_5/extensions/findReferences-02.js index 0d35907bd55..8a438efdac0 100644 --- a/js/src/tests/js1_8_5/extensions/findReferences-02.js +++ b/js/src/tests/js1_8_5/extensions/findReferences-02.js @@ -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 {