author | Terrence Cole <terrence@mozilla.com> |
Fri, 17 Feb 2012 17:27:37 -0800 | |
changeset 87149 | ece583b83508f0dda79f1e2ff63393150d9b0731 |
parent 87148 | f0ac2d720c7b1e75b61a51ba31751b063c9a6e41 |
child 87150 | 1dcee8f1559a0dac6b9f49c5c052417f03e754df |
push id | 22083 |
push user | bmo@edmorley.co.uk |
push date | Sat, 18 Feb 2012 11:19:19 +0000 |
treeherder | mozilla-central@20478b673212 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | billm |
bugs | 727135 |
milestone | 13.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/gc/Barrier.h | file | annotate | diff | comparison | revisions | |
js/src/jsfriendapi.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsgc.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsgcmark.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsgcmark.h | file | annotate | diff | comparison | revisions | |
js/src/jsinfer.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsinfer.h | file | annotate | diff | comparison | revisions | |
js/src/jsscope.cpp | file | annotate | diff | comparison | revisions | |
js/src/jsscope.h | file | annotate | diff | comparison | revisions | |
js/src/jswatchpoint.cpp | file | annotate | diff | comparison | revisions |
--- a/js/src/gc/Barrier.h +++ b/js/src/gc/Barrier.h @@ -401,16 +401,17 @@ class HeapId inline HeapId &operator=(jsid id); inline HeapId &operator=(const HeapId &v); bool operator==(jsid id) const { return value == id; } bool operator!=(jsid id) const { return value != id; } jsid get() const { return value; } + jsid *unsafeGet() { return &value; } operator jsid() const { return value; } private: inline void pre(); inline void post(); HeapId(const HeapId &v); };
--- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -172,17 +172,17 @@ JS_FRIEND_API(JSBool) JS_WrapPropertyDescriptor(JSContext *cx, js::PropertyDescriptor *desc) { return cx->compartment->wrap(cx, desc); } JS_FRIEND_API(void) JS_TraceShapeCycleCollectorChildren(JSTracer *trc, void *shape) { - MarkCycleCollectorChildren(trc, (const Shape *)shape); + MarkCycleCollectorChildren(trc, (Shape *)shape); } AutoPreserveCompartment::AutoPreserveCompartment(JSContext *cx JS_GUARD_OBJECT_NOTIFIER_PARAM_NO_INIT) : cx(cx), oldCompartment(cx->compartment) { JS_GUARD_OBJECT_NOTIFIER_INIT; }
--- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2261,17 +2261,17 @@ AutoGCRooter::trace(JSTracer *trc) case OBJECT: if (static_cast<AutoObjectRooter *>(this)->obj) MarkObjectRoot(trc, &static_cast<AutoObjectRooter *>(this)->obj, "JS::AutoObjectRooter.obj"); 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: { AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector; MarkValueRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector"); return; }
--- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -56,17 +56,17 @@ PushMarkStack(GCMarker *gcmarker, JSObje static inline void PushMarkStack(GCMarker *gcmarker, JSFunction *thing); 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); static inline void PushMarkStack(GCMarker *gcmarker, types::TypeObject *thing); /*** Object Marking ***/ @@ -259,55 +259,60 @@ MarkGCThingRoot(JSTracer *trc, void *thi if (!thing) return; MarkKind(trc, thing, GetGCThingTraceKind(thing)); } /*** 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); MarkIdInternal(trc, id); } void 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()); } } void 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]); } } /*** Value Marking ***/ static inline void MarkValueInternal(JSTracer *trc, Value *v) { @@ -360,23 +365,16 @@ MarkValueRootRange(JSTracer *trc, size_t static void MarkObject(JSTracer *trc, const HeapPtr<GlobalObject, JSScript *> &thing, const char *name) { JS_SET_TRACING_NAME(trc, name); 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) { JS_SET_TRACING_NAME(trc, name); MarkValueInternal(trc, v); } void MarkCrossCompartmentValue(JSTracer *trc, HeapValue *v, const char *name) @@ -455,20 +453,20 @@ PushMarkStack(GCMarker *gcmarker, JSScri * refer to other scripts only indirectly (like via nested functions) and * we cannot get to deep recursion. */ if (thing->markIfUnmarked(gcmarker->getMarkColor())) MarkChildren(gcmarker, 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); /* We mark shapes directly rather than pushing on the stack. */ if (thing->markIfUnmarked(gcmarker->getMarkColor())) ScanShape(gcmarker, thing); } @@ -481,22 +479,22 @@ PushMarkStack(GCMarker *gcmarker, BaseSh JS_COMPARTMENT_ASSERT(gcmarker->runtime, thing); /* We mark base shapes directly rather than pushing on the stack. */ if (thing->markIfUnmarked(gcmarker->getMarkColor())) ScanBaseShape(gcmarker, 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))) PushMarkStack(gcmarker, JSID_TO_OBJECT(id)); shape = shape->previous(); if (shape && shape->markIfUnmarked(gcmarker->getMarkColor())) goto restart; @@ -707,17 +705,17 @@ MarkChildren(JSTracer *trc, JSScript *sc if (script->hasAnyBreakpointsOrStepMode()) script->markTrapClosures(trc); } 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"); } static inline void MarkBaseShapeGetterSetter(JSTracer *trc, BaseShape *base) { if (base->hasGetterObject()) @@ -770,22 +768,22 @@ MarkCycleCollectorChildren(JSTracer *trc * This function is used by the cycle collector to trace through a * shape. The cycle collector does not care about shapes or base * shapes, so those are not marked. Instead, any shapes or base shapes * that are encountered have their children marked. Stack space is * bounded. If two shapes in a row have the same parent pointer, the * 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); } static void ScanTypeObject(GCMarker *gcmarker, types::TypeObject *type) { if (!type->singleton) { @@ -818,17 +816,17 @@ ScanTypeObject(GCMarker *gcmarker, types static void MarkChildren(JSTracer *trc, types::TypeObject *type) { if (!type->singleton) { unsigned count = type->getPropertyCount(); 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"); } } if (type->proto) MarkObject(trc, &type->proto, "type_proto"); if (type->singleton && !type->lazy()) MarkObject(trc, &type->singleton, "type_singleton");
--- a/js/src/jsgcmark.h +++ b/js/src/jsgcmark.h @@ -78,20 +78,20 @@ void MarkKind(JSTracer *trc, void *thing, JSGCTraceKind kind); void 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); void MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name); /*** Value Marking ***/ @@ -111,20 +111,16 @@ MarkValueRootRange(JSTracer *trc, size_t inline void MarkValueRootRange(JSTracer *trc, Value *begin, Value *end, const char *name) { MarkValueRootRange(trc, end - begin, begin, 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); /* * Mark a value that may be in a different compartment from the compartment * being GC'd. (Although it won't be marked if it's in the wrong compartment.) */ @@ -139,17 +135,17 @@ void MarkChildren(JSTracer *trc, JSObject *obj); /* * Trace through the shape and any shapes it contains to mark * non-shape children. This is exposed to the JS API as * JS_TraceShapeCycleCollectorChildren. */ void -MarkCycleCollectorChildren(JSTracer *trc, const Shape *shape); +MarkCycleCollectorChildren(JSTracer *trc, Shape *shape); void PushArena(GCMarker *gcmarker, ArenaHeader *aheader); /*** Generic ***/ /* * The Mark() functions interface should only be used by code that must be
--- a/js/src/jsinfer.cpp +++ b/js/src/jsinfer.cpp @@ -2613,17 +2613,17 @@ struct types::ObjectTableKey jsid *ids; uint32_t nslots; uint32_t nfixed; JSObject *proto; 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)); } static inline bool match(const ObjectTableKey &v, JSObject *obj) { if (obj->slotSpan() != v.nslots || obj->numFixedSlots() != v.nfixed || obj->getProto() != v.proto) {
--- a/js/src/jsinfer.h +++ b/js/src/jsinfer.h @@ -663,17 +663,17 @@ struct TypeNewScript /* Allocation kind to use for newly constructed objects. */ gc::AllocKind allocKind; /* * 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 * scripted setter is added to one of the object's prototypes while it is * in the middle of being initialized, so we can walk the stack and fixup * any objects which look for in-progress objects which were prematurely * set with their final shape. Initialization can traverse stack frames, * in which case FRAME_PUSH/FRAME_POP are used.
--- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1057,17 +1057,17 @@ JSObject::rollbackProperties(JSContext * } } Shape * JSObject::replaceWithNewEquivalentShape(JSContext *cx, Shape *oldShape, Shape *newShape) { JS_ASSERT_IF(oldShape != lastProperty(), inDictionaryMode() && - nativeLookup(cx, oldShape->maybePropid()) == oldShape); + nativeLookup(cx, oldShape->propidRef()) == oldShape); JSObject *self = this; if (!inDictionaryMode()) { RootObject selfRoot(cx, &self); RootShape newRoot(cx, &newShape); if (!toDictionaryMode(cx)) return NULL; @@ -1081,17 +1081,17 @@ JSObject::replaceWithNewEquivalentShape( if (!newShape) return NULL; new (newShape) Shape(oldShape->base()->unowned(), 0); } 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 * enumeration order (see bug 601399). */ StackShape nshape(oldShape); newShape->initDictionaryShape(nshape, self->numFixedSlots(), oldShape->listp);
--- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -769,18 +769,22 @@ struct Shape : public js::gc::Cell void incrementNumLinearSearches() { uint32_t count = numLinearSearches(); JS_ASSERT(count < LINEAR_SEARCHES_MAX); slotInfo = slotInfo & ~LINEAR_SEARCHES_MASK; 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_; } /* * If SHORTID is set in shape->flags, we use shape->shortid rather * than id when calling shape's getter or setter. */ @@ -994,17 +998,17 @@ struct StackShape { JS_ASSERT(base); JS_ASSERT(!JSID_IS_VOID(propid)); JS_ASSERT(slot <= SHAPE_INVALID_SLOT); } 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), shortid(shape->shortid_) {} bool hasSlot() const { return (attrs & JSPROP_SHARED) == 0; } bool hasMissingSlot() const { return maybeSlot() == SHAPE_INVALID_SLOT; } @@ -1080,27 +1084,27 @@ Shape::search(JSContext *cx, Shape *star if (start->isBigEnoughForAPropertyTable()) { RootShape startRoot(cx, &start); RootId idRoot(cx, &id); if (start->hashify(cx)) { Shape **spp = start->table().search(id, adding); return SHAPE_FETCH(spp); } } - /* + /* * No table built -- there weren't enough entries, or OOM occurred. * Don't increment numLinearSearches, to keep hasTable() false. */ JS_ASSERT(!start->hasTable()); } else { start->incrementNumLinearSearches(); } for (Shape *shape = start; shape; shape = shape->parent) { - if (shape->maybePropid() == id) + if (shape->propidRef() == id) return shape; } return NULL; } } // namespace js
--- a/js/src/jswatchpoint.cpp +++ b/js/src/jswatchpoint.cpp @@ -205,39 +205,43 @@ WatchpointMap::markIteratively(JSTracer HeapPtrObject tmp(e.key.object); MarkObject(trc, &tmp, "held Watchpoint object"); JS_ASSERT(tmp == e.key.object); marked = true; } 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"); marked = true; } } } return marked; } void 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"); } } void WatchpointMap::sweepAll(JSRuntime *rt) {