Split Persistent into Persistent and UniquePersistent
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 27 Nov 2013 09:30:49 +0000 (09:30 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 27 Nov 2013 09:30:49 +0000 (09:30 +0000)
R=svenpanne@chromium.org

BUG=

Review URL: https://codereview.chromium.org/88013002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18093 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

include/v8.h
test/cctest/test-api.cc

index a15edf2..2d02562 100644 (file)
@@ -123,8 +123,10 @@ template <class T> class Handle;
 template <class T> class Local;
 template <class T> class Eternal;
 template<class T> class NonCopyablePersistentTraits;
+template<class T> class PersistentBase;
 template<class T,
          class M = NonCopyablePersistentTraits<T> > class Persistent;
+template<class T> class UniquePersistent;
 template<class T, class P> class WeakCallbackObject;
 class FunctionTemplate;
 class ObjectTemplate;
@@ -257,17 +259,17 @@ template <class T> class Handle {
    * The handles' references are not checked.
    */
   template <class S> V8_INLINE bool operator==(const Handle<S>& that) const {
-    internal::Object** a = reinterpret_cast<internal::Object**>(**this);
-    internal::Object** b = reinterpret_cast<internal::Object**>(*that);
+    internal::Object** a = reinterpret_cast<internal::Object**>(this->val_);
+    internal::Object** b = reinterpret_cast<internal::Object**>(that.val_);
     if (a == 0) return b == 0;
     if (b == 0) return false;
     return *a == *b;
   }
 
   template <class S> V8_INLINE bool operator==(
-      const Persistent<S>& that) const {
-    internal::Object** a = reinterpret_cast<internal::Object**>(**this);
-    internal::Object** b = reinterpret_cast<internal::Object**>(*that);
+      const PersistentBase<S>& that) const {
+    internal::Object** a = reinterpret_cast<internal::Object**>(this->val_);
+    internal::Object** b = reinterpret_cast<internal::Object**>(that.val_);
     if (a == 0) return b == 0;
     if (b == 0) return false;
     return *a == *b;
@@ -304,7 +306,8 @@ template <class T> class Handle {
   V8_INLINE static Handle<T> New(Isolate* isolate, Handle<T> that) {
     return New(isolate, that.val_);
   }
-  V8_INLINE static Handle<T> New(Isolate* isolate, const Persistent<T>& that) {
+  V8_INLINE static Handle<T> New(Isolate* isolate,
+                                 const PersistentBase<T>& that) {
     return New(isolate, that.val_);
   }
 
@@ -320,6 +323,8 @@ template <class T> class Handle {
  private:
   friend class Utils;
   template<class F, class M> friend class Persistent;
+  template<class F> friend class PersistentBase;
+  template<class F> friend class Handle;
   template<class F> friend class Local;
   template<class F> friend class FunctionCallbackInfo;
   template<class F> friend class PropertyCallbackInfo;
@@ -383,9 +388,8 @@ template <class T> class Local : public Handle<T> {
    * the original handle is destroyed/disposed.
    */
   V8_INLINE static Local<T> New(Isolate* isolate, Handle<T> that);
-  template<class M>
   V8_INLINE static Local<T> New(Isolate* isolate,
-                                const Persistent<T, M>& that);
+                                const PersistentBase<T>& that);
 
 #ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
 
@@ -396,8 +400,10 @@ template <class T> class Local : public Handle<T> {
  private:
   friend class Utils;
   template<class F> friend class Eternal;
+  template<class F> friend class PersistentBase;
   template<class F, class M> friend class Persistent;
   template<class F> friend class Handle;
+  template<class F> friend class Local;
   template<class F> friend class FunctionCallbackInfo;
   template<class F> friend class PropertyCallbackInfo;
   friend class String;
@@ -462,6 +468,137 @@ class WeakReferenceCallbacks {
 
 
 /**
+ * An object reference that is independent of any handle scope.  Where
+ * a Local handle only lives as long as the HandleScope in which it was
+ * allocated, a PersistentBase handle remains valid until it is explicitly
+ * disposed.
+ *
+ * A persistent handle contains a reference to a storage cell within
+ * the v8 engine which holds an object value and which is updated by
+ * the garbage collector whenever the object is moved.  A new storage
+ * cell can be created using the constructor or PersistentBase::Reset and
+ * existing handles can be disposed using PersistentBase::Reset.
+ *
+ */
+template <class T> class PersistentBase {
+ public:
+  /**
+   * If non-empty, destroy the underlying storage cell
+   * IsEmpty() will return true after this call.
+   */
+  V8_INLINE void Reset();
+  /**
+   * If non-empty, destroy the underlying storage cell
+   * and create a new one with the contents of other if other is non empty
+   */
+  template <class S>
+  V8_INLINE void Reset(Isolate* isolate, const Handle<S>& other);
+
+  /**
+   * If non-empty, destroy the underlying storage cell
+   * and create a new one with the contents of other if other is non empty
+   */
+  template <class S>
+  V8_INLINE void Reset(Isolate* isolate, const PersistentBase<S>& other);
+
+  V8_INLINE bool IsEmpty() const { return val_ == 0; }
+
+  template <class S>
+  V8_INLINE bool operator==(const PersistentBase<S>& that) const {
+    internal::Object** a = reinterpret_cast<internal::Object**>(this->val_);
+    internal::Object** b = reinterpret_cast<internal::Object**>(that.val_);
+    if (a == 0) return b == 0;
+    if (b == 0) return false;
+    return *a == *b;
+  }
+
+  template <class S> V8_INLINE bool operator==(const Handle<S>& that) const {
+    internal::Object** a = reinterpret_cast<internal::Object**>(this->val_);
+    internal::Object** b = reinterpret_cast<internal::Object**>(that.val_);
+    if (a == 0) return b == 0;
+    if (b == 0) return false;
+    return *a == *b;
+  }
+
+  template <class S>
+  V8_INLINE bool operator!=(const PersistentBase<S>& that) const {
+    return !operator==(that);
+  }
+
+  template <class S> V8_INLINE bool operator!=(const Handle<S>& that) const {
+    return !operator==(that);
+  }
+
+  template<typename P>
+  V8_INLINE void SetWeak(
+      P* parameter,
+      typename WeakCallbackData<T, P>::Callback callback);
+
+  template<typename S, typename P>
+  V8_INLINE void SetWeak(
+      P* parameter,
+      typename WeakCallbackData<S, P>::Callback callback);
+
+  V8_INLINE void ClearWeak();
+
+  /**
+   * Marks the reference to this object independent. Garbage collector is free
+   * to ignore any object groups containing this object. Weak callback for an
+   * independent handle should not assume that it will be preceded by a global
+   * GC prologue callback or followed by a global GC epilogue callback.
+   */
+  V8_INLINE void MarkIndependent();
+
+  /**
+   * Marks the reference to this object partially dependent. Partially dependent
+   * handles only depend on other partially dependent handles and these
+   * dependencies are provided through object groups. It provides a way to build
+   * smaller object groups for young objects that represent only a subset of all
+   * external dependencies. This mark is automatically cleared after each
+   * garbage collection.
+   */
+  V8_INLINE void MarkPartiallyDependent();
+
+  V8_INLINE bool IsIndependent() const;
+
+  /** Checks if the handle holds the only reference to an object. */
+  V8_INLINE bool IsNearDeath() const;
+
+  /** Returns true if the handle's reference is weak.  */
+  V8_INLINE bool IsWeak() const;
+
+  /**
+   * Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface
+   * description in v8-profiler.h for details.
+   */
+  V8_INLINE void SetWrapperClassId(uint16_t class_id);
+
+  /**
+   * Returns the class ID previously assigned to this handle or 0 if no class ID
+   * was previously assigned.
+   */
+  V8_INLINE uint16_t WrapperClassId() const;
+
+ private:
+  friend class Isolate;
+  friend class Utils;
+  template<class F> friend class Handle;
+  template<class F> friend class Local;
+  template<class F1, class F2> friend class Persistent;
+  template<class F> friend class UniquePersistent;
+  template<class F> friend class PersistentBase;
+  template<class F> friend class ReturnValue;
+
+  explicit V8_INLINE PersistentBase(T* val) : val_(val) {}
+  PersistentBase(PersistentBase& other); // NOLINT
+  void operator=(PersistentBase&);
+  V8_INLINE static T* New(Isolate* isolate, T* that);
+
+  T* val_;
+};
+
+
+/**
  * Default traits for Persistent. This class does not allow
  * use of the copy constructor or assignment operator.
  * At present kResetInDestructor is not set, but that will change in a future
@@ -501,33 +638,26 @@ struct CopyablePersistentTraits {
 
 
 /**
- * An object reference that is independent of any handle scope.  Where
- * a Local handle only lives as long as the HandleScope in which it was
- * allocated, a Persistent handle remains valid until it is explicitly
- * disposed.
- *
- * A persistent handle contains a reference to a storage cell within
- * the v8 engine which holds an object value and which is updated by
- * the garbage collector whenever the object is moved.  A new storage
- * cell can be created using the constructor or Persistent::Reset and
- * existing handles can be disposed using Persistent::Reset.
+ * A PersistentBase which allows copy and assignment.
  *
  * Copy, assignment and destructor bevavior is controlled by the traits
  * class M.
+ *
+ * Note: Persistent class hierarchy is subject to future changes.
  */
-template <class T, class M> class Persistent {
+template <class T, class M> class Persistent : public PersistentBase<T> {
  public:
   /**
    * A Persistent with no storage cell.
    */
-  V8_INLINE Persistent() : val_(0) { }
+  V8_INLINE Persistent() : PersistentBase<T>(0) { }
   /**
    * Construct a Persistent from a Handle.
    * When the Handle is non-empty, a new storage cell is created
    * pointing to the same object, and no flags are set.
    */
   template <class S> V8_INLINE Persistent(Isolate* isolate, Handle<S> that)
-      : val_(New(isolate, *that)) {
+      : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
     TYPE_CHECK(T, S);
   }
   /**
@@ -537,7 +667,7 @@ template <class T, class M> class Persistent {
    */
   template <class S, class M2>
   V8_INLINE Persistent(Isolate* isolate, const Persistent<S, M2>& that)
-    : val_(New(isolate, *that)) {
+    : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
     TYPE_CHECK(T, S);
   }
   /**
@@ -546,11 +676,11 @@ template <class T, class M> class Persistent {
    * traits class is called, allowing the setting of flags based on the
    * copied Persistent.
    */
-  V8_INLINE Persistent(const Persistent& that) : val_(0) {
+  V8_INLINE Persistent(const Persistent& that) : PersistentBase<T>(0) {
     Copy(that);
   }
   template <class S, class M2>
-  V8_INLINE Persistent(const Persistent<S, M2>& that) : val_(0) {
+  V8_INLINE Persistent(const Persistent<S, M2>& that) : PersistentBase<T>(0) {
     Copy(that);
   }
   V8_INLINE Persistent& operator=(const Persistent& that) { // NOLINT
@@ -568,31 +698,11 @@ template <class T, class M> class Persistent {
    * can result in a memory leak, it is recommended to always set this flag.
    */
   V8_INLINE ~Persistent() {
-    if (M::kResetInDestructor) Reset();
+    if (M::kResetInDestructor) this->Reset();
   }
 
-  /**
-   * If non-empty, destroy the underlying storage cell
-   * IsEmpty() will return true after this call.
-   */
-  V8_INLINE void Reset();
-  /**
-   * If non-empty, destroy the underlying storage cell
-   * and create a new one with the contents of other if other is non empty
-   */
-  template <class S>
-  V8_INLINE void Reset(Isolate* isolate, const Handle<S>& other);
-  /**
-   * If non-empty, destroy the underlying storage cell
-   * and create a new one with the contents of other if other is non empty
-   */
-  template <class S, class M2>
-  V8_INLINE void Reset(Isolate* isolate, const Persistent<S, M2>& other);
-
   V8_DEPRECATED("Use Reset instead",
-                V8_INLINE void Dispose()) { Reset(); }
-
-  V8_INLINE bool IsEmpty() const { return val_ == 0; }
+                V8_INLINE void Dispose()) { this->Reset(); }
 
   // TODO(dcarney): this is pretty useless, fix or remove
   template <class S>
@@ -610,42 +720,6 @@ template <class T, class M> class Persistent {
     return Persistent<S>::Cast(*this);
   }
 
-  template <class S, class M2>
-  V8_INLINE bool operator==(const Persistent<S, M2>& that) const {
-    internal::Object** a = reinterpret_cast<internal::Object**>(**this);
-    internal::Object** b = reinterpret_cast<internal::Object**>(*that);
-    if (a == 0) return b == 0;
-    if (b == 0) return false;
-    return *a == *b;
-  }
-
-  template <class S> V8_INLINE bool operator==(const Handle<S>& that) const {
-    internal::Object** a = reinterpret_cast<internal::Object**>(**this);
-    internal::Object** b = reinterpret_cast<internal::Object**>(*that);
-    if (a == 0) return b == 0;
-    if (b == 0) return false;
-    return *a == *b;
-  }
-
-  template <class S, class M2>
-  V8_INLINE bool operator!=(const Persistent<S, M2>& that) const {
-    return !operator==(that);
-  }
-
-  template <class S> V8_INLINE bool operator!=(const Handle<S>& that) const {
-    return !operator==(that);
-  }
-
-  template<typename P>
-  V8_INLINE void SetWeak(
-      P* parameter,
-      typename WeakCallbackData<T, P>::Callback callback);
-
-  template<typename S, typename P>
-  V8_INLINE void SetWeak(
-      P* parameter,
-      typename WeakCallbackData<S, P>::Callback callback);
-
   template<typename S, typename P>
   V8_DEPRECATED(
       "Use SetWeak instead",
@@ -660,60 +734,20 @@ template <class T, class M> class Persistent {
           P* parameter,
           typename WeakReferenceCallbacks<T, P>::Revivable callback));
 
-  V8_INLINE void ClearWeak();
-
-  /**
-   * Marks the reference to this object independent. Garbage collector is free
-   * to ignore any object groups containing this object. Weak callback for an
-   * independent handle should not assume that it will be preceded by a global
-   * GC prologue callback or followed by a global GC epilogue callback.
-   */
-  V8_INLINE void MarkIndependent();
-
-  /**
-   * Marks the reference to this object partially dependent. Partially dependent
-   * handles only depend on other partially dependent handles and these
-   * dependencies are provided through object groups. It provides a way to build
-   * smaller object groups for young objects that represent only a subset of all
-   * external dependencies. This mark is automatically cleared after each
-   * garbage collection.
-   */
-  V8_INLINE void MarkPartiallyDependent();
-
-  V8_INLINE bool IsIndependent() const;
-
-  /** Checks if the handle holds the only reference to an object. */
-  V8_INLINE bool IsNearDeath() const;
-
-  /** Returns true if the handle's reference is weak.  */
-  V8_INLINE bool IsWeak() const;
-
-  /**
-   * Assigns a wrapper class ID to the handle. See RetainedObjectInfo interface
-   * description in v8-profiler.h for details.
-   */
-  V8_INLINE void SetWrapperClassId(uint16_t class_id);
-
-  /**
-   * Returns the class ID previously assigned to this handle or 0 if no class ID
-   * was previously assigned.
-   */
-  V8_INLINE uint16_t WrapperClassId() const;
-
   V8_DEPRECATED("This will be removed",
                 V8_INLINE T* ClearAndLeak());
 
   V8_DEPRECATED("This will be removed",
-                V8_INLINE void Clear()) { val_ = 0; }
+                V8_INLINE void Clear()) { this->val_ = 0; }
 
   // TODO(dcarney): remove
 #ifndef V8_ALLOW_ACCESS_TO_RAW_HANDLE_CONSTRUCTOR
 
  private:
 #endif
-  template <class S> V8_INLINE Persistent(S* that) : val_(that) { }
+  template <class S> V8_INLINE Persistent(S* that) : PersistentBase<T>(that) { }
 
-  V8_INLINE T* operator*() const { return val_; }
+  V8_INLINE T* operator*() const { return this->val_; }
 
  private:
   friend class Isolate;
@@ -723,13 +757,81 @@ template <class T, class M> class Persistent {
   template<class F1, class F2> friend class Persistent;
   template<class F> friend class ReturnValue;
 
-  V8_INLINE static T* New(Isolate* isolate, T* that);
   template<class S, class M2>
   V8_INLINE void Copy(const Persistent<S, M2>& that);
+};
 
-  T* val_;
+
+/**
+ * A PersistentBase which has move semantics.
+ *
+ * Note: Persistent class hierarchy is subject to future changes.
+ */
+template<class T>
+class UniquePersistent : public PersistentBase<T> {
+  struct RValue {
+    V8_INLINE explicit RValue(UniquePersistent* object) : object(object) {}
+    UniquePersistent* object;
+  };
+
+ public:
+    /**
+   * A UniquePersistent with no storage cell.
+   */
+  V8_INLINE UniquePersistent() : PersistentBase<T>(0) { }
+  /**
+   * Construct a UniquePersistent from a Handle.
+   * When the Handle is non-empty, a new storage cell is created
+   * pointing to the same object, and no flags are set.
+   */
+  template <class S>
+  V8_INLINE UniquePersistent(Isolate* isolate, Handle<S> that)
+      : PersistentBase<T>(PersistentBase<T>::New(isolate, *that)) {
+    TYPE_CHECK(T, S);
+  }
+  /**
+   * Construct a UniquePersistent from a PersistentBase.
+   * When the Persistent is non-empty, a new storage cell is created
+   * pointing to the same object, and no flags are set.
+   */
+  template <class S>
+  V8_INLINE UniquePersistent(Isolate* isolate, const PersistentBase<S>& that)
+    : PersistentBase<T>(PersistentBase<T>::New(isolate, that.val_)) {
+    TYPE_CHECK(T, S);
+  }
+  /**
+   * Move constructor.
+   */
+  V8_INLINE UniquePersistent(RValue rvalue)
+    : PersistentBase<T>(rvalue.object->val_) {
+    rvalue.object->val_ = 0;
+  }
+  V8_INLINE ~UniquePersistent() { this->Reset(); }
+  /**
+   * Move via assignment.
+   */
+  template<class S>
+  V8_INLINE UniquePersistent& operator=(UniquePersistent<S> rhs) {
+    TYPE_CHECK(T, S);
+    this->val_ = rhs.val_;
+    rhs.val_ = 0;
+    return *this;
+  }
+  /**
+   * Cast operator for moves.
+   */
+  V8_INLINE operator RValue() { return RValue(this); }
+  /**
+   * Pass allows returning uniques from functions, etc.
+   */
+  V8_INLINE UniquePersistent Pass() { return UniquePersistent(RValue(this)); }
+
+ private:
+  UniquePersistent(UniquePersistent&);
+  void operator=(UniquePersistent&);
 };
 
+
  /**
  * A stack-allocated class that governs a number of local handles.
  * After a handle scope has been created, all local handles will be
@@ -4886,6 +4988,7 @@ class V8_EXPORT V8 {
   template <class T> friend class Handle;
   template <class T> friend class Local;
   template <class T> friend class Eternal;
+  template <class T> friend class PersistentBase;
   template <class T, class M> friend class Persistent;
   friend class Context;
 };
@@ -5678,8 +5781,7 @@ Local<T> Local<T>::New(Isolate* isolate, Handle<T> that) {
 }
 
 template <class T>
-template <class M>
-Local<T> Local<T>::New(Isolate* isolate, const Persistent<T, M>& that) {
+Local<T> Local<T>::New(Isolate* isolate, const PersistentBase<T>& that) {
   return New(isolate, that.val_);
 }
 
@@ -5717,8 +5819,8 @@ Local<T> Eternal<T>::Get(Isolate* isolate) {
 }
 
 
-template <class T, class M>
-T* Persistent<T, M>::New(Isolate* isolate, T* that) {
+template <class T>
+T* PersistentBase<T>::New(Isolate* isolate, T* that) {
   if (that == NULL) return NULL;
   internal::Object** p = reinterpret_cast<internal::Object**>(that);
   return reinterpret_cast<T*>(
@@ -5731,7 +5833,7 @@ template <class T, class M>
 template <class S, class M2>
 void Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
   TYPE_CHECK(T, S);
-  Reset();
+  this->Reset();
   if (that.IsEmpty()) return;
   internal::Object** p = reinterpret_cast<internal::Object**>(that.val_);
   this->val_ = reinterpret_cast<T*>(V8::CopyPersistent(p));
@@ -5739,8 +5841,8 @@ void Persistent<T, M>::Copy(const Persistent<S, M2>& that) {
 }
 
 
-template <class T, class M>
-bool Persistent<T, M>::IsIndependent() const {
+template <class T>
+bool PersistentBase<T>::IsIndependent() const {
   typedef internal::Internals I;
   if (this->IsEmpty()) return false;
   return I::GetNodeFlag(reinterpret_cast<internal::Object**>(this->val_),
@@ -5748,8 +5850,8 @@ bool Persistent<T, M>::IsIndependent() const {
 }
 
 
-template <class T, class M>
-bool Persistent<T, M>::IsNearDeath() const {
+template <class T>
+bool PersistentBase<T>::IsNearDeath() const {
   typedef internal::Internals I;
   if (this->IsEmpty()) return false;
   uint8_t node_state =
@@ -5759,8 +5861,8 @@ bool Persistent<T, M>::IsNearDeath() const {
 }
 
 
-template <class T, class M>
-bool Persistent<T, M>::IsWeak() const {
+template <class T>
+bool PersistentBase<T>::IsWeak() const {
   typedef internal::Internals I;
   if (this->IsEmpty()) return false;
   return I::GetNodeState(reinterpret_cast<internal::Object**>(this->val_)) ==
@@ -5768,17 +5870,17 @@ bool Persistent<T, M>::IsWeak() const {
 }
 
 
-template <class T, class M>
-void Persistent<T, M>::Reset() {
+template <class T>
+void PersistentBase<T>::Reset() {
   if (this->IsEmpty()) return;
   V8::DisposeGlobal(reinterpret_cast<internal::Object**>(this->val_));
   val_ = 0;
 }
 
 
-template <class T, class M>
+template <class T>
 template <class S>
-void Persistent<T, M>::Reset(Isolate* isolate, const Handle<S>& other) {
+void PersistentBase<T>::Reset(Isolate* isolate, const Handle<S>& other) {
   TYPE_CHECK(T, S);
   Reset();
   if (other.IsEmpty()) return;
@@ -5786,10 +5888,10 @@ void Persistent<T, M>::Reset(Isolate* isolate, const Handle<S>& other) {
 }
 
 
-template <class T,  class M>
-template <class S, class M2>
-void Persistent<T, M>::Reset(Isolate* isolate,
-                             const Persistent<S, M2>& other) {
+template <class T>
+template <class S>
+void PersistentBase<T>::Reset(Isolate* isolate,
+                              const PersistentBase<S>& other) {
   TYPE_CHECK(T, S);
   Reset();
   if (other.IsEmpty()) return;
@@ -5797,9 +5899,9 @@ void Persistent<T, M>::Reset(Isolate* isolate,
 }
 
 
-template <class T, class M>
+template <class T>
 template <typename S, typename P>
-void Persistent<T, M>::SetWeak(
+void PersistentBase<T>::SetWeak(
     P* parameter,
     typename WeakCallbackData<S, P>::Callback callback) {
   TYPE_CHECK(S, T);
@@ -5811,9 +5913,9 @@ void Persistent<T, M>::SetWeak(
 }
 
 
-template <class T, class M>
+template <class T>
 template <typename P>
-void Persistent<T, M>::SetWeak(
+void PersistentBase<T>::SetWeak(
     P* parameter,
     typename WeakCallbackData<T, P>::Callback callback) {
   SetWeak<T, P>(parameter, callback);
@@ -5843,14 +5945,14 @@ void Persistent<T, M>::MakeWeak(
 }
 
 
-template <class T, class M>
-void Persistent<T, M>::ClearWeak() {
+template <class T>
+void PersistentBase<T>::ClearWeak() {
   V8::ClearWeak(reinterpret_cast<internal::Object**>(this->val_));
 }
 
 
-template <class T, class M>
-void Persistent<T, M>::MarkIndependent() {
+template <class T>
+void PersistentBase<T>::MarkIndependent() {
   typedef internal::Internals I;
   if (this->IsEmpty()) return;
   I::UpdateNodeFlag(reinterpret_cast<internal::Object**>(this->val_),
@@ -5859,8 +5961,8 @@ void Persistent<T, M>::MarkIndependent() {
 }
 
 
-template <class T, class M>
-void Persistent<T, M>::MarkPartiallyDependent() {
+template <class T>
+void PersistentBase<T>::MarkPartiallyDependent() {
   typedef internal::Internals I;
   if (this->IsEmpty()) return;
   I::UpdateNodeFlag(reinterpret_cast<internal::Object**>(this->val_),
@@ -5872,14 +5974,14 @@ void Persistent<T, M>::MarkPartiallyDependent() {
 template <class T, class M>
 T* Persistent<T, M>::ClearAndLeak() {
   T* old;
-  old = val_;
-  val_ = NULL;
+  old = this->val_;
+  this->val_ = NULL;
   return old;
 }
 
 
-template <class T, class M>
-void Persistent<T, M>::SetWrapperClassId(uint16_t class_id) {
+template <class T>
+void PersistentBase<T>::SetWrapperClassId(uint16_t class_id) {
   typedef internal::Internals I;
   if (this->IsEmpty()) return;
   internal::Object** obj = reinterpret_cast<internal::Object**>(this->val_);
@@ -5888,8 +5990,8 @@ void Persistent<T, M>::SetWrapperClassId(uint16_t class_id) {
 }
 
 
-template <class T, class M>
-uint16_t Persistent<T, M>::WrapperClassId() const {
+template <class T>
+uint16_t PersistentBase<T>::WrapperClassId() const {
   typedef internal::Internals I;
   if (this->IsEmpty()) return 0;
   internal::Object** obj = reinterpret_cast<internal::Object**>(this->val_);
index 23756db..94b397f 100644 (file)
@@ -3299,6 +3299,73 @@ THREADED_TEST(ResettingGlobalHandleToEmpty) {
 }
 
 
+template<class T>
+static v8::UniquePersistent<T> PassUnique(v8::UniquePersistent<T> unique) {
+  return unique.Pass();
+}
+
+
+template<class T>
+static v8::UniquePersistent<T> ReturnUnique(v8::Isolate* isolate,
+                                            const v8::Persistent<T> & global) {
+  v8::UniquePersistent<String> unique(isolate, global);
+  return unique.Pass();
+}
+
+
+THREADED_TEST(UniquePersistent) {
+  v8::Isolate* isolate = CcTest::isolate();
+  v8::Persistent<String> global;
+  {
+    v8::HandleScope scope(isolate);
+    global.Reset(isolate, v8_str("str"));
+  }
+  v8::internal::GlobalHandles* global_handles =
+      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
+  int initial_handle_count = global_handles->global_handles_count();
+  {
+    v8::UniquePersistent<String> unique(isolate, global);
+    CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
+    // Test assignment via Pass
+    {
+      v8::UniquePersistent<String> copy = unique.Pass();
+      CHECK(unique.IsEmpty());
+      CHECK(copy == global);
+      CHECK_EQ(initial_handle_count + 1,
+               global_handles->global_handles_count());
+      unique = copy.Pass();
+    }
+    // Test ctor via Pass
+    {
+      v8::UniquePersistent<String> copy(unique.Pass());
+      CHECK(unique.IsEmpty());
+      CHECK(copy == global);
+      CHECK_EQ(initial_handle_count + 1,
+               global_handles->global_handles_count());
+      unique = copy.Pass();
+    }
+    // Test pass through function call
+    {
+      v8::UniquePersistent<String> copy = PassUnique(unique.Pass());
+      CHECK(unique.IsEmpty());
+      CHECK(copy == global);
+      CHECK_EQ(initial_handle_count + 1,
+               global_handles->global_handles_count());
+      unique = copy.Pass();
+    }
+    CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
+  }
+  // Test pass from function call
+  {
+    v8::UniquePersistent<String> unique = ReturnUnique(isolate, global);
+    CHECK(unique == global);
+    CHECK_EQ(initial_handle_count + 1, global_handles->global_handles_count());
+  }
+  CHECK_EQ(initial_handle_count, global_handles->global_handles_count());
+  global.Reset();
+}
+
+
 THREADED_TEST(GlobalHandleUpcast) {
   v8::Isolate* isolate = CcTest::isolate();
   v8::HandleScope scope(isolate);