OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef Persistent_h | 5 #ifndef Persistent_h |
6 #define Persistent_h | 6 #define Persistent_h |
7 | 7 |
8 #include "platform/heap/Member.h" | 8 #include "platform/heap/Member.h" |
9 #include "platform/heap/PersistentNode.h" | 9 #include "platform/heap/PersistentNode.h" |
10 #include "wtf/Allocator.h" | 10 #include "wtf/Allocator.h" |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
70 checkPointer(); | 70 checkPointer(); |
71 } | 71 } |
72 | 72 |
73 template<typename U> | 73 template<typename U> |
74 PersistentBase(const Member<U>& other) : m_raw(other) | 74 PersistentBase(const Member<U>& other) : m_raw(other) |
75 { | 75 { |
76 initialize(); | 76 initialize(); |
77 checkPointer(); | 77 checkPointer(); |
78 } | 78 } |
79 | 79 |
| 80 PersistentBase(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(
-1)) |
| 81 { |
| 82 initialize(); |
| 83 checkPointer(); |
| 84 } |
| 85 |
80 ~PersistentBase() | 86 ~PersistentBase() |
81 { | 87 { |
82 uninitialize(); | 88 uninitialize(); |
83 m_raw = nullptr; | 89 m_raw = nullptr; |
84 } | 90 } |
85 | 91 |
| 92 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(
-1); } |
| 93 |
86 template<typename VisitorDispatcher> | 94 template<typename VisitorDispatcher> |
87 void trace(VisitorDispatcher visitor) | 95 void trace(VisitorDispatcher visitor) |
88 { | 96 { |
89 static_assert(sizeof(T), "T must be fully defined"); | 97 static_assert(sizeof(T), "T must be fully defined"); |
90 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); | 98 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); |
91 if (weaknessConfiguration == WeakPersistentConfiguration) { | 99 if (weaknessConfiguration == WeakPersistentConfiguration) { |
92 visitor->registerWeakCell(&m_raw); | 100 visitor->registerWeakCell(&m_raw); |
93 } else { | 101 } else { |
94 visitor->mark(m_raw); | 102 visitor->mark(m_raw); |
95 } | 103 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 initialize(); | 185 initialize(); |
178 return; | 186 return; |
179 } | 187 } |
180 uninitialize(); | 188 uninitialize(); |
181 } | 189 } |
182 | 190 |
183 NO_LAZY_SWEEP_SANITIZE_ADDRESS | 191 NO_LAZY_SWEEP_SANITIZE_ADDRESS |
184 void initialize() | 192 void initialize() |
185 { | 193 { |
186 ASSERT(!m_persistentNode); | 194 ASSERT(!m_persistentNode); |
187 if (!m_raw) | 195 if (!m_raw || isHashTableDeletedValue()) |
188 return; | 196 return; |
189 | 197 |
190 TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weak
nessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessCon
figuration, crossThreadnessConfiguration>::trace>::trampoline; | 198 TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weak
nessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessCon
figuration, crossThreadnessConfiguration>::trace>::trampoline; |
191 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ | 199 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ |
192 ProcessHeap::crossThreadPersistentRegion().allocatePersistentNode(m_
persistentNode, this, traceCallback); | 200 ProcessHeap::crossThreadPersistentRegion().allocatePersistentNode(m_
persistentNode, this, traceCallback); |
193 return; | 201 return; |
194 } | 202 } |
195 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | 203 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); |
196 ASSERT(state->checkThread()); | 204 ASSERT(state->checkThread()); |
197 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(
this, traceCallback); | 205 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(
this, traceCallback); |
198 #if ENABLE(ASSERT) | 206 #if ENABLE(ASSERT) |
199 m_state = state; | 207 m_state = state; |
200 #endif | 208 #endif |
201 } | 209 } |
202 | 210 |
203 void uninitialize() | 211 void uninitialize() |
204 { | 212 { |
| 213 if (!m_persistentNode) |
| 214 return; |
| 215 |
205 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ | 216 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ |
206 if (acquireLoad(reinterpret_cast<void* volatile*>(&m_persistentNode)
)) | 217 if (acquireLoad(reinterpret_cast<void* volatile*>(&m_persistentNode)
)) |
207 ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_
persistentNode); | 218 ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_
persistentNode); |
208 return; | 219 return; |
209 } | 220 } |
210 | 221 |
211 if (!m_persistentNode) | |
212 return; | |
213 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | 222 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); |
214 ASSERT(state->checkThread()); | 223 ASSERT(state->checkThread()); |
215 // Persistent handle must be created and destructed in the same thread. | 224 // Persistent handle must be created and destructed in the same thread. |
216 ASSERT(m_state == state); | 225 ASSERT(m_state == state); |
217 state->freePersistentNode(m_persistentNode); | 226 state->freePersistentNode(m_persistentNode); |
218 m_persistentNode = nullptr; | 227 m_persistentNode = nullptr; |
219 } | 228 } |
220 | 229 |
221 void checkPointer() | 230 void checkPointer() |
222 { | 231 { |
223 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | 232 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) |
224 if (!m_raw) | 233 if (!m_raw || isHashTableDeletedValue()) |
225 return; | 234 return; |
226 | 235 |
227 // ThreadHeap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | 236 // ThreadHeap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable |
228 // object. In other words, it checks that the pointer is either of: | 237 // object. In other words, it checks that the pointer is either of: |
229 // | 238 // |
230 // (a) a pointer to the head of an on-heap object. | 239 // (a) a pointer to the head of an on-heap object. |
231 // (b) a pointer to the head of an on-heap mixin object. | 240 // (b) a pointer to the head of an on-heap mixin object. |
232 // | 241 // |
233 // Otherwise, ThreadHeap::isHeapObjectAlive will crash when it calls | 242 // Otherwise, ThreadHeap::isHeapObjectAlive will crash when it calls |
234 // header->checkHeader(). | 243 // header->checkHeader(). |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 public: | 374 public: |
366 CrossThreadPersistent() : Parent() { } | 375 CrossThreadPersistent() : Parent() { } |
367 CrossThreadPersistent(std::nullptr_t) : Parent(nullptr) { } | 376 CrossThreadPersistent(std::nullptr_t) : Parent(nullptr) { } |
368 CrossThreadPersistent(T* raw) : Parent(raw) { } | 377 CrossThreadPersistent(T* raw) : Parent(raw) { } |
369 CrossThreadPersistent(T& raw) : Parent(raw) { } | 378 CrossThreadPersistent(T& raw) : Parent(raw) { } |
370 CrossThreadPersistent(const CrossThreadPersistent& other) : Parent(other) {
} | 379 CrossThreadPersistent(const CrossThreadPersistent& other) : Parent(other) {
} |
371 template<typename U> | 380 template<typename U> |
372 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : Parent(other)
{ } | 381 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : Parent(other)
{ } |
373 template<typename U> | 382 template<typename U> |
374 CrossThreadPersistent(const Member<U>& other) : Parent(other) { } | 383 CrossThreadPersistent(const Member<U>& other) : Parent(other) { } |
| 384 CrossThreadPersistent(WTF::HashTableDeletedValueType x) : Parent(x) { } |
375 | 385 |
376 T* atomicGet() { return Parent::atomicGet(); } | 386 T* atomicGet() { return Parent::atomicGet(); } |
377 | 387 |
378 template<typename U> | 388 template<typename U> |
379 CrossThreadPersistent& operator=(U* other) | 389 CrossThreadPersistent& operator=(U* other) |
380 { | 390 { |
381 Parent::operator=(other); | 391 Parent::operator=(other); |
382 return *this; | 392 return *this; |
383 } | 393 } |
384 | 394 |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
675 | 685 |
676 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } | 686 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } |
677 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } | 687 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } |
678 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } | 688 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } |
679 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } | 689 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } |
680 | 690 |
681 } // namespace blink | 691 } // namespace blink |
682 | 692 |
683 namespace WTF { | 693 namespace WTF { |
684 | 694 |
| 695 template <typename T> |
| 696 struct CrossThreadPersistentHash : MemberHash<T> { |
| 697 STATIC_ONLY(CrossThreadPersistentHash); |
| 698 }; |
| 699 |
| 700 template <typename T> |
| 701 struct DefaultHash<blink::CrossThreadPersistent<T>> { |
| 702 STATIC_ONLY(DefaultHash); |
| 703 using Hash = CrossThreadPersistentHash<T>; |
| 704 }; |
| 705 |
685 template<typename T> | 706 template<typename T> |
686 struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> { | 707 struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> { |
687 STATIC_ONLY(ParamStorageTraits); | 708 STATIC_ONLY(ParamStorageTraits); |
688 static_assert(sizeof(T), "T must be fully defined"); | 709 static_assert(sizeof(T), "T must be fully defined"); |
689 using StorageType = blink::WeakPersistent<T>; | 710 using StorageType = blink::WeakPersistent<T>; |
690 | 711 |
691 static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) {
return value.value(); } | 712 static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) {
return value.value(); } |
692 | 713 |
693 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent | 714 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent |
694 // into it. | 715 // into it. |
(...skipping 15 matching lines...) Expand all Loading... |
710 // into it. | 731 // into it. |
711 // | 732 // |
712 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty
pe like | 733 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty
pe like |
713 // CrossThreadWeakPersistent<>. | 734 // CrossThreadWeakPersistent<>. |
714 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR
eference<T>::create(value.get())); } | 735 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR
eference<T>::create(value.get())); } |
715 }; | 736 }; |
716 | 737 |
717 } // namespace WTF | 738 } // namespace WTF |
718 | 739 |
719 #endif // Persistent_h | 740 #endif // Persistent_h |
OLD | NEW |