Bug 727135 - Make jsid marking interfaces indirect; r=billm

This will allow the GC to move jsid referenced objects.
This commit is contained in:
Terrence Cole 2012-02-17 17:27:37 -08:00
Родитель b295527033
Коммит 23c654c7d0
10 изменённых файлов: 52 добавлений и 49 удалений

Просмотреть файл

@ -406,6 +406,7 @@ class HeapId
bool operator!=(jsid id) const { return value != id; }
jsid get() const { return value; }
jsid *unsafeGet() { return &value; }
operator jsid() const { return value; }
private:

Просмотреть файл

@ -177,7 +177,7 @@ JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc)
JS_FRIEND_API(void)
JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape)
{
MarkCycleCollectorChildren(trc, (const Shape *)shape);
MarkCycleCollectorChildren(trc, (Shape *)shape);
}
AutoPreserveCompartment::AutoPreserveCompartment(JSContext *cx

Просмотреть файл

@ -2266,7 +2266,7 @@ AutoGCRooter::trace(JSTracer *trc)
return;
case ID:
MarkIdRoot(trc, static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
MarkIdRoot(trc, &static_cast<AutoIdRooter *>(this)->id_, "JS::AutoIdRooter.id_");
return;
case VALVECTOR: {

Просмотреть файл

@ -61,7 +61,7 @@ static inline void
PushMarkStack(GCMarker *gcmarker, JSScript *thing);
static inline void
PushMarkStack(GCMarker *gcmarker, const Shape *thing);
PushMarkStack(GCMarker *gcmarker, Shape *thing);
static inline void
PushMarkStack(GCMarker *gcmarker, JSString *thing);
@ -264,23 +264,28 @@ MarkGCThingRoot(JSTracer *trc, void *thing, const char *name)
/*** ID Marking ***/
static inline void
MarkIdInternal(JSTracer *trc, const jsid &id)
MarkIdInternal(JSTracer *trc, jsid *id)
{
if (JSID_IS_STRING(id))
MarkInternal(trc, JSID_TO_STRING(id));
else if (JS_UNLIKELY(JSID_IS_OBJECT(id)))
MarkInternal(trc, JSID_TO_OBJECT(id));
if (JSID_IS_STRING(*id)) {
JSString *str = JSID_TO_STRING(*id);
MarkInternal(trc, str);
*id = ATOM_TO_JSID(reinterpret_cast<JSAtom *>(str));
} else if (JS_UNLIKELY(JSID_IS_OBJECT(*id))) {
JSObject *obj = JSID_TO_OBJECT(*id);
MarkInternal(trc, obj);
*id = OBJECT_TO_JSID(obj);
}
}
void
MarkId(JSTracer *trc, const HeapId &id, const char *name)
MarkId(JSTracer *trc, HeapId *id, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkIdInternal(trc, id);
MarkIdInternal(trc, id->unsafeGet());
}
void
MarkIdRoot(JSTracer *trc, const jsid &id, const char *name)
MarkIdRoot(JSTracer *trc, jsid *id, const char *name)
{
JS_ROOT_MARKING_ASSERT(trc);
JS_SET_TRACING_NAME(trc, name);
@ -292,7 +297,7 @@ MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name)
{
for (size_t i = 0; i < len; ++i) {
JS_SET_TRACING_INDEX(trc, name, i);
MarkIdInternal(trc, vec[i]);
MarkIdInternal(trc, vec[i].unsafeGet());
}
}
@ -302,7 +307,7 @@ MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
JS_ROOT_MARKING_ASSERT(trc);
for (size_t i = 0; i < len; ++i) {
JS_SET_TRACING_INDEX(trc, name, i);
MarkIdInternal(trc, vec[i]);
MarkIdInternal(trc, &vec[i]);
}
}
@ -364,13 +369,6 @@ MarkObject(JSTracer *trc, const HeapPtr<GlobalObject, JSScript *> &thing, const
MarkInternal(trc, thing.get());
}
void
MarkShape(JSTracer *trc, HeapPtr<const Shape> *thing, const char *name)
{
JS_SET_TRACING_NAME(trc, name);
MarkInternal(trc, const_cast<Shape *>(thing->get()));
}
void
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name)
{
@ -460,10 +458,10 @@ PushMarkStack(GCMarker *gcmarker, JSScript *thing)
}
static void
ScanShape(GCMarker *gcmarker, const Shape *shape);
ScanShape(GCMarker *gcmarker, Shape *shape);
static void
PushMarkStack(GCMarker *gcmarker, const Shape *thing)
PushMarkStack(GCMarker *gcmarker, Shape *thing)
{
JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing);
@ -486,12 +484,12 @@ PushMarkStack(GCMarker *gcmarker, BaseShape *thing)
}
static void
ScanShape(GCMarker *gcmarker, const Shape *shape)
ScanShape(GCMarker *gcmarker, Shape *shape)
{
restart:
PushMarkStack(gcmarker, shape->base());
jsid id = shape->maybePropid();
const HeapId &id = shape->propidRef();
if (JSID_IS_STRING(id))
PushMarkStack(gcmarker, JSID_TO_STRING(id));
else if (JS_UNLIKELY(JSID_IS_OBJECT(id)))
@ -712,7 +710,7 @@ static void
MarkChildren(JSTracer *trc, Shape *shape)
{
MarkBaseShapeUnbarriered(trc, shape->base(), "base");
MarkId(trc, shape->maybePropid(), "propid");
MarkId(trc, &shape->propidRef(), "propid");
if (shape->previous())
MarkShape(trc, &shape->previousRef(), "parent");
}
@ -775,12 +773,12 @@ MarkCycleCollectorChildren(JSTracer *trc, BaseShape *base, JSObject **prevParent
* parent pointer will only be marked once.
*/
void
MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape)
MarkCycleCollectorChildren(JSTracer *trc, Shape *shape)
{
JSObject *prevParent = NULL;
do {
MarkCycleCollectorChildren(trc, shape->base(), &prevParent);
MarkId(trc, shape->maybePropid(), "propid");
MarkId(trc, &shape->propidRef(), "propid");
shape = shape->previous();
} while (shape);
}
@ -823,7 +821,7 @@ MarkChildren(JSTracer *trc, types::TypeObject *type)
for (unsigned i = 0; i < count; i++) {
types::Property *prop = type->getProperty(i);
if (prop)
MarkId(trc, prop->id, "type_prop");
MarkId(trc, &prop->id, "type_prop");
}
}

