Index: third_party/WebKit/Source/platform/heap/Persistent.h |
diff --git a/third_party/WebKit/Source/platform/heap/Persistent.h b/third_party/WebKit/Source/platform/heap/Persistent.h |
index 794753c93dd8661116a915453cb52540a94db514..9b4581627dc03cecf380ee25928c2dcff2c7d0ec 100644 |
--- a/third_party/WebKit/Source/platform/heap/Persistent.h |
+++ b/third_party/WebKit/Source/platform/heap/Persistent.h |
@@ -33,6 +33,39 @@ enum CrossThreadnessPersistentConfiguration { |
CrossThreadPersistentConfiguration |
}; |
+// Auxillary template, probing if |void T::clear()| exists and is accessible. |
+// Used to conditionally clear the contents of a static persistent. |
+template <typename T> |
+class CanClearPersistentReference { |
+ typedef char YesType; |
+ typedef struct NoType { char padding[8]; } NoType; |
+ |
+ // Check if class T has public method "void clear()". |
+ template <typename V> |
+ static YesType checkHasClearMethod( |
+ V* p, |
+ typename std::enable_if< |
+ std::is_same<decltype(p->clear()), void>::value>::type* = nullptr); |
+ template <typename V> |
+ static NoType checkHasClearMethod(...); |
+ |
+ public: |
+ static const bool value = sizeof(YesType) + sizeof(T) == |
+ sizeof(checkHasClearMethod<T>(nullptr)) + sizeof(T); |
+}; |
+ |
+template <typename T, bool = CanClearPersistentReference<T>::value> |
+class ClearStaticPersistentReference { |
+ public: |
+ static void clear(T*) {} |
+}; |
+ |
+template <typename T> |
+class ClearStaticPersistentReference<T, true> { |
+ public: |
+ static void clear(T* ptr) { ptr->clear(); } |
+}; |
+ |
template <typename T, |
WeaknessPersistentConfiguration weaknessConfiguration, |
CrossThreadnessPersistentConfiguration crossThreadnessConfiguration> |
@@ -157,8 +190,8 @@ class PersistentBase { |
PersistentBase* registerAsStaticReference() { |
if (m_persistentNode) { |
ASSERT(ThreadState::current()); |
- ThreadState::current()->registerStaticPersistentNode(m_persistentNode, |
- nullptr); |
+ ThreadState::current()->registerStaticPersistentNode( |
+ m_persistentNode, &PersistentBase::clearPersistentNode); |
LEAK_SANITIZER_IGNORE_OBJECT(this); |
} |
return this; |
@@ -191,6 +224,16 @@ class PersistentBase { |
uninitialize(); |
} |
+ // Used when the registered PersistentNode of this object is |
+ // released during ThreadState shutdown, clearing the association. |
+ static void clearPersistentNode(void* self, |
+ ThreadState::ReleasePersistentMode mode) { |
+ PersistentBase* persistent = reinterpret_cast<PersistentBase*>(self); |
+ ClearStaticPersistentReference<T>::clear(persistent->get()); |
+ if (mode == ThreadState::ReleasePersistent) |
+ persistent->uninitialize(); |
+ } |
+ |
template <typename VisitorDispatcher> |
void tracePersistent(VisitorDispatcher visitor) { |
static_assert(sizeof(T), "T must be fully defined"); |
@@ -600,11 +643,13 @@ class PersistentHeapCollectionBase : public Collection { |
// Used when the registered PersistentNode of this object is |
// released during ThreadState shutdown, clearing the association. |
- static void clearPersistentNode(void* self) { |
+ static void clearPersistentNode(void* self, |
+ ThreadState::ReleasePersistentMode mode) { |
PersistentHeapCollectionBase<Collection>* collection = |
- (reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self)); |
- collection->uninitialize(); |
+ reinterpret_cast<PersistentHeapCollectionBase<Collection>*>(self); |
collection->clear(); |
+ if (mode == ThreadState::ReleasePersistent) |
+ collection->uninitialize(); |
} |
NO_SANITIZE_ADDRESS |