| Index: sky/engine/platform/heap/Handle.h
|
| diff --git a/sky/engine/platform/heap/Handle.h b/sky/engine/platform/heap/Handle.h
|
| index 87fd1fb1be9e218fdd32073fac10e0a00c6e2855..da7e346a3087922dac85a3d7dcece4ba11012040 100644
|
| --- a/sky/engine/platform/heap/Handle.h
|
| +++ b/sky/engine/platform/heap/Handle.h
|
| @@ -31,14 +31,13 @@
|
| #ifndef Handle_h
|
| #define Handle_h
|
|
|
| -#include "platform/heap/ThreadState.h"
|
| -#include "platform/heap/Visitor.h"
|
| #include "wtf/Functional.h"
|
| #include "wtf/HashFunctions.h"
|
| -#include "wtf/Locker.h"
|
| +#include "wtf/PassOwnPtr.h"
|
| #include "wtf/RawPtr.h"
|
| #include "wtf/RefCounted.h"
|
| #include "wtf/TypeTraits.h"
|
| +#include "wtf/text/AtomicString.h"
|
|
|
| // Classes that contain heap references but aren't themselves heap
|
| // allocated, have some extra macros available which allows their use
|
| @@ -98,529 +97,27 @@
|
|
|
| namespace blink {
|
|
|
| -template<typename T> class HeapTerminatedArray;
|
| -
|
| -template<typename T> class Member;
|
| -
|
| -class PersistentNode {
|
| +class Visitor {
|
| public:
|
| - explicit PersistentNode(TraceCallback trace)
|
| - : m_trace(trace)
|
| + template<typename T>
|
| + void mark(T* t)
|
| {
|
| }
|
| -
|
| - bool isAlive() { return m_trace; }
|
| -
|
| - virtual ~PersistentNode()
|
| + template<typename T>
|
| + void trace(const T* t)
|
| {
|
| - ASSERT(isAlive());
|
| - m_trace = 0;
|
| }
|
| -
|
| - // Ideally the trace method should be virtual and automatically dispatch
|
| - // to the most specific implementation. However having a virtual method
|
| - // on PersistentNode leads to too eager template instantiation with MSVC
|
| - // which leads to include cycles.
|
| - // Instead we call the constructor with a TraceCallback which knows the
|
| - // type of the most specific child and calls trace directly. See
|
| - // TraceMethodDelegate in Visitor.h for how this is done.
|
| - void trace(Visitor* visitor)
|
| + template<typename T>
|
| + void trace(T* t)
|
| {
|
| - m_trace(visitor, this);
|
| }
|
| -
|
| -protected:
|
| - TraceCallback m_trace;
|
| -
|
| -private:
|
| - PersistentNode* m_next;
|
| - PersistentNode* m_prev;
|
| -
|
| - template<typename RootsAccessor, typename Owner> friend class PersistentBase;
|
| - friend class PersistentAnchor;
|
| -};
|
| -
|
| -
|
| -// RootsAccessor for Persistent that provides access to thread-local list
|
| -// of persistent handles. Can only be used to create handles that
|
| -// are constructed and destructed on the same thread.
|
| -template<ThreadAffinity Affinity>
|
| -class ThreadLocalPersistents {
|
| -public:
|
| - static PersistentNode* roots() { return state()->roots(); }
|
| -
|
| - // No locking required. Just check that we are at the right thread.
|
| - class Lock {
|
| - public:
|
| - Lock() { state()->checkThread(); }
|
| - };
|
| -
|
| -private:
|
| - static ThreadState* state() { return ThreadStateFor<Affinity>::state(); }
|
| -};
|
| -
|
| -// Base class for persistent handles. RootsAccessor specifies which list to
|
| -// link resulting handle into. Owner specifies the class containing trace
|
| -// method.
|
| -template<typename RootsAccessor, typename Owner>
|
| -class PersistentBase : public PersistentNode {
|
| -public:
|
| - ~PersistentBase()
|
| - {
|
| - typename RootsAccessor::Lock lock;
|
| - ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is using the same roots list.
|
| - ASSERT(isAlive());
|
| - ASSERT(m_next->isAlive());
|
| - ASSERT(m_prev->isAlive());
|
| - m_next->m_prev = m_prev;
|
| - m_prev->m_next = m_next;
|
| - }
|
| -
|
| -protected:
|
| - inline PersistentBase()
|
| - : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline)
|
| -#if ENABLE(ASSERT)
|
| - , m_roots(RootsAccessor::roots())
|
| -#endif
|
| + template<typename T>
|
| + void trace(const T& t)
|
| {
|
| - typename RootsAccessor::Lock lock;
|
| - m_prev = RootsAccessor::roots();
|
| - m_next = m_prev->m_next;
|
| - m_prev->m_next = this;
|
| - m_next->m_prev = this;
|
| }
|
| -
|
| - inline explicit PersistentBase(const PersistentBase& otherref)
|
| - : PersistentNode(otherref.m_trace)
|
| -#if ENABLE(ASSERT)
|
| - , m_roots(RootsAccessor::roots())
|
| -#endif
|
| - {
|
| - // We don't support allocation of thread local Persistents while doing
|
| - // thread shutdown/cleanup.
|
| - typename RootsAccessor::Lock lock;
|
| - ASSERT(otherref.m_roots == m_roots); // Handles must belong to the same list.
|
| - PersistentBase* other = const_cast<PersistentBase*>(&otherref);
|
| - m_prev = other;
|
| - m_next = other->m_next;
|
| - other->m_next = this;
|
| - m_next->m_prev = this;
|
| - }
|
| -
|
| - inline PersistentBase& operator=(const PersistentBase& otherref) { return *this; }
|
| -
|
| -#if ENABLE(ASSERT)
|
| -private:
|
| - PersistentNode* m_roots;
|
| -#endif
|
| };
|
|
|
| -// A dummy Persistent handle that ensures the list of persistents is never null.
|
| -// This removes a test from a hot path.
|
| -class PersistentAnchor : public PersistentNode {
|
| -public:
|
| - void trace(Visitor* visitor)
|
| - {
|
| - for (PersistentNode* current = m_next; current != this; current = current->m_next)
|
| - current->trace(visitor);
|
| - }
|
| -
|
| - int numberOfPersistents()
|
| - {
|
| - int numberOfPersistents = 0;
|
| - for (PersistentNode* current = m_next; current != this; current = current->m_next)
|
| - ++numberOfPersistents;
|
| - return numberOfPersistents;
|
| - }
|
| -
|
| - virtual ~PersistentAnchor()
|
| - {
|
| - // FIXME: oilpan: Ideally we should have no left-over persistents at this point. However currently there is a
|
| - // large number of objects leaked when we tear down the main thread. Since some of these might contain a
|
| - // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee there are no remaining Persistents at
|
| - // this point.
|
| - }
|
| -
|
| -private:
|
| - PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &PersistentAnchor::trace>::trampoline)
|
| - {
|
| - m_next = this;
|
| - m_prev = this;
|
| - }
|
| -
|
| - friend class ThreadState;
|
| -};
|
| -
|
| -// Persistent handles are used to store pointers into the
|
| -// managed heap. As long as the Persistent handle is alive
|
| -// the GC will keep the object pointed to alive. Persistent
|
| -// handles can be stored in objects and they are not scoped.
|
| -// Persistent handles must not be used to contain pointers
|
| -// between objects that are in the managed heap. They are only
|
| -// meant to point to managed heap objects from variables/members
|
| -// outside the managed heap.
|
| -//
|
| -// A Persistent is always a GC root from the point of view of
|
| -// the garbage collector.
|
| -//
|
| -// We have to construct and destruct Persistent with default RootsAccessor in
|
| -// the same thread.
|
| -template<typename T, typename RootsAccessor = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > >
|
| -class Persistent : public PersistentBase<RootsAccessor, Persistent<T, RootsAccessor> > {
|
| - WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(Persistent);
|
| - WTF_DISALLOW_ZERO_ASSIGNMENT(Persistent);
|
| -public:
|
| - Persistent() : m_raw(0) { }
|
| -
|
| - Persistent(std::nullptr_t) : m_raw(0) { }
|
| -
|
| - Persistent(T* raw) : m_raw(raw)
|
| - {
|
| - recordBacktrace();
|
| - }
|
| -
|
| - explicit Persistent(T& raw) : m_raw(&raw)
|
| - {
|
| - recordBacktrace();
|
| - }
|
| -
|
| - Persistent(const Persistent& other) : m_raw(other) { recordBacktrace(); }
|
| -
|
| - template<typename U>
|
| - Persistent(const Persistent<U, RootsAccessor>& other) : m_raw(other) { recordBacktrace(); }
|
| -
|
| - template<typename U>
|
| - Persistent(const Member<U>& other) : m_raw(other) { recordBacktrace(); }
|
| -
|
| - template<typename U>
|
| - Persistent(const RawPtr<U>& other) : m_raw(other.get()) { recordBacktrace(); }
|
| -
|
| - template<typename U>
|
| - Persistent& operator=(U* other)
|
| - {
|
| - m_raw = other;
|
| - recordBacktrace();
|
| - return *this;
|
| - }
|
| -
|
| - Persistent& operator=(std::nullptr_t)
|
| - {
|
| - m_raw = 0;
|
| - return *this;
|
| - }
|
| -
|
| - void clear() { m_raw = 0; }
|
| -
|
| - virtual ~Persistent()
|
| - {
|
| - m_raw = 0;
|
| - }
|
| -
|
| - template<typename U>
|
| - U* as() const
|
| - {
|
| - return static_cast<U*>(m_raw);
|
| - }
|
| -
|
| - void trace(Visitor* visitor)
|
| - {
|
| -#if ENABLE(GC_PROFILE_MARKING)
|
| - visitor->setHostInfo(this, m_tracingName.isEmpty() ? "Persistent" : m_tracingName);
|
| -#endif
|
| - visitor->mark(m_raw);
|
| - }
|
| -
|
| - RawPtr<T> release()
|
| - {
|
| - RawPtr<T> result = m_raw;
|
| - m_raw = 0;
|
| - return result;
|
| - }
|
| -
|
| - T& operator*() const { return *m_raw; }
|
| -
|
| - bool operator!() const { return !m_raw; }
|
| -
|
| - operator T*() const { return m_raw; }
|
| - operator RawPtr<T>() const { return m_raw; }
|
| -
|
| - T* operator->() const { return *this; }
|
| -
|
| - Persistent& operator=(const Persistent& other)
|
| - {
|
| - m_raw = other;
|
| - recordBacktrace();
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - Persistent& operator=(const Persistent<U, RootsAccessor>& other)
|
| - {
|
| - m_raw = other;
|
| - recordBacktrace();
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - Persistent& operator=(const Member<U>& other)
|
| - {
|
| - m_raw = other;
|
| - recordBacktrace();
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - Persistent& operator=(const RawPtr<U>& other)
|
| - {
|
| - m_raw = other;
|
| - recordBacktrace();
|
| - return *this;
|
| - }
|
| -
|
| - T* get() const { return m_raw; }
|
| -
|
| -private:
|
| - inline void recordBacktrace() const { }
|
| - T* m_raw;
|
| -};
|
| -
|
| -// Members are used in classes to contain strong pointers to other oilpan heap
|
| -// allocated objects.
|
| -// All Member fields of a class must be traced in the class' trace method.
|
| -// During the mark phase of the GC all live objects are marked as live and
|
| -// all Member fields of a live object will be traced marked as live as well.
|
| -template<typename T>
|
| -class Member {
|
| - WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(Member);
|
| - WTF_DISALLOW_ZERO_ASSIGNMENT(Member);
|
| -public:
|
| - Member() : m_raw(0)
|
| - {
|
| - }
|
| -
|
| - Member(std::nullptr_t) : m_raw(0)
|
| - {
|
| - }
|
| -
|
| - Member(T* raw) : m_raw(raw)
|
| - {
|
| - }
|
| -
|
| - explicit Member(T& raw) : m_raw(&raw)
|
| - {
|
| - }
|
| -
|
| - template<typename U>
|
| - Member(const RawPtr<U>& other) : m_raw(other.get())
|
| - {
|
| - }
|
| -
|
| - Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1))
|
| - {
|
| - }
|
| -
|
| - bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(-1); }
|
| -
|
| - template<typename U>
|
| - Member(const Persistent<U>& other) : m_raw(other) { }
|
| -
|
| - Member(const Member& other) : m_raw(other) { }
|
| -
|
| - template<typename U>
|
| - Member(const Member<U>& other) : m_raw(other) { }
|
| -
|
| - T* release()
|
| - {
|
| - T* result = m_raw;
|
| - m_raw = 0;
|
| - return result;
|
| - }
|
| -
|
| - template<typename U>
|
| - U* as() const
|
| - {
|
| - return static_cast<U*>(m_raw);
|
| - }
|
| -
|
| - bool operator!() const { return !m_raw; }
|
| -
|
| - operator T*() const { return m_raw; }
|
| -
|
| - T* operator->() const { return m_raw; }
|
| - T& operator*() const { return *m_raw; }
|
| - template<typename U>
|
| - operator RawPtr<U>() const { return m_raw; }
|
| -
|
| - template<typename U>
|
| - Member& operator=(const Persistent<U>& other)
|
| - {
|
| - m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - Member& operator=(const Member<U>& other)
|
| - {
|
| - m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - Member& operator=(U* other)
|
| - {
|
| - m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - Member& operator=(RawPtr<U> other)
|
| - {
|
| - m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - Member& operator=(std::nullptr_t)
|
| - {
|
| - m_raw = 0;
|
| - return *this;
|
| - }
|
| -
|
| - void swap(Member<T>& other) { std::swap(m_raw, other.m_raw); }
|
| -
|
| - T* get() const { return m_raw; }
|
| -
|
| - void clear() { m_raw = 0; }
|
| -
|
| -
|
| -protected:
|
| - void verifyTypeIsGarbageCollected() const
|
| - {
|
| - }
|
| -
|
| - T* m_raw;
|
| -
|
| - friend class Visitor;
|
| -};
|
| -
|
| -template<typename T>
|
| -class TraceTrait<Member<T> > {
|
| -public:
|
| - static void trace(Visitor* visitor, void* self)
|
| - {
|
| - TraceTrait<T>::mark(visitor, *static_cast<Member<T>*>(self));
|
| - }
|
| -};
|
| -
|
| -// TraceTrait to allow compilation of trace method bodies when oilpan is disabled.
|
| -// This should never be called, but is needed to compile.
|
| -template<typename T>
|
| -class TraceTrait<RefPtr<T> > {
|
| -public:
|
| - static void trace(Visitor*, void*)
|
| - {
|
| - ASSERT_NOT_REACHED();
|
| - }
|
| -};
|
| -
|
| -template<typename T>
|
| -class TraceTrait<OwnPtr<T> > {
|
| -public:
|
| - static void trace(Visitor* visitor, OwnPtr<T>* ptr)
|
| - {
|
| - ASSERT_NOT_REACHED();
|
| - }
|
| -};
|
| -
|
| -template <typename T> struct RemoveHeapPointerWrapperTypes {
|
| - typedef typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<T, Member>::Type, WeakMember>::Type, RawPtr>::Type Type;
|
| -};
|
| -
|
| -// This trace trait for std::pair will null weak members if their referent is
|
| -// collected. If you have a collection that contain weakness it does not remove
|
| -// entries from the collection that contain nulled weak members.
|
| -template<typename T, typename U>
|
| -class TraceTrait<std::pair<T, U> > {
|
| -public:
|
| - static void trace(Visitor* visitor, std::pair<T, U>* pair)
|
| - {
|
| - }
|
| -};
|
| -
|
| -// WeakMember is similar to Member in that it is used to point to other oilpan
|
| -// heap allocated objects.
|
| -// However instead of creating a strong pointer to the object, the WeakMember creates
|
| -// a weak pointer, which does not keep the pointee alive. Hence if all pointers to
|
| -// to a heap allocated object are weak the object will be garbage collected. At the
|
| -// time of GC the weak pointers will automatically be set to null.
|
| -template<typename T>
|
| -class WeakMember : public Member<T> {
|
| - WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(WeakMember);
|
| - WTF_DISALLOW_ZERO_ASSIGNMENT(WeakMember);
|
| -public:
|
| - WeakMember() : Member<T>() { }
|
| -
|
| - WeakMember(std::nullptr_t) : Member<T>(nullptr) { }
|
| -
|
| - WeakMember(T* raw) : Member<T>(raw) { }
|
| -
|
| - WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { }
|
| -
|
| - template<typename U>
|
| - WeakMember(const Persistent<U>& other) : Member<T>(other) { }
|
| -
|
| - template<typename U>
|
| - WeakMember(const Member<U>& other) : Member<T>(other) { }
|
| -
|
| - template<typename U>
|
| - WeakMember& operator=(const Persistent<U>& other)
|
| - {
|
| - this->m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - WeakMember& operator=(const Member<U>& other)
|
| - {
|
| - this->m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - WeakMember& operator=(U* other)
|
| - {
|
| - this->m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - template<typename U>
|
| - WeakMember& operator=(const RawPtr<U>& other)
|
| - {
|
| - this->m_raw = other;
|
| - return *this;
|
| - }
|
| -
|
| - WeakMember& operator=(std::nullptr_t)
|
| - {
|
| - this->m_raw = 0;
|
| - return *this;
|
| - }
|
| -
|
| -private:
|
| - T** cell() const { return const_cast<T**>(&this->m_raw); }
|
| -
|
| - friend class Visitor;
|
| -};
|
| -
|
| -// Comparison operators between (Weak)Members and Persistents
|
| -template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.get() == b.get(); }
|
| -template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.get() != b.get(); }
|
| -template<typename T, typename U> inline bool operator==(const Member<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
|
| -template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
|
| -template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); }
|
| -template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); }
|
| -template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
|
| -template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
|
| -
|
| +#define WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TYPE)
|
|
|
| template<typename T>
|
| class DummyBase {
|
| @@ -649,129 +146,6 @@ public:
|
|
|
| namespace WTF {
|
|
|
| -template <typename T> struct VectorTraits<blink::Member<T> > : VectorTraitsBase<blink::Member<T> > {
|
| - static const bool needsDestruction = false;
|
| - static const bool canInitializeWithMemset = true;
|
| - static const bool canMoveWithMemcpy = true;
|
| -};
|
| -
|
| -template <typename T> struct VectorTraits<blink::WeakMember<T> > : VectorTraitsBase<blink::WeakMember<T> > {
|
| - static const bool needsDestruction = false;
|
| - static const bool canInitializeWithMemset = true;
|
| - static const bool canMoveWithMemcpy = true;
|
| -};
|
| -
|
| -template<typename T> struct HashTraits<blink::Member<T> > : SimpleClassHashTraits<blink::Member<T> > {
|
| - static const bool needsDestruction = false;
|
| - // FIXME: The distinction between PeekInType and PassInType is there for
|
| - // the sake of the reference counting handles. When they are gone the two
|
| - // types can be merged into PassInType.
|
| - // FIXME: Implement proper const'ness for iterator types. Requires support
|
| - // in the marking Visitor.
|
| - typedef RawPtr<T> PeekInType;
|
| - typedef RawPtr<T> PassInType;
|
| - typedef blink::Member<T>* IteratorGetType;
|
| - typedef const blink::Member<T>* IteratorConstGetType;
|
| - typedef blink::Member<T>& IteratorReferenceType;
|
| - typedef T* const IteratorConstReferenceType;
|
| - static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
|
| - static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x->get(); }
|
| - // FIXME: Similarly, there is no need for a distinction between PeekOutType
|
| - // and PassOutType without reference counting.
|
| - typedef T* PeekOutType;
|
| - typedef T* PassOutType;
|
| -
|
| - template<typename U>
|
| - static void store(const U& value, blink::Member<T>& storage) { storage = value; }
|
| -
|
| - static PeekOutType peek(const blink::Member<T>& value) { return value; }
|
| - static PassOutType passOut(const blink::Member<T>& value) { return value; }
|
| -};
|
| -
|
| -template<typename T> struct HashTraits<blink::WeakMember<T> > : SimpleClassHashTraits<blink::WeakMember<T> > {
|
| - static const bool needsDestruction = false;
|
| - // FIXME: The distinction between PeekInType and PassInType is there for
|
| - // the sake of the reference counting handles. When they are gone the two
|
| - // types can be merged into PassInType.
|
| - // FIXME: Implement proper const'ness for iterator types. Requires support
|
| - // in the marking Visitor.
|
| - typedef RawPtr<T> PeekInType;
|
| - typedef RawPtr<T> PassInType;
|
| - typedef blink::WeakMember<T>* IteratorGetType;
|
| - typedef const blink::WeakMember<T>* IteratorConstGetType;
|
| - typedef blink::WeakMember<T>& IteratorReferenceType;
|
| - typedef T* const IteratorConstReferenceType;
|
| - static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
|
| - static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x->get(); }
|
| - // FIXME: Similarly, there is no need for a distinction between PeekOutType
|
| - // and PassOutType without reference counting.
|
| - typedef T* PeekOutType;
|
| - typedef T* PassOutType;
|
| -
|
| - template<typename U>
|
| - static void store(const U& value, blink::WeakMember<T>& storage) { storage = value; }
|
| -
|
| - static PeekOutType peek(const blink::WeakMember<T>& value) { return value; }
|
| - static PassOutType passOut(const blink::WeakMember<T>& value) { return value; }
|
| - static bool traceInCollection(blink::Visitor* visitor, blink::WeakMember<T>& weakMember, ShouldWeakPointersBeMarkedStrongly strongify)
|
| - {
|
| - }
|
| -};
|
| -
|
| -template<typename T> struct PtrHash<blink::Member<T> > : PtrHash<T*> {
|
| - template<typename U>
|
| - static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); }
|
| - static bool equal(T* a, const blink::Member<T>& b) { return a == b; }
|
| - static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
|
| - template<typename U, typename V>
|
| - static bool equal(const U& a, const V& b) { return a == b; }
|
| -};
|
| -
|
| -template<typename T> struct PtrHash<blink::WeakMember<T> > : PtrHash<blink::Member<T> > {
|
| -};
|
| -
|
| -template<typename P> struct PtrHash<blink::Persistent<P> > : PtrHash<P*> {
|
| - using PtrHash<P*>::hash;
|
| - static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
|
| - using PtrHash<P*>::equal;
|
| - static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
|
| - static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
|
| - static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
|
| -};
|
| -
|
| -// PtrHash is the default hash for hash tables with members.
|
| -template<typename T> struct DefaultHash<blink::Member<T> > {
|
| - typedef PtrHash<blink::Member<T> > Hash;
|
| -};
|
| -
|
| -template<typename T> struct DefaultHash<blink::WeakMember<T> > {
|
| - typedef PtrHash<blink::WeakMember<T> > Hash;
|
| -};
|
| -
|
| -template<typename T> struct DefaultHash<blink::Persistent<T> > {
|
| - typedef PtrHash<blink::Persistent<T> > Hash;
|
| -};
|
| -
|
| -template<typename T>
|
| -struct NeedsTracing<blink::Member<T> > {
|
| - static const bool value = true;
|
| -};
|
| -
|
| -template<typename T>
|
| -struct IsWeak<blink::WeakMember<T> > {
|
| - static const bool value = true;
|
| -};
|
| -
|
| -template<typename T> inline T* getPtr(const blink::Member<T>& p)
|
| -{
|
| - return p.get();
|
| -}
|
| -
|
| -template<typename T> inline T* getPtr(const blink::Persistent<T>& p)
|
| -{
|
| - return p.get();
|
| -}
|
| -
|
| // For wtf/Functional.h
|
| template<typename T, bool isGarbageCollected> struct PointerParamStorageTraits;
|
|
|
|
|