| 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
|
|
|