From 156933f7b345e0f64e2cc81b9426e95c0402a8c0 Mon Sep 17 00:00:00 2001 From: Terrence Cole Date: Fri, 17 Feb 2012 17:27:37 -0800 Subject: [PATCH] Bug 727135 - Make jsid marking interfaces indirect; r=billm This will allow the GC to move jsid referenced objects. --- js/src/gc/Barrier.h | 1 + js/src/jsfriendapi.cpp | 2 +- js/src/jsgc.cpp | 2 +- js/src/jsgcmark.cpp | 50 ++++++++++++++++++++--------------------- js/src/jsgcmark.h | 10 +++------ js/src/jsinfer.cpp | 2 +- js/src/jsinfer.h | 2 +- js/src/jsscope.cpp | 4 ++-- js/src/jsscope.h | 14 +++++++----- js/src/jswatchpoint.cpp | 14 +++++++----- 10 files changed, 52 insertions(+), 49 deletions(-) diff --git a/js/src/gc/Barrier.h b/js/src/gc/Barrier.h index 0919a9aac98..c82e509b4bd 100644 --- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -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: diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index f67611376a1..cdb3786bfdb 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -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 diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 5baf96212bd..a7e42a43148 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2266,7 +2266,7 @@ AutoGCRooter::trace(JSTracer *trc) return; case ID: - MarkIdRoot(trc, static_cast(this)->id_, "JS::AutoIdRooter.id_"); + MarkIdRoot(trc, &static_cast(this)->id_, "JS::AutoIdRooter.id_"); return; case VALVECTOR: { diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index 96a96681e55..8b77c71ea40 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -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(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 &thing, const MarkInternal(trc, thing.get()); } -void -MarkShape(JSTracer *trc, HeapPtr *thing, const char *name) -{ - JS_SET_TRACING_NAME(trc, name); - MarkInternal(trc, const_cast(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"); } } diff --git a/js/src/jsgcmark.h b/js/src/jsgcmark.h index 0003ea3573d..c686618e25a 100644 --- a/js/src/jsgcmark.h +++ b/js/src/jsgcmark.h @@ -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 that needs a unique cast. */ -void -MarkShape(JSTracer *trc, HeapPtr *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); diff --git a/js/src/jsinfer.cpp b/js/src/jsinfer.cpp index 2e6756d2899..eedd148126e 100644 --- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -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)); } diff --git a/js/src/jsinfer.h b/js/src/jsinfer.h index 8a7fc83ed81..a536d520a8b 100644 --- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -668,7 +668,7 @@ struct TypeNewScript * Shape to use for newly constructed objects. Reflects all definite * properties the object will have. */ - HeapPtr shape; + HeapPtrShape shape; /* * Order in which properties become initialized. We need this in case a diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index d4ca4446d40..7d77726aff0 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -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 diff --git a/js/src/jsscope.h b/js/src/jsscope.h index 01cd314e24b..6d608ae810e 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -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)->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; } diff --git a/js/src/jswatchpoint.cpp b/js/src/jswatchpoint.cpp index 24ba13978ab..a37a2eb8344 100644 --- a/js/src/jswatchpoint.cpp +++ b/js/src/jswatchpoint.cpp @@ -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"); }