Bug 860572 - Allow JSPropertyDescriptor to use Rooted; r=jonco

This commit is contained in:
Terrence Cole 2013-04-12 16:34:27 -07:00
parent fb71ffd4ce
commit 7aae601b79
4 changed files with 137 additions and 18 deletions

View File

@ -67,6 +67,7 @@ MarkExactStackRoot(JSTracer *trc, Rooted<void*> *rooter, ThingRootKind kind)
case THING_ROOT_ID: MarkIdRoot(trc, (jsid *)addr, "exact-id"); break;
case THING_ROOT_PROPERTY_ID: MarkIdRoot(trc, &((js::PropertyId *)addr)->asId(), "exact-propertyid"); break;
case THING_ROOT_BINDINGS: ((Bindings *)addr)->trace(trc); break;
case THING_ROOT_PROPERTY_DESCRIPTOR: ((JSPropertyDescriptor *)addr)->trace(trc); break;
default: JS_NOT_REACHED("Invalid THING_ROOT kind"); break;
}
}
@ -415,19 +416,7 @@ AutoGCRooter::trace(JSTracer *trc)
case DESCRIPTOR : {
PropertyDescriptor &desc = *static_cast<AutoPropertyDescriptorRooter *>(this);
if (desc.obj)
MarkObjectRoot(trc, &desc.obj, "Descriptor::obj");
MarkValueRoot(trc, &desc.value, "Descriptor::value");
if ((desc.attrs & JSPROP_GETTER) && desc.getter) {
JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.getter);
MarkObjectRoot(trc, &tmp, "Descriptor::get");
desc.getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, tmp);
}
if (desc.attrs & JSPROP_SETTER && desc.setter) {
JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, desc.setter);
MarkObjectRoot(trc, &tmp, "Descriptor::set");
desc.setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp);
}
desc.trace(trc);
return;
}
@ -648,6 +637,24 @@ StackShape::AutoRooter::trace(JSTracer *trc)
MarkIdRoot(trc, (jsid*) &shape->propid, "StackShape::AutoRooter id");
}
void
JSPropertyDescriptor::trace(JSTracer *trc)
{
if (obj)
MarkObjectRoot(trc, &obj, "Descriptor::obj");
MarkValueRoot(trc, &value, "Descriptor::value");
if ((attrs & JSPROP_GETTER) && getter) {
JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, getter);
MarkObjectRoot(trc, &tmp, "Descriptor::get");
getter = JS_DATA_TO_FUNC_PTR(JSPropertyOp, tmp);
}
if ((attrs & JSPROP_SETTER) && setter) {
JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, setter);
MarkObjectRoot(trc, &tmp, "Descriptor::set");
setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp);
}
}
void
js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
{

View File

@ -29,14 +29,23 @@ using namespace mozilla;
#if defined(DEBUG) && defined(JS_GC_ZEAL) && defined(JSGC_ROOT_ANALYSIS) && !defined(JS_THREADSAFE)
template <typename T>
bool
CheckNonAddressThing(uintptr_t *w, T *t)
{
return w >= (uintptr_t*)t && w < (uintptr_t*)(t + 1);
}
JS_ALWAYS_INLINE bool
CheckStackRootThing(uintptr_t *w, void *address, ThingRootKind kind)
{
if (kind != THING_ROOT_BINDINGS)
return address == static_cast<void*>(w);
if (kind == THING_ROOT_BINDINGS)
return CheckNonAddressThing(w, static_cast<Bindings*>(address));
Bindings *bp = static_cast<Bindings*>(address);
return w >= (uintptr_t*)bp && w < (uintptr_t*)(bp + 1);
if (kind == THING_ROOT_PROPERTY_DESCRIPTOR)
return CheckNonAddressThing(w, static_cast<PropertyDescriptor*>(address));
return address == static_cast<void*>(w);
}
struct Rooter {

View File

@ -3326,13 +3326,115 @@ struct JSPropertyDescriptor {
unsigned shortid;
JSPropertyOp getter;
JSStrictPropertyOp setter;
jsval value;
JS::Value value;
JSPropertyDescriptor() : obj(NULL), attrs(0), shortid(0), getter(NULL),
setter(NULL), value(JSVAL_VOID)
{}
void trace(JSTracer *trc);
};
namespace JS {
template <typename Outer>
class PropertyDescriptorOperations
{
const JSPropertyDescriptor * desc() const { return static_cast<const Outer*>(this)->extract(); }
JSPropertyDescriptor * desc() { return static_cast<Outer*>(this)->extract(); }
public:
bool isEnumerable() const { return desc()->attrs & JSPROP_ENUMERATE; }
bool isReadonly() const { return desc()->attrs & JSPROP_READONLY; }
bool isPermanent() const { return desc()->attrs & JSPROP_PERMANENT; }
bool hasNativeAccessors() const { return desc()->attrs & JSPROP_NATIVE_ACCESSORS; }
bool hasGetterObject() const { return desc()->attrs & JSPROP_GETTER; }
bool hasSetterObject() const { return desc()->attrs & JSPROP_SETTER; }
bool isShared() const { return desc()->attrs & JSPROP_SHARED; }
bool isIndex() const { return desc()->attrs & JSPROP_INDEX; }
bool hasShortId() const { return desc()->attrs & JSPROP_SHORTID; }
bool hasAttributes(unsigned attrs) const { return desc()->attrs & attrs; }
JS::MutableHandleObject object() { return JS::MutableHandleObject::fromMarkedLocation(&desc()->obj); }
unsigned attributes() const { return desc()->attrs; }
unsigned shortid() const {
MOZ_ASSERT(hasShortId());
return desc()->shortid;
}
JSPropertyOp getter() const { MOZ_ASSERT(!hasGetterObject()); return desc()->getter; }
JSStrictPropertyOp setter() const { MOZ_ASSERT(!hasSetterObject()); return desc()->setter; }
JS::HandleObject getterObject() const {
MOZ_ASSERT(hasGetterObject());
return JS::HandleObject::fromMarkedLocation(reinterpret_cast<JSObject *const *>(&desc()->getter));
}
JS::HandleObject setterObject() const {
MOZ_ASSERT(hasSetterObject());
return JS::HandleObject::fromMarkedLocation(reinterpret_cast<JSObject *const *>(&desc()->setter));
}
JS::MutableHandleValue value() { return JS::MutableHandleValue::fromMarkedLocation(&desc()->value); }
void setAttributes(unsigned attrs) { desc()->attrs = attrs; }
void setShortId(unsigned id) { desc()->shortid = id; }
void setGetter(JSPropertyOp op) { desc()->getter = op; }
void setSetter(JSStrictPropertyOp op) { desc()->setter = op; }
void setGetterObject(JSObject *obj) { desc()->getter = reinterpret_cast<JSPropertyOp>(obj); }
void setSetterObject(JSObject *obj) { desc()->setter = reinterpret_cast<JSStrictPropertyOp>(obj); }
};
} /* namespace JS */
namespace js {
template <>
struct RootMethods<JSPropertyDescriptor> {
static JSPropertyDescriptor initial() { return JSPropertyDescriptor(); }
static ThingRootKind kind() { return THING_ROOT_PROPERTY_DESCRIPTOR; }
static bool poisoned(const JSPropertyDescriptor &desc) {
return (desc.obj && JS::IsPoisonedPtr(desc.obj)) ||
(desc.attrs & JSPROP_GETTER && desc.getter && JS::IsPoisonedPtr(desc.getter)) ||
(desc.attrs & JSPROP_SETTER && desc.setter && JS::IsPoisonedPtr(desc.setter)) ||
(desc.value.isGCThing() && JS::IsPoisonedPtr(desc.value.toGCThing()));
}
};
template <>
class RootedBase<JSPropertyDescriptor>
: public JS::PropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor> >
{
friend class JS::PropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor> >;
const JSPropertyDescriptor *extract() const {
return static_cast<const JS::Rooted<JSPropertyDescriptor>*>(this)->address();
}
JSPropertyDescriptor *extract() {
return static_cast<JS::Rooted<JSPropertyDescriptor>*>(this)->address();
}
};
template <>
class HandleBase<JSPropertyDescriptor>
: public JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor> >
{
friend class JS::PropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor> >;
const JSPropertyDescriptor *extract() const {
return static_cast<const JS::Handle<JSPropertyDescriptor>*>(this)->address();
}
};
template <>
class MutableHandleBase<JSPropertyDescriptor>
: public JS::PropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor> >
{
friend class JS::PropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor> >;
const JSPropertyDescriptor *extract() const {
return static_cast<const JS::MutableHandle<JSPropertyDescriptor>*>(this)->address();
}
JSPropertyDescriptor *extract() {
return static_cast<JS::MutableHandle<JSPropertyDescriptor>*>(this)->address();
}
};
} /* namespace js */
/*
* Like JS_GetPropertyAttrsGetterAndSetterById but will return a property on
* an object on the prototype chain (returned in objp). If data->obj is null,

View File

@ -244,6 +244,7 @@ enum ThingRootKind
THING_ROOT_VALUE,
THING_ROOT_TYPE,
THING_ROOT_BINDINGS,
THING_ROOT_PROPERTY_DESCRIPTOR,
THING_ROOT_LIMIT
};