| 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
|
|
|