Revision: 20341
Author:   [email protected]
Date:     Mon Mar 31 10:03:20 2014 UTC
Log:      Implement PersistentValueVector, analogous to PersistentValueMap.

BUG=
[email protected]

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

Patch from Daniel Vogelheim <[email protected]>.
http://code.google.com/p/v8/source/detail?r=20341

Modified:
 /branches/bleeding_edge/include/v8-util.h
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/test/cctest/test-api.cc

=======================================
--- /branches/bleeding_edge/include/v8-util.h   Fri Mar 28 09:35:50 2014 UTC
+++ /branches/bleeding_edge/include/v8-util.h   Mon Mar 31 10:03:20 2014 UTC
@@ -30,6 +30,7 @@

 #include "v8.h"
 #include <map>
+#include <vector>

 /**
  * Support for Persistent containers.
@@ -386,6 +387,123 @@
       : PersistentValueMap<K, V, Traits>(isolate) {}
 };

+
+class DefaultPersistentValueVectorTraits {
+ public:
+  typedef std::vector<PersistentContainerValue> Impl;
+
+  static void Append(Impl* impl, PersistentContainerValue value) {
+    impl->push_back(value);
+  }
+  static bool IsEmpty(const Impl* impl) {
+    return impl->empty();
+  }
+  static size_t Size(const Impl* impl) {
+    return impl->size();
+  }
+  static PersistentContainerValue Get(const Impl* impl, size_t i) {
+    return (i < impl->size()) ? impl->at(i) : kPersistentContainerNotFound;
+  }
+  static void ReserveCapacity(Impl* impl, size_t capacity) {
+    impl->reserve(capacity);
+  }
+  static void Clear(Impl* impl) {
+    impl->clear();
+  }
+};
+
+
+/**
+ * A vector wrapper that safely stores UniquePersistent values.
+ * C++11 embedders don't need this class, as they can use UniquePersistent
+ * directly in std containers.
+ *
+ * This class relies on a backing vector implementation, whose type and methods + * are described by the Traits class. The backing map will handle values of type
+ * PersistentContainerValue, with all conversion into and out of V8
+ * handles being transparently handled by this class.
+ */
+template<typename V, typename Traits = DefaultPersistentValueVectorTraits>
+class PersistentValueVector {
+ public:
+  explicit PersistentValueVector(Isolate* isolate) : isolate_(isolate) { }
+
+  ~PersistentValueVector() {
+    Clear();
+  }
+
+  /**
+   * Append a value to the vector.
+   */
+  void Append(Local<V> value) {
+    UniquePersistent<V> persistent(isolate_, value);
+    Traits::Append(&impl_, ClearAndLeak(&persistent));
+  }
+
+  /**
+   * Append a persistent's value to the vector.
+   */
+  void Append(UniquePersistent<V> persistent) {
+    Traits::Append(&impl_, ClearAndLeak(&persistent));
+  };
+
+  /**
+   * Are there any values in the vector?
+   */
+  bool IsEmpty() const {
+    return Traits::IsEmpty(&impl_);
+  }
+
+  /**
+   * How many elements are in the vector?
+   */
+  size_t Size() const {
+    return Traits::Size(&impl_);
+  }
+
+  /**
+   * Retrieve the i-th value in the vector.
+   */
+  Local<V> Get(size_t index) const {
+    return Local<V>::New(isolate_, FromVal(Traits::Get(&impl_, index)));
+  }
+
+  /**
+   * Remove all elements from the vector.
+   */
+  void Clear() {
+    size_t length = Traits::Size(&impl_);
+    for (size_t i = 0; i < length; i++) {
+      UniquePersistent<V> p;
+      p.val_ = FromVal(Traits::Get(&impl_, i));
+    }
+    Traits::Clear(&impl_);
+  }
+
+  /**
+   * Reserve capacity in the vector.
+   * (Efficiency gains depend on the backing implementation.)
+   */
+  void ReserveCapacity(size_t capacity) {
+    Traits::ReserveCapacity(&impl_, capacity);
+  }
+
+ private:
+  static PersistentContainerValue ClearAndLeak(
+      UniquePersistent<V>* persistent) {
+    V* v = persistent->val_;
+    persistent->val_ = 0;
+    return reinterpret_cast<PersistentContainerValue>(v);
+  }
+
+  static V* FromVal(PersistentContainerValue v) {
+    return reinterpret_cast<V*>(v);
+  }
+
+  Isolate* isolate_;
+  typename Traits::Impl impl_;
+};
+
 }  // namespace v8

 #endif  // V8_UTIL_H_
