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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
159 // Register the persistent node as a 'static reference', | 159 // Register the persistent node as a 'static reference', |
160 // belonging to the current thread and a persistent that must | 160 // belonging to the current thread and a persistent that must |
161 // be cleared when the ThreadState itself is cleared out and | 161 // be cleared when the ThreadState itself is cleared out and |
162 // destructed. | 162 // destructed. |
163 // | 163 // |
164 // Static singletons arrange for this to happen, either to ensure | 164 // Static singletons arrange for this to happen, either to ensure |
165 // clean LSan leak reports or to register a thread-local persistent | 165 // clean LSan leak reports or to register a thread-local persistent |
166 // needing to be cleared out before the thread is terminated. | 166 // needing to be cleared out before the thread is terminated. |
167 PersistentBase* RegisterAsStaticReference() { | 167 PersistentBase* RegisterAsStaticReference() { |
168 if (persistent_node_) { | 168 if (persistent_node_) { |
169 ASSERT(ThreadState::Current()); | 169 DCHECK(ThreadState::Current()); |
170 ThreadState::Current()->RegisterStaticPersistentNode(persistent_node_, | 170 ThreadState::Current()->RegisterStaticPersistentNode(persistent_node_, |
171 nullptr); | 171 nullptr); |
172 LEAK_SANITIZER_IGNORE_OBJECT(this); | 172 LEAK_SANITIZER_IGNORE_OBJECT(this); |
173 } | 173 } |
174 return this; | 174 return this; |
175 } | 175 } |
176 | 176 |
177 protected: | 177 protected: |
178 NO_SANITIZE_ADDRESS | 178 NO_SANITIZE_ADDRESS |
179 T* AtomicGet() { | 179 T* AtomicGet() { |
(...skipping 27 matching lines...) Expand all Loading... |
207 "T needs to be a garbage collected object"); | 207 "T needs to be a garbage collected object"); |
208 if (weaknessConfiguration == kWeakPersistentConfiguration) { | 208 if (weaknessConfiguration == kWeakPersistentConfiguration) { |
209 visitor->RegisterWeakCallback(this, HandleWeakPersistent); | 209 visitor->RegisterWeakCallback(this, HandleWeakPersistent); |
210 } else { | 210 } else { |
211 visitor->Mark(raw_); | 211 visitor->Mark(raw_); |
212 } | 212 } |
213 } | 213 } |
214 | 214 |
215 NO_SANITIZE_ADDRESS | 215 NO_SANITIZE_ADDRESS |
216 void Initialize() { | 216 void Initialize() { |
217 ASSERT(!persistent_node_); | 217 DCHECK(!persistent_node_); |
218 if (!raw_ || IsHashTableDeletedValue()) | 218 if (!raw_ || IsHashTableDeletedValue()) |
219 return; | 219 return; |
220 | 220 |
221 TraceCallback trace_callback = | 221 TraceCallback trace_callback = |
222 TraceMethodDelegate<PersistentBase, | 222 TraceMethodDelegate<PersistentBase, |
223 &PersistentBase::TracePersistent>::Trampoline; | 223 &PersistentBase::TracePersistent>::Trampoline; |
224 if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { | 224 if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { |
225 ProcessHeap::GetCrossThreadPersistentRegion().AllocatePersistentNode( | 225 ProcessHeap::GetCrossThreadPersistentRegion().AllocatePersistentNode( |
226 persistent_node_, this, trace_callback); | 226 persistent_node_, this, trace_callback); |
227 return; | 227 return; |
228 } | 228 } |
229 ThreadState* state = | 229 ThreadState* state = |
230 ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); | 230 ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); |
231 ASSERT(state->CheckThread()); | 231 DCHECK(state->CheckThread()); |
232 persistent_node_ = state->GetPersistentRegion()->AllocatePersistentNode( | 232 persistent_node_ = state->GetPersistentRegion()->AllocatePersistentNode( |
233 this, trace_callback); | 233 this, trace_callback); |
234 #if DCHECK_IS_ON() | 234 #if DCHECK_IS_ON() |
235 state_ = state; | 235 state_ = state; |
236 #endif | 236 #endif |
237 } | 237 } |
238 | 238 |
239 void Uninitialize() { | 239 void Uninitialize() { |
240 if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { | 240 if (crossThreadnessConfiguration == kCrossThreadPersistentConfiguration) { |
241 if (AcquireLoad(reinterpret_cast<void* volatile*>(&persistent_node_))) | 241 if (AcquireLoad(reinterpret_cast<void* volatile*>(&persistent_node_))) |
242 ProcessHeap::GetCrossThreadPersistentRegion().FreePersistentNode( | 242 ProcessHeap::GetCrossThreadPersistentRegion().FreePersistentNode( |
243 persistent_node_); | 243 persistent_node_); |
244 return; | 244 return; |
245 } | 245 } |
246 | 246 |
247 if (!persistent_node_) | 247 if (!persistent_node_) |
248 return; | 248 return; |
249 ThreadState* state = | 249 ThreadState* state = |
250 ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); | 250 ThreadStateFor<ThreadingTrait<T>::kAffinity>::GetState(); |
251 ASSERT(state->CheckThread()); | 251 DCHECK(state->CheckThread()); |
252 // Persistent handle must be created and destructed in the same thread. | 252 // Persistent handle must be created and destructed in the same thread. |
253 ASSERT(state_ == state); | 253 #if DCHECK_IS_ON() |
| 254 DCHECK_EQ(state_, state); |
| 255 #endif |
254 state->FreePersistentNode(persistent_node_); | 256 state->FreePersistentNode(persistent_node_); |
255 persistent_node_ = nullptr; | 257 persistent_node_ = nullptr; |
256 } | 258 } |
257 | 259 |
258 void CheckPointer() const { | 260 void CheckPointer() const { |
259 #if DCHECK_IS_ON() | 261 #if DCHECK_IS_ON() |
260 if (!raw_ || IsHashTableDeletedValue()) | 262 if (!raw_ || IsHashTableDeletedValue()) |
261 return; | 263 return; |
262 | 264 |
263 if (crossThreadnessConfiguration != kCrossThreadPersistentConfiguration) { | 265 if (crossThreadnessConfiguration != kCrossThreadPersistentConfiguration) { |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 PersistentHeapCollectionBase(const OtherCollection& other) | 562 PersistentHeapCollectionBase(const OtherCollection& other) |
561 : Collection(other) { | 563 : Collection(other) { |
562 Initialize(); | 564 Initialize(); |
563 } | 565 } |
564 | 566 |
565 ~PersistentHeapCollectionBase() { Uninitialize(); } | 567 ~PersistentHeapCollectionBase() { Uninitialize(); } |
566 | 568 |
567 // See PersistentBase::registerAsStaticReference() comment. | 569 // See PersistentBase::registerAsStaticReference() comment. |
568 PersistentHeapCollectionBase* RegisterAsStaticReference() { | 570 PersistentHeapCollectionBase* RegisterAsStaticReference() { |
569 if (persistent_node_) { | 571 if (persistent_node_) { |
570 ASSERT(ThreadState::Current()); | 572 DCHECK(ThreadState::Current()); |
571 ThreadState::Current()->RegisterStaticPersistentNode( | 573 ThreadState::Current()->RegisterStaticPersistentNode( |
572 persistent_node_, | 574 persistent_node_, |
573 &PersistentHeapCollectionBase<Collection>::ClearPersistentNode); | 575 &PersistentHeapCollectionBase<Collection>::ClearPersistentNode); |
574 LEAK_SANITIZER_IGNORE_OBJECT(this); | 576 LEAK_SANITIZER_IGNORE_OBJECT(this); |
575 } | 577 } |
576 return this; | 578 return this; |
577 } | 579 } |
578 | 580 |
579 private: | 581 private: |
580 template <typename VisitorDispatcher> | 582 template <typename VisitorDispatcher> |
581 void TracePersistent(VisitorDispatcher visitor) { | 583 void TracePersistent(VisitorDispatcher visitor) { |
582 static_assert(sizeof(Collection), "Collection must be fully defined"); | 584 static_assert(sizeof(Collection), "Collection must be fully defined"); |
583 visitor->Trace(*static_cast<Collection*>(this)); | 585 visitor->Trace(*static_cast<Collection*>(this)); |
584 } | 586 } |
585 | 587 |
586 // Used when the registered PersistentNode of this object is | 588 // Used when the registered PersistentNode of this object is |
587 // released during ThreadState shutdown, clearing the association. | 589 // released during ThreadState shutdown, clearing the association. |
588 static void ClearPersistentNode(void* self) { | 590 static void ClearPersistentNode(void* self) { |
589 PersistentHeapCollectionBase<Collection>* collection = | 591 PersistentHeapCollectionBase<Collection>* collection = |
590 (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self)); | 592 (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self)); |
591 collection->Uninitialize(); | 593 collection->Uninitialize(); |
592 collection->Clear(); | 594 collection->Clear(); |
593 } | 595 } |
594 | 596 |
595 NO_SANITIZE_ADDRESS | 597 NO_SANITIZE_ADDRESS |
596 void Initialize() { | 598 void Initialize() { |
597 // FIXME: Derive affinity based on the collection. | 599 // FIXME: Derive affinity based on the collection. |
598 ThreadState* state = ThreadState::Current(); | 600 ThreadState* state = ThreadState::Current(); |
599 ASSERT(state->CheckThread()); | 601 DCHECK(state->CheckThread()); |
600 persistent_node_ = state->GetPersistentRegion()->AllocatePersistentNode( | 602 persistent_node_ = state->GetPersistentRegion()->AllocatePersistentNode( |
601 this, | 603 this, |
602 TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, | 604 TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, |
603 &PersistentHeapCollectionBase< | 605 &PersistentHeapCollectionBase< |
604 Collection>::TracePersistent>::Trampoline); | 606 Collection>::TracePersistent>::Trampoline); |
605 #if DCHECK_IS_ON() | 607 #if DCHECK_IS_ON() |
606 state_ = state; | 608 state_ = state; |
607 #endif | 609 #endif |
608 } | 610 } |
609 | 611 |
610 void Uninitialize() { | 612 void Uninitialize() { |
611 if (!persistent_node_) | 613 if (!persistent_node_) |
612 return; | 614 return; |
613 ThreadState* state = ThreadState::Current(); | 615 ThreadState* state = ThreadState::Current(); |
614 ASSERT(state->CheckThread()); | 616 DCHECK(state->CheckThread()); |
615 // Persistent handle must be created and destructed in the same thread. | 617 // Persistent handle must be created and destructed in the same thread. |
616 ASSERT(state_ == state); | 618 #if DCHECK_IS_ON() |
| 619 DCHECK_EQ(state_, state); |
| 620 #endif |
617 state->FreePersistentNode(persistent_node_); | 621 state->FreePersistentNode(persistent_node_); |
618 persistent_node_ = nullptr; | 622 persistent_node_ = nullptr; |
619 } | 623 } |
620 | 624 |
621 PersistentNode* persistent_node_; | 625 PersistentNode* persistent_node_; |
622 #if DCHECK_IS_ON() | 626 #if DCHECK_IS_ON() |
623 ThreadState* state_; | 627 ThreadState* state_; |
624 #endif | 628 #endif |
625 }; | 629 }; |
626 | 630 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
805 static blink::CrossThreadPersistent<T> Unwrap( | 809 static blink::CrossThreadPersistent<T> Unwrap( |
806 const blink::CrossThreadWeakPersistent<T>& wrapped) { | 810 const blink::CrossThreadWeakPersistent<T>& wrapped) { |
807 blink::CrossThreadPersistentRegion::LockScope persistentLock( | 811 blink::CrossThreadPersistentRegion::LockScope persistentLock( |
808 blink::ProcessHeap::GetCrossThreadPersistentRegion()); | 812 blink::ProcessHeap::GetCrossThreadPersistentRegion()); |
809 return blink::CrossThreadPersistent<T>(wrapped.Get()); | 813 return blink::CrossThreadPersistent<T>(wrapped.Get()); |
810 } | 814 } |
811 }; | 815 }; |
812 } | 816 } |
813 | 817 |
814 #endif // Persistent_h | 818 #endif // Persistent_h |
OLD | NEW |