Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: third_party/WebKit/Source/platform/heap/Handle.h

Issue 1919663002: Unify and generalize thread static persistent finalization. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: generalize clearing Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2014 Google Inc. All rights reserved. 2 * Copyright (C) 2014 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 return *this; 175 return *this;
176 } 176 }
177 177
178 template<typename U> 178 template<typename U>
179 PersistentBase& operator=(const Member<U>& other) 179 PersistentBase& operator=(const Member<U>& other)
180 { 180 {
181 assign(other); 181 assign(other);
182 return *this; 182 return *this;
183 } 183 }
184 184
185 #if defined(LEAK_SANITIZER) 185 // Register the persistent node as a 'static reference',
186 // belonging to the current thread and a persistent that must
187 // be cleared when the ThreadState itself is cleared out and
188 // destructed.
189 //
190 // Static singletons arrange for this to happen, either to ensure
191 // clean LSan leak reports or to register a thread-local persistent
192 // needing to be cleared out before the thread is terminated.
186 PersistentBase* registerAsStaticReference() 193 PersistentBase* registerAsStaticReference()
187 { 194 {
188 if (m_persistentNode) { 195 if (m_persistentNode) {
189 ASSERT(ThreadState::current()); 196 ASSERT(ThreadState::current());
190 ThreadState::current()->registerStaticPersistentNode(m_persistentNod e); 197 ThreadState::current()->registerStaticPersistentNode(m_persistentNod e, nullptr);
191 LEAK_SANITIZER_IGNORE_OBJECT(this); 198 LEAK_SANITIZER_IGNORE_OBJECT(this);
192 } 199 }
193 return this; 200 return this;
194 } 201 }
195 #endif
196 202
197 protected: 203 protected:
198 T* atomicGet() { return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<vo id* volatile*>(&m_raw))); } 204 T* atomicGet() { return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<vo id* volatile*>(&m_raw))); }
199 205
200 private: 206 private:
201 NO_LAZY_SWEEP_SANITIZE_ADDRESS 207 NO_LAZY_SWEEP_SANITIZE_ADDRESS
202 void assign(T* ptr) 208 void assign(T* ptr)
203 { 209 {
204 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) 210 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
205 releaseStore(reinterpret_cast<void* volatile*>(&m_raw), ptr); 211 releaseStore(reinterpret_cast<void* volatile*>(&m_raw), ptr);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 if (!m_persistentNode) 246 if (!m_persistentNode)
241 return; 247 return;
242 248
243 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) { 249 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) {
244 ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_pers istentNode); 250 ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_pers istentNode);
245 } else { 251 } else {
246 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::st ate(); 252 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::st ate();
247 ASSERT(state->checkThread()); 253 ASSERT(state->checkThread());
248 // Persistent handle must be created and destructed in the same thre ad. 254 // Persistent handle must be created and destructed in the same thre ad.
249 ASSERT(m_state == state); 255 ASSERT(m_state == state);
250 state->getPersistentRegion()->freePersistentNode(m_persistentNode); 256 state->freePersistentNode(m_persistentNode);
251 } 257 }
252 m_persistentNode = nullptr; 258 m_persistentNode = nullptr;
253 } 259 }
254 260
255 void checkPointer() 261 void checkPointer()
256 { 262 {
257 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) 263 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER)
258 if (!m_raw) 264 if (!m_raw)
259 return; 265 return;
260 266
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 Parent::operator=(other); 329 Parent::operator=(other);
324 return *this; 330 return *this;
325 } 331 }
326 332
327 template<typename U> 333 template<typename U>
328 Persistent& operator=(const Member<U>& other) 334 Persistent& operator=(const Member<U>& other)
329 { 335 {
330 Parent::operator=(other); 336 Parent::operator=(other);
331 return *this; 337 return *this;
332 } 338 }
333
334 // Requests that the thread state clear this handle when the thread shuts
335 // down. This is intended for use with ThreadSpecific<Persistent<T>>.
336 // It's important that the Persistent<T> exist until then, because this
337 // takes a raw pointer to that handle.
338 //
339 // Example:
340 // Foo& sharedFoo()
341 // {
342 // DEFINE_THREAD_SAFE_STATIC_LOCAL(
343 // ThreadSpecific<Persistent<Foo>>, threadSpecificFoo,
344 // new ThreadSpecific<Persistent<Foo>>);
345 // Persistent<Foo>& fooHandle = *threadSpecificFoo;
346 // if (!fooHandle) {
347 // fooHandle = new Foo;
348 // fooHandle.clearOnThreadShutdown();
349 // }
350 // return *fooHandle;
351 // }
352 void clearOnThreadShutdown()
353 {
354 void (*closure)(Persistent<T>*) = [](Persistent<T>* handle)
355 {
356 *handle = nullptr;
357 };
358 ThreadState::current()->registerThreadShutdownHook(WTF::bind(closure, th is));
359 }
360 }; 339 };
361 340
362 // WeakPersistent is a way to create a weak pointer from an off-heap object 341 // WeakPersistent is a way to create a weak pointer from an off-heap object
363 // to an on-heap object. The m_raw is automatically cleared when the pointee 342 // to an on-heap object. The m_raw is automatically cleared when the pointee
364 // gets collected. 343 // gets collected.
365 // 344 //
366 // We have to construct and destruct WeakPersistent in the same thread. 345 // We have to construct and destruct WeakPersistent in the same thread.
367 // 346 //
368 // Note that collections of WeakPersistents are not supported. Use a persistent 347 // Note that collections of WeakPersistents are not supported. Use a persistent
369 // collection of WeakMembers instead. 348 // collection of WeakMembers instead.
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 uninitialize(); 527 uninitialize();
549 } 528 }
550 529
551 template<typename VisitorDispatcher> 530 template<typename VisitorDispatcher>
552 void trace(VisitorDispatcher visitor) 531 void trace(VisitorDispatcher visitor)
553 { 532 {
554 static_assert(sizeof(Collection), "Collection must be fully defined"); 533 static_assert(sizeof(Collection), "Collection must be fully defined");
555 visitor->trace(*static_cast<Collection*>(this)); 534 visitor->trace(*static_cast<Collection*>(this));
556 } 535 }
557 536
558 #if defined(LEAK_SANITIZER) 537 // See PersistentBase::registerAsStaticReference() comment.
559 PersistentHeapCollectionBase* registerAsStaticReference() 538 PersistentHeapCollectionBase* registerAsStaticReference()
560 { 539 {
561 if (m_persistentNode) { 540 if (m_persistentNode) {
562 ASSERT(ThreadState::current()); 541 ASSERT(ThreadState::current());
563 ThreadState::current()->registerStaticPersistentNode(m_persistentNod e); 542 ThreadState::current()->registerStaticPersistentNode(m_persistentNod e, &PersistentHeapCollectionBase<Collection>::clearPersistentNode);
564 LEAK_SANITIZER_IGNORE_OBJECT(this); 543 LEAK_SANITIZER_IGNORE_OBJECT(this);
565 } 544 }
566 return this; 545 return this;
567 } 546 }
568 #endif
569 547
570 private: 548 private:
571 549
550 // Used when the registered PersistentNode of this object is
551 // released during ThreadState shutdown, clearing the association.
552 static void clearPersistentNode(void *self)
553 {
554 (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self))->uni nitialize();
haraken 2016/04/25 08:39:23 Why does PersistentHeapCollectionBase need to call
sof 2016/04/25 08:53:04 It also needs to clear the connection; see Persist
555 }
556
572 NO_LAZY_SWEEP_SANITIZE_ADDRESS 557 NO_LAZY_SWEEP_SANITIZE_ADDRESS
573 void initialize() 558 void initialize()
574 { 559 {
575 // FIXME: Derive affinity based on the collection. 560 // FIXME: Derive affinity based on the collection.
576 ThreadState* state = ThreadState::current(); 561 ThreadState* state = ThreadState::current();
577 ASSERT(state->checkThread()); 562 ASSERT(state->checkThread());
578 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode( this, TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentH eapCollectionBase<Collection>::trace>::trampoline); 563 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode( this, TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentH eapCollectionBase<Collection>::trace>::trampoline);
579 #if ENABLE(ASSERT) 564 #if ENABLE(ASSERT)
580 m_state = state; 565 m_state = state;
581 #endif 566 #endif
582 } 567 }
583 568
584 void uninitialize() 569 void uninitialize()
585 { 570 {
571 if (!m_persistentNode)
haraken 2016/04/25 08:39:23 Just curious, why do we need this check?
sof 2016/04/25 08:53:05 If you have a PersistentCollectionBase stuck in TL
572 return;
586 ThreadState* state = ThreadState::current(); 573 ThreadState* state = ThreadState::current();
587 ASSERT(state->checkThread()); 574 ASSERT(state->checkThread());
588 // Persistent handle must be created and destructed in the same thread. 575 // Persistent handle must be created and destructed in the same thread.
589 ASSERT(m_state == state); 576 ASSERT(m_state == state);
590 state->getPersistentRegion()->freePersistentNode(m_persistentNode); 577 state->freePersistentNode(m_persistentNode);
578 m_persistentNode = nullptr;
591 } 579 }
592 580
593 PersistentNode* m_persistentNode; 581 PersistentNode* m_persistentNode;
594 #if ENABLE(ASSERT) 582 #if ENABLE(ASSERT)
595 ThreadState* m_state; 583 ThreadState* m_state;
596 #endif 584 #endif
597 }; 585 };
598 586
599 template< 587 template<
600 typename KeyArg, 588 typename KeyArg,
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after
1227 // into it. 1215 // into it.
1228 // 1216 //
1229 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty pe like 1217 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty pe like
1230 // CrossThreadWeakPersistent<>. 1218 // CrossThreadWeakPersistent<>.
1231 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR eference<T>::create(value.get())); } 1219 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR eference<T>::create(value.get())); }
1232 }; 1220 };
1233 1221
1234 } // namespace WTF 1222 } // namespace WTF
1235 1223
1236 #endif 1224 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698