=======================================
--- /branches/bleeding_edge/include/v8.h        Wed Mar 26 12:50:13 2014 UTC
+++ /branches/bleeding_edge/include/v8.h        Mon Mar 31 10:03:20 2014 UTC
@@ -129,6 +129,7 @@
          class M = NonCopyablePersistentTraits<T> > class Persistent;
 template<class T> class UniquePersistent;
 template<class K, class V, class T> class PersistentValueMap;
+template<class V, class T> class PersistentValueVector;
 template<class T, class P> class WeakCallbackObject;
 class FunctionTemplate;
 class ObjectTemplate;
@@ -417,6 +418,7 @@
   friend class HandleScope;
   friend class EscapableHandleScope;
   template<class F1, class F2, class F3> friend class PersistentValueMap;
+  template<class F1, class F2> friend class PersistentValueVector;

   V8_INLINE static Local<T> New(Isolate* isolate, T* that);
 };
@@ -586,6 +588,7 @@
   template<class F> friend class PersistentBase;
   template<class F> friend class ReturnValue;
   template<class F1, class F2, class F3> friend class PersistentValueMap;
+  template<class F1, class F2> friend class PersistentValueVector;
   friend class Object;

   explicit V8_INLINE PersistentBase(T* val) : val_(val) {}
=======================================
--- /branches/bleeding_edge/test/cctest/test-api.cc Fri Mar 28 15:25:24 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-api.cc Mon Mar 31 10:03:20 2014 UTC
@@ -3590,6 +3590,49 @@
       WeakStdMapTraits<int, v8::Object> > WeakPersistentValueMap;
   TestPersistentValueMap<WeakPersistentValueMap>();
 }
+
+
+TEST(PersistentValueVector) {
+  LocalContext env;
+  v8::Isolate* isolate = env->GetIsolate();
+  v8::internal::GlobalHandles* global_handles =
+      reinterpret_cast<v8::internal::Isolate*>(isolate)->global_handles();
+  int handle_count = global_handles->global_handles_count();
+  HandleScope scope(isolate);
+
+  v8::PersistentValueVector<v8::Object> vector(isolate);
+
+  Local<v8::Object> obj1 = v8::Object::New(isolate);
+  Local<v8::Object> obj2 = v8::Object::New(isolate);
+  v8::UniquePersistent<v8::Object> obj3(isolate, v8::Object::New(isolate));
+
+  CHECK(vector.IsEmpty());
+  CHECK_EQ(0, static_cast<int>(vector.Size()));
+
+  vector.ReserveCapacity(3);
+  CHECK(vector.IsEmpty());
+
+  vector.Append(obj1);
+  vector.Append(obj2);
+  vector.Append(obj1);
+  vector.Append(obj3.Pass());
+  vector.Append(obj1);
+
+  CHECK(!vector.IsEmpty());
+  CHECK_EQ(5, static_cast<int>(vector.Size()));
+  CHECK(obj3.IsEmpty());
+  CHECK_EQ(obj1, vector.Get(0));
+  CHECK_EQ(obj1, vector.Get(2));
+  CHECK_EQ(obj1, vector.Get(4));
+  CHECK_EQ(obj2, vector.Get(1));
+
+  CHECK_EQ(5 + handle_count, global_handles->global_handles_count());
+
+  vector.Clear();
+  CHECK(vector.IsEmpty());
+  CHECK_EQ(0, static_cast<int>(vector.Size()));
+  CHECK_EQ(handle_count, global_handles->global_handles_count());
+}


 THREADED_TEST(GlobalHandleUpcast) {

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to