Index: third_party/WebKit/Source/platform/heap/Handle.h |
diff --git a/third_party/WebKit/Source/platform/heap/Handle.h b/third_party/WebKit/Source/platform/heap/Handle.h |
index 7a42f16933ae0987fbaae494616325a347a58123..292897f29b72a9aab4cd69fb0532a5946f0ffcf7 100644 |
--- a/third_party/WebKit/Source/platform/heap/Handle.h |
+++ b/third_party/WebKit/Source/platform/heap/Handle.h |
@@ -181,17 +181,23 @@ public: |
return *this; |
} |
-#if defined(LEAK_SANITIZER) |
+ // Register the persistent node as a 'static reference', |
+ // belonging to the current thread and a persistent that must |
+ // be cleared when the ThreadState itself is cleared out and |
+ // destructed. |
+ // |
+ // Static singletons arrange for this to happen, either to ensure |
+ // clean LSan leak reports or to register a thread-local persistent |
+ // needing to be cleared out before the thread is terminated. |
PersistentBase* registerAsStaticReference() |
{ |
if (m_persistentNode) { |
ASSERT(ThreadState::current()); |
- ThreadState::current()->registerStaticPersistentNode(m_persistentNode); |
+ ThreadState::current()->registerStaticPersistentNode(m_persistentNode, nullptr); |
LEAK_SANITIZER_IGNORE_OBJECT(this); |
} |
return this; |
} |
-#endif |
protected: |
T* atomicGet() { return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<void* volatile*>(&m_raw))); } |
@@ -246,7 +252,7 @@ private: |
ASSERT(state->checkThread()); |
// Persistent handle must be created and destructed in the same thread. |
ASSERT(m_state == state); |
- state->getPersistentRegion()->freePersistentNode(m_persistentNode); |
+ state->freePersistentNode(m_persistentNode); |
} |
m_persistentNode = nullptr; |
} |
@@ -329,33 +335,6 @@ public: |
Parent::operator=(other); |
return *this; |
} |
- |
- // Requests that the thread state clear this handle when the thread shuts |
- // down. This is intended for use with ThreadSpecific<Persistent<T>>. |
- // It's important that the Persistent<T> exist until then, because this |
- // takes a raw pointer to that handle. |
- // |
- // Example: |
- // Foo& sharedFoo() |
- // { |
- // DEFINE_THREAD_SAFE_STATIC_LOCAL( |
- // ThreadSpecific<Persistent<Foo>>, threadSpecificFoo, |
- // new ThreadSpecific<Persistent<Foo>>); |
- // Persistent<Foo>& fooHandle = *threadSpecificFoo; |
- // if (!fooHandle) { |
- // fooHandle = new Foo; |
- // fooHandle.clearOnThreadShutdown(); |
- // } |
- // return *fooHandle; |
- // } |
- void clearOnThreadShutdown() |
- { |
- void (*closure)(Persistent<T>*) = [](Persistent<T>* handle) |
- { |
- *handle = nullptr; |
- }; |
- ThreadState::current()->registerThreadShutdownHook(WTF::bind(closure, this)); |
- } |
}; |
// WeakPersistent is a way to create a weak pointer from an off-heap object |
@@ -554,20 +533,26 @@ public: |
visitor->trace(*static_cast<Collection*>(this)); |
} |
-#if defined(LEAK_SANITIZER) |
+ // See PersistentBase::registerAsStaticReference() comment. |
PersistentHeapCollectionBase* registerAsStaticReference() |
{ |
if (m_persistentNode) { |
ASSERT(ThreadState::current()); |
- ThreadState::current()->registerStaticPersistentNode(m_persistentNode); |
+ ThreadState::current()->registerStaticPersistentNode(m_persistentNode, &PersistentHeapCollectionBase<Collection>::clearPersistentNode); |
LEAK_SANITIZER_IGNORE_OBJECT(this); |
} |
return this; |
} |
-#endif |
private: |
+ // Used when the registered PersistentNode of this object is |
+ // released during ThreadState shutdown, clearing the association. |
+ static void clearPersistentNode(void *self) |
+ { |
+ (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self))->uninitialize(); |
+ } |
+ |
NO_LAZY_SWEEP_SANITIZE_ADDRESS |
void initialize() |
{ |
@@ -582,11 +567,14 @@ private: |
void uninitialize() |
{ |
+ if (!m_persistentNode) |
+ return; |
ThreadState* state = ThreadState::current(); |
ASSERT(state->checkThread()); |
// Persistent handle must be created and destructed in the same thread. |
ASSERT(m_state == state); |
- state->getPersistentRegion()->freePersistentNode(m_persistentNode); |
+ state->freePersistentNode(m_persistentNode); |
+ m_persistentNode = nullptr; |
} |
PersistentNode* m_persistentNode; |