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