};
+template <typename K, typename V>
+class DefaultPhantomPersistentValueMapTraits : public StdMapTraits<K, V> {
+ private:
+ template <typename T>
+ struct RemovePointer;
+
+ public:
+ // Weak callback & friends:
+ static const PersistentContainerCallbackType kCallbackType = kNotWeak;
+ typedef PersistentValueMap<
+ K, V, DefaultPhantomPersistentValueMapTraits<K, V> > MapType;
+ typedef void PhantomCallbackDataType;
+
+ static PhantomCallbackDataType* PhantomCallbackParameter(MapType* map,
+ const K& key,
+ Local<V> value) {
+ return NULL;
+ }
+ static MapType* MapFromPhantomCallbackData(
+ const PhantomCallbackData<PhantomCallbackDataType>& data) {
+ return NULL;
+ }
+ static K KeyFromPhantomCallbackData(
+ const PhantomCallbackData<PhantomCallbackDataType>& data) {
+ return K();
+ }
+ static void DisposeCallbackData(PhantomCallbackDataType* data) {}
+ static void Dispose(Isolate* isolate, UniquePersistent<V> value, K key) {}
+
+ private:
+ template <typename T>
+ struct RemovePointer<T*> {
+ typedef T Type;
+ };
+};
+
+
/**
* A map wrapper that allows using UniquePersistent as a mapped value.
* C++11 embedders don't need this class, as they can use UniquePersistent
* PersistentContainerValue, with all conversion into and out of V8
* handles being transparently handled by this class.
*/
-template<typename K, typename V, typename Traits>
-class PersistentValueMap {
+template <typename K, typename V, typename Traits>
+class PersistentValueMapBase {
public:
- explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {}
-
- ~PersistentValueMap() { Clear(); }
-
Isolate* GetIsolate() { return isolate_; }
/**
}
/**
- * Put value into map. Depending on Traits::kIsWeak, the value will be held
- * by the map strongly or weakly.
- * Returns old value as UniquePersistent.
- */
- UniquePersistent<V> Set(const K& key, Local<V> value) {
- UniquePersistent<V> persistent(isolate_, value);
- return SetUnique(key, &persistent);
- }
-
- /**
- * Put value into map, like Set(const K&, Local<V>).
- */
- UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
- return SetUnique(key, &value);
- }
-
- /**
* Return value for key and remove it from the map.
*/
UniquePersistent<V> Remove(const K& key) {
}
private:
- friend class PersistentValueMap;
+ friend class PersistentValueMapBase;
+ friend class PersistentValueMap<K, V, Traits>;
+ friend class PhantomPersistentValueMap<K, V, Traits>;
explicit PersistentValueReference(PersistentContainerValue value)
: value_(value) { }
return PersistentValueReference(Traits::Get(&impl_, key));
}
+ protected:
+ explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
+
+ ~PersistentValueMapBase() { Clear(); }
+
+ Isolate* isolate() { return isolate_; }
+ typename Traits::Impl* impl() { return &impl_; }
+
+ static V* FromVal(PersistentContainerValue v) {
+ return reinterpret_cast<V*>(v);
+ }
+
+ static PersistentContainerValue ClearAndLeak(
+ UniquePersistent<V>* persistent) {
+ V* v = persistent->val_;
+ persistent->val_ = 0;
+ return reinterpret_cast<PersistentContainerValue>(v);
+ }
+
+ static PersistentContainerValue Leak(UniquePersistent<V>* persistent) {
+ return reinterpret_cast<PersistentContainerValue>(persistent->val_);
+ }
+
/**
- * Put a value into the map and update the reference.
- * Restrictions of GetReference apply here as well.
+ * Return a container value as UniquePersistent and make sure the weak
+ * callback is properly disposed of. All remove functionality should go
+ * through this.
*/
- UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
- PersistentValueReference* reference) {
- *reference = Leak(&value);
- return SetUnique(key, &value);
+ static UniquePersistent<V> Release(PersistentContainerValue v) {
+ UniquePersistent<V> p;
+ p.val_ = FromVal(v);
+ if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
+ Traits::DisposeCallbackData(
+ p.template ClearWeak<typename Traits::WeakCallbackDataType>());
+ }
+ return p.Pass();
}
private:
- PersistentValueMap(PersistentValueMap&);
- void operator=(PersistentValueMap&);
+ PersistentValueMapBase(PersistentValueMapBase&);
+ void operator=(PersistentValueMapBase&);
+
+ static bool SetReturnValueFromVal(ReturnValue<Value>* returnValue,
+ PersistentContainerValue value) {
+ bool hasValue = value != kPersistentContainerNotFound;
+ if (hasValue) {
+ returnValue->SetInternal(
+ *reinterpret_cast<internal::Object**>(FromVal(value)));
+ }
+ return hasValue;
+ }
+
+ Isolate* isolate_;
+ typename Traits::Impl impl_;
+};
+
+
+template <typename K, typename V, typename Traits>
+class PersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
+ public:
+ explicit PersistentValueMap(Isolate* isolate)
+ : PersistentValueMapBase<K, V, Traits>(isolate) {}
+
+ typedef
+ typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
+ PersistentValueReference;
+
+ /**
+ * Put value into map. Depending on Traits::kIsWeak, the value will be held
+ * by the map strongly or weakly.
+ * Returns old value as UniquePersistent.
+ */
+ UniquePersistent<V> Set(const K& key, Local<V> value) {
+ UniquePersistent<V> persistent(this->isolate(), value);
+ return SetUnique(key, &persistent);
+ }
+
+ /**
+ * Put value into map, like Set(const K&, Local<V>).
+ */
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
+ return SetUnique(key, &value);
+ }
/**
* Put the value into the map, and set the 'weak' callback when demanded
*/
UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
if (Traits::kCallbackType != kNotWeak) {
- Local<V> value(Local<V>::New(isolate_, *persistent));
+ Local<V> value(Local<V>::New(this->isolate(), *persistent));
persistent->template SetWeak<typename Traits::WeakCallbackDataType>(
Traits::WeakCallbackParameter(this, key, value), WeakCallback);
}
PersistentContainerValue old_value =
- Traits::Set(&impl_, key, ClearAndLeak(persistent));
- return Release(old_value).Pass();
+ Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
+ return this->Release(old_value).Pass();
+ }
+
+ /**
+ * Put a value into the map and update the reference.
+ * Restrictions of GetReference apply here as well.
+ */
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
+ PersistentValueReference* reference) {
+ *reference = this->Leak(&value);
+ return SetUnique(key, &value);
}
+ private:
static void WeakCallback(
const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
if (Traits::kCallbackType != kNotWeak) {
Traits::DisposeCallbackData(data.GetParameter());
}
}
+};
- static V* FromVal(PersistentContainerValue v) {
- return reinterpret_cast<V*>(v);
- }
- static bool SetReturnValueFromVal(
- ReturnValue<Value>* returnValue, PersistentContainerValue value) {
- bool hasValue = value != kPersistentContainerNotFound;
- if (hasValue) {
- returnValue->SetInternal(
- *reinterpret_cast<internal::Object**>(FromVal(value)));
- }
- return hasValue;
- }
+template <typename K, typename V, typename Traits>
+class PhantomPersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
+ public:
+ explicit PhantomPersistentValueMap(Isolate* isolate)
+ : PersistentValueMapBase<K, V, Traits>(isolate) {}
- static PersistentContainerValue ClearAndLeak(
- UniquePersistent<V>* persistent) {
- V* v = persistent->val_;
- persistent->val_ = 0;
- return reinterpret_cast<PersistentContainerValue>(v);
+ typedef
+ typename PersistentValueMapBase<K, V, Traits>::PersistentValueReference
+ PersistentValueReference;
+
+ /**
+ * Put value into map. Depending on Traits::kIsWeak, the value will be held
+ * by the map strongly or weakly.
+ * Returns old value as UniquePersistent.
+ */
+ UniquePersistent<V> Set(const K& key, Local<V> value) {
+ UniquePersistent<V> persistent(this->isolate(), value);
+ return SetUnique(key, &persistent);
}
- static PersistentContainerValue Leak(
- UniquePersistent<V>* persistent) {
- return reinterpret_cast<PersistentContainerValue>(persistent->val_);
+ /**
+ * Put value into map, like Set(const K&, Local<V>).
+ */
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value) {
+ return SetUnique(key, &value);
}
/**
- * Return a container value as UniquePersistent and make sure the weak
- * callback is properly disposed of. All remove functionality should go
- * through this.
+ * Put the value into the map, and set the 'weak' callback when demanded
+ * by the Traits class.
*/
- static UniquePersistent<V> Release(PersistentContainerValue v) {
- UniquePersistent<V> p;
- p.val_ = FromVal(v);
- if (Traits::kCallbackType != kNotWeak && p.IsWeak()) {
- Traits::DisposeCallbackData(
- p.template ClearWeak<typename Traits::WeakCallbackDataType>());
+ UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
+ if (Traits::kCallbackType != kNotWeak) {
+ Local<V> value(Local<V>::New(this->isolate(), *persistent));
+ persistent->template SetPhantom<typename Traits::WeakCallbackDataType>(
+ Traits::WeakCallbackParameter(this, key, value), WeakCallback, 0, 1);
}
- return p.Pass();
+ PersistentContainerValue old_value =
+ Traits::Set(this->impl(), key, this->ClearAndLeak(persistent));
+ return this->Release(old_value).Pass();
}
- Isolate* isolate_;
- typename Traits::Impl impl_;
+ /**
+ * Put a value into the map and update the reference.
+ * Restrictions of GetReference apply here as well.
+ */
+ UniquePersistent<V> Set(const K& key, UniquePersistent<V> value,
+ PersistentValueReference* reference) {
+ *reference = this->Leak(&value);
+ return SetUnique(key, &value);
+ }
+
+ private:
+ static void WeakCallback(
+ const PhantomCallbackData<typename Traits::WeakCallbackDataType>& data) {
+ if (Traits::kCallbackType != kNotWeak) {
+ PhantomPersistentValueMap<K, V, Traits>* persistentValueMap =
+ Traits::MapFromPhantomCallbackData(data);
+ K key = Traits::KeyFromPhantomCallbackData(data);
+ Traits::Dispose(data.GetIsolate(), persistentValueMap->Remove(key).Pass(),
+ key);
+ Traits::DisposeCallbackData(data.GetParameter());
+ }
+ }
};
class M = NonCopyablePersistentTraits<T> > class Persistent;
template<class T> class UniquePersistent;
template<class K, class V, class T> class PersistentValueMap;
+template <class K, class V, class T>
+class PersistentValueMapBase;
+template <class K, class V, class T>
+class PhantomPersistentValueMap;
template<class V, class T> class PersistentValueVector;
template<class T, class P> class WeakCallbackObject;
class FunctionTemplate;
template<class F> friend class internal::CustomArguments;
friend class HandleScope;
friend class EscapableHandleScope;
- template<class F1, class F2, class F3> friend class PersistentValueMap;
+ template <class F1, class F2, class F3>
+ friend class PersistentValueMapBase;
template<class F1, class F2> friend class PersistentValueVector;
template <class S> V8_INLINE Local(S* that) : Handle<T>(that) { }
};
-template <typename T, typename U = void, typename V = void>
+template <typename T>
class PhantomCallbackData : public internal::CallbackData<T> {
public:
- typedef void (*Callback)(const PhantomCallbackData<T, U, V>& data);
+ typedef void (*Callback)(const PhantomCallbackData<T>& data);
- V8_INLINE U* GetInternalField1() const { return internal_field1_; }
- V8_INLINE V* GetInternalField2() const { return internal_field2_; }
+ V8_INLINE void* GetInternalField1() const { return internal_field1_; }
+ V8_INLINE void* GetInternalField2() const { return internal_field2_; }
- PhantomCallbackData(Isolate* isolate, T* parameter, U* internal_field1,
- V* internal_field2)
+ PhantomCallbackData(Isolate* isolate, T* parameter, void* internal_field1,
+ void* internal_field2)
: internal::CallbackData<T>(isolate, parameter),
internal_field1_(internal_field1),
internal_field2_(internal_field2) {}
private:
- U* internal_field1_;
- V* internal_field2_;
+ void* internal_field1_;
+ void* internal_field2_;
};
};
+static const int kNoInternalFieldIndex = -1;
+
+
/**
* 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
// specify a parameter for the callback or the location of two internal
// fields in the dying object.
template <typename P>
- V8_INLINE void SetPhantom(
- P* parameter,
- typename PhantomCallbackData<P, void, void>::Callback callback);
- template <typename P, typename Q>
- V8_INLINE void SetPhantom(
- P* parameter, int internal_field_index1,
- typename PhantomCallbackData<P, Q, void>::Callback callback);
- template <typename P, typename Q, typename R>
- V8_INLINE void SetPhantom(
- P* parameter, int internal_field_index1, int internal_field_index2,
- typename PhantomCallbackData<P, Q, R>::Callback callback);
+ V8_INLINE void SetPhantom(P* parameter,
+ typename PhantomCallbackData<P>::Callback callback,
+ int internal_field_index1 = kNoInternalFieldIndex,
+ int internal_field_index2 = kNoInternalFieldIndex);
template<typename P>
V8_INLINE P* ClearWeak();
template<class F> friend class UniquePersistent;
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, class F3>
+ friend class PersistentValueMapBase;
template<class F1, class F2> friend class PersistentValueVector;
friend class Object;
/** Gets the number of internal fields for this Object. */
int InternalFieldCount();
- static const int kNoInternalFieldIndex = -1;
-
/** Same as above, but works for Persistents */
V8_INLINE static int InternalFieldCount(
const PersistentBase<Object>& object) {
template<class F> friend class ReturnValue;
template<class F> friend class FunctionCallbackInfo;
template<class F> friend class PropertyCallbackInfo;
- template<class F, class G, class H> friend class PersistentValueMap;
+ template <class F, class G, class H>
+ friend class PersistentValueMapBase;
V8_INLINE void SetInternal(internal::Object* value) { *value_ = value; }
V8_INLINE internal::Object* GetDefaultValue();
V8_INLINE explicit ReturnValue(internal::Object** slot);
void VisitHandlesForPartialDependence(PersistentHandleVisitor* visitor);
private:
- template<class K, class V, class Traits> friend class PersistentValueMap;
+ template <class K, class V, class Traits>
+ friend class PersistentValueMapBase;
Isolate();
Isolate(const Isolate&);
typedef WeakCallbackData<Value, void>::Callback WeakCallback;
static void MakeWeak(internal::Object** global_handle, void* data,
WeakCallback weak_callback);
- static void MakePhantom(
- internal::Object** global_handle, void* data,
- // Must be 0 or kNoInternalFieldIndex.
- int internal_field_index1,
- // Must be 1 or kNoInternalFieldIndex.
- int internal_field_index2,
- PhantomCallbackData<void, void, void>::Callback weak_callback);
+ static void MakePhantom(internal::Object** global_handle, void* data,
+ // Must be 0 or kNoInternalFieldIndex.
+ int internal_field_index1,
+ // Must be 1 or kNoInternalFieldIndex.
+ int internal_field_index2,
+ PhantomCallbackData<void>::Callback weak_callback);
static void* ClearWeak(internal::Object** global_handle);
static void Eternalize(Isolate* isolate,
Value* handle,
template <class T>
template <typename P>
void PersistentBase<T>::SetPhantom(
- P* parameter,
- typename PhantomCallbackData<P, void, void>::Callback callback) {
- typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
- V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
- Object::kNoInternalFieldIndex, Object::kNoInternalFieldIndex,
- reinterpret_cast<Callback>(callback));
-}
-
-
-template <class T>
-template <typename P, typename Q>
-void PersistentBase<T>::SetPhantom(
- P* parameter, int internal_field_index1,
- typename PhantomCallbackData<P, Q, void>::Callback callback) {
- typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
- V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
- internal_field_index1, Object::kNoInternalFieldIndex,
- reinterpret_cast<Callback>(callback));
-}
-
-
-template <class T>
-template <typename P, typename Q, typename R>
-void PersistentBase<T>::SetPhantom(
- P* parameter, int internal_field_index1, int internal_field_index2,
- typename PhantomCallbackData<P, Q, R>::Callback callback) {
- typedef typename PhantomCallbackData<void, void, void>::Callback Callback;
+ P* parameter, typename PhantomCallbackData<P>::Callback callback,
+ int internal_field_index1, int internal_field_index2) {
+ typedef typename PhantomCallbackData<void>::Callback Callback;
V8::MakePhantom(reinterpret_cast<internal::Object**>(this->val_), parameter,
internal_field_index1, internal_field_index2,
reinterpret_cast<Callback>(callback));
}
-void V8::MakePhantom(
- i::Object** object, void* parameter, int internal_field_index1,
- int internal_field_index2,
- PhantomCallbackData<void, void, void>::Callback weak_callback) {
+void V8::MakePhantom(i::Object** object, void* parameter,
+ int internal_field_index1, int internal_field_index2,
+ PhantomCallbackData<void>::Callback weak_callback) {
if (internal_field_index1 == 0) {
if (internal_field_index2 == 1) {
i::GlobalHandles::MakePhantom(object, parameter, 2, weak_callback);
} else {
- DCHECK_EQ(internal_field_index2, Object::kNoInternalFieldIndex);
+ DCHECK_EQ(internal_field_index2, kNoInternalFieldIndex);
i::GlobalHandles::MakePhantom(object, parameter, 1, weak_callback);
}
} else {
- DCHECK_EQ(internal_field_index1, Object::kNoInternalFieldIndex);
- DCHECK_EQ(internal_field_index2, Object::kNoInternalFieldIndex);
+ DCHECK_EQ(internal_field_index1, kNoInternalFieldIndex);
+ DCHECK_EQ(internal_field_index2, kNoInternalFieldIndex);
i::GlobalHandles::MakePhantom(object, parameter, 0, weak_callback);
}
}
// Zap with harmless value.
*location() = Smi::FromInt(0);
- typedef PhantomCallbackData<void, void, void> Data;
+ typedef PhantomCallbackData<void> Data;
if (!internal_field0->IsSmi()) internal_field0 = nullptr;
if (!internal_field1->IsSmi()) internal_field1 = nullptr;
}
-typedef PhantomCallbackData<void, void, void>::Callback GenericCallback;
+typedef PhantomCallbackData<void>::Callback GenericCallback;
void GlobalHandles::MakePhantom(Object** location, void* parameter,
// It would be nice to template this one, but it's really hard to get
// the template instantiator to work right if you do.
- static void MakePhantom(
- Object** location, void* parameter, int number_of_internal_fields,
- PhantomCallbackData<void, void, void>::Callback weak_callback);
+ static void MakePhantom(Object** location, void* parameter,
+ int number_of_internal_fields,
+ PhantomCallbackData<void>::Callback weak_callback);
void RecordStats(HeapStats* stats);
class GlobalHandles::PendingPhantomCallback {
public:
- typedef PhantomCallbackData<void, void, void> Data;
+ typedef PhantomCallbackData<void> Data;
PendingPhantomCallback(Node* node, Data data, Data::Callback callback)
: node_(node), data_(data), callback_(callback) {}
};
-void CheckInternalFields(const v8::PhantomCallbackData<
- v8::Persistent<v8::Object>, Trivial, Trivial2>& data) {
+void CheckInternalFields(
+ const v8::PhantomCallbackData<v8::Persistent<v8::Object>>& data) {
v8::Persistent<v8::Object>* handle = data.GetParameter();
handle->Reset();
- Trivial* t1 = data.GetInternalField1();
- Trivial2* t2 = data.GetInternalField2();
+ Trivial* t1 = reinterpret_cast<Trivial*>(data.GetInternalField1());
+ Trivial2* t2 = reinterpret_cast<Trivial2*>(data.GetInternalField2());
CHECK_EQ(42, t1->x());
CHECK_EQ(103, t2->x());
t1->set_x(1729);
reinterpret_cast<Trivial2*>(obj->GetAlignedPointerFromInternalField(1));
CHECK_EQ(103, t2->x());
- handle.SetPhantom<v8::Persistent<v8::Object>, Trivial, Trivial2>(
- &handle, 0, 1, CheckInternalFields);
+ handle.SetPhantom<v8::Persistent<v8::Object>>(&handle, CheckInternalFields,
+ 0, 1);
if (!global_gc) {
handle.MarkIndependent();
}