Support old and new weak handle API

R=dcarney@chromium.org
BUG=

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

Cr-Commit-Position: refs/heads/master@{#26246}
This commit is contained in:
erikcorry 2015-01-23 03:28:35 -08:00 committed by Commit bot
parent 8a78fd6d2e
commit 8c58ed1a0c
6 changed files with 250 additions and 152 deletions

View File

@ -105,6 +105,43 @@ class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
};
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
@ -115,13 +152,9 @@ class DefaultPersistentValueMapTraits : public StdMapTraits<K, V> {
* 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_; }
/**
@ -167,23 +200,6 @@ class PersistentValueMap {
reinterpret_cast<internal::Object**>(FromVal(Traits::Get(&impl_, key))));
}
/**
* 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.
*/
@ -237,7 +253,9 @@ class PersistentValueMap {
}
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) { }
@ -263,61 +281,18 @@ class PersistentValueMap {
return PersistentValueReference(Traits::Get(&impl_, key));
}
/**
* 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 = Leak(&value);
return SetUnique(key, &value);
}
protected:
explicit PersistentValueMapBase(Isolate* isolate) : isolate_(isolate) {}
private:
PersistentValueMap(PersistentValueMap&);
void operator=(PersistentValueMap&);
~PersistentValueMapBase() { Clear(); }
/**
* Put the value into the map, and set the 'weak' callback when demanded
* by the Traits class.
*/
UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
if (Traits::kCallbackType != kNotWeak) {
Local<V> value(Local<V>::New(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();
}
static void WeakCallback(
const WeakCallbackData<V, typename Traits::WeakCallbackDataType>& data) {
if (Traits::kCallbackType != kNotWeak) {
PersistentValueMap<K, V, Traits>* persistentValueMap =
Traits::MapFromWeakCallbackData(data);
K key = Traits::KeyFromWeakCallbackData(data);
Traits::Dispose(data.GetIsolate(),
persistentValueMap->Remove(key).Pass(), key);
Traits::DisposeCallbackData(data.GetParameter());
}
}
Isolate* isolate() { return isolate_; }
typename Traits::Impl* impl() { return &impl_; }
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;
}
static PersistentContainerValue ClearAndLeak(
UniquePersistent<V>* persistent) {
V* v = persistent->val_;
@ -325,8 +300,7 @@ class PersistentValueMap {
return reinterpret_cast<PersistentContainerValue>(v);
}
static PersistentContainerValue Leak(
UniquePersistent<V>* persistent) {
static PersistentContainerValue Leak(UniquePersistent<V>* persistent) {
return reinterpret_cast<PersistentContainerValue>(persistent->val_);
}
@ -345,11 +319,159 @@ class PersistentValueMap {
return p.Pass();
}
private:
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
* by the Traits class.
*/
UniquePersistent<V> SetUnique(const K& key, UniquePersistent<V>* persistent) {
if (Traits::kCallbackType != kNotWeak) {
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(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) {
PersistentValueMap<K, V, Traits>* persistentValueMap =
Traits::MapFromWeakCallbackData(data);
K key = Traits::KeyFromWeakCallbackData(data);
Traits::Dispose(data.GetIsolate(),
persistentValueMap->Remove(key).Pass(), key);
Traits::DisposeCallbackData(data.GetParameter());
}
}
};
template <typename K, typename V, typename Traits>
class PhantomPersistentValueMap : public PersistentValueMapBase<K, V, Traits> {
public:
explicit PhantomPersistentValueMap(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
* by the Traits class.
*/
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);
}
PersistentContainerValue old_value =
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 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());
}
}
};
/**
* A map that uses UniquePersistent as value and std::map as the backing
* implementation. Persistents are held non-weak.

View File

@ -111,6 +111,10 @@ 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 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;
@ -401,7 +405,8 @@ template <class T> class Local : public Handle<T> {
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) { }
@ -428,23 +433,23 @@ template <class T> class Eternal {
};
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_;
};
@ -463,6 +468,9 @@ class WeakCallbackData : public internal::CallbackData<P> {
};
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
@ -550,17 +558,10 @@ template <class T> class PersistentBase {
// 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();
@ -615,7 +616,8 @@ template <class T> class PersistentBase {
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;
@ -2516,8 +2518,6 @@ class V8_EXPORT Object : public Value {
/** 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) {
@ -2734,7 +2734,8 @@ class ReturnValue {
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);
@ -5231,7 +5232,8 @@ class V8_EXPORT Isolate {
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&);
@ -5583,13 +5585,12 @@ class V8_EXPORT V8 {
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,
@ -6477,33 +6478,9 @@ void PersistentBase<T>::SetWeak(
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));

View File

@ -434,20 +434,19 @@ void V8::MakeWeak(i::Object** object, void* parameter,
}
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);
}
}

View File

@ -285,7 +285,7 @@ class GlobalHandles::Node {
// 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;
@ -562,7 +562,7 @@ void GlobalHandles::MakeWeak(Object** location, void* parameter,
}
typedef PhantomCallbackData<void, void, void>::Callback GenericCallback;
typedef PhantomCallbackData<void>::Callback GenericCallback;
void GlobalHandles::MakePhantom(Object** location, void* parameter,

View File

@ -145,9 +145,9 @@ class GlobalHandles {
// 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);
@ -345,7 +345,7 @@ class GlobalHandles {
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) {}

View File

@ -7715,12 +7715,12 @@ class Trivial2 {
};
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);
@ -7756,8 +7756,8 @@ void InternalFieldCallback(bool global_gc) {
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();
}