Bug 1107639 - Give PersistentRooted<Value> the standard operations on Value r=terrence
authorJon Coppeard <jcoppeard@mozilla.com>
Fri, 23 Jan 2015 10:23:56 +0000
changeset 225358 71097bb1ddcc73334d89d83e6e1f1b95f3a87f29
parent 225357 d39d7e6ac6b8e376b2b02892013d46f2f8b615a4
child 225359 852a970ae0d29218bb5e92ee1d0110a7a06f1aa0
push id28159
push userryanvm@gmail.com
push dateFri, 23 Jan 2015 17:30:19 +0000
treeherdermozilla-central@a6bbabebed2f [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 - Give PersistentRooted<Value> the standard operations on Value r=terrence
js/public/RootingAPI.h
js/public/Value.h
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -113,16 +113,19 @@ template <typename T>
 class HandleBase {};
 
 template <typename T>
 class MutableHandleBase {};
 
 template <typename T>
 class HeapBase {};
 
+template <typename T>
+class PersistentRootedBase {};
+
 /*
  * js::NullPtr acts like a nullptr pointer in contexts that require a Handle.
  *
  * Handle provides an implicit constructor for js::NullPtr so that, given:
  *   foo(Handle<JSObject*> h);
  * callers can simply write:
  *   foo(js::NullPtr());
  * which avoids creating a Rooted<JSObject*> just to pass nullptr.
@@ -1093,18 +1096,20 @@ MutableHandle<T>::MutableHandle(Persiste
  * In the context of Firefox, this is a severe restriction: almost everything in
  * Firefox is owned by some JS object or another, so using PersistentRooted in
  * such objects would introduce leaks. For these kinds of edges, Heap<T> or
  * TenuredHeap<T> would be better types. It's up to the implementor of the type
  * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
  * marked when the object itself is marked.
  */
 template<typename T>
-class PersistentRooted : private mozilla::LinkedListElement<PersistentRooted<T>> {
-    typedef mozilla::LinkedListElement<PersistentRooted<T>> Base;
+class PersistentRooted : public js::PersistentRootedBase<T>,
+                         private mozilla::LinkedListElement<PersistentRooted<T>>
+{
+    typedef mozilla::LinkedListElement<PersistentRooted<T>> ListBase;
 
     friend class mozilla::LinkedList<PersistentRooted>;
     friend class mozilla::LinkedListElement<PersistentRooted>;
 
     friend struct js::gc::PersistentRootedMarker<T>;
 
     friend void js::gc::FinishPersistentRootedChains(JSRuntime *rt);
 
@@ -1144,17 +1149,17 @@ class PersistentRooted : private mozilla
          *
          * This requires mutating rhs's links, but those should be 'mutable'
          * anyway. C++ doesn't let us declare mutable base classes.
          */
         const_cast<PersistentRooted &>(rhs).setNext(this);
     }
 
     bool initialized() {
-        return Base::isInList();
+        return ListBase::isInList();
     }
 
     void init(JSContext *cx) {
         init(cx, js::GCMethods<T>::initial());
     }
 
     void init(JSContext *cx, T initial)
     {
@@ -1170,17 +1175,17 @@ class PersistentRooted : private mozilla
     {
         ptr = initial;
         registerWithRuntime(rt);
     }
 
     void reset() {
         if (initialized()) {
             set(js::GCMethods<T>::initial());
-            Base::remove();
+            ListBase::remove();
         }
     }
 
     /*
      * Important: Return a reference here so passing a Rooted<T> to
      * something that takes a |const T&| is not a GC hazard.
      */
     operator const T&() const { return ptr; }
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -1845,16 +1845,34 @@ class RootedBase<JS::Value> : public Mut
     }
 
     friend class MutableValueOperations<JS::Rooted<JS::Value> >;
     JS::Value * extractMutable() {
         return static_cast<JS::Rooted<JS::Value>*>(this)->address();
     }
 };
 
+/*
+ * Augment the generic PersistentRooted<T> interface when T = Value with type-querying,
+ * value-extracting, and mutating operations.
+ */
+template <>
+class PersistentRootedBase<JS::Value> : public MutableValueOperations<JS::PersistentRooted<JS::Value>>
+{
+    friend class ValueOperations<JS::PersistentRooted<JS::Value>>;
+    const JS::Value * extract() const {
+        return static_cast<const JS::PersistentRooted<JS::Value>*>(this)->address();
+    }
+
+    friend class MutableValueOperations<JS::PersistentRooted<JS::Value>>;
+    JS::Value * extractMutable() {
+        return static_cast<JS::PersistentRooted<JS::Value>*>(this)->address();
+    }
+};
+
 } // namespace js
 
 inline jsval_layout
 JSVAL_TO_IMPL(JS::Value v)
 {
     return v.data;
 }