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/Heap.h" | 8 #include "platform/heap/Heap.h" |
9 #include "platform/heap/Member.h" | 9 #include "platform/heap/Member.h" |
10 #include "platform/heap/PersistentNode.h" | 10 #include "platform/heap/PersistentNode.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 enum WeaknessPersistentConfiguration { | 26 enum WeaknessPersistentConfiguration { |
27 NonWeakPersistentConfiguration, | 27 NonWeakPersistentConfiguration, |
28 WeakPersistentConfiguration | 28 WeakPersistentConfiguration |
29 }; | 29 }; |
30 | 30 |
31 enum CrossThreadnessPersistentConfiguration { | 31 enum CrossThreadnessPersistentConfiguration { |
32 SingleThreadPersistentConfiguration, | 32 SingleThreadPersistentConfiguration, |
33 CrossThreadPersistentConfiguration | 33 CrossThreadPersistentConfiguration |
34 }; | 34 }; |
35 | 35 |
| 36 // Auxillary template, probing if |void T::clear()| exists and is accessible. |
| 37 // Used to conditionally clear the contents of a static persistent. |
| 38 template <typename T> |
| 39 class CanClearPersistentReference { |
| 40 typedef char YesType; |
| 41 typedef struct NoType { char padding[8]; } NoType; |
| 42 |
| 43 // Check if class T has public method "void clear()". |
| 44 template <typename V> |
| 45 static YesType checkHasClearMethod( |
| 46 V* p, |
| 47 typename std::enable_if< |
| 48 std::is_same<decltype(p->clear()), void>::value>::type* = nullptr); |
| 49 template <typename V> |
| 50 static NoType checkHasClearMethod(...); |
| 51 |
| 52 public: |
| 53 static const bool value = |
| 54 sizeof(YesType) + sizeof(T) == |
| 55 sizeof(checkHasClearMethod<T>(nullptr)) + sizeof(T); |
| 56 }; |
| 57 |
| 58 template <typename T, bool = CanClearPersistentReference<T>::value> |
| 59 class ClearStaticPersistentReference { |
| 60 public: |
| 61 static void clear(T*) {} |
| 62 }; |
| 63 |
| 64 template <typename T> |
| 65 class ClearStaticPersistentReference<T, true> { |
| 66 public: |
| 67 static void clear(T* ptr) { ptr->clear(); } |
| 68 }; |
| 69 |
36 template <typename T, | 70 template <typename T, |
37 WeaknessPersistentConfiguration weaknessConfiguration, | 71 WeaknessPersistentConfiguration weaknessConfiguration, |
38 CrossThreadnessPersistentConfiguration crossThreadnessConfiguration> | 72 CrossThreadnessPersistentConfiguration crossThreadnessConfiguration> |
39 class PersistentBase { | 73 class PersistentBase { |
40 USING_FAST_MALLOC(PersistentBase); | 74 USING_FAST_MALLOC(PersistentBase); |
41 IS_PERSISTENT_REFERENCE_TYPE(); | 75 IS_PERSISTENT_REFERENCE_TYPE(); |
42 | 76 |
43 public: | 77 public: |
44 PersistentBase() : m_raw(nullptr) { | 78 PersistentBase() : m_raw(nullptr) { |
45 saveCreationThreadHeap(); | 79 saveCreationThreadHeap(); |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 // belonging to the current thread and a persistent that must | 184 // belonging to the current thread and a persistent that must |
151 // be cleared when the ThreadState itself is cleared out and | 185 // be cleared when the ThreadState itself is cleared out and |
152 // destructed. | 186 // destructed. |
153 // | 187 // |
154 // Static singletons arrange for this to happen, either to ensure | 188 // Static singletons arrange for this to happen, either to ensure |
155 // clean LSan leak reports or to register a thread-local persistent | 189 // clean LSan leak reports or to register a thread-local persistent |
156 // needing to be cleared out before the thread is terminated. | 190 // needing to be cleared out before the thread is terminated. |
157 PersistentBase* registerAsStaticReference() { | 191 PersistentBase* registerAsStaticReference() { |
158 if (m_persistentNode) { | 192 if (m_persistentNode) { |
159 ASSERT(ThreadState::current()); | 193 ASSERT(ThreadState::current()); |
160 ThreadState::current()->registerStaticPersistentNode(m_persistentNode, | 194 ThreadState::current()->registerStaticPersistentNode( |
161 nullptr); | 195 m_persistentNode, &PersistentBase::clearPersistentNode); |
162 LEAK_SANITIZER_IGNORE_OBJECT(this); | 196 LEAK_SANITIZER_IGNORE_OBJECT(this); |
163 } | 197 } |
164 return this; | 198 return this; |
165 } | 199 } |
166 | 200 |
167 protected: | 201 protected: |
168 NO_SANITIZE_ADDRESS | 202 NO_SANITIZE_ADDRESS |
169 T* atomicGet() { | 203 T* atomicGet() { |
170 return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<void* volatile*>( | 204 return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<void* volatile*>( |
171 const_cast<typename std::remove_const<T>::type**>(&m_raw)))); | 205 const_cast<typename std::remove_const<T>::type**>(&m_raw)))); |
(...skipping 12 matching lines...) Expand all Loading... |
184 } | 218 } |
185 checkPointer(); | 219 checkPointer(); |
186 if (m_raw) { | 220 if (m_raw) { |
187 if (!m_persistentNode) | 221 if (!m_persistentNode) |
188 initialize(); | 222 initialize(); |
189 return; | 223 return; |
190 } | 224 } |
191 uninitialize(); | 225 uninitialize(); |
192 } | 226 } |
193 | 227 |
| 228 // Used when the registered PersistentNode of this object is |
| 229 // released during ThreadState shutdown, clearing the association. |
| 230 static void clearPersistentNode(void* self, |
| 231 ThreadState::ReleasePersistentMode mode) { |
| 232 PersistentBase* persistent = |
| 233 (reinterpret_cast<PersistentBase*>(self)); |
| 234 ClearStaticPersistentReference<T>::clear(persistent->get()); |
| 235 if (mode == ThreadState::ReleasePersistent) |
| 236 persistent->uninitialize(); |
| 237 } |
| 238 |
194 template <typename VisitorDispatcher> | 239 template <typename VisitorDispatcher> |
195 void tracePersistent(VisitorDispatcher visitor) { | 240 void tracePersistent(VisitorDispatcher visitor) { |
196 static_assert(sizeof(T), "T must be fully defined"); | 241 static_assert(sizeof(T), "T must be fully defined"); |
197 static_assert(IsGarbageCollectedType<T>::value, | 242 static_assert(IsGarbageCollectedType<T>::value, |
198 "T needs to be a garbage collected object"); | 243 "T needs to be a garbage collected object"); |
199 if (weaknessConfiguration == WeakPersistentConfiguration) { | 244 if (weaknessConfiguration == WeakPersistentConfiguration) { |
200 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) | 245 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) |
201 visitor->registerWeakCellWithCallback(reinterpret_cast<void**>(this), | 246 visitor->registerWeakCellWithCallback(reinterpret_cast<void**>(this), |
202 handleWeakPersistent); | 247 handleWeakPersistent); |
203 else | 248 else |
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 | 638 |
594 private: | 639 private: |
595 template <typename VisitorDispatcher> | 640 template <typename VisitorDispatcher> |
596 void tracePersistent(VisitorDispatcher visitor) { | 641 void tracePersistent(VisitorDispatcher visitor) { |
597 static_assert(sizeof(Collection), "Collection must be fully defined"); | 642 static_assert(sizeof(Collection), "Collection must be fully defined"); |
598 visitor->trace(*static_cast<Collection*>(this)); | 643 visitor->trace(*static_cast<Collection*>(this)); |
599 } | 644 } |
600 | 645 |
601 // Used when the registered PersistentNode of this object is | 646 // Used when the registered PersistentNode of this object is |
602 // released during ThreadState shutdown, clearing the association. | 647 // released during ThreadState shutdown, clearing the association. |
603 static void clearPersistentNode(void* self) { | 648 static void clearPersistentNode(void* self, |
| 649 ThreadState::ReleasePersistentMode mode) { |
604 PersistentHeapCollectionBase<Collection>* collection = | 650 PersistentHeapCollectionBase<Collection>* collection = |
605 (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self)); | 651 (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self)); |
606 collection->uninitialize(); | |
607 collection->clear(); | 652 collection->clear(); |
| 653 if (mode == ThreadState::ReleasePersistent) |
| 654 collection->uninitialize(); |
608 } | 655 } |
609 | 656 |
610 NO_SANITIZE_ADDRESS | 657 NO_SANITIZE_ADDRESS |
611 void initialize() { | 658 void initialize() { |
612 // FIXME: Derive affinity based on the collection. | 659 // FIXME: Derive affinity based on the collection. |
613 ThreadState* state = ThreadState::current(); | 660 ThreadState* state = ThreadState::current(); |
614 ASSERT(state->checkThread()); | 661 ASSERT(state->checkThread()); |
615 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode( | 662 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode( |
616 this, | 663 this, |
617 TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, | 664 TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
820 static blink::CrossThreadPersistent<T> Unwrap( | 867 static blink::CrossThreadPersistent<T> Unwrap( |
821 const blink::CrossThreadWeakPersistent<T>& wrapped) { | 868 const blink::CrossThreadWeakPersistent<T>& wrapped) { |
822 blink::CrossThreadPersistentRegion::LockScope persistentLock( | 869 blink::CrossThreadPersistentRegion::LockScope persistentLock( |
823 blink::ProcessHeap::crossThreadPersistentRegion()); | 870 blink::ProcessHeap::crossThreadPersistentRegion()); |
824 return blink::CrossThreadPersistent<T>(wrapped.get()); | 871 return blink::CrossThreadPersistent<T>(wrapped.get()); |
825 } | 872 } |
826 }; | 873 }; |
827 } | 874 } |
828 | 875 |
829 #endif // Persistent_h | 876 #endif // Persistent_h |
OLD | NEW |