| Index: Source/heap/Handle.h
|
| diff --git a/Source/heap/Handle.h b/Source/heap/Handle.h
|
| index 17342087a18f9960a31c66a846aa96c32c1f96b4..0c21425f0cc88f1d83891bab5523a676b36a7e1b 100644
|
| --- a/Source/heap/Handle.h
|
| +++ b/Source/heap/Handle.h
|
| @@ -41,12 +41,22 @@
|
| namespace WebCore {
|
|
|
| template<typename T> class Member;
|
| +template<typename T> struct OffHeapCollectionTraceTrait;
|
|
|
| class PersistentNode {
|
| public:
|
| - explicit PersistentNode(TraceCallback trace) : m_trace(trace) { }
|
| + explicit PersistentNode(TraceCallback trace)
|
| + : m_trace(trace)
|
| + {
|
| + }
|
|
|
| - virtual ~PersistentNode() { }
|
| + bool isAlive() { return m_trace; }
|
| +
|
| + virtual ~PersistentNode()
|
| + {
|
| + 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
|
| @@ -78,6 +88,9 @@ public:
|
| ~PersistentBase()
|
| {
|
| #ifndef NDEBUG
|
| + ASSERT(isAlive());
|
| + ASSERT(m_next->isAlive());
|
| + ASSERT(m_prev->isAlive());
|
| m_threadState->checkThread();
|
| #endif
|
| m_next->m_prev = m_prev;
|
| @@ -138,7 +151,11 @@ public:
|
| void trace(Visitor*) { }
|
|
|
| private:
|
| - virtual ~PersistentAnchor() { }
|
| + virtual ~PersistentAnchor()
|
| + {
|
| + ASSERT(m_next == this);
|
| + ASSERT(m_prev == this);
|
| + }
|
| PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &PersistentAnchor::trace>::trampoline)
|
| {
|
| m_next = this;
|
| @@ -411,6 +428,55 @@ template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
|
| 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(); }
|
|
|
| +template<typename Collection, ThreadAffinity Affinity = MainThreadOnly> class CollectionPersistent;
|
| +
|
| +// Used to inject correctly typed operator[] into CollectionPersistent when we are wrapping Vector.
|
| +template<typename T> class IndexingBehavior { };
|
| +
|
| +template<typename T, size_t inlineCapacity>
|
| +class IndexingBehavior<CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator> > > {
|
| + typedef CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator> > CollectionPersistentType;
|
| +public:
|
| + T& operator[] (size_t i) { return (**static_cast<CollectionPersistentType*>(this))[i]; }
|
| + const T& operator[] (size_t i) const { return (**static_cast<const CollectionPersistentType*>(this))[i]; }
|
| +};
|
| +
|
| +template<typename Collection, ThreadAffinity Affinity>
|
| +class CollectionPersistent
|
| + : public PersistentBase<Affinity, CollectionPersistent<Collection, Affinity> >
|
| + , public IndexingBehavior<CollectionPersistent<Collection, Affinity> > {
|
| +public:
|
| + typedef Collection CollectionType;
|
| + typedef typename Collection::iterator iterator;
|
| + typedef typename Collection::const_iterator const_iterator;
|
| +
|
| + CollectionPersistent() { }
|
| + explicit CollectionPersistent(size_t size) : m_collection(Collection(size)) { }
|
| + explicit CollectionPersistent(const Collection& collection) : m_collection(collection) { }
|
| + CollectionPersistent& operator=(const Collection& collection) { m_collection = collection; return *this; }
|
| + Collection* operator->() { return &m_collection; }
|
| + const Collection* operator->() const { return &m_collection; }
|
| + Collection& operator*() { return m_collection; }
|
| + const Collection& operator*() const { return m_collection; }
|
| +
|
| + void trace(Visitor* visitor)
|
| + {
|
| + OffHeapCollectionTraceTrait<Collection>::trace(visitor, m_collection);
|
| + }
|
| +
|
| +#if defined(TRACE_GC_MARKING) && TRACE_GC_MARKING
|
| + virtual const char* name() OVERRIDE
|
| + {
|
| + ASSERT(this == static_cast<PersistentNode*>(this));
|
| + const char* n = FieldAnnotationBase::fromAddress(this);
|
| + return n ? n : "CollectionPersistent";
|
| + }
|
| +#endif
|
| +
|
| +private:
|
| + Collection m_collection;
|
| +};
|
| +
|
| // Template aliases for the transition period where we want to support
|
| // both reference counting and garbage collection based on a
|
| // compile-time flag.
|
| @@ -518,13 +584,13 @@ template<typename T> struct HashTraits<WebCore::Member<T> > : SimpleClassHashTra
|
| // in the marking Visitor.
|
| typedef T* PeekInType;
|
| typedef T* PassInType;
|
| - typedef T* IteratorGetType;
|
| - typedef T* IteratorConstGetType;
|
| + typedef WebCore::Member<T>* IteratorGetType;
|
| + typedef const WebCore::Member<T>* IteratorConstGetType;
|
| typedef T* IteratorReferenceType;
|
| typedef T* IteratorConstReferenceType;
|
| static IteratorConstGetType getToConstGetConversion(const WebCore::Member<T>* x) { return x->get(); }
|
| - static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return x; }
|
| - static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x; }
|
| + static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return x->get(); }
|
| + 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;
|
| @@ -546,13 +612,13 @@ template<typename T> struct HashTraits<WebCore::WeakMember<T> > : SimpleClassHas
|
| // in the marking Visitor.
|
| typedef T* PeekInType;
|
| typedef T* PassInType;
|
| - typedef T* IteratorGetType;
|
| - typedef T* IteratorConstGetType;
|
| + typedef WebCore::WeakMember<T>* IteratorGetType;
|
| + typedef const WebCore::WeakMember<T>* IteratorConstGetType;
|
| typedef T* IteratorReferenceType;
|
| typedef T* IteratorConstReferenceType;
|
| static IteratorConstGetType getToConstGetConversion(const WebCore::WeakMember<T>* x) { return x->get(); }
|
| - static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return x; }
|
| - static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x; }
|
| + static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return x->get(); }
|
| + 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;
|
|
|