Bug 629817 - Add an AutoShapeVector to root shape vectors on the stack (r=luke)

This commit is contained in:
Bill McCloskey 2011-02-07 12:06:32 -08:00
parent b84e4431ab
commit 667b23ee82
7 changed files with 91 additions and 79 deletions

View File

@ -1867,7 +1867,7 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp)
* the root set covered by tvr.count.
*/
Value *mergesort_tmp = vec + newlen;
MakeValueRangeGCSafe(mergesort_tmp, newlen);
MakeRangeGCSafe(mergesort_tmp, newlen);
tvr.changeLength(newlen * 2);
/* Here len == 2 * (newlen + undefs + number_of_holes). */
@ -1932,7 +1932,7 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp)
return false;
}
mergesort_tmp = vec + 2 * newlen;
MakeValueRangeGCSafe(mergesort_tmp, 2 * newlen);
MakeRangeGCSafe(mergesort_tmp, 2 * newlen);
tvr.changeArray(vec, newlen * 4);
elemsize = 2 * sizeof(Value);
}

View File

@ -2241,7 +2241,8 @@ class AutoGCRooter {
DESCRIPTOR = -13, /* js::AutoPropertyDescriptorRooter */
STRING = -14, /* js::AutoStringRooter */
IDVECTOR = -15, /* js::AutoIdVector */
BINDINGS = -16 /* js::Bindings */
BINDINGS = -16, /* js::Bindings */
SHAPEVECTOR = -17 /* js::AutoShapeVector */
};
private:
@ -3227,28 +3228,28 @@ ContextAllocPolicy::reportAllocOverflow() const
js_ReportAllocationOverflow(cx);
}
class AutoValueVector : private AutoGCRooter
template<class T>
class AutoVectorRooter : protected AutoGCRooter
{
public:
explicit AutoValueVector(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, VALVECTOR), vector(cx)
explicit AutoVectorRooter(JSContext *cx, ptrdiff_t tag
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, tag), vector(cx)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
size_t length() const { return vector.length(); }
bool append(const Value &v) { return vector.append(v); }
bool append(const T &v) { return vector.append(v); }
void popBack() { vector.popBack(); }
bool growBy(size_t inc) {
/* N.B. Value's default ctor leaves the Value undefined */
size_t oldLength = vector.length();
if (!vector.growByUninitialized(inc))
return false;
MakeValueRangeGCSafe(vector.begin() + oldLength, vector.end());
MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
return true;
}
@ -3258,10 +3259,9 @@ class AutoValueVector : private AutoGCRooter
vector.shrinkBy(oldLength - newLength);
return true;
}
/* N.B. Value's default ctor leaves the Value undefined */
if (!vector.growByUninitialized(newLength - oldLength))
return false;
MakeValueRangeGCSafe(vector.begin() + oldLength, vector.end());
MakeRangeGCSafe(vector.begin() + oldLength, vector.end());
return true;
}
@ -3269,14 +3269,33 @@ class AutoValueVector : private AutoGCRooter
return vector.reserve(newLength);
}
Value &operator[](size_t i) { return vector[i]; }
const Value &operator[](size_t i) const { return vector[i]; }
T &operator[](size_t i) { return vector[i]; }
const T &operator[](size_t i) const { return vector[i]; }
const Value *begin() const { return vector.begin(); }
Value *begin() { return vector.begin(); }
const T *begin() const { return vector.begin(); }
T *begin() { return vector.begin(); }
const Value *end() const { return vector.end(); }
Value *end() { return vector.end(); }
const T *end() const { return vector.end(); }
T *end() { return vector.end(); }
const T &back() const { return vector.back(); }
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Vector<T, 8> vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoValueVector : public AutoVectorRooter<Value>
{
public:
explicit AutoValueVector(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooter<Value>(cx, VALVECTOR)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
const jsval *jsval_begin() const { return Jsvalify(begin()); }
jsval *jsval_begin() { return Jsvalify(begin()); }
@ -3284,72 +3303,32 @@ class AutoValueVector : private AutoGCRooter
const jsval *jsval_end() const { return Jsvalify(end()); }
jsval *jsval_end() { return Jsvalify(end()); }
const Value &back() const { return vector.back(); }
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Vector<Value, 8> vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoIdVector : private AutoGCRooter
class AutoIdVector : public AutoVectorRooter<jsid>
{
public:
explicit AutoIdVector(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoGCRooter(cx, IDVECTOR), vector(cx)
: AutoVectorRooter<jsid>(cx, IDVECTOR)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
size_t length() const { return vector.length(); }
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};
bool append(jsid id) { return vector.append(id); }
void popBack() { vector.popBack(); }
bool growBy(size_t inc) {
/* N.B. jsid's default ctor leaves the jsid undefined */
size_t oldLength = vector.length();
if (!vector.growByUninitialized(inc))
return false;
MakeIdRangeGCSafe(vector.begin() + oldLength, vector.end());
return true;
class AutoShapeVector : public AutoVectorRooter<const Shape *>
{
public:
explicit AutoShapeVector(JSContext *cx
JS_GUARD_OBJECT_NOTIFIER_PARAM)
: AutoVectorRooter<const Shape *>(cx, SHAPEVECTOR)
{
JS_GUARD_OBJECT_NOTIFIER_INIT;
}
bool resize(size_t newLength) {
size_t oldLength = vector.length();
if (newLength <= oldLength) {
vector.shrinkBy(oldLength - newLength);
return true;
}
/* N.B. jsid's default ctor leaves the jsid undefined */
if (!vector.growByUninitialized(newLength - oldLength))
return false;
MakeIdRangeGCSafe(vector.begin() + oldLength, vector.end());
return true;
}
bool reserve(size_t newLength) {
return vector.reserve(newLength);
}
jsid &operator[](size_t i) { return vector[i]; }
const jsid &operator[](size_t i) const { return vector[i]; }
const jsid *begin() const { return vector.begin(); }
jsid *begin() { return vector.begin(); }
const jsid *end() const { return vector.end(); }
jsid *end() { return vector.end(); }
const jsid &back() const { return vector.back(); }
friend void AutoGCRooter::trace(JSTracer *trc);
private:
Vector<jsid, 8> vector;
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
};

View File

@ -248,7 +248,7 @@ StackSpace::pushInvokeArgs(JSContext *cx, uintN argc, InvokeArgsGuard *ag)
Value *vp = start;
Value *vpend = vp + nvals;
/* Don't need to MakeValueRangeGCSafe: the VM stack is conservatively marked. */
/* Don't need to MakeRangeGCSafe: the VM stack is conservatively marked. */
/* Use invokeArgEnd to root [vp, vpend) until the frame is pushed. */
ag->prevInvokeArgEnd = invokeArgEnd;

View File

@ -1601,6 +1601,12 @@ AutoGCRooter::trace(JSTracer *trc)
return;
}
case SHAPEVECTOR: {
Vector<const Shape *, 8> &vector = static_cast<js::AutoShapeVector *>(this)->vector;
MarkShapeRange(trc, vector.length(), vector.begin(), "js::AutoShapeVector.vector");
return;
}
case BINDINGS: {
static_cast<js::AutoBindingsRooter *>(this)->bindings.trace(trc);
return;

View File

@ -623,6 +623,21 @@ MarkValueRange(JSTracer *trc, size_t len, Value *vec, const char *name)
MarkValueRange(trc, vec, vec + len, name);
}
static inline void
MarkShapeRange(JSTracer *trc, const Shape **beg, const Shape **end, const char *name)
{
for (const Shape **sp = beg; sp < end; ++sp) {
JS_SET_TRACING_INDEX(trc, name, sp - beg);
(*sp)->trace(trc);
}
}
static inline void
MarkShapeRange(JSTracer *trc, size_t len, const Shape **vec, const char *name)
{
MarkShapeRange(trc, vec, vec + len, name);
}
/* N.B. Assumes JS_SET_TRACING_NAME/INDEX has already been called. */
static inline void
MarkGCThing(JSTracer *trc, void *thing, uint32 kind)

View File

@ -3426,7 +3426,7 @@ JSObject::copyPropertiesFrom(JSContext *cx, JSObject *obj)
if (!isNative())
return true;
Vector<const Shape *> shapes(cx);
AutoShapeVector shapes(cx);
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
if (!shapes.append(&r.front()))
return false;
@ -3725,8 +3725,8 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
return false;
}
} else {
Vector<const Shape *, 8> shapes(cx);
shapes.growByUninitialized(count);
AutoShapeVector shapes(cx);
shapes.growBy(count);
for (Shape::Range r(obj->lastProperty()); !r.empty(); r.popFront()) {
shape = &r.front();

View File

@ -1145,28 +1145,40 @@ ValueArgToConstRef(const Value &v)
/******************************************************************************/
static JS_ALWAYS_INLINE void
MakeValueRangeGCSafe(Value *vec, size_t len)
MakeRangeGCSafe(Value *vec, size_t len)
{
PodZero(vec, len);
}
static JS_ALWAYS_INLINE void
MakeValueRangeGCSafe(Value *beg, Value *end)
MakeRangeGCSafe(Value *beg, Value *end)
{
PodZero(beg, end - beg);
}
static JS_ALWAYS_INLINE void
MakeIdRangeGCSafe(jsid *beg, jsid *end)
MakeRangeGCSafe(jsid *beg, jsid *end)
{
for (jsid *id = beg; id != end; ++id)
*id = INT_TO_JSID(0);
}
static JS_ALWAYS_INLINE void
MakeIdRangeGCSafe(jsid *vec, size_t len)
MakeRangeGCSafe(jsid *vec, size_t len)
{
MakeIdRangeGCSafe(vec, vec + len);
MakeRangeGCSafe(vec, vec + len);
}
static JS_ALWAYS_INLINE void
MakeRangeGCSafe(const Shape **beg, const Shape **end)
{
PodZero(beg, end - beg);
}
static JS_ALWAYS_INLINE void
MakeRangeGCSafe(const Shape **vec, size_t len)
{
PodZero(vec, len);
}
static JS_ALWAYS_INLINE void