Просмотреть файл

@ -83,10 +83,10 @@ MarkGCThingRoot(JSTracer *trc, void *thing, const char *name);
/*** ID Marking ***/
void
MarkId(JSTracer *trc, const HeapId &id, const char *name);
MarkId(JSTracer *trc, HeapId *id, const char *name);
void
MarkIdRoot(JSTracer *trc, const jsid &id, const char *name);
MarkIdRoot(JSTracer *trc, jsid *id, const char *name);
void
MarkIdRange(JSTracer *trc, size_t len, js::HeapId *vec, const char *name);
@ -116,10 +116,6 @@ MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name)
/*** Special Cases ***/
/* TypeNewObject contains a HeapPtr<const Shape> that needs a unique cast. */
void
MarkShape(JSTracer *trc, HeapPtr<const Shape> *thing, const char *name);
/* Direct value access used by the write barriers and the methodjit */
void
MarkValueUnbarriered(JSTracer *trc, Value *v, const char *name);
@ -144,7 +140,7 @@ MarkChildren(JSTracer *trc, JSObject *obj);
* JS_TraceShapeCycleCollectorChildren.
*/
void
MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape);
MarkCycleCollectorChildren(JSTracer *trc, Shape *shape);
void
PushArena(GCMarker *gcmarker, ArenaHeader *aheader);

Просмотреть файл

