Implement PersistentValueVector, analogous to PersistentValueMap.

BUG=
R=dcarney@chromium.org

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

Patch from Daniel Vogelheim <vogelheim@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20341 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
dcarney@chromium.org 2014-03-31 10:03:20 +00:00
parent a2f82479c4
commit 8b304a6832
3 changed files with 164 additions and 0 deletions

View File

@ -30,6 +30,7 @@
#include "v8.h"
#include <map>
#include <vector>
/**
* Support for Persistent containers.
@ -386,6 +387,123 @@ class StdPersistentValueMap : public PersistentValueMap<K, V, Traits> {
: 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_

View File

@ -129,6 +129,7 @@ template<class T,
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 @@ template <class T> class Local : public Handle<T> {
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 T> class PersistentBase {
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) {}

View File

@ -3592,6 +3592,49 @@ TEST(PersistentValueMap) {
}
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::Isolate* isolate = CcTest::isolate();
v8::HandleScope scope(isolate);