Bug 1147669 - Replace id marking functions with TraceEdge; r=jonco
☠☠ backed out by 99415fbccf83 ☠ ☠
authorTerrence Cole <terrence@mozilla.com>
Thu, 26 Mar 2015 10:23:30 -0700
changeset 265174 35ad82ff9ee770505514230b39864694cd045a75
parent 265173 ffe7f2e2a0f0099870373f80a102c11860d00c4e
child 265175 0bd8c4ec41fa8c4df77bfafe5508f9924be3f650
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1147669
milestone39.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
Bug 1147669 - Replace id marking functions with TraceEdge; r=jonco
js/src/gc/Marking.cpp
js/src/gc/Marking.h
js/src/gc/RootMarking.cpp
js/src/gc/Tracer.cpp
js/src/jit/JitFrames.cpp
js/src/jsatom.h
js/src/jswatchpoint.cpp
js/src/vm/JSONParser.cpp
js/src/vm/Shape.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -1074,82 +1074,16 @@ gc::MarkGCThingRoot(JSTracer *trc, void 
 }
 
 void
 gc::MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name)
 {
     MarkGCThingInternal(trc, thingp, name);
 }
 
-/*** ID Marking ***/
-
-static inline void
-MarkIdInternal(JSTracer *trc, jsid *id)
-{
-    if (JSID_IS_STRING(*id)) {
-        JSString *str = JSID_TO_STRING(*id);
-        JSString *prior = str;
-        trc->setTracingLocation((void *)id);
-        MarkInternal(trc, &str);
-        if (str != prior)
-            *id = NON_INTEGER_ATOM_TO_JSID(reinterpret_cast<JSAtom *>(str));
-    } else if (JSID_IS_SYMBOL(*id)) {
-        JS::Symbol *sym = JSID_TO_SYMBOL(*id);
-        JS::Symbol *prior = sym;
-        trc->setTracingLocation((void *)id);
-        MarkInternal(trc, &sym);
-        if (sym != prior)
-            *id = SYMBOL_TO_JSID(sym);
-    } else {
-        /* Unset realLocation manually if we do not call MarkInternal. */
-        trc->unsetTracingLocation();
-    }
-}
-
-void
-gc::MarkId(JSTracer *trc, BarrieredBase<jsid> *id, const char *name)
-{
-    trc->setTracingName(name);
-    MarkIdInternal(trc, id->unsafeGet());
-}
-
-void
-gc::MarkIdRoot(JSTracer *trc, jsid *id, const char *name)
-{
-    JS_ROOT_MARKING_ASSERT(trc);
-    trc->setTracingName(name);
-    MarkIdInternal(trc, id);
-}
-
-void
-gc::MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name)
-{
-    trc->setTracingName(name);
-    MarkIdInternal(trc, id);
-}
-
-void
-gc::MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name)
-{
-    for (size_t i = 0; i < len; ++i) {
-        trc->setTracingIndex(name, i);
-        MarkIdInternal(trc, vec[i].unsafeGet());
-    }
-}
-
-void
-gc::MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name)
-{
-    JS_ROOT_MARKING_ASSERT(trc);
-    for (size_t i = 0; i < len; ++i) {
-        trc->setTracingIndex(name, i);
-        MarkIdInternal(trc, &vec[i]);
-    }
-}
-
 /*** Value Marking ***/
 
 static inline void
 MarkValueInternal(JSTracer *trc, Value *v)
 {
     if (v->isMarkable()) {
         MOZ_ASSERT(v->toGCThing());
         void *thing = v->toGCThing();
@@ -1591,17 +1525,17 @@ gc::MarkCycleCollectorChildren(JSTracer 
     MarkObjectUnbarriered(trc, &global, "global");
 
     do {
         MOZ_ASSERT(global == shape->compartment()->unsafeUnbarrieredMaybeGlobal());
 
         MOZ_ASSERT(shape->base());
         shape->base()->assertConsistency();
 
-        MarkId(trc, &shape->propidRef(), "propid");
+        TraceEdge(trc, &shape->propidRef(), "propid");
 
         if (shape->hasGetterObject()) {
             JSObject *tmp = shape->getterObject();
             MarkObjectUnbarriered(trc, &tmp, "getter");
             MOZ_ASSERT(tmp == shape->getterObject());
         }
 
         if (shape->hasSetterObject()) {
@@ -1615,17 +1549,17 @@ gc::MarkCycleCollectorChildren(JSTracer 
 }
 
 static void
 ScanObjectGroup(GCMarker *gcmarker, ObjectGroup *group)
 {
     unsigned count = group->getPropertyCount();
     for (unsigned i = 0; i < count; i++) {
         if (ObjectGroup::Property *prop = group->getProperty(i))
-            MarkId(gcmarker, &prop->id, "ObjectGroup property id");
+            DoMarking(gcmarker, prop->id.get());
     }
 
     if (group->proto().isObject())
         gcmarker->traverse(group->proto().toObject());
 
     group->compartment()->mark();
 
     if (GlobalObject *global = group->compartment()->unsafeUnbarrieredMaybeGlobal())
@@ -1651,17 +1585,17 @@ ScanObjectGroup(GCMarker *gcmarker, Obje
 }
 
 static void
 gc::MarkChildren(JSTracer *trc, ObjectGroup *group)
 {
     unsigned count = group->getPropertyCount();
     for (unsigned i = 0; i < count; i++) {
         if (ObjectGroup::Property *prop = group->getProperty(i))
-            MarkId(trc, &prop->id, "group_property");
+            TraceEdge(trc, &prop->id, "group_property");
     }
 
     if (group->proto().isObject())
         MarkObject(trc, &group->protoRaw(), "group_proto");
 
     if (group->newScript())
         group->newScript()->trace(trc);
 
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -204,33 +204,16 @@ void
 MarkKind(JSTracer *trc, void **thingp, JSGCTraceKind kind);
 
 void
 MarkGCThingRoot(JSTracer *trc, void **thingp, const char *name);
 
 void
 MarkGCThingUnbarriered(JSTracer *trc, void **thingp, const char *name);
 
-/*** ID Marking ***/
-
-void
-MarkId(JSTracer *trc, BarrieredBase<jsid> *id, const char *name);
-
-void
-MarkIdRoot(JSTracer *trc, jsid *id, const char *name);
-
-void
-MarkIdUnbarriered(JSTracer *trc, jsid *id, const char *name);
-
-void
-MarkIdRange(JSTracer *trc, size_t len, HeapId *vec, const char *name);
-
-void
-MarkIdRootRange(JSTracer *trc, size_t len, jsid *vec, const char *name);
-
 /*** Value Marking ***/
 
 bool
 IsValueMarked(Value *v);
 
 bool
 IsValueAboutToBeFinalized(Value *v);
 
@@ -255,16 +238,20 @@ MarkObjectSlots(JSTracer *trc, NativeObj
 void
 MarkCycleCollectorChildren(JSTracer *trc, Shape *shape);
 
 void
 PushArena(GCMarker *gcmarker, ArenaHeader *aheader);
 
 /*** Generic ***/
 
+template <typename T>
+static bool
+IsMarked(T **thingp);
+
 inline bool
 IsMarked(BarrieredBase<Value> *v)
 {
     if (!v->isMarkable())
         return true;
     return IsValueMarked(v->unsafeGet());
 }
 
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -99,17 +99,17 @@ MarkExactStackRootsAcrossTypes(T context
     MarkExactStackRootList<BaseShape *, MarkBaseShapeRoot>(trc, context, "exact-baseshape");
     MarkExactStackRootList<ObjectGroup *, MarkObjectGroupRoot>(
         trc, context, "exact-objectgroup");
     MarkExactStackRootList<JSString *, MarkStringRoot>(trc, context, "exact-string");
     MarkExactStackRootList<JS::Symbol *, MarkSymbolRoot>(trc, context, "exact-symbol");
     MarkExactStackRootList<jit::JitCode *, MarkJitCodeRoot>(trc, context, "exact-jitcode");
     MarkExactStackRootList<JSScript *, MarkScriptRoot>(trc, context, "exact-script");
     MarkExactStackRootList<LazyScript *, MarkLazyScriptRoot>(trc, context, "exact-lazy-script");
-    MarkExactStackRootList<jsid, MarkIdRoot>(trc, context, "exact-id");
+    MarkExactStackRootList<jsid, TraceRoot>(trc, context, "exact-id");
     MarkExactStackRootList<Value, TraceRoot>(trc, context, "exact-value");
     MarkExactStackRootList<TypeSet::Type, TypeSet::MarkTypeRoot>(trc, context, "TypeSet::Type");
     MarkExactStackRootList<Bindings, MarkBindingsRoot>(trc, context, "Bindings");
     MarkExactStackRootList<JSPropertyDescriptor, MarkPropertyDescriptorRoot>(
         trc, context, "JSPropertyDescriptor");
 }
 
 static void
@@ -119,30 +119,30 @@ MarkExactStackRoots(JSRuntime* rt, JSTra
         MarkExactStackRootsAcrossTypes<JSContext*>(cx.get(), trc);
     MarkExactStackRootsAcrossTypes<PerThreadData*>(&rt->mainThread, trc);
 }
 
 void
 JS::AutoIdArray::trace(JSTracer *trc)
 {
     MOZ_ASSERT(tag_ == IDARRAY);
-    gc::MarkIdRange(trc, idArray->length, idArray->vector, "JSAutoIdArray.idArray");
+    TraceRange(trc, idArray->length, idArray->begin(), "JSAutoIdArray.idArray");
 }
 
 inline void
 AutoGCRooter::trace(JSTracer *trc)
 {
     switch (tag_) {
       case PARSER:
         frontend::MarkParser(trc, this);
         return;
 
       case IDARRAY: {
         JSIdArray *ida = static_cast<AutoIdArray *>(this)->idArray;
-        MarkIdRange(trc, ida->length, ida->vector, "JS::AutoIdArray.idArray");
+        TraceRange(trc, ida->length, ida->begin(), "JS::AutoIdArray.idArray");
         return;
       }
 
       case DESCVECTOR: {
         AutoPropertyDescriptorVector::VectorImpl &descriptors =
             static_cast<AutoPropertyDescriptorVector *>(this)->vector;
         for (size_t i = 0, len = descriptors.length(); i < len; i++)
             descriptors[i].trace(trc);
@@ -152,24 +152,24 @@ AutoGCRooter::trace(JSTracer *trc)
       case VALVECTOR: {
         AutoValueVector::VectorImpl &vector = static_cast<AutoValueVector *>(this)->vector;
         TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoValueVector.vector");
         return;
       }
 
       case IDVECTOR: {
         AutoIdVector::VectorImpl &vector = static_cast<AutoIdVector *>(this)->vector;
-        MarkIdRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
+        TraceRootRange(trc, vector.length(), vector.begin(), "js::AutoIdVector.vector");
         return;
       }
 
       case IDVALVECTOR: {
         AutoIdValueVector::VectorImpl &vector = static_cast<AutoIdValueVector *>(this)->vector;
         for (size_t i = 0; i < vector.length(); i++) {
-            MarkIdRoot(trc, &vector[i].id, "js::AutoIdValueVector id");
+            TraceRoot(trc, &vector[i].id, "js::AutoIdValueVector id");
             TraceRoot(trc, &vector[i].value, "js::AutoIdValueVector value");
         }
         return;
       }
 
       case SHAPEVECTOR: {
         AutoShapeVector::VectorImpl &vector = static_cast<js::AutoShapeVector *>(this)->vector;
         MarkShapeRootRange(trc, vector.length(), const_cast<Shape **>(vector.begin()),
@@ -327,17 +327,17 @@ AutoHashableValueRooter::trace(JSTracer 
 }
 
 void
 StackShape::trace(JSTracer *trc)
 {
     if (base)
         MarkBaseShapeRoot(trc, (BaseShape**) &base, "StackShape base");
 
-    MarkIdRoot(trc, (jsid*) &propid, "StackShape id");
+    TraceRoot(trc, (jsid*) &propid, "StackShape id");
 
     if ((attrs & JSPROP_GETTER) && rawGetter)
         MarkObjectRoot(trc, (JSObject**)&rawGetter, "StackShape getter");
 
     if ((attrs & JSPROP_SETTER) && rawSetter)
         MarkObjectRoot(trc, (JSObject**)&rawSetter, "StackShape setter");
 }
 
@@ -401,18 +401,18 @@ js::gc::MarkPersistentRootedChains(JSTra
     PersistentRootedMarker<JSObject*>::markChainIfNotNull<MarkObjectRoot>(
         trc, rt->objectPersistentRooteds, "PersistentRooted<JSObject *>");
     PersistentRootedMarker<JSScript*>::markChainIfNotNull<MarkScriptRoot>(
         trc, rt->scriptPersistentRooteds, "PersistentRooted<JSScript *>");
     PersistentRootedMarker<JSString*>::markChainIfNotNull<MarkStringRoot>(
         trc, rt->stringPersistentRooteds, "PersistentRooted<JSString *>");
 
     // Mark the PersistentRooted chains of types that are never null.
-    PersistentRootedMarker<jsid>::markChain<MarkIdRoot>(trc, rt->idPersistentRooteds,
-                                                        "PersistentRooted<jsid>");
+    PersistentRootedMarker<jsid>::markChain<TraceRoot>(trc, rt->idPersistentRooteds,
+                                                       "PersistentRooted<jsid>");
     PersistentRootedMarker<Value>::markChain<TraceRoot>(trc, rt->valuePersistentRooteds,
                                                         "PersistentRooted<Value>");
 }
 
 void
 js::gc::GCRuntime::markRuntime(JSTracer *trc,
                                TraceOrMarkRuntime traceOrMark,
                                TraceRootsOrUsedSaved rootsSource)
--- a/js/src/gc/Tracer.cpp
+++ b/js/src/gc/Tracer.cpp
@@ -33,17 +33,17 @@ JS_PUBLIC_API(void)
 JS_CallUnbarrieredValueTracer(JSTracer *trc, Value *valuep, const char *name)
 {
     TraceManuallyBarrieredEdge(trc, valuep, name);
 }
 
 JS_PUBLIC_API(void)
 JS_CallUnbarrieredIdTracer(JSTracer *trc, jsid *idp, const char *name)
 {
-    MarkIdUnbarriered(trc, idp, name);
+    TraceManuallyBarrieredEdge(trc, idp, name);
 }
 
 JS_PUBLIC_API(void)
 JS_CallUnbarrieredObjectTracer(JSTracer *trc, JSObject **objp, const char *name)
 {
     MarkObjectUnbarriered(trc, objp, name);
 }
 
@@ -63,17 +63,17 @@ JS_PUBLIC_API(void)
 JS_CallValueTracer(JSTracer *trc, JS::Heap<JS::Value> *valuep, const char *name)
 {
     TraceManuallyBarrieredEdge(trc, valuep->unsafeGet(), name);
 }
 
 JS_PUBLIC_API(void)
 JS_CallIdTracer(JSTracer *trc, JS::Heap<jsid> *idp, const char *name)
 {
-    MarkIdUnbarriered(trc, idp->unsafeGet(), name);
+    TraceManuallyBarrieredEdge(trc, idp->unsafeGet(), name);
 }
 
 JS_PUBLIC_API(void)
 JS_CallObjectTracer(JSTracer *trc, JS::Heap<JSObject *> *objp, const char *name)
 {
     MarkObjectUnbarriered(trc, objp->unsafeGet(), name);
 }
 
--- a/js/src/jit/JitFrames.cpp
+++ b/js/src/jit/JitFrames.cpp
@@ -1324,26 +1324,26 @@ MarkJitExitFrame(JSTracer *trc, const Ji
         // difference between the two. The fields that need marking are all in
         // the common base class.
         IonOOLPropertyOpExitFrameLayout *oolgetter =
             frame.isExitFrameLayout<IonOOLPropertyOpExitFrameLayout>()
             ? frame.exitFrame()->as<IonOOLPropertyOpExitFrameLayout>()
             : frame.exitFrame()->as<IonOOLSetterOpExitFrameLayout>();
         gc::MarkJitCodeRoot(trc, oolgetter->stubCode(), "ion-ool-property-op-code");
         TraceRoot(trc, oolgetter->vp(), "ion-ool-property-op-vp");
-        gc::MarkIdRoot(trc, oolgetter->id(), "ion-ool-property-op-id");
+        TraceRoot(trc, oolgetter->id(), "ion-ool-property-op-id");
         gc::MarkObjectRoot(trc, oolgetter->obj(), "ion-ool-property-op-obj");
         return;
     }
 
     if (frame.isExitFrameLayout<IonOOLProxyExitFrameLayout>()) {
         IonOOLProxyExitFrameLayout *oolproxy = frame.exitFrame()->as<IonOOLProxyExitFrameLayout>();
         gc::MarkJitCodeRoot(trc, oolproxy->stubCode(), "ion-ool-proxy-code");
         TraceRoot(trc, oolproxy->vp(), "ion-ool-proxy-vp");
-        gc::MarkIdRoot(trc, oolproxy->id(), "ion-ool-proxy-id");
+        TraceRoot(trc, oolproxy->id(), "ion-ool-proxy-id");
         gc::MarkObjectRoot(trc, oolproxy->proxy(), "ion-ool-proxy-proxy");
         gc::MarkObjectRoot(trc, oolproxy->receiver(), "ion-ool-proxy-receiver");
         return;
     }
 
     if (frame.isExitFrameLayout<IonDOMExitFrameLayout>()) {
         IonDOMExitFrameLayout *dom = frame.exitFrame()->as<IonDOMExitFrameLayout>();
         gc::MarkObjectRoot(trc, dom->thisObjAddress(), "ion-dom-args");
--- a/js/src/jsatom.h
+++ b/js/src/jsatom.h
@@ -17,16 +17,21 @@
 #include "vm/CommonPropertyNames.h"
 
 class JSAtom;
 class JSAutoByteString;
 
 struct JSIdArray {
     int length;
     js::HeapId vector[1];    /* actually, length jsid words */
+
+    js::HeapId *begin() { return vector; }
+    const js::HeapId *begin() const { return vector; }
+    js::HeapId *end() { return vector + length; }
+    const js::HeapId *end() const { return vector + length; }
 };
 
 namespace js {
 
 JS_STATIC_ASSERT(sizeof(HashNumber) == 4);
 
 static MOZ_ALWAYS_INLINE js::HashNumber
 HashId(jsid id)
--- a/js/src/jswatchpoint.cpp
+++ b/js/src/jswatchpoint.cpp
@@ -167,17 +167,17 @@ WatchpointMap::markIteratively(JSTracer 
                 MarkObject(trc, const_cast<PreBarrieredObject *>(&entry.key().object),
                            "held Watchpoint object");
                 marked = true;
             }
 
             MOZ_ASSERT(JSID_IS_STRING(priorKeyId) ||
                        JSID_IS_INT(priorKeyId) ||
                        JSID_IS_SYMBOL(priorKeyId));
-            MarkId(trc, const_cast<PreBarrieredId *>(&entry.key().id), "WatchKey::id");
+            TraceEdge(trc, const_cast<PreBarrieredId *>(&entry.key().id), "WatchKey::id");
 
             if (entry.value().closure && !IsObjectMarked(&entry.value().closure)) {
                 MarkObject(trc, &entry.value().closure, "Watchpoint::closure");
                 marked = true;
             }
 
             /* We will sweep this entry in sweepAll if !objectIsLive. */
             if (priorKeyObj != entry.key().object || priorKeyId != entry.key().id)
@@ -193,17 +193,17 @@ WatchpointMap::markAll(JSTracer *trc)
     for (Map::Enum e(map); !e.empty(); e.popFront()) {
         Map::Entry &entry = e.front();
         WatchKey key = entry.key();
         WatchKey prior = key;
         MOZ_ASSERT(JSID_IS_STRING(prior.id) || JSID_IS_INT(prior.id) || JSID_IS_SYMBOL(prior.id));
 
         MarkObject(trc, const_cast<PreBarrieredObject *>(&key.object),
                    "held Watchpoint object");
-        MarkId(trc, const_cast<PreBarrieredId *>(&key.id), "WatchKey::id");
+        TraceEdge(trc, const_cast<PreBarrieredId *>(&key.id), "WatchKey::id");
         MarkObject(trc, &entry.value().closure, "Watchpoint::closure");
 
         if (prior.object != key.object || prior.id != key.id)
             e.rekeyFront(key);
     }
 }
 
 void
--- a/js/src/vm/JSONParser.cpp
+++ b/js/src/vm/JSONParser.cpp
@@ -47,17 +47,17 @@ JSONParserBase::trace(JSTracer *trc)
         if (stack[i].state == FinishArrayElement) {
             ElementVector &elements = stack[i].elements();
             for (size_t j = 0; j < elements.length(); j++)
                 TraceRoot(trc, &elements[j], "JSONParser element");
         } else {
             PropertyVector &properties = stack[i].properties();
             for (size_t j = 0; j < properties.length(); j++) {
                 TraceRoot(trc, &properties[j].value, "JSONParser property value");
-                gc::MarkIdRoot(trc, &properties[j].id, "JSONParser property id");
+                TraceRoot(trc, &properties[j].id, "JSONParser property id");
             }
         }
     }
 }
 
 template <typename CharT>
 void
 JSONParser<CharT>::getTextPosition(uint32_t *column, uint32_t *line)
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -1356,17 +1356,17 @@ Shape::searchLinear(jsid id)
 
     return nullptr;
 }
 
 inline void
 Shape::markChildren(JSTracer *trc)
 {
     MarkBaseShape(trc, &base_, "base");
-    gc::MarkId(trc, &propidRef(), "propid");
+    TraceEdge(trc, &propidRef(), "propid");
     if (parent)
         MarkShape(trc, &parent, "parent");
 
     if (hasGetterObject())
         gc::MarkObjectUnbarriered(trc, &asAccessorShape().getterObj, "getter");
 
     if (hasSetterObject())
         gc::MarkObjectUnbarriered(trc, &asAccessorShape().setterObj, "setter");