Bug 766347 - Adjust Handle<T> constructors to only accept Rooted<S> or Handle<S> where S is convertible to T. r=luke
authorJeff Walden <jwalden@mit.edu>
Tue, 19 Jun 2012 15:01:58 -0700
changeset 106405 24e8950269e3bc088a0c7aee017b0d0561e3d874
parent 106404 ef7120aa56754ce5a0ed0557c27900db6154b199
child 106406 89cb0e3b4693923bacd4e2643dc4195835435703
push id23447
push userdanderson@mozilla.com
push dateTue, 11 Sep 2012 17:34:27 +0000
treeherdermozilla-central@fdfaef738a00 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs766347
milestone16.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 766347 - Adjust Handle<T> constructors to only accept Rooted<S> or Handle<S> where S is convertible to T. r=luke
content/base/src/nsINode.cpp
js/src/gc/Root.h
--- a/js/src/gc/Root.h
+++ b/js/src/gc/Root.h
@@ -3,20 +3,25 @@
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef jsgc_root_h__
 #define jsgc_root_h__
 
+#ifdef __cplusplus
+
+#include "mozilla/TypeTraits.h"
+
 #include "jspubtd.h"
 
 #include "js/Utility.h"
 
+
 #ifdef __cplusplus
 
 namespace js {
 namespace gc {
 struct Cell;
 } /* namespace gc */
 } /* namespace js */
 
@@ -74,19 +79,21 @@ struct RootMethods { };
  * Reference to a T that has been rooted elsewhere. This is most useful
  * as a parameter type, which guarantees that the T lvalue is properly
  * rooted. See "Move GC Stack Rooting" above.
  */
 template <typename T>
 class Handle
 {
   public:
-    /* Copy handles of different types, with implicit coercion. */
-    template <typename S> Handle(Handle<S> handle) {
-        testAssign<S>();
+    /* Creates a handle from a handle of a type convertible to T. */
+    template <typename S>
+    Handle(Handle<S> handle,
+           typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
+    {
         ptr = reinterpret_cast<const T *>(handle.address());
     }
 
     /*
      * This may be called only if the location of the T is guaranteed
      * to be marked (for some reason other than being a Rooted),
      * e.g., if it is guaranteed to be reachable from an implicit root.
      *
@@ -97,38 +104,31 @@ class Handle
         h.ptr = p;
         return h;
     }
 
     /*
      * Construct a handle from an explicitly rooted location. This is the
      * normal way to create a handle, and normally happens implicitly.
      */
-    template <typename S> inline Handle(Rooted<S> &root);
+    template <typename S>
+    inline
+    Handle(Rooted<S> &root,
+           typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0);
 
     const T *address() const { return ptr; }
     T value() const { return *ptr; }
 
     operator T () const { return value(); }
     T operator ->() const { return value(); }
 
   private:
     Handle() {}
 
     const T *ptr;
-
-    template <typename S>
-    void testAssign() {
-#ifdef DEBUG
-        T a = RootMethods<T>::initial();
-        S b = RootMethods<S>::initial();
-        a = b;
-        (void)a;
-#endif
-    }
 };
 
 typedef Handle<JSObject*>    HandleObject;
 typedef Handle<JSFunction*>  HandleFunction;
 typedef Handle<JSScript*>    HandleScript;
 typedef Handle<JSString*>    HandleString;
 typedef Handle<jsid>         HandleId;
 typedef Handle<Value>        HandleValue;
@@ -209,19 +209,19 @@ class Rooted
     T ptr;
 
     Rooted() MOZ_DELETE;
     Rooted(const Rooted &) MOZ_DELETE;
 };
 
 template<typename T> template <typename S>
 inline
-Handle<T>::Handle(Rooted<S> &root)
+Handle<T>::Handle(Rooted<S> &root,
+                  typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy)
 {
-    testAssign<S>();
     ptr = reinterpret_cast<const T *>(root.address());
 }
 
 typedef Rooted<JSObject*>    RootedObject;
 typedef Rooted<JSFunction*>  RootedFunction;
 typedef Rooted<JSScript*>    RootedScript;
 typedef Rooted<JSString*>    RootedString;
 typedef Rooted<jsid>         RootedId;