| Index: third_party/WebKit/Source/wtf/StdLibExtras.h
|
| diff --git a/third_party/WebKit/Source/wtf/StdLibExtras.h b/third_party/WebKit/Source/wtf/StdLibExtras.h
|
| index 62acd8582e0fdf7eee3a7b68cec156a9236f5512..520f4c1cdaaa2fe7a8fe8116f962d2f85f06bf72 100644
|
| --- a/third_party/WebKit/Source/wtf/StdLibExtras.h
|
| +++ b/third_party/WebKit/Source/wtf/StdLibExtras.h
|
| @@ -29,6 +29,7 @@
|
| #include "wtf/Assertions.h"
|
| #include "wtf/CPU.h"
|
| #include "wtf/CheckedArithmetic.h"
|
| +#include "wtf/TypeTraits.h"
|
| #include <cstddef>
|
|
|
| #if ENABLE(ASSERT)
|
| @@ -59,21 +60,73 @@ private:
|
| #endif
|
|
|
| // Use this to declare and define a static local variable (static T;) so that
|
| -// it is leaked so that its destructors are not called at exit.
|
| +// it is leaked so that its destructors are not called at exit.
|
| +//
|
| +// If the object pointed to by the static local is on the Oilpan heap, a strong
|
| +// Persistent<> is created to keep the pointed-to heap object alive. This makes
|
| +// both the Persistent<> and the heap object reachable by LeakSanitizer's leak
|
| +// detection pass. We do not want these intentional leaks to be reported by LSan,
|
| +// hence the static local is registered with Oilpan
|
| +// (see RegisterStaticLocalReference<> below.)
|
| +//
|
| +// Upon Blink shutdown, we release all these statics and perform a final round
|
| +// of GCs to sweep out their now-unreachable object graphs. The end result being
|
| +// a tidied heap that the LeakSanitizer can then scan to report real leaks.
|
| +//
|
| +// Should you not want to register a static reference to an Oilpan object for
|
| +// finalization upon shutdown, DEFINE_STATIC_LOCAL_NO_REGISTER() is provided.
|
| #ifndef DEFINE_STATIC_LOCAL
|
|
|
| +template<typename T>
|
| +class CanRegisterStaticLocalReference {
|
| + typedef char YesType;
|
| + typedef struct NoType {
|
| + char padding[8];
|
| + } NoType;
|
| +
|
| + // Check if class T has public method "T* registerAsStaticReference()".
|
| + template<typename V> static YesType checkHasRegisterAsStaticReferenceMethod(V* p, typename WTF::EnableIf<WTF::IsSubclass<V, typename std::remove_pointer<decltype(p->registerAsStaticReference())>::type>::value>::Type* = 0);
|
| + template<typename V> static NoType checkHasRegisterAsStaticReferenceMethod(...);
|
| +public:
|
| +
|
| + static const bool value = sizeof(YesType) + sizeof(T) == sizeof(checkHasRegisterAsStaticReferenceMethod<T>(nullptr)) + sizeof(T);
|
| +};
|
| +
|
| +template<typename T, bool = CanRegisterStaticLocalReference<T>::value>
|
| +class RegisterStaticLocalReference {
|
| +public:
|
| + static T* registerStatic(T* ptr)
|
| + {
|
| + return ptr;
|
| + }
|
| +};
|
| +
|
| +template<typename T>
|
| +class RegisterStaticLocalReference<T, true> {
|
| +public:
|
| + static T* registerStatic(T* ptr)
|
| + {
|
| + return static_cast<T*>(ptr->registerAsStaticReference());
|
| + }
|
| +};
|
| +
|
| #if ENABLE(ASSERT)
|
| #define DEFINE_STATIC_LOCAL(type, name, arguments) \
|
| static StaticLocalVerifier name##StaticLocalVerifier; \
|
| - ASSERT(name##StaticLocalVerifier.isNotRacy()); \
|
| + ASSERT(name##StaticLocalVerifier.isNotRacy()); \
|
| + static type& name = *RegisterStaticLocalReference<type>::registerStatic(new type arguments)
|
| +#define DEFINE_STATIC_LOCAL_NO_REGISTER(type, name, arguments) \
|
| + static StaticLocalVerifier name##StaticLocalVerifier; \
|
| + ASSERT(name##StaticLocalVerifier.isNotRacy()); \
|
| static type& name = *new type arguments
|
| #else
|
| #define DEFINE_STATIC_LOCAL(type, name, arguments) \
|
| + static type& name = *RegisterStaticLocalReference<type>::registerStatic(new type arguments)
|
| +#define DEFINE_STATIC_LOCAL_NO_REGISTER(type, name, arguments) \
|
| static type& name = *new type arguments
|
| #endif
|
|
|
| -#endif
|
| -
|
| +#endif // DEFINE_STATIC_LOCAL
|
|
|
| // Use this to declare and define a static local pointer to a ref-counted object so that
|
| // it is leaked so that the object's destructors are not called at exit.
|
|
|