Bug 1107639 - Remove public Add/RemoveRoot API r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 23 Jan 2015 10:23:58 +0000
changeset 225289 572c6cb0e79c24c4bebd86adf321f4e4a7ff2680
parent 225288 0f9dec52a4bd933efefbb7844dd16ef78d35cdd9
child 225290 892355089c65f853fb408ee86d759f5d4828cfdc
push id54520
push userjcoppeard@mozilla.com
push dateFri, 23 Jan 2015 10:26:00 +0000
treeherdermozilla-inbound@572c6cb0e79c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1107639
milestone38.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 1107639 - Remove public Add/RemoveRoot API r=terrence
js/src/gc/GCRuntime.h
js/src/gc/RootMarking.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jsgc.cpp
js/src/jsgc.h
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -267,30 +267,35 @@ class ChainedIter
         MOZ_ASSERT(!iter1_.done());
         return iter1_.get();
     }
 
     operator T() const { return get(); }
     T operator->() const { return get(); }
 };
 
+typedef js::HashMap<Value *,
+                    const char *,
+                    js::DefaultHasher<Value *>,
+                    js::SystemAllocPolicy> RootedValueMap;
+
 class GCRuntime
 {
   public:
     explicit GCRuntime(JSRuntime *rt);
     bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
     void finishRoots();
     void finish();
 
     inline int zeal();
     inline bool upcomingZealousGC();
     inline bool needZealousGC();
 
-    template <typename T> bool addRoot(T *rp, const char *name, JSGCRootType rootType);
-    void removeRoot(void *rp);
+    bool addRoot(Value *vp, const char *name);
+    void removeRoot(Value *vp);
     void setMarkStackLimit(size_t limit);
 
     void setParameter(JSGCParamKey key, uint32_t value);
     uint32_t getParameter(JSGCParamKey key, const AutoLockGC &lock);
 
     bool isHeapBusy() { return heapState != js::Idle; }
     bool isHeapMajorCollecting() { return heapState == js::MajorCollecting; }
     bool isHeapMinorCollecting() { return heapState == js::MinorCollecting; }
@@ -660,17 +665,17 @@ class GCRuntime
     // is moved back to the emptyChunks pool and scheduled for eventual
     // release.
     ChunkPool             availableChunks_;
 
     // When all arenas in a chunk are used, it is moved to the fullChunks pool
     // so as to reduce the cost of operations on the available lists.
     ChunkPool             fullChunks_;
 
-    js::RootedValueMap rootsHash;
+    RootedValueMap rootsHash;
 
     size_t maxMallocBytes;
 
     /*
      * Number of the committed arenas in all GC chunks including empty chunks.
      */
     mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> numArenasFreeCommitted;
     void *verifyPreData;
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -440,31 +440,17 @@ js::gc::GCRuntime::markRuntime(JSTracer 
 
         if (!rt->isBeingDestroyed()) {
             MarkExactStackRoots(rt, trc);
             rt->markSelfHostingGlobal(trc);
         }
 
         for (RootRange r = rootsHash.all(); !r.empty(); r.popFront()) {
             const RootEntry &entry = r.front();
-            const char *name = entry.value().name ? entry.value().name : "root";
-            JSGCRootType type = entry.value().type;
-            void *key = entry.key();
-            if (type == JS_GC_ROOT_VALUE_PTR) {
-                MarkValueRoot(trc, reinterpret_cast<Value *>(key), name);
-            } else if (*reinterpret_cast<void **>(key)){
-                if (type == JS_GC_ROOT_STRING_PTR)
-                    MarkStringRoot(trc, reinterpret_cast<JSString **>(key), name);
-                else if (type == JS_GC_ROOT_OBJECT_PTR)
-                    MarkObjectRoot(trc, reinterpret_cast<JSObject **>(key), name);
-                else if (type == JS_GC_ROOT_SCRIPT_PTR)
-                    MarkScriptRoot(trc, reinterpret_cast<JSScript **>(key), name);
-                else
-                    MOZ_CRASH("unexpected js::RootInfo::type value");
-            }
+            MarkValueRoot(trc, entry.key(), entry.value());
         }
 
         MarkPersistentRootedChains(trc);
     }
 
     if (rt->scriptAndCountsVector) {
         ScriptAndCountsVector &vec = *rt->scriptAndCountsVector;
         for (size_t i = 0; i < vec.length(); i++)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1496,140 +1496,16 @@ JS_strdup(JSRuntime *rt, const char *s)
     if (!p)
         return nullptr;
     return static_cast<char*>(js_memcpy(p, s, n));
 }
 
 #undef JS_AddRoot
 
 JS_PUBLIC_API(bool)
-JS::AddValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddValueRoot(cx, vp->unsafeGet(), nullptr);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddStringRoot(cx, rp->unsafeGet(), nullptr);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddObjectRoot(cx, rp->unsafeGet(), nullptr);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddNamedValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp, const char *name)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddValueRoot(cx, vp->unsafeGet(), name);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddNamedValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp, const char *name)
-{
-    return AddValueRootRT(rt, vp->unsafeGet(), name);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddNamedStringRoot(JSContext *cx, JS::Heap<JSString *> *rp, const char *name)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddStringRoot(cx, rp->unsafeGet(), name);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddNamedObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp, const char *name)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddObjectRoot(cx, rp->unsafeGet(), name);
-}
-
-JS_PUBLIC_API(bool)
-JS::AddNamedScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp, const char *name)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return AddScriptRoot(cx, rp->unsafeGet(), name);
-}
-
-/* We allow unrooting from finalizers within the GC */
-
-JS_PUBLIC_API(void)
-JS::RemoveValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp)
-{
-    CHECK_REQUEST(cx);
-    RemoveRoot(cx->runtime(), (void *)vp);
-    *vp = UndefinedValue();
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveStringRoot(JSContext *cx, JS::Heap<JSString *> *rp)
-{
-    CHECK_REQUEST(cx);
-    RemoveRoot(cx->runtime(), (void *)rp);
-    *rp = nullptr;
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp)
-{
-    CHECK_REQUEST(cx);
-    RemoveRoot(cx->runtime(), (void *)rp);
-    *rp = nullptr;
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp)
-{
-    CHECK_REQUEST(cx);
-    RemoveRoot(cx->runtime(), (void *)rp);
-    *rp = nullptr;
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp)
-{
-    RemoveRoot(rt, (void *)vp);
-    *vp = UndefinedValue();
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveStringRootRT(JSRuntime *rt, JS::Heap<JSString *> *rp)
-{
-    RemoveRoot(rt, (void *)rp);
-    *rp = nullptr;
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveObjectRootRT(JSRuntime *rt, JS::Heap<JSObject *> *rp)
-{
-    RemoveRoot(rt, (void *)rp);
-    *rp = nullptr;
-}
-
-JS_PUBLIC_API(void)
-JS::RemoveScriptRootRT(JSRuntime *rt, JS::Heap<JSScript *> *rp)
-{
-    RemoveRoot(rt, (void *)rp);
-    *rp = nullptr;
-}
-
-JS_PUBLIC_API(bool)
 JS_AddExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
 {
     return rt->gc.addBlackRootsTracer(traceOp, data);
 }
 
 JS_PUBLIC_API(void)
 JS_RemoveExtraGCRootsTracer(JSRuntime *rt, JSTraceDataOp traceOp, void *data)
 {
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1991,93 +1991,16 @@ JS_updateMallocCounter(JSContext *cx, si
 
 extern JS_PUBLIC_API(char *)
 JS_strdup(JSContext *cx, const char *s);
 
 /* Duplicate a string.  Does not report an error on failure. */
 extern JS_PUBLIC_API(char *)
 JS_strdup(JSRuntime *rt, const char *s);
 
-namespace JS {
-
-/*
- * A GC root is a pointer to a jsval, JSObject * or JSString * that itself
- * points into the GC heap. JS_AddValueRoot takes a pointer to a jsval and
- * JS_AddGCThingRoot takes a pointer to a JSObject * or JString *.
- *
- * Note that, since JS_Add*Root stores the address of a variable (of type
- * jsval, JSString *, or JSObject *), that variable must live until
- * JS_Remove*Root is called to remove that variable. For example, after:
- *
- *   void some_function() {
- *     jsval v;
- *     JS_AddNamedValueRoot(cx, &v, "name");
- *
- * the caller must perform
- *
- *     JS_RemoveValueRoot(cx, &v);
- *
- * before some_function() returns.
- *
- * Also, use JS_AddNamed*Root(cx, &structPtr->memberObj, "structPtr->memberObj")
- * in preference to JS_Add*Root(cx, &structPtr->memberObj), in order to identify
- * roots by their source callsites.  This way, you can find the callsite while
- * debugging if you should fail to do JS_Remove*Root(cx, &structPtr->memberObj)
- * before freeing structPtr's memory.
- */
-extern JS_PUBLIC_API(bool)
-AddValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp);
-
-extern JS_PUBLIC_API(bool)
-AddStringRoot(JSContext *cx, JS::Heap<JSString *> *rp);
-
-extern JS_PUBLIC_API(bool)
-AddObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp);
-
-extern JS_PUBLIC_API(bool)
-AddNamedValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp, const char *name);
-
-extern JS_PUBLIC_API(bool)
-AddNamedValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp, const char *name);
-
-extern JS_PUBLIC_API(bool)
-AddNamedStringRoot(JSContext *cx, JS::Heap<JSString *> *rp, const char *name);
-
-extern JS_PUBLIC_API(bool)
-AddNamedObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp, const char *name);
-
-extern JS_PUBLIC_API(bool)
-AddNamedScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp, const char *name);
-
-extern JS_PUBLIC_API(void)
-RemoveValueRoot(JSContext *cx, JS::Heap<JS::Value> *vp);
-
-extern JS_PUBLIC_API(void)
-RemoveStringRoot(JSContext *cx, JS::Heap<JSString *> *rp);
-
-extern JS_PUBLIC_API(void)
-RemoveObjectRoot(JSContext *cx, JS::Heap<JSObject *> *rp);
-
-extern JS_PUBLIC_API(void)
-RemoveScriptRoot(JSContext *cx, JS::Heap<JSScript *> *rp);
-
-extern JS_PUBLIC_API(void)
-RemoveValueRootRT(JSRuntime *rt, JS::Heap<JS::Value> *vp);
-
-extern JS_PUBLIC_API(void)
-RemoveStringRootRT(JSRuntime *rt, JS::Heap<JSString *> *rp);
-
-extern JS_PUBLIC_API(void)
-RemoveObjectRootRT(JSRuntime *rt, JS::Heap<JSObject *> *rp);
-
-extern JS_PUBLIC_API(void)
-RemoveScriptRootRT(JSRuntime *rt, JS::Heap<JSScript *> *rp);
-
-} /* namespace JS */
-
 /*
  * Register externally maintained GC roots.
  *
  * traceOp: the trace operation. For each root the implementation should call
  *          JS_CallTracer whenever the root contains a traceable thing.
  * data:    the data argument to pass to each invocation of traceOp.
  */
 extern JS_PUBLIC_API(bool)
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -1490,20 +1490,16 @@ GCRuntime::getParameter(JSGCParamKey key
 void
 GCRuntime::setMarkStackLimit(size_t limit)
 {
     MOZ_ASSERT(!isHeapBusy());
     AutoStopVerifyingBarriers pauseVerification(rt, false);
     marker.setMaxCapacity(limit);
 }
 
-template <typename T> struct BarrierOwner {};
-template <typename T> struct BarrierOwner<T *> { typedef T result; };
-template <> struct BarrierOwner<Value> { typedef HeapValue result; };
-
 bool
 GCRuntime::addBlackRootsTracer(JSTraceDataOp traceOp, void *data)
 {
     AssertHeapIsIdle(rt);
     return !!blackRootTracers.append(Callback<JSTraceDataOp>(traceOp, data));
 }
 
 void
@@ -1591,108 +1587,53 @@ GCRuntime::callWeakPointerCallbacks() co
     }
 }
 
 JS::GCSliceCallback
 GCRuntime::setSliceCallback(JS::GCSliceCallback callback) {
     return stats.setSliceCallback(callback);
 }
 