@ -2618,7 +2618,7 @@ struct types::ObjectTableKey
typedef JSObject * Lookup;
static inline uint32_t hash(JSObject *obj) {
return (uint32_t) (JSID_BITS(obj->lastProperty()->propid()) ^
return (uint32_t) (JSID_BITS(obj->lastProperty()->propid().get()) ^
obj->slotSpan() ^ obj->numFixedSlots() ^
((uint32_t)(size_t)obj->getProto() >> 2));
}

Просмотреть файл

@ -668,7 +668,7 @@ struct TypeNewScript
* Shape to use for newly constructed objects. Reflects all definite
* properties the object will have.
*/
HeapPtr<const Shape> shape;
HeapPtrShape shape;
/*
* Order in which properties become initialized. We need this in case a

Просмотреть файл

@ -1062,7 +1062,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
{
JS_ASSERT_IF(oldShape != lastProperty(),
inDictionaryMode() &&
nativeLookup(cx, oldShape->maybePropid()) == oldShape);
nativeLookup(cx, oldShape->propidRef()) == oldShape);
JSObject *self = this;
@ -1086,7 +1086,7 @@ JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *n
PropertyTable &table = self->lastProperty()->table();
Shape **spp = oldShape->isEmptyShape()
? NULL
: table.search(oldShape->maybePropid(), false);
: table.search(oldShape->propidRef(), false);
/*
* Splice the new shape into the same position as the old shape, preserving

Просмотреть файл

@ -774,8 +774,12 @@ struct Shape : public js::gc::Cell
slotInfo = slotInfo | ((count + 1) << LINEAR_SEARCHES_SHIFT);
}
jsid propid() const { JS_ASSERT(!isEmptyShape()); return maybePropid(); }
const HeapId &maybePropid() const { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
const HeapId &propid() const {
JS_ASSERT(!isEmptyShape());
JS_ASSERT(!JSID_IS_VOID(propid_));
return propid_;
}
HeapId &propidRef() { JS_ASSERT(!JSID_IS_VOID(propid_)); return propid_; }
int16_t shortid() const { JS_ASSERT(hasShortID()); return maybeShortid(); }
int16_t maybeShortid() const { return shortid_; }
@ -999,7 +1003,7 @@ struct StackShape
StackShape(const Shape *shape)
: base(shape->base()->unowned()),
propid(shape->maybePropid()),
propid(const_cast<Shape *>(shape)->propidRef()),
slot_(shape->slotInfo & Shape::SLOT_MASK),
attrs(shape->attrs),
flags(shape->flags),
@ -1085,7 +1089,7 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
return SHAPE_FETCH(spp);
}
}
/*
/*
* No table built -- there weren't enough entries, or OOM occurred.
* Don't increment numLinearSearches, to keep hasTable() false.
*/
@ -1095,7 +1099,7 @@ Shape::search(JSContext *cx, Shape *start, jsid id, Shape ***pspp, bool adding)
}
for (Shape *shape = start; shape; shape = shape->parent) {
if (shape->maybePropid() == id)
if (shape->propidRef() == id)
return shape;
}

Просмотреть файл

@ -210,7 +210,9 @@ WatchpointMap::markIteratively(JSTracer *trc)
const HeapId &id = e.key.id;
JS_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id));
MarkId(trc, id, "WatchKey::id");
HeapId tmp(id.get());
MarkId(trc, &tmp, "WatchKey::id");
JS_ASSERT(tmp.get() == id.get());
if (e.value.closure && IsAboutToBeFinalized(e.value.closure)) {
MarkObject(trc, &e.value.closure, "Watchpoint::closure");
@ -226,13 +228,15 @@ WatchpointMap::markAll(JSTracer *trc)
{
for (Map::Range r = map.all(); !r.empty(); r.popFront()) {
Map::Entry &e = r.front();
HeapPtrObject tmp(e.key.object);
MarkObject(trc, &tmp, "held Watchpoint object");
JS_ASSERT(tmp == e.key.object);
HeapPtrObject tmpObj(e.key.object);
MarkObject(trc, &tmpObj, "held Watchpoint object");
JS_ASSERT(tmpObj == e.key.object);
const HeapId &id = e.key.id;
JS_ASSERT(JSID_IS_STRING(id) || JSID_IS_INT(id));
MarkId(trc, id, "WatchKey::id");
HeapId tmpId(id.get());
MarkId(trc, &tmpId, "WatchKey::id");
JS_ASSERT(tmpId.get() == id.get());
MarkObject(trc, &e.value.closure, "Watchpoint::closure");
}