diff --git a/include/v8-util.h b/include/v8-util.h index 1eaf1ab68f..ca36b6c58b 100644 --- a/include/v8-util.h +++ b/include/v8-util.h @@ -105,6 +105,43 @@ class DefaultPersistentValueMapTraits : public StdMapTraits { }; +template +class DefaultPhantomPersistentValueMapTraits : public StdMapTraits { + private: + template + struct RemovePointer; + + public: + // Weak callback & friends: + static const PersistentContainerCallbackType kCallbackType = kNotWeak; + typedef PersistentValueMap< + K, V, DefaultPhantomPersistentValueMapTraits > MapType; + typedef void PhantomCallbackDataType; + + static PhantomCallbackDataType* PhantomCallbackParameter(MapType* map, + const K& key, + Local value) { + return NULL; + } + static MapType* MapFromPhantomCallbackData( + const PhantomCallbackData& data) { + return NULL; + } + static K KeyFromPhantomCallbackData( + const PhantomCallbackData& data) { + return K(); + } + static void DisposeCallbackData(PhantomCallbackDataType* data) {} + static void Dispose(Isolate* isolate, UniquePersistent value, K key) {} + + private: + template + struct RemovePointer { + 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 { * PersistentContainerValue, with all conversion into and out of V8 * handles being transparently handled by this class. */ -template -class PersistentValueMap { +template +class PersistentValueMapBase { public: - explicit PersistentValueMap(Isolate* isolate) : isolate_(isolate) {} - - ~PersistentValueMap() { Clear(); } - Isolate* GetIsolate() { return isolate_; } /** @@ -167,23 +200,6 @@ class PersistentValueMap { reinterpret_cast(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 Set(const K& key, Local value) { - UniquePersistent persistent(isolate_, value); - return SetUnique(key, &persistent); - } - - /** - * Put value into map, like Set(const K&, Local). - */ - UniquePersistent Set(const K& key, UniquePersistent 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; + friend class PhantomPersistentValueMap; 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 Set(const K& key, UniquePersistent 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 SetUnique(const K& key, UniquePersistent* persistent) { - if (Traits::kCallbackType != kNotWeak) { - Local value(Local::New(isolate_, *persistent)); - persistent->template SetWeak( - 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& data) { - if (Traits::kCallbackType != kNotWeak) { - PersistentValueMap* 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); } - static bool SetReturnValueFromVal( - ReturnValue* returnValue, PersistentContainerValue value) { - bool hasValue = value != kPersistentContainerNotFound; - if (hasValue) { - returnValue->SetInternal( - *reinterpret_cast(FromVal(value))); - } - return hasValue; - } - static PersistentContainerValue ClearAndLeak( UniquePersistent* persistent) { V* v = persistent->val_; @@ -325,8 +300,7 @@ class PersistentValueMap { return reinterpret_cast(v); } - static PersistentContainerValue Leak( - UniquePersistent* persistent) { + static PersistentContainerValue Leak(UniquePersistent* persistent) { return reinterpret_cast(persistent->val_); } @@ -345,11 +319,159 @@ class PersistentValueMap { return p.Pass(); } + private: + PersistentValueMapBase(PersistentValueMapBase&); + void operator=(PersistentValueMapBase&); + + static bool SetReturnValueFromVal(ReturnValue* returnValue, + PersistentContainerValue value) { + bool hasValue = value != kPersistentContainerNotFound; + if (hasValue) { + returnValue->SetInternal( + *reinterpret_cast(FromVal(value))); + } + return hasValue; + } + Isolate* isolate_; typename Traits::Impl impl_; }; +template +class PersistentValueMap : public PersistentValueMapBase { + public: + explicit PersistentValueMap(Isolate* isolate) + : PersistentValueMapBase(isolate) {} + + typedef + typename PersistentValueMapBase::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 Set(const K& key, Local value) { + UniquePersistent persistent(this->isolate(), value); + return SetUnique(key, &persistent); + } + + /** + * Put value into map, like Set(const K&, Local). + */ + UniquePersistent Set(const K& key, UniquePersistent value) { + return SetUnique(key, &value); + } + + /** + * Put the value into the map, and set the 'weak' callback when demanded + * by the Traits class. + */ + UniquePersistent SetUnique(const K& key, UniquePersistent* persistent) { + if (Traits::kCallbackType != kNotWeak) { + Local value(Local::New(this->isolate(), *persistent)); + persistent->template SetWeak( + 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 Set(const K& key, UniquePersistent value, + PersistentValueReference* reference) { + *reference = this->Leak(&value); + return SetUnique(key, &value); + } + + private: + static void WeakCallback( + const WeakCallbackData& data) { + if (Traits::kCallbackType != kNotWeak) { + PersistentValueMap* persistentValueMap = + Traits::MapFromWeakCallbackData(data); + K key = Traits::KeyFromWeakCallbackData(data); + Traits::Dispose(data.GetIsolate(), + persistentValueMap->Remove(key).Pass(), key); + Traits::DisposeCallbackData(data.GetParameter()); + } + } +}; + + +template +class PhantomPersistentValueMap : public PersistentValueMapBase { + public: + explicit PhantomPersistentValueMap(Isolate* isolate) + : PersistentValueMapBase(isolate) {} + + typedef + typename PersistentValueMapBase::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 Set(const K& key, Local value) { + UniquePersistent persistent(this->isolate(), value); + return SetUnique(key, &persistent); + } + + /** + * Put value into map, like Set(const K&, Local). + */ + UniquePersistent Set(const K& key, UniquePersistent value) { + return SetUnique(key, &value); + } + + /** + * Put the value into the map, and set the 'weak' callback when demanded + * by the Traits class. + */ + UniquePersistent SetUnique(const K& key, UniquePersistent* persistent) { + if (Traits::kCallbackType != kNotWeak) { + Local value(Local::New(this->isolate(), *persistent)); + persistent->template SetPhantom( + 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 Set(const K& key, UniquePersistent value, + PersistentValueReference* reference) { + *reference = this->Leak(&value); + return SetUnique(key, &value); + } + + private: + static void WeakCallback( + const PhantomCallbackData& data) { + if (Traits::kCallbackType != kNotWeak) { + PhantomPersistentValueMap* 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. diff --git a/include/v8.h b/include/v8.h index a11346247b..5dbf9933ec 100644 --- a/include/v8.h +++ b/include/v8.h @@ -111,6 +111,10 @@ template > class Persistent; template class UniquePersistent; template class PersistentValueMap; +template +class PersistentValueMapBase; +template +class PhantomPersistentValueMap; template class PersistentValueVector; template class WeakCallbackObject; class FunctionTemplate; @@ -401,7 +405,8 @@ template class Local : public Handle { template friend class internal::CustomArguments; friend class HandleScope; friend class EscapableHandleScope; - template friend class PersistentValueMap; + template + friend class PersistentValueMapBase; template friend class PersistentValueVector; template V8_INLINE Local(S* that) : Handle(that) { } @@ -428,23 +433,23 @@ template class Eternal { }; -template +template class PhantomCallbackData : public internal::CallbackData { public: - typedef void (*Callback)(const PhantomCallbackData& data); + typedef void (*Callback)(const PhantomCallbackData& 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(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

{ }; +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 PersistentBase { // specify a parameter for the callback or the location of two internal // fields in the dying object. template - V8_INLINE void SetPhantom( - P* parameter, - typename PhantomCallbackData::Callback callback); - template - V8_INLINE void SetPhantom( - P* parameter, int internal_field_index1, - typename PhantomCallbackData::Callback callback); - template - V8_INLINE void SetPhantom( - P* parameter, int internal_field_index1, int internal_field_index2, - typename PhantomCallbackData::Callback callback); + V8_INLINE void SetPhantom(P* parameter, + typename PhantomCallbackData

::Callback callback, + int internal_field_index1 = kNoInternalFieldIndex, + int internal_field_index2 = kNoInternalFieldIndex); template V8_INLINE P* ClearWeak(); @@ -615,7 +616,8 @@ template class PersistentBase { template friend class UniquePersistent; template friend class PersistentBase; template friend class ReturnValue; - template friend class PersistentValueMap; + template + friend class PersistentValueMapBase; template 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) { @@ -2734,7 +2734,8 @@ class ReturnValue { template friend class ReturnValue; template friend class FunctionCallbackInfo; template friend class PropertyCallbackInfo; - template friend class PersistentValueMap; + template + 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 friend class PersistentValueMap; + template + friend class PersistentValueMapBase; Isolate(); Isolate(const Isolate&); @@ -5583,13 +5585,12 @@ class V8_EXPORT V8 { typedef WeakCallbackData::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::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::Callback weak_callback); static void* ClearWeak(internal::Object** global_handle); static void Eternalize(Isolate* isolate, Value* handle, @@ -6477,33 +6478,9 @@ void PersistentBase::SetWeak( template template void PersistentBase::SetPhantom( - P* parameter, - typename PhantomCallbackData::Callback callback) { - typedef typename PhantomCallbackData::Callback Callback; - V8::MakePhantom(reinterpret_cast(this->val_), parameter, - Object::kNoInternalFieldIndex, Object::kNoInternalFieldIndex, - reinterpret_cast(callback)); -} - - -template -template -void PersistentBase::SetPhantom( - P* parameter, int internal_field_index1, - typename PhantomCallbackData::Callback callback) { - typedef typename PhantomCallbackData::Callback Callback; - V8::MakePhantom(reinterpret_cast(this->val_), parameter, - internal_field_index1, Object::kNoInternalFieldIndex, - reinterpret_cast(callback)); -} - - -template -template -void PersistentBase::SetPhantom( - P* parameter, int internal_field_index1, int internal_field_index2, - typename PhantomCallbackData::Callback callback) { - typedef typename PhantomCallbackData::Callback Callback; + P* parameter, typename PhantomCallbackData

::Callback callback, + int internal_field_index1, int internal_field_index2) { + typedef typename PhantomCallbackData::Callback Callback; V8::MakePhantom(reinterpret_cast(this->val_), parameter, internal_field_index1, internal_field_index2, reinterpret_cast(callback)); diff --git a/src/api.cc b/src/api.cc index 18da41b7f1..3ad5a64f59 100644 --- a/src/api.cc +++ b/src/api.cc @@ -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::Callback weak_callback) { +void V8::MakePhantom(i::Object** object, void* parameter, + int internal_field_index1, int internal_field_index2, + PhantomCallbackData::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); } } diff --git a/src/global-handles.cc b/src/global-handles.cc index d717c48249..4048416ca6 100644 --- a/src/global-handles.cc +++ b/src/global-handles.cc @@ -285,7 +285,7 @@ class GlobalHandles::Node { // Zap with harmless value. *location() = Smi::FromInt(0); - typedef PhantomCallbackData Data; + typedef PhantomCallbackData 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::Callback GenericCallback; +typedef PhantomCallbackData::Callback GenericCallback; void GlobalHandles::MakePhantom(Object** location, void* parameter, diff --git a/src/global-handles.h b/src/global-handles.h index fe9ed5a258..20da53a185 100644 --- a/src/global-handles.h +++ b/src/global-handles.h @@ -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::Callback weak_callback); + static void MakePhantom(Object** location, void* parameter, + int number_of_internal_fields, + PhantomCallbackData::Callback weak_callback); void RecordStats(HeapStats* stats); @@ -345,7 +345,7 @@ class GlobalHandles { class GlobalHandles::PendingPhantomCallback { public: - typedef PhantomCallbackData Data; + typedef PhantomCallbackData Data; PendingPhantomCallback(Node* node, Data data, Data::Callback callback) : node_(node), data_(data), callback_(callback) {} diff --git a/test/cctest/test-api.cc b/test/cctest/test-api.cc index 4d39aa543d..63edb01de0 100644 --- a/test/cctest/test-api.cc +++ b/test/cctest/test-api.cc @@ -7715,12 +7715,12 @@ class Trivial2 { }; -void CheckInternalFields(const v8::PhantomCallbackData< - v8::Persistent, Trivial, Trivial2>& data) { +void CheckInternalFields( + const v8::PhantomCallbackData>& data) { v8::Persistent* handle = data.GetParameter(); handle->Reset(); - Trivial* t1 = data.GetInternalField1(); - Trivial2* t2 = data.GetInternalField2(); + Trivial* t1 = reinterpret_cast(data.GetInternalField1()); + Trivial2* t2 = reinterpret_cast(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(obj->GetAlignedPointerFromInternalField(1)); CHECK_EQ(103, t2->x()); - handle.SetPhantom, Trivial, Trivial2>( - &handle, 0, 1, CheckInternalFields); + handle.SetPhantom>(&handle, CheckInternalFields, + 0, 1); if (!global_gc) { handle.MarkIndependent(); }