-template <typename T>
 bool
-GCRuntime::addRoot(T *rp, const char *name, JSGCRootType rootType)
+GCRuntime::addRoot(Value *vp, const char *name)
 {
     /*
      * Sometimes Firefox will hold weak references to objects and then convert
      * them to strong references by calling AddRoot (e.g., via PreserveWrapper,
      * or ModifyBusyCount in workers). We need a read barrier to cover these
      * cases.
      */
     if (isIncrementalGCInProgress())
-        BarrierOwner<T>::result::writeBarrierPre(*rp);
-
-    return rootsHash.put((void *)rp, RootInfo(name, rootType));
-}
-
-void
-GCRuntime::removeRoot(void *rp)
-{
-    rootsHash.remove(rp);
+        HeapValue::writeBarrierPre(*vp);
+
+    return rootsHash.put(vp, name);
+}
+
+void
+GCRuntime::removeRoot(Value *vp)
+{
+    rootsHash.remove(vp);
     poke();
 }
 
-template <typename T>
-static bool
-AddRoot(JSRuntime *rt, T *rp, const char *name, JSGCRootType rootType)
-{
-    return rt->gc.addRoot(rp, name, rootType);
-}
-
-template <typename T>
-static bool
-AddRoot(JSContext *cx, T *rp, const char *name, JSGCRootType rootType)
-{
-    bool ok = cx->runtime()->gc.addRoot(rp, name, rootType);
-    if (!ok)
-        JS_ReportOutOfMemory(cx);
-    return ok;
-}
-
-bool
-js::AddValueRoot(JSContext *cx, Value *vp, const char *name)
-{
-    return AddRoot(cx, vp, name, JS_GC_ROOT_VALUE_PTR);
-}
-
-extern bool
-js::AddValueRootRT(JSRuntime *rt, js::Value *vp, const char *name)
-{
-    return AddRoot(rt, vp, name, JS_GC_ROOT_VALUE_PTR);
-}
-
-extern bool
-js::AddStringRoot(JSContext *cx, JSString **rp, const char *name)
-{
-    return AddRoot(cx, rp, name, JS_GC_ROOT_STRING_PTR);
-}
-
-extern bool
-js::AddObjectRoot(JSContext *cx, JSObject **rp, const char *name)
-{
-    return AddRoot(cx, rp, name, JS_GC_ROOT_OBJECT_PTR);
-}
-
-extern bool
-js::AddObjectRoot(JSRuntime *rt, JSObject **rp, const char *name)
-{
-    return AddRoot(rt, rp, name, JS_GC_ROOT_OBJECT_PTR);
-}
-
-extern bool
-js::AddScriptRoot(JSContext *cx, JSScript **rp, const char *name)
-{
-    return AddRoot(cx, rp, name, JS_GC_ROOT_SCRIPT_PTR);
-}
-
 extern JS_FRIEND_API(bool)
 js::AddRawValueRoot(JSContext *cx, Value *vp, const char *name)
 {
-    return AddRoot(cx, vp, name, JS_GC_ROOT_VALUE_PTR);
+    MOZ_ASSERT(vp);
+    MOZ_ASSERT(name);
+    bool ok = cx->runtime()->gc.addRoot(vp, name);
+    if (!ok)
+        JS_ReportOutOfMemory(cx);
+    return ok;
 }
 
 extern JS_FRIEND_API(void)
 js::RemoveRawValueRoot(JSContext *cx, Value *vp)
 {
-    RemoveRoot(cx->runtime(), vp);
-}
-
-void
-js::RemoveRoot(JSRuntime *rt, void *rp)
-{
-    rt->gc.removeRoot(rp);
+    cx->runtime()->gc.removeRoot(vp);
 }
 
 void
 GCRuntime::setMaxMallocBytes(size_t value)
 {
     /*
      * For compatibility treat any value that exceeds PTRDIFF_T_MAX to
      * mean that value.
--- a/js/src/jsgc.h
+++ b/js/src/jsgc.h
@@ -827,56 +827,16 @@ class ArenaLists
     friend class GCRuntime;
 };
 
 /* The number of GC cycles an empty chunk can survive before been released. */
 const size_t MAX_EMPTY_CHUNK_AGE = 4;
 
 } /* namespace gc */
 
