| 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 26ba1d8d02958298aacfc73daea5743ccbbce201..9c2d45744f754091bead5ea4c82687101c395c93 100644
|
| --- a/third_party/WebKit/Source/wtf/StdLibExtras.h
|
| +++ b/third_party/WebKit/Source/wtf/StdLibExtras.h
|
| @@ -26,26 +26,141 @@
|
| #ifndef WTF_StdLibExtras_h
|
| #define WTF_StdLibExtras_h
|
|
|
| +#include <cstddef>
|
| #include "base/numerics/safe_conversions.h"
|
| #include "wtf/Assertions.h"
|
| #include "wtf/CPU.h"
|
| #include "wtf/LeakAnnotations.h"
|
| +#include "wtf/Noncopyable.h"
|
| #include "wtf/TypeTraits.h"
|
| -#include <cstddef>
|
|
|
| #if DCHECK_IS_ON()
|
| -#include "wtf/Noncopyable.h"
|
| #include "wtf/Threading.h"
|
| +#endif
|
| +
|
| +// Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable
|
| +// (|static T;|) so that it is leaked and its destructors are not called at
|
| +// exit. T may also be a Blink garbage collected object, in which case it is
|
| +// wrapped up by an off-heap |Persistent<T>| reference to the object, keeping
|
| +// it alive across GCs.
|
| +//
|
| +// |DEFINE_STATIC_LOCAL()| takes an optional fourth argument of type
|
| +// |CheckScriptWrappable|. Rarely needed, but the argument serves to
|
| +// selectively disable verification |DCHECK()|s that the declared
|
| +// singleton doesn't contain any embedded |ScriptWrappable| instances.
|
| +// Having singletons retain such objects risks leaking v8 wrapper objects
|
| +// across contexts in a renderer process, which must not happen.
|
| +// However, if the singleton definition and use can be shown not to
|
| +// leak its |ScriptWrappable|s, the check can be disabled by supplying
|
| +// |CheckScriptWrappable::No| as a fourth argument. Its use isn't
|
| +// encouraged, so please consider alternatives to declaring a singleton.
|
| +//
|
| +#define DEFINE_STATIC_LOCAL(Type, Name, Arguments, ...) \
|
| + static WTF::StaticSingleton<Type, ##__VA_ARGS__> s_##Name( \
|
| + (WTF::StaticSingleton<Type, ##__VA_ARGS__>::enterScope(), \
|
| + new WTF::StaticSingleton<Type, ##__VA_ARGS__>::WrapperType Arguments)); \
|
| + Type& Name = s_##Name.get()
|
| +
|
| +namespace blink {
|
| +template <typename T>
|
| +class Persistent;
|
| +class ScriptWrappable;
|
| +
|
| +} // namespace blink
|
| +
|
| +namespace WTF {
|
| +
|
| +enum class CheckScriptWrappable {
|
| + No,
|
| + Yes,
|
| +};
|
|
|
| -class WTF_EXPORT StaticLocalVerifier {
|
| - WTF_MAKE_NONCOPYABLE(StaticLocalVerifier);
|
| +template <typename Type,
|
| + CheckScriptWrappable checkScriptWrappable = CheckScriptWrappable::Yes>
|
| +class StaticSingleton final {
|
| + WTF_MAKE_NONCOPYABLE(StaticSingleton);
|
|
|
| public:
|
| - StaticLocalVerifier()
|
| - : m_safelyInitialized(WTF::isBeforeThreadCreated()),
|
| - m_thread(WTF::internal::currentThreadSyscall()) {}
|
| + template <typename T,
|
| + bool = WTF::IsGarbageCollectedType<T>::value &&
|
| + !WTF::IsPersistentReferenceType<T>::value>
|
| + struct Wrapper {
|
| + using type = T;
|
| +
|
| + static T& unwrap(T* singleton) { return *singleton; }
|
| + };
|
| +
|
| + template <typename T>
|
| + struct Wrapper<T, true> {
|
| + using type = blink::Persistent<T>;
|
| +
|
| + static T& unwrap(blink::Persistent<T>* singleton) {
|
| + DCHECK(singleton);
|
| + // If this assert triggers, you're supplying an empty ("()") 'Arguments'
|
| + // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish
|
| + // to create as a static singleton and wrapped up with a Persistent
|
| + // reference.
|
| + DCHECK(*singleton);
|
| + return **singleton;
|
| + }
|
| + };
|
| +
|
| + using WrapperType = typename Wrapper<Type>::type;
|
| +
|
| + static_assert(
|
| + !WTF::IsPersistentReferenceType<WrapperType>::value ||
|
| + !WTF::IsSubclass<
|
| + typename WTF::RemoveTemplate<WrapperType,
|
| + blink::Persistent>::type,
|
| + blink::ScriptWrappable>::value,
|
| + "It is unsafe to keep a static singleton to a ScriptWrappable-derived "
|
| + "object");
|
| +
|
| + // To cooperate with leak detection(LSan) for Blink garbage collected objects,
|
| + // the objects owned by persistent local statics will in some cases have to be
|
| + // finalized prior to leak checking. This only applies to static references to
|
| + // Blink heap objects and what they transitively hold on to. Hence the
|
| + // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
|
| + // details.
|
| +
|
| + explicit StaticSingleton(WrapperType* instance)
|
| + : m_instance(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance))
|
| +#if DCHECK_IS_ON()
|
| + ,
|
| + m_safelyInitialized(WTF::isBeforeThreadCreated()),
|
| + m_thread(WTF::internal::currentThreadSyscall())
|
| +#endif
|
| + {
|
| + leaveScope();
|
| + }
|
| +
|
| + Type& get() const {
|
| +#if DCHECK_IS_ON()
|
| + DCHECK(isNotRacy());
|
| +#endif
|
| + return Wrapper<Type>::unwrap(m_instance);
|
| + }
|
| +
|
| + operator Type&() { return get(); }
|
| +
|
| + static void enterScope() {
|
| +#if DCHECK_IS_ON()
|
| + if (checkScriptWrappable == CheckScriptWrappable::Yes)
|
| + NoScriptWrappableScope<WrapperType>::enter();
|
| +#endif
|
| + }
|
| +
|
| + static void leaveScope() {
|
| +#if DCHECK_IS_ON()
|
| + if (checkScriptWrappable == CheckScriptWrappable::Yes)
|
| + NoScriptWrappableScope<WrapperType>::leave();
|
| +#endif
|
| + }
|
| +
|
| + private:
|
| +#if DCHECK_IS_ON()
|
|
|
| - bool isNotRacy() {
|
| + bool isNotRacy() const {
|
| // Make sure that this 1) is safely initialized, 2) keeps being called
|
| // on the same thread, or 3) is called within
|
| // AtomicallyInitializedStatic (i.e. with a lock held).
|
| @@ -54,71 +169,29 @@ class WTF_EXPORT StaticLocalVerifier {
|
| WTF::isAtomicallyInitializedStaticMutexLockHeld();
|
| }
|
|
|
| - private:
|
| + template <typename T, bool = WTF::IsPersistentReferenceType<T>::value>
|
| + struct NoScriptWrappableScope {
|
| + static void enter() {}
|
| + static void leave() {}
|
| + };
|
| +
|
| + template <typename T>
|
| + struct NoScriptWrappableScope<T, true> {
|
| + static void enter() { T::enterNoScriptWrappableScope(); }
|
| + static void leave() { T::leaveNoScriptWrappableScope(); }
|
| + };
|
| +#endif
|
| + WrapperType* m_instance;
|
| +
|
| +#if DCHECK_IS_ON()
|
| bool m_safelyInitialized;
|
| ThreadIdentifier m_thread;
|
| -};
|
| #endif
|
| -
|
| -namespace blink {
|
| -template <typename T>
|
| -class Persistent;
|
| -};
|
| -
|
| -template <typename T,
|
| - bool = WTF::IsGarbageCollectedType<T>::value &&
|
| - !WTF::IsPersistentReferenceType<T>::value>
|
| -class StaticLocalWrapper {
|
| - public:
|
| - using WrapType = T;
|
| -
|
| - static T& unwrap(T* singleton) { return *singleton; }
|
| };
|
|
|
| -template <typename T>
|
| -class StaticLocalWrapper<T, true> {
|
| - public:
|
| - using WrapType = blink::Persistent<T>;
|
| -
|
| - static T& unwrap(blink::Persistent<T>* singleton) {
|
| - DCHECK(singleton);
|
| - // If this assert triggers, you're supplying an empty ("()") 'Arguments'
|
| - // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish
|
| - // to create as a static singleton and wrapped up with a Persistent
|
| - // reference.
|
| - DCHECK(*singleton);
|
| - return **singleton;
|
| - }
|
| -};
|
| -
|
| -#if DCHECK_IS_ON()
|
| -#define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name) \
|
| - static StaticLocalVerifier Name##StaticLocalVerifier; \
|
| - DCHECK(Name##StaticLocalVerifier.isNotRacy())
|
| -#else
|
| -#define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name)
|
| -#endif
|
| +} // namespace WTF
|
|
|
| -// Use DEFINE_STATIC_LOCAL() to declare and define a static local variable
|
| -// (static T;) so that it is leaked and its destructors are not called at exit.
|
| -// T may also be a Blink garbage collected object, in which case it is
|
| -// wrapped up by an off-heap Persistent<T> reference to the object, keeping
|
| -// it alive across GCs.
|
| -//
|
| -// To cooperate with leak detection(LSan) for Blink garbage collected objects,
|
| -// the objects owned by persistent local statics will in some cases have to be
|
| -// finalized prior to leak checking. This only applies to static references to
|
| -// Blink heap objects and what they transitively hold on to. Hence the
|
| -// LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
|
| -// details.
|
| -//
|
| -#define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
|
| - DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name); \
|
| - using WrappedTypeFor##Name = StaticLocalWrapper<Type>::WrapType; \
|
| - static WrappedTypeFor##Name* WrappedInstanceFor##Name = \
|
| - LEAK_SANITIZER_REGISTER_STATIC_LOCAL( \
|
| - WrappedTypeFor##Name, new WrappedTypeFor##Name Arguments); \
|
| - Type& Name = StaticLocalWrapper<Type>::unwrap(WrappedInstanceFor##Name);
|
| +using WTF::CheckScriptWrappable;
|
|
|
| // 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
|
|
|