Chromium Code Reviews| 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 a585ac832b03ae1955c647e43186b9f5f395c363..eea7f773333979c8cca67292310bc8a428277912 100644 |
| --- a/third_party/WebKit/Source/platform/heap/Handle.h |
| +++ b/third_party/WebKit/Source/platform/heap/Handle.h |
| @@ -59,7 +59,8 @@ enum WeaknessPersistentConfiguration { |
| enum CrossThreadnessPersistentConfiguration { |
| SingleThreadPersistentConfiguration, |
| - CrossThreadPersistentConfiguration |
| + CrossThreadPersistentConfiguration, |
| + XThreadPersistentConfiguration |
| }; |
| template<typename T, WeaknessPersistentConfiguration weaknessConfiguration, CrossThreadnessPersistentConfiguration crossThreadnessConfiguration> |
| @@ -203,6 +204,10 @@ private: |
| NO_LAZY_SWEEP_SANITIZE_ADDRESS |
| void assign(T* ptr) |
| { |
| + if (crossThreadnessConfiguration == XThreadPersistentConfiguration |
| + && ThreadState::forObject(m_raw) != ThreadState::forObject(ptr)) { |
| + uninitialize(); |
| + } |
| m_raw = ptr; |
| checkPointer(); |
| if (m_raw) { |
| @@ -218,11 +223,15 @@ private: |
| void initialize() |
| { |
| ASSERT(!m_persistentNode); |
| - if (!m_raw) |
| + if (!m_raw || m_raw == reinterpret_cast<T*>(-1)) |
| return; |
| TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weaknessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessConfiguration, crossThreadnessConfiguration>::trace>::trampoline; |
| - if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
| + if (crossThreadnessConfiguration == XThreadPersistentConfiguration) { |
| + BasePage* page = pageFromObject(m_raw); |
| + ASSERT(page); |
| + m_persistentNode = page->heap()->threadState()->xThreadPersistentRegion()->allocatePersistentNode(this, traceCallback); |
| + } else if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
| m_persistentNode = ThreadState::crossThreadPersistentRegion().allocatePersistentNode(this, traceCallback); |
| } else { |
| ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
| @@ -239,7 +248,13 @@ private: |
| if (!m_persistentNode) |
| return; |
| - if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
| + if (crossThreadnessConfiguration == XThreadPersistentConfiguration) { |
| + ASSERT(m_raw); |
| + ASSERT(m_raw != reinterpret_cast<T*>(-1)); |
| + BasePage* page = pageFromObject(m_raw); |
| + ASSERT(page); |
| + page->heap()->threadState()->xThreadPersistentRegion()->freePersistentNode(m_persistentNode); |
| + } else if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
| ThreadState::crossThreadPersistentRegion().freePersistentNode(m_persistentNode); |
| } else { |
| ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(); |
| @@ -253,6 +268,10 @@ private: |
| void checkPointer() |
| { |
| + if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { |
| + ThreadState* threadState = ThreadState::forObject(m_raw); |
| + ASSERT(!threadState || !threadState->perThreadHeapEnabled()); |
| + } |
| #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
| if (!m_raw) |
| return; |
| @@ -525,6 +544,69 @@ public: |
| } |
| }; |
| +template<typename T> |
| +class XThreadPersistent : public PersistentBase<T, NonWeakPersistentConfiguration, XThreadPersistentConfiguration> { |
|
haraken
2016/01/07 08:06:22
I'm considering a way to land the per-thread heap
|
| + typedef PersistentBase<T, NonWeakPersistentConfiguration, XThreadPersistentConfiguration> Parent; |
| +public: |
| + XThreadPersistent() : Parent() { } |
| + XThreadPersistent(std::nullptr_t) : Parent(nullptr) { } |
| + XThreadPersistent(T* raw) : Parent(raw) { } |
| + XThreadPersistent(T& raw) : Parent(raw) { } |
| + XThreadPersistent(const XThreadPersistent& other) : Parent(other) { } |
| + template<typename U> |
| + XThreadPersistent(const XThreadPersistent<U>& other) : Parent(other) { } |
| + template<typename U> |
| + XThreadPersistent(const Member<U>& other) : Parent(other) { } |
| + template<typename U> |
| + XThreadPersistent(const RawPtr<U>& other) : Parent(other.get()) { } |
| + |
| + template<typename U> |
| + XThreadPersistent& operator=(U* other) |
| + { |
| + Parent::operator=(other); |
| + return *this; |
| + } |
| + |
| + XThreadPersistent& operator=(std::nullptr_t) |
| + { |
| + Parent::operator=(nullptr); |
| + return *this; |
| + } |
| + |
| + XThreadPersistent& operator=(const XThreadPersistent& other) |
| + { |
| + Parent::operator=(other); |
| + return *this; |
| + } |
| + |
| + template<typename U> |
| + XThreadPersistent& operator=(const XThreadPersistent<U>& other) |
| + { |
| + Parent::operator=(other); |
| + return *this; |
| + } |
| + |
| + template<typename U> |
| + XThreadPersistent& operator=(const Member<U>& other) |
| + { |
| + Parent::operator=(other); |
| + return *this; |
| + } |
| + |
| + template<typename U> |
| + XThreadPersistent& operator=(const RawPtr<U>& other) |
| + { |
| + Parent::operator=(other); |
| + return *this; |
| + } |
| + |
| + explicit XThreadPersistent(WTF::HashTableDeletedValueType) : Parent(reinterpret_cast<T*>(-1)) |
| + { |
| + } |
| + |
| + bool isHashTableDeletedValue() const { return *this == reinterpret_cast<T*>(-1); } |
| +}; |
| + |
| template<typename Collection> |
| class PersistentHeapCollectionBase : public Collection { |
| // We overload the various new and delete operators with using the WTF PartitionAllocator to ensure persistent |
| @@ -1030,12 +1112,15 @@ class PLATFORM_EXPORT DummyBase<void> { }; |
| #define RefPtrWillBeWeakMember blink::WeakMember |
| #define RefPtrWillBeWeakPersistent blink::WeakPersistent |
| #define RefPtrWillBeCrossThreadPersistent blink::CrossThreadPersistent |
| +#define RefPtrWillBeXThreadPersistent blink::XThreadPersistent |
| #define RawPtrWillBeMember blink::Member |
| #define RawPtrWillBePersistent blink::Persistent |
| +#define RawPtrWillBeXThreadPersistent blink::XThreadPersistent |
| #define RawPtrWillBeWeakMember blink::WeakMember |
| #define RawPtrWillBeWeakPersistent blink::WeakPersistent |
| #define RawPtrWillBeUntracedMember blink::UntracedMember |
| #define OwnPtrWillBeCrossThreadPersistent blink::CrossThreadPersistent |
| +#define OwnPtrWillBeXThreadPersistent blink::XThreadPersistent |
| #define OwnPtrWillBeMember blink::Member |
| #define OwnPtrWillBePersistent blink::Persistent |
| #define OwnPtrWillBeRawPtr WTF::RawPtr |
| @@ -1121,12 +1206,15 @@ template<typename T> T* adoptPtrWillBeNoop(T* ptr) |
| #define RefPtrWillBeWeakMember WTF::RefPtr |
| #define RefPtrWillBeWeakPersistent WTF::RefPtr |
| #define RefPtrWillBeCrossThreadPersistent WTF::RefPtr |
| +#define RefPtrWillBeXThreadPersistent WTF::RefPtr |
| #define RawPtrWillBeMember WTF::RawPtr |
| #define RawPtrWillBePersistent WTF::RawPtr |
| +#define RawPtrWillBeXThreadPersistent WTF::RawPtr |
| #define RawPtrWillBeWeakMember WTF::RawPtr |
| #define RawPtrWillBeWeakPersistent WTF::RawPtr |
| #define RawPtrWillBeUntracedMember WTF::RawPtr |
| #define OwnPtrWillBeCrossThreadPersistent WTF::OwnPtr |
| +#define OwnPtrWillBeXThreadPersistent WTF::OwnPtr |
| #define OwnPtrWillBeMember WTF::OwnPtr |
| #define OwnPtrWillBePersistent WTF::OwnPtr |
| #define OwnPtrWillBeRawPtr WTF::OwnPtr |
| @@ -1542,7 +1630,7 @@ struct PointerParamStorageTraits<T*, false> { |
| template<typename T> |
| struct PointerParamStorageTraits<T*, true> { |
| static_assert(sizeof(T), "T must be fully defined"); |
| - using StorageType = blink::CrossThreadPersistent<T>; |
| + using StorageType = blink::XThreadPersistent<T>; |
| static StorageType wrap(T* value) { return value; } |
| static T* unwrap(const StorageType& value) { return value.get(); } |
| @@ -1573,6 +1661,43 @@ struct ParamStorageTraits<blink::AllowCrossThreadWeakPersistent<T>> { |
| template<typename T> |
| PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; |
| +template<typename T> struct HashTraits<blink::XThreadPersistent<T>> : SimpleClassHashTraits<blink::XThreadPersistent<T>> { |
| + static const bool emptyValueIsZero = false; // Persistent's constructor needs to be called properly. |
| + |
| + // 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. |
| + using PeekInType = const blink::XThreadPersistent<T>&; |
| + using PassInType = const blink::XThreadPersistent<T>&; |
| + using IteratorGetType = blink::XThreadPersistent<T>*; |
| + using IteratorConstGetType = const blink::XThreadPersistent<T>*; |
| + using IteratorReferenceType = blink::XThreadPersistent<T>&; |
| + using IteratorConstReferenceType = const blink::XThreadPersistent<T>&; |
| + static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; } |
| + static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return *x; } |
| + // FIXME: Similarly, there is no need for a distinction between PeekOutType |
| + // and PassOutType without reference counting. |
| + using PeekOutType = T*; |
| + using PassOutType = T*; |
| + |
| + template<typename U> |
| + static void store(const U& value, blink::Persistent<T>& storage) { storage = value; } |
| + |
| + static PeekOutType peek(const blink::XThreadPersistent<T>& value) { return value; } |
| + static PassOutType passOut(const blink::XThreadPersistent<T>& value) { return value; } |
| +}; |
| + |
| +template<typename T> struct PtrHash<blink::XThreadPersistent<T>> : PtrHash<T*> { |
| + static unsigned hash(const blink::XThreadPersistent<T>& key) { return PtrHash<T*>::hash(key.get()); } |
| + static bool equal(const blink::XThreadPersistent<T>& a, const blink::XThreadPersistent<T>& b) { return a == b; } |
| +}; |
| + |
| +template<typename T> struct DefaultHash<blink::XThreadPersistent<T>> { |
| + using Hash = PtrHash<blink::XThreadPersistent<T>>; |
| +}; |
| + |
| } // namespace WTF |
| #endif |