-typedef enum JSGCRootType {
-    JS_GC_ROOT_VALUE_PTR,
-    JS_GC_ROOT_STRING_PTR,
-    JS_GC_ROOT_OBJECT_PTR,
-    JS_GC_ROOT_SCRIPT_PTR
-} JSGCRootType;
-
-struct RootInfo {
-    RootInfo() {}
-    RootInfo(const char *name, JSGCRootType type) : name(name), type(type) {}
-    const char *name;
-    JSGCRootType type;
-};
-
-typedef js::HashMap<void *,
-                    RootInfo,
-                    js::DefaultHasher<void *>,
-                    js::SystemAllocPolicy> RootedValueMap;
-
-extern bool
-AddValueRoot(JSContext *cx, js::Value *vp, const char *name);
-
-extern bool
-AddValueRootRT(JSRuntime *rt, js::Value *vp, const char *name);
-
-extern bool
-AddStringRoot(JSContext *cx, JSString **rp, const char *name);
-
-extern bool
-AddObjectRoot(JSContext *cx, JSObject **rp, const char *name);
-
-extern bool
-AddObjectRoot(JSRuntime *rt, JSObject **rp, const char *name);
-
-extern bool
-AddScriptRoot(JSContext *cx, JSScript **rp, const char *name);
-
-extern void
-RemoveRoot(JSRuntime *rt, void *rp);
-
 } /* namespace js */
 
 extern bool
 js_InitGC(JSRuntime *rt, uint32_t maxbytes);
 
 extern void
 js_FinishGC(JSRuntime *rt);