зеркало из https://github.com/mozilla/gecko-dev.git
Bug 727135 - Make jsid marking interfaces indirect; r=billm
This will allow the GC to move jsid referenced objects.
This commit is contained in:
Родитель
b295527033
Коммит
23c654c7d0
|
@ -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");
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче