Index: third_party/WebKit/Source/platform/heap/Handle.h |
diff --git a/third_party/WebKit/Source/platform/heap/Handle.h b/third_party/WebKit/Source/platform/heap/Handle.h |
index 432b9d7c1885e01acfe50a1def69a37b9ffaf6c3..9175d24bbcf016038748f4658de2062d680de724 100644 |
--- a/third_party/WebKit/Source/platform/heap/Handle.h |
+++ b/third_party/WebKit/Source/platform/heap/Handle.h |
@@ -34,13 +34,12 @@ |
#include "platform/heap/Heap.h" |
#include "platform/heap/HeapAllocator.h" |
#include "platform/heap/InlinedGlobalMarkingVisitor.h" |
-#include "platform/heap/PersistentNode.h" |
+#include "platform/heap/Member.h" |
+#include "platform/heap/Persistent.h" |
#include "platform/heap/ThreadState.h" |
#include "platform/heap/TraceTraits.h" |
#include "platform/heap/Visitor.h" |
#include "wtf/Allocator.h" |
-#include "wtf/Atomics.h" |
-#include "wtf/HashFunctions.h" |
#if defined(LEAK_SANITIZER) |
#include "wtf/LeakAnnotations.h" |
@@ -48,1033 +47,6 @@ |
namespace blink { |
-// Marker used to annotate persistent objects and collections with, |
-// so as to enable reliable testing for persistent references via |
-// a type trait (see TypeTraits.h's IsPersistentReferenceType<>.) |
-#define IS_PERSISTENT_REFERENCE_TYPE() \ |
- public: \ |
- using IsPersistentReferenceTypeMarker = int; \ |
- private: |
- |
-enum WeaknessPersistentConfiguration { |
- NonWeakPersistentConfiguration, |
- WeakPersistentConfiguration |
-}; |
- |
-enum CrossThreadnessPersistentConfiguration { |
- SingleThreadPersistentConfiguration, |
- CrossThreadPersistentConfiguration |
-}; |
- |
-template<typename T, WeaknessPersistentConfiguration weaknessConfiguration, CrossThreadnessPersistentConfiguration crossThreadnessConfiguration> |
-class PersistentBase { |
- USING_FAST_MALLOC(PersistentBase); |
- IS_PERSISTENT_REFERENCE_TYPE(); |
-public: |
- PersistentBase() : m_raw(nullptr) |
- { |
- initialize(); |
- } |
- |
- PersistentBase(std::nullptr_t) : m_raw(nullptr) |
- { |
- initialize(); |
- } |
- |
- PersistentBase(T* raw) : m_raw(raw) |
- { |
- initialize(); |
- checkPointer(); |
- } |
- |
- PersistentBase(T& raw) : m_raw(&raw) |
- { |
- initialize(); |
- checkPointer(); |
- } |
- |
- PersistentBase(const PersistentBase& other) : m_raw(other) |
- { |
- initialize(); |
- checkPointer(); |
- } |
- |
- template<typename U> |
- PersistentBase(const PersistentBase<U, weaknessConfiguration, crossThreadnessConfiguration>& other) : m_raw(other) |
- { |
- initialize(); |
- checkPointer(); |
- } |
- |
- template<typename U> |
- PersistentBase(const Member<U>& other) : m_raw(other) |
- { |
- initialize(); |
- checkPointer(); |
- } |
- |
- ~PersistentBase() |
- { |
- uninitialize(); |
- m_raw = nullptr; |
- } |
- |
- template<typename VisitorDispatcher> |
- void trace(VisitorDispatcher visitor) |
- { |
- static_assert(sizeof(T), "T must be fully defined"); |
- static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage collected object"); |
- if (weaknessConfiguration == WeakPersistentConfiguration) { |
- visitor->registerWeakCell(&m_raw); |
- } else { |
- visitor->mark(m_raw); |
- } |
- } |
- |
- T* release() |
- { |
- T* result = m_raw; |
- assign(nullptr); |
- return result; |
- } |
- |
- void clear() { assign(nullptr); } |
- T& operator*() const { return *m_raw; } |
- explicit operator bool() const { return m_raw; } |
- operator T*() const { return m_raw; } |
- T* operator->() const { return *this; } |
- T* get() const { return m_raw; } |
- |
- template<typename U> |
- PersistentBase& operator=(U* other) |
- { |
- assign(other); |
- return *this; |
- } |
- |
- PersistentBase& operator=(std::nullptr_t) |
- { |
- assign(nullptr); |
- return *this; |
- } |
- |
- PersistentBase& operator=(const PersistentBase& other) |
- { |
- assign(other); |
- return *this; |
- } |
- |
- template<typename U> |
- PersistentBase& operator=(const PersistentBase<U, weaknessConfiguration, crossThreadnessConfiguration>& other) |
- { |
- assign(other); |
- return *this; |
- } |
- |
- template<typename U> |
- PersistentBase& operator=(const Member<U>& other) |
- { |
- assign(other); |
- return *this; |
- } |
- |
- // Register the persistent node as a 'static reference', |
- // belonging to the current thread and a persistent that must |
- // be cleared when the ThreadState itself is cleared out and |
- // destructed. |
- // |
- // Static singletons arrange for this to happen, either to ensure |
- // clean LSan leak reports or to register a thread-local persistent |
- // needing to be cleared out before the thread is terminated. |
- PersistentBase* registerAsStaticReference() |
- { |
- if (m_persistentNode) { |
- ASSERT(ThreadState::current()); |
- ThreadState::current()->registerStaticPersistentNode(m_persistentNode, nullptr); |
- LEAK_SANITIZER_IGNORE_OBJECT(this); |
- } |
- return this; |
- } |
- |
-protected: |
- T* atomicGet() { return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<void* volatile*>(&m_raw))); } |
- |
-private: |
- NO_LAZY_SWEEP_SANITIZE_ADDRESS |
- void assign(T* ptr) |
- { |
- if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) |
- releaseStore(reinterpret_cast<void* volatile*>(&m_raw), ptr); |
- else |
- m_raw = ptr; |
- checkPointer(); |
- if (m_raw) { |
- if (!m_persistentNode) |
- initialize(); |
- return; |
- } |
- uninitialize(); |
- } |
- |
- NO_LAZY_SWEEP_SANITIZE_ADDRESS |
- void initialize() |
- { |
- ASSERT(!m_persistentNode); |
- if (!m_raw) |
- return; |
- |
- TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weaknessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessConfiguration, crossThreadnessConfiguration>::trace>::trampoline; |
- if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
- ProcessHeap::crossThreadPersistentRegion().allocatePersistentNode(m_persistentNode, this, traceCallback); |
- return; |
- } |
- ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
- ASSERT(state->checkThread()); |
- m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(this, traceCallback); |
-#if ENABLE(ASSERT) |
- m_state = state; |
-#endif |
- } |
- |
- void uninitialize() |
- { |
- if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
- if (acquireLoad(reinterpret_cast<void* volatile*>(&m_persistentNode))) |
- ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_persistentNode); |
- return; |
- } |
- |
- if (!m_persistentNode) |
- return; |
- ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
- ASSERT(state->checkThread()); |
- // Persistent handle must be created and destructed in the same thread. |
- ASSERT(m_state == state); |
- state->freePersistentNode(m_persistentNode); |
- m_persistentNode = nullptr; |
- } |
- |
- void checkPointer() |
- { |
-#if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
- if (!m_raw) |
- return; |
- |
- // ThreadHeap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable |
- // object. In other words, it checks that the pointer is either of: |
- // |
- // (a) a pointer to the head of an on-heap object. |
- // (b) a pointer to the head of an on-heap mixin object. |
- // |
- // Otherwise, ThreadHeap::isHeapObjectAlive will crash when it calls |
- // header->checkHeader(). |
- ThreadHeap::isHeapObjectAlive(m_raw); |
-#endif |
- } |
- |
- // m_raw is accessed most, so put it at the first field. |
- T* m_raw; |
- PersistentNode* m_persistentNode = nullptr; |
-#if ENABLE(ASSERT) |
- ThreadState* m_state = nullptr; |
-#endif |
-}; |
- |
-// Persistent is a way to create a strong pointer from an off-heap object |
-// to another on-heap object. As long as the Persistent handle is alive |
-// the GC will keep the object pointed to alive. The Persistent handle is |
-// always a GC root from the point of view of the GC. |
-// |
-// We have to construct and destruct Persistent in the same thread. |
-template<typename T> |
-class Persistent : public PersistentBase<T, NonWeakPersistentConfiguration, SingleThreadPersistentConfiguration> { |
- typedef PersistentBase<T, NonWeakPersistentConfiguration, SingleThreadPersistentConfiguration> Parent; |
-public: |
- Persistent() : Parent() { } |
- Persistent(std::nullptr_t) : Parent(nullptr) { } |
- Persistent(T* raw) : Parent(raw) { } |
- Persistent(T& raw) : Parent(raw) { } |
- Persistent(const Persistent& other) : Parent(other) { } |
- template<typename U> |
- Persistent(const Persistent<U>& other) : Parent(other) { } |
- template<typename U> |
- Persistent(const Member<U>& other) : Parent(other) { } |
- |
- template<typename U> |
- Persistent& operator=(U* other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- Persistent& operator=(std::nullptr_t) |
- { |
- Parent::operator=(nullptr); |
- return *this; |
- } |
- |
- Persistent& operator=(const Persistent& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- Persistent& operator=(const Persistent<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- Persistent& operator=(const Member<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
-}; |
- |
-// WeakPersistent is a way to create a weak pointer from an off-heap object |
-// to an on-heap object. The m_raw is automatically cleared when the pointee |
-// gets collected. |
-// |
-// We have to construct and destruct WeakPersistent in the same thread. |
-// |
-// Note that collections of WeakPersistents are not supported. Use a persistent |
-// collection of WeakMembers instead. |
-// |
-// HashSet<WeakPersistent<T>> m_set; // wrong |
-// PersistentHeapHashSet<WeakMember<T>> m_set; // correct |
-template<typename T> |
-class WeakPersistent : public PersistentBase<T, WeakPersistentConfiguration, SingleThreadPersistentConfiguration> { |
- typedef PersistentBase<T, WeakPersistentConfiguration, SingleThreadPersistentConfiguration> Parent; |
-public: |
- WeakPersistent() : Parent() { } |
- WeakPersistent(std::nullptr_t) : Parent(nullptr) { } |
- WeakPersistent(T* raw) : Parent(raw) { } |
- WeakPersistent(T& raw) : Parent(raw) { } |
- WeakPersistent(const WeakPersistent& other) : Parent(other) { } |
- template<typename U> |
- WeakPersistent(const WeakPersistent<U>& other) : Parent(other) { } |
- template<typename U> |
- WeakPersistent(const Member<U>& other) : Parent(other) { } |
- |
- template<typename U> |
- WeakPersistent& operator=(U* other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- WeakPersistent& operator=(std::nullptr_t) |
- { |
- Parent::operator=(nullptr); |
- return *this; |
- } |
- |
- WeakPersistent& operator=(const WeakPersistent& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- WeakPersistent& operator=(const WeakPersistent<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- WeakPersistent& operator=(const Member<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
-}; |
- |
-// Unlike Persistent, we can destruct a CrossThreadPersistent in a thread |
-// different from the construction thread. |
-template<typename T> |
-class CrossThreadPersistent : public PersistentBase<T, NonWeakPersistentConfiguration, CrossThreadPersistentConfiguration> { |
- typedef PersistentBase<T, NonWeakPersistentConfiguration, CrossThreadPersistentConfiguration> Parent; |
-public: |
- CrossThreadPersistent() : Parent() { } |
- CrossThreadPersistent(std::nullptr_t) : Parent(nullptr) { } |
- CrossThreadPersistent(T* raw) : Parent(raw) { } |
- CrossThreadPersistent(T& raw) : Parent(raw) { } |
- CrossThreadPersistent(const CrossThreadPersistent& other) : Parent(other) { } |
- template<typename U> |
- CrossThreadPersistent(const CrossThreadPersistent<U>& other) : Parent(other) { } |
- template<typename U> |
- CrossThreadPersistent(const Member<U>& other) : Parent(other) { } |
- |
- T* atomicGet() { return Parent::atomicGet(); } |
- |
- template<typename U> |
- CrossThreadPersistent& operator=(U* other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- CrossThreadPersistent& operator=(std::nullptr_t) |
- { |
- Parent::operator=(nullptr); |
- return *this; |
- } |
- |
- CrossThreadPersistent& operator=(const CrossThreadPersistent& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- CrossThreadPersistent& operator=(const CrossThreadPersistent<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- CrossThreadPersistent& operator=(const Member<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
-}; |
- |
-// Combines the behavior of CrossThreadPersistent and WeakPersistent. |
-template<typename T> |
-class CrossThreadWeakPersistent : public PersistentBase<T, WeakPersistentConfiguration, CrossThreadPersistentConfiguration> { |
- typedef PersistentBase<T, WeakPersistentConfiguration, CrossThreadPersistentConfiguration> Parent; |
-public: |
- CrossThreadWeakPersistent() : Parent() { } |
- CrossThreadWeakPersistent(std::nullptr_t) : Parent(nullptr) { } |
- CrossThreadWeakPersistent(T* raw) : Parent(raw) { } |
- CrossThreadWeakPersistent(T& raw) : Parent(raw) { } |
- CrossThreadWeakPersistent(const CrossThreadWeakPersistent& other) : Parent(other) { } |
- template<typename U> |
- CrossThreadWeakPersistent(const CrossThreadWeakPersistent<U>& other) : Parent(other) { } |
- template<typename U> |
- CrossThreadWeakPersistent(const Member<U>& other) : Parent(other) { } |
- |
- template<typename U> |
- CrossThreadWeakPersistent& operator=(U* other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- CrossThreadWeakPersistent& operator=(std::nullptr_t) |
- { |
- Parent::operator=(nullptr); |
- return *this; |
- } |
- |
- CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
- |
- template<typename U> |
- CrossThreadWeakPersistent& operator=(const Member<U>& other) |
- { |
- Parent::operator=(other); |
- return *this; |
- } |
-}; |
- |
-template<typename Collection> |
-class PersistentHeapCollectionBase : public Collection { |
- // We overload the various new and delete operators with using the WTF PartitionAllocator to ensure persistent |
- // heap collections are always allocated off-heap. This allows persistent collections to be used in |
- // DEFINE_STATIC_LOCAL et. al. |
- WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::PartitionAllocator); |
- IS_PERSISTENT_REFERENCE_TYPE(); |
-public: |
- PersistentHeapCollectionBase() |
- { |
- initialize(); |
- } |
- |
- PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Collection(other) |
- { |
- initialize(); |
- } |
- |
- template<typename OtherCollection> |
- PersistentHeapCollectionBase(const OtherCollection& other) : Collection(other) |
- { |
- initialize(); |
- } |
- |
- ~PersistentHeapCollectionBase() |
- { |
- uninitialize(); |
- } |
- |
- template<typename VisitorDispatcher> |
- void trace(VisitorDispatcher visitor) |
- { |
- static_assert(sizeof(Collection), "Collection must be fully defined"); |
- visitor->trace(*static_cast<Collection*>(this)); |
- } |
- |
- // See PersistentBase::registerAsStaticReference() comment. |
- PersistentHeapCollectionBase* registerAsStaticReference() |
- { |
- if (m_persistentNode) { |
- ASSERT(ThreadState::current()); |
- ThreadState::current()->registerStaticPersistentNode(m_persistentNode, &PersistentHeapCollectionBase<Collection>::clearPersistentNode); |
- LEAK_SANITIZER_IGNORE_OBJECT(this); |
- } |
- return this; |
- } |
- |
-private: |
- |
- // Used when the registered PersistentNode of this object is |
- // released during ThreadState shutdown, clearing the association. |
- static void clearPersistentNode(void *self) |
- { |
- PersistentHeapCollectionBase<Collection>* collection = (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self)); |
- collection->uninitialize(); |
- collection->clear(); |
- } |
- |
- NO_LAZY_SWEEP_SANITIZE_ADDRESS |
- void initialize() |
- { |
- // FIXME: Derive affinity based on the collection. |
- ThreadState* state = ThreadState::current(); |
- ASSERT(state->checkThread()); |
- m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(this, TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentHeapCollectionBase<Collection>::trace>::trampoline); |
-#if ENABLE(ASSERT) |
- m_state = state; |
-#endif |
- } |
- |
- void uninitialize() |
- { |
- if (!m_persistentNode) |
- return; |
- ThreadState* state = ThreadState::current(); |
- ASSERT(state->checkThread()); |
- // Persistent handle must be created and destructed in the same thread. |
- ASSERT(m_state == state); |
- state->freePersistentNode(m_persistentNode); |
- m_persistentNode = nullptr; |
- } |
- |
- PersistentNode* m_persistentNode; |
-#if ENABLE(ASSERT) |
- ThreadState* m_state; |
-#endif |
-}; |
- |
-template< |
- typename KeyArg, |
- typename MappedArg, |
- typename HashArg = typename DefaultHash<KeyArg>::Hash, |
- typename KeyTraitsArg = HashTraits<KeyArg>, |
- typename MappedTraitsArg = HashTraits<MappedArg>> |
-class PersistentHeapHashMap : public PersistentHeapCollectionBase<HeapHashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { }; |
- |
-template< |
- typename ValueArg, |
- typename HashArg = typename DefaultHash<ValueArg>::Hash, |
- typename TraitsArg = HashTraits<ValueArg>> |
-class PersistentHeapHashSet : public PersistentHeapCollectionBase<HeapHashSet<ValueArg, HashArg, TraitsArg>> { }; |
- |
-template< |
- typename ValueArg, |
- typename HashArg = typename DefaultHash<ValueArg>::Hash, |
- typename TraitsArg = HashTraits<ValueArg>> |
-class PersistentHeapLinkedHashSet : public PersistentHeapCollectionBase<HeapLinkedHashSet<ValueArg, HashArg, TraitsArg>> { }; |
- |
-template< |
- typename ValueArg, |
- size_t inlineCapacity = 0, |
- typename HashArg = typename DefaultHash<ValueArg>::Hash> |
-class PersistentHeapListHashSet : public PersistentHeapCollectionBase<HeapListHashSet<ValueArg, inlineCapacity, HashArg>> { }; |
- |
-template< |
- typename ValueArg, |
- typename HashFunctions = typename DefaultHash<ValueArg>::Hash, |
- typename Traits = HashTraits<ValueArg>> |
-class PersistentHeapHashCountedSet : public PersistentHeapCollectionBase<HeapHashCountedSet<ValueArg, HashFunctions, Traits>> { }; |
- |
-template<typename T, size_t inlineCapacity = 0> |
-class PersistentHeapVector : public PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>> { |
-public: |
- PersistentHeapVector() |
- { |
- initializeUnusedSlots(); |
- } |
- |
- explicit PersistentHeapVector(size_t size) |
- : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(size) |
- { |
- initializeUnusedSlots(); |
- } |
- |
- PersistentHeapVector(const PersistentHeapVector& other) |
- : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(other) |
- { |
- initializeUnusedSlots(); |
- } |
- |
- template<size_t otherCapacity> |
- PersistentHeapVector(const HeapVector<T, otherCapacity>& other) |
- : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(other) |
- { |
- initializeUnusedSlots(); |
- } |
- |
-private: |
- void initializeUnusedSlots() |
- { |
- // The PersistentHeapVector is allocated off heap along with its |
- // inline buffer (if any.) Maintain the invariant that unused |
- // slots are cleared for the off-heap inline buffer also. |
- size_t unusedSlots = this->capacity() - this->size(); |
- if (unusedSlots) |
- this->clearUnusedSlots(this->end(), this->end() + unusedSlots); |
- } |
-}; |
- |
-template<typename T, size_t inlineCapacity = 0> |
-class PersistentHeapDeque : public PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>> { |
-public: |
- PersistentHeapDeque() { } |
- |
- template<size_t otherCapacity> |
- PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other) |
- : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other) |
- { |
- } |
-}; |
- |
-// 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 { |
- DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
-public: |
- Member() : m_raw(nullptr) |
- { |
- } |
- |
- Member(std::nullptr_t) : m_raw(nullptr) |
- { |
- } |
- |
- Member(T* raw) : m_raw(raw) |
- { |
- checkPointer(); |
- } |
- |
- explicit Member(T& raw) : m_raw(&raw) |
- { |
- checkPointer(); |
- } |
- |
- 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) |
- { |
- checkPointer(); |
- } |
- |
- Member(const Member& other) : m_raw(other) |
- { |
- checkPointer(); |
- } |
- |
- template<typename U> |
- Member(const Member<U>& other) : m_raw(other) |
- { |
- checkPointer(); |
- } |
- |
- T* release() |
- { |
- T* result = m_raw; |
- m_raw = nullptr; |
- return result; |
- } |
- |
- explicit operator bool() 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> |
- Member& operator=(const Persistent<U>& other) |
- { |
- m_raw = other; |
- checkPointer(); |
- return *this; |
- } |
- |
- template<typename U> |
- Member& operator=(const Member<U>& other) |
- { |
- m_raw = other; |
- checkPointer(); |
- return *this; |
- } |
- |
- template<typename U> |
- Member& operator=(U* other) |
- { |
- m_raw = other; |
- checkPointer(); |
- return *this; |
- } |
- |
- Member& operator=(std::nullptr_t) |
- { |
- m_raw = nullptr; |
- return *this; |
- } |
- |
- void swap(Member<T>& other) |
- { |
- std::swap(m_raw, other.m_raw); |
- checkPointer(); |
- } |
- |
- T* get() const { return m_raw; } |
- |
- void clear() { m_raw = nullptr; } |
- |
- |
-protected: |
- void checkPointer() |
- { |
-#if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
- if (!m_raw) |
- return; |
- // HashTable can store a special value (which is not aligned to the |
- // allocation granularity) to Member<> to represent a deleted entry. |
- // Thus we treat a pointer that is not aligned to the granularity |
- // as a valid pointer. |
- if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) |
- return; |
- |
- // TODO(haraken): What we really want to check here is that the pointer |
- // is a traceable object. In other words, the pointer is either of: |
- // |
- // (a) a pointer to the head of an on-heap object. |
- // (b) a pointer to the head of an on-heap mixin object. |
- // |
- // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), |
- // but we cannot call it here because it requires to include T.h. |
- // So we currently only try to implement the check for (a), but do |
- // not insist that T's definition is in scope. |
- if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) |
- ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); |
-#endif |
- } |
- |
- T* m_raw; |
- |
- template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStrongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
- friend class Visitor; |
- |
-}; |
- |
-// 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> { |
-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; |
- this->checkPointer(); |
- return *this; |
- } |
- |
- template<typename U> |
- WeakMember& operator=(const Member<U>& other) |
- { |
- this->m_raw = other; |
- this->checkPointer(); |
- return *this; |
- } |
- |
- template<typename U> |
- WeakMember& operator=(U* other) |
- { |
- this->m_raw = other; |
- this->checkPointer(); |
- return *this; |
- } |
- |
- WeakMember& operator=(std::nullptr_t) |
- { |
- this->m_raw = nullptr; |
- return *this; |
- } |
- |
-private: |
- T** cell() const { return const_cast<T**>(&this->m_raw); } |
- |
- template<typename Derived> friend class VisitorHelper; |
-}; |
- |
-// UntracedMember is a pointer to an on-heap object that is not traced for some |
-// reason. Please don't use this unless you understand what you're doing. |
-// Basically, all pointers to on-heap objects must be stored in either of |
-// Persistent, Member or WeakMember. It is not allowed to leave raw pointers to |
-// on-heap objects. However, there can be scenarios where you have to use raw |
-// pointers for some reason, and in that case you can use UntracedMember. Of |
-// course, it must be guaranteed that the pointing on-heap object is kept alive |
-// while the raw pointer is pointing to the object. |
-template<typename T> |
-class UntracedMember final : public Member<T> { |
-public: |
- UntracedMember() : Member<T>() { } |
- |
- UntracedMember(std::nullptr_t) : Member<T>(nullptr) { } |
- |
- UntracedMember(T* raw) : Member<T>(raw) { } |
- |
- template<typename U> |
- UntracedMember(const Persistent<U>& other) : Member<T>(other) { } |
- |
- template<typename U> |
- UntracedMember(const Member<U>& other) : Member<T>(other) { } |
- |
- UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } |
- |
- template<typename U> |
- UntracedMember& operator=(const Persistent<U>& other) |
- { |
- this->m_raw = other; |
- this->checkPointer(); |
- return *this; |
- } |
- |
- template<typename U> |
- UntracedMember& operator=(const Member<U>& other) |
- { |
- this->m_raw = other; |
- this->checkPointer(); |
- return *this; |
- } |
- |
- template<typename U> |
- UntracedMember& operator=(U* other) |
- { |
- this->m_raw = other; |
- this->checkPointer(); |
- return *this; |
- } |
- |
- UntracedMember& operator=(std::nullptr_t) |
- { |
- this->m_raw = nullptr; |
- return *this; |
- } |
-}; |
- |
-// Comparison operators between (Weak)Members, Persistents, and UntracedMembers. |
-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 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 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, bool = IsGarbageCollectedType<T>::value> |
-class RawPtrOrMemberTrait { |
- STATIC_ONLY(RawPtrOrMemberTrait) |
-public: |
- using Type = T*; |
-}; |
- |
-template<typename T> |
-class RawPtrOrMemberTrait<T, true> { |
- STATIC_ONLY(RawPtrOrMemberTrait) |
-public: |
- using Type = Member<T>; |
-}; |
- |
-// Abstraction for injecting calls to an object's 'dispose()' method |
-// on leaving a stack scope, ensuring earlier release of resources |
-// than waiting until the object is eventually GCed. |
-template<typename T, void (T::*Disposer)() = (&T::dispose)> |
-class ScopedDisposal { |
- STACK_ALLOCATED(); |
-public: |
- ScopedDisposal(T* object) |
- : m_object(object) |
- { |
- } |
- |
- ~ScopedDisposal() |
- { |
- if (m_object) |
- (m_object->*Disposer)(); |
- } |
- |
- void clear() { m_object.clear(); } |
- |
-private: |
- typename RawPtrOrMemberTrait<T>::Type m_object; |
-}; |
- |
-// SelfKeepAlive<Object> is the idiom to use for objects that have to keep |
-// themselves temporarily alive and cannot rely on there being some |
-// external reference in that interval: |
-// |
-// class Opener { |
-// public: |
-// ... |
-// void open() |
-// { |
-// // Retain a self-reference while in an open()ed state: |
-// m_keepAlive = this; |
-// .... |
-// } |
-// |
-// void close() |
-// { |
-// // Clear self-reference that ensured we were kept alive while opened. |
-// m_keepAlive.clear(); |
-// .... |
-// } |
-// |
-// private: |
-// ... |
-// SelfKeepAlive m_keepAlive; |
-// }; |
-// |
-// The responsibility to call clear() in a timely fashion resides with the implementation |
-// of the object. |
-// |
-// |
-template<typename Self> |
-class SelfKeepAlive final { |
- DISALLOW_NEW(); |
-public: |
- SelfKeepAlive() |
- { |
- } |
- |
- explicit SelfKeepAlive(Self* self) |
- { |
- assign(self); |
- } |
- |
- SelfKeepAlive& operator=(Self* self) |
- { |
- assign(self); |
- return *this; |
- } |
- |
- void clear() |
- { |
- m_keepAlive.clear(); |
- } |
- |
- typedef Persistent<Self> (SelfKeepAlive::*UnspecifiedBoolType); |
- operator UnspecifiedBoolType() const { return m_keepAlive ? &SelfKeepAlive::m_keepAlive : 0; } |
- |
-private: |
- void assign(Self* self) |
- { |
- ASSERT(!m_keepAlive || m_keepAlive.get() == self); |
- m_keepAlive = self; |
- } |
- |
- GC_PLUGIN_IGNORE("420515") |
- Persistent<Self> m_keepAlive; |
-}; |
- |
-// Only a very reduced form of weak heap object references can currently be held |
-// by WTF::Closure<>s. i.e., bound as a 'this' pointer only. |
-// |
-// TODO(sof): once wtf/Functional.h is able to work over platform/heap/ types |
-// (like CrossThreadWeakPersistent<>), drop the restriction on weak persistent |
-// use by function closures (and rename this ad-hoc type.) |
-template<typename T> |
-class WeakPersistentThisPointer { |
- STACK_ALLOCATED(); |
-public: |
- explicit WeakPersistentThisPointer(T* value) : m_value(value) { } |
- WeakPersistent<T> value() const { return m_value; } |
-private: |
- WeakPersistent<T> m_value; |
-}; |
- |
-template<typename T> |
-class CrossThreadWeakPersistentThisPointer { |
- STACK_ALLOCATED(); |
-public: |
- explicit CrossThreadWeakPersistentThisPointer(T* value) : m_value(value) { } |
- CrossThreadWeakPersistent<T> value() const { return m_value; } |
-private: |
- CrossThreadWeakPersistent<T> m_value; |
-}; |
- |
-template <typename T> |
-Persistent<T> wrapPersistent(T* value) |
-{ |
- return Persistent<T>(value); |
-} |
- |
-template <typename T> |
-CrossThreadPersistent<T> wrapCrossThreadPersistent(T* value) |
-{ |
- return CrossThreadPersistent<T>(value); |
-} |
- |
// LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the current scope |
// will be exempted from LSan consideration. |
// |
@@ -1106,90 +78,4 @@ public: |
} // namespace blink |
-namespace WTF { |
- |
-template <typename T> |
-struct MemberHash : PtrHash<T> { |
- STATIC_ONLY(MemberHash); |
- template <typename U> |
- static unsigned hash(const U& key) { return PtrHash<T>::hash(key); } |
- template <typename U, typename V> |
- static bool equal(const U& a, const V& b) { return a == b; } |
-}; |
- |
-template <typename T> |
-struct WeakMemberHash : MemberHash<T> { |
- STATIC_ONLY(WeakMemberHash); |
-}; |
- |
-template <typename T> |
-struct UntracedMemberHash : MemberHash<T> { |
- STATIC_ONLY(UntracedMemberHash); |
-}; |
- |
-// PtrHash is the default hash for hash tables with members. |
-template <typename T> |
-struct DefaultHash<blink::Member<T>> { |
- STATIC_ONLY(DefaultHash); |
- using Hash = MemberHash<T>; |
-}; |
- |
-template <typename T> |
-struct DefaultHash<blink::WeakMember<T>> { |
- STATIC_ONLY(DefaultHash); |
- using Hash = WeakMemberHash<T>; |
-}; |
- |
-template <typename T> |
-struct DefaultHash<blink::UntracedMember<T>> { |
- STATIC_ONLY(DefaultHash); |
- using Hash = UntracedMemberHash<T>; |
-}; |
- |
-template<typename T> |
-struct NeedsTracing<blink::Member<T>> { |
- STATIC_ONLY(NeedsTracing); |
- static const bool value = true; |
-}; |
- |
-template<typename T> |
-struct IsWeak<blink::WeakMember<T>> { |
- STATIC_ONLY(IsWeak); |
- static const bool value = true; |
-}; |
- |
-template<typename T> |
-struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> { |
- STATIC_ONLY(ParamStorageTraits); |
- static_assert(sizeof(T), "T must be fully defined"); |
- using StorageType = blink::WeakPersistent<T>; |
- |
- static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) { return value.value(); } |
- |
- // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent |
- // into it. |
- // |
- // TODO(sof): remove this hack once wtf/Functional.h can also work with a type like |
- // WeakPersistent<>. |
- static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakReference<T>::create(value.get())); } |
-}; |
- |
-template<typename T> |
-struct ParamStorageTraits<blink::CrossThreadWeakPersistentThisPointer<T>> { |
- STATIC_ONLY(ParamStorageTraits); |
- static_assert(sizeof(T), "T must be fully defined"); |
- using StorageType = blink::CrossThreadWeakPersistent<T>; |
- |
- static StorageType wrap(const blink::CrossThreadWeakPersistentThisPointer<T>& value) { return value.value(); } |
- |
- // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent |
- // into it. |
- // |
- // TODO(sof): remove this hack once wtf/Functional.h can also work with a type like |
- // CrossThreadWeakPersistent<>. |
- static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakReference<T>::create(value.get())); } |
-}; |
- |
-} // namespace WTF |
- |
#endif |