Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(236)

Side by Side Diff: third_party/WebKit/Source/wtf/StdLibExtras.h

Issue 2680843006: Tidy DEFINE_(THREAD_SAFE_)STATIC_LOCAL() implementations. (Closed)
Patch Set: explain safety of HTMLTableSectionElement singletons Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. 2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */ 24 */
25 25
26 #ifndef WTF_StdLibExtras_h 26 #ifndef WTF_StdLibExtras_h
27 #define WTF_StdLibExtras_h 27 #define WTF_StdLibExtras_h
28 28
29 #include <cstddef>
29 #include "base/numerics/safe_conversions.h" 30 #include "base/numerics/safe_conversions.h"
30 #include "wtf/Assertions.h" 31 #include "wtf/Assertions.h"
31 #include "wtf/CPU.h" 32 #include "wtf/CPU.h"
32 #include "wtf/LeakAnnotations.h" 33 #include "wtf/LeakAnnotations.h"
34 #include "wtf/Noncopyable.h"
33 #include "wtf/TypeTraits.h" 35 #include "wtf/TypeTraits.h"
34 #include <cstddef>
35 36
36 #if DCHECK_IS_ON() 37 #if DCHECK_IS_ON()
37 #include "wtf/Noncopyable.h"
38 #include "wtf/Threading.h" 38 #include "wtf/Threading.h"
39 #endif
39 40
40 class WTF_EXPORT StaticLocalVerifier { 41 // Use |DEFINE_STATIC_LOCAL()| to declare and define a static local variable
41 WTF_MAKE_NONCOPYABLE(StaticLocalVerifier); 42 // (|static T;|) so that it is leaked and its destructors are not called at
43 // exit. T may also be a Blink garbage collected object, in which case it is
44 // wrapped up by an off-heap |Persistent<T>| reference to the object, keeping
45 // it alive across GCs.
46 //
47 // |DEFINE_STATIC_LOCAL()| takes an optional fourth argument of type
48 // |CheckScriptWrappable|. Rarely needed, but the argument serves to
49 // selectively disable verification |DCHECK()|s that the declared
50 // singleton doesn't contain any embedded |ScriptWrappable| instances.
51 // Having singletons retain such objects risks leaking v8 wrapper objects
52 // across contexts in a renderer process, which must not happen.
53 // However, if the singleton definition and use can be shown not to
54 // leak its |ScriptWrappable|s, the check can be disabled by supplying
55 // |CheckScriptWrappable::No| as a fourth argument. Its use isn't
56 // encouraged, so please consider alternatives to declaring a singleton.
57 //
58 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments, ...) \
59 static WTF::StaticSingleton<Type, ##__VA_ARGS__> s_##Name( \
60 (WTF::StaticSingleton<Type, ##__VA_ARGS__>::enterScope(), \
61 new WTF::StaticSingleton<Type, ##__VA_ARGS__>::WrapperType Arguments)); \
62 Type& Name = s_##Name.get()
63
64 namespace blink {
65 template <typename T>
66 class Persistent;
67 class ScriptWrappable;
68
69 } // namespace blink
70
71 namespace WTF {
72
73 enum class CheckScriptWrappable {
74 No,
75 Yes,
76 };
77
78 template <typename Type,
79 CheckScriptWrappable checkScriptWrappable = CheckScriptWrappable::Yes>
80 class StaticSingleton final {
81 WTF_MAKE_NONCOPYABLE(StaticSingleton);
42 82
43 public: 83 public:
44 StaticLocalVerifier() 84 template <typename T,
45 : m_safelyInitialized(WTF::isBeforeThreadCreated()), 85 bool = WTF::IsGarbageCollectedType<T>::value &&
46 m_thread(WTF::internal::currentThreadSyscall()) {} 86 !WTF::IsPersistentReferenceType<T>::value>
87 struct Wrapper {
88 using type = T;
47 89
48 bool isNotRacy() { 90 static T& unwrap(T* singleton) { return *singleton; }
91 };
92
93 template <typename T>
94 struct Wrapper<T, true> {
95 using type = blink::Persistent<T>;
96
97 static T& unwrap(blink::Persistent<T>* singleton) {
98 DCHECK(singleton);
99 // If this assert triggers, you're supplying an empty ("()") 'Arguments'
100 // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish
101 // to create as a static singleton and wrapped up with a Persistent
102 // reference.
103 DCHECK(*singleton);
104 return **singleton;
105 }
106 };
107
108 using WrapperType = typename Wrapper<Type>::type;
109
110 static_assert(
111 !WTF::IsPersistentReferenceType<WrapperType>::value ||
112 !WTF::IsSubclass<
113 typename WTF::RemoveTemplate<WrapperType,
114 blink::Persistent>::type,
115 blink::ScriptWrappable>::value,
116 "It is unsafe to keep a static singleton to a ScriptWrappable-derived "
117 "object");
118
119 // To cooperate with leak detection(LSan) for Blink garbage collected objects,
120 // the objects owned by persistent local statics will in some cases have to be
121 // finalized prior to leak checking. This only applies to static references to
122 // Blink heap objects and what they transitively hold on to. Hence the
123 // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
124 // details.
125
126 explicit StaticSingleton(WrapperType* instance)
127 : m_instance(LEAK_SANITIZER_REGISTER_STATIC_LOCAL(WrapperType, instance))
128 #if DCHECK_IS_ON()
129 ,
130 m_safelyInitialized(WTF::isBeforeThreadCreated()),
131 m_thread(WTF::internal::currentThreadSyscall())
132 #endif
133 {
134 leaveScope();
135 }
136
137 Type& get() const {
138 #if DCHECK_IS_ON()
139 DCHECK(isNotRacy());
140 #endif
141 return Wrapper<Type>::unwrap(m_instance);
142 }
143
144 operator Type&() { return get(); }
145
146 static void enterScope() {
147 #if DCHECK_IS_ON()
148 if (checkScriptWrappable == CheckScriptWrappable::Yes)
149 NoScriptWrappableScope<WrapperType>::enter();
150 #endif
151 }
152
153 static void leaveScope() {
154 #if DCHECK_IS_ON()
155 if (checkScriptWrappable == CheckScriptWrappable::Yes)
156 NoScriptWrappableScope<WrapperType>::leave();
157 #endif
158 }
159
160 private:
161 #if DCHECK_IS_ON()
162
163 bool isNotRacy() const {
49 // Make sure that this 1) is safely initialized, 2) keeps being called 164 // Make sure that this 1) is safely initialized, 2) keeps being called
50 // on the same thread, or 3) is called within 165 // on the same thread, or 3) is called within
51 // AtomicallyInitializedStatic (i.e. with a lock held). 166 // AtomicallyInitializedStatic (i.e. with a lock held).
52 return m_safelyInitialized || 167 return m_safelyInitialized ||
53 m_thread == WTF::internal::currentThreadSyscall() || 168 m_thread == WTF::internal::currentThreadSyscall() ||
54 WTF::isAtomicallyInitializedStaticMutexLockHeld(); 169 WTF::isAtomicallyInitializedStaticMutexLockHeld();
55 } 170 }
56 171
57 private: 172 template <typename T, bool = WTF::IsPersistentReferenceType<T>::value>
173 struct NoScriptWrappableScope {
174 static void enter() {}
175 static void leave() {}
176 };
177
178 template <typename T>
179 struct NoScriptWrappableScope<T, true> {
180 static void enter() { T::enterNoScriptWrappableScope(); }
181 static void leave() { T::leaveNoScriptWrappableScope(); }
182 };
183 #endif
184 WrapperType* m_instance;
185
186 #if DCHECK_IS_ON()
58 bool m_safelyInitialized; 187 bool m_safelyInitialized;
59 ThreadIdentifier m_thread; 188 ThreadIdentifier m_thread;
60 };
61 #endif 189 #endif
62
63 namespace blink {
64 template <typename T>
65 class Persistent;
66 }; 190 };
67 191
68 template <typename T, 192 } // namespace WTF
69 bool = WTF::IsGarbageCollectedType<T>::value &&
70 !WTF::IsPersistentReferenceType<T>::value>
71 class StaticLocalWrapper {
72 public:
73 using WrapType = T;
74 193
75 static T& unwrap(T* singleton) { return *singleton; } 194 using WTF::CheckScriptWrappable;
76 };
77
78 template <typename T>
79 class StaticLocalWrapper<T, true> {
80 public:
81 using WrapType = blink::Persistent<T>;
82
83 static T& unwrap(blink::Persistent<T>* singleton) {
84 DCHECK(singleton);
85 // If this assert triggers, you're supplying an empty ("()") 'Arguments'
86 // argument to DEFINE_STATIC_LOCAL() - it must be the heap object you wish
87 // to create as a static singleton and wrapped up with a Persistent
88 // reference.
89 DCHECK(*singleton);
90 return **singleton;
91 }
92 };
93
94 #if DCHECK_IS_ON()
95 #define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name) \
96 static StaticLocalVerifier Name##StaticLocalVerifier; \
97 DCHECK(Name##StaticLocalVerifier.isNotRacy())
98 #else
99 #define DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name)
100 #endif
101
102 // Use DEFINE_STATIC_LOCAL() to declare and define a static local variable
103 // (static T;) so that it is leaked and its destructors are not called at exit.
104 // T may also be a Blink garbage collected object, in which case it is
105 // wrapped up by an off-heap Persistent<T> reference to the object, keeping
106 // it alive across GCs.
107 //
108 // To cooperate with leak detection(LSan) for Blink garbage collected objects,
109 // the objects owned by persistent local statics will in some cases have to be
110 // finalized prior to leak checking. This only applies to static references to
111 // Blink heap objects and what they transitively hold on to. Hence the
112 // LEAK_SANITIZER_REGISTER_STATIC_LOCAL() use, it taking care of the grungy
113 // details.
114 //
115 #define DEFINE_STATIC_LOCAL(Type, Name, Arguments) \
116 DEFINE_STATIC_LOCAL_CHECK_THREADSAFE_ACCESS(Name); \
117 using WrappedTypeFor##Name = StaticLocalWrapper<Type>::WrapType; \
118 static WrappedTypeFor##Name* WrappedInstanceFor##Name = \
119 LEAK_SANITIZER_REGISTER_STATIC_LOCAL( \
120 WrappedTypeFor##Name, new WrappedTypeFor##Name Arguments); \
121 Type& Name = StaticLocalWrapper<Type>::unwrap(WrappedInstanceFor##Name);
122 195
123 // Use this to declare and define a static local pointer to a ref-counted object 196 // Use this to declare and define a static local pointer to a ref-counted object
124 // so that it is leaked so that the object's destructors are not called at 197 // so that it is leaked so that the object's destructors are not called at
125 // exit. This macro should be used with ref-counted objects rather than 198 // exit. This macro should be used with ref-counted objects rather than
126 // DEFINE_STATIC_LOCAL macro, as this macro does not lead to an extra memory 199 // DEFINE_STATIC_LOCAL macro, as this macro does not lead to an extra memory
127 // allocation. 200 // allocation.
128 #define DEFINE_STATIC_REF(type, name, arguments) \ 201 #define DEFINE_STATIC_REF(type, name, arguments) \
129 static type* name = PassRefPtr<type>(arguments).leakRef(); 202 static type* name = PassRefPtr<type>(arguments).leakRef();
130 203
131 /* 204 /*
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 enum NotNullTag { NotNull }; 312 enum NotNullTag { NotNull };
240 inline void* operator new(size_t, NotNullTag, void* location) { 313 inline void* operator new(size_t, NotNullTag, void* location) {
241 DCHECK(location); 314 DCHECK(location);
242 return location; 315 return location;
243 } 316 }
244 317
245 using WTF::bitwiseCast; 318 using WTF::bitwiseCast;
246 using WTF::safeCast; 319 using WTF::safeCast;
247 320
248 #endif // WTF_StdLibExtras_h 321 #endif // WTF_StdLibExtras_h
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698