OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef Member_h | 5 #ifndef Member_h |
6 #define Member_h | 6 #define Member_h |
7 | 7 |
8 #include "wtf/Allocator.h" | 8 #include "wtf/Allocator.h" |
9 #include "wtf/HashFunctions.h" | 9 #include "wtf/HashFunctions.h" |
10 #include "wtf/HashTraits.h" | 10 #include "wtf/HashTraits.h" |
11 | 11 |
12 namespace blink { | 12 namespace blink { |
13 | 13 |
14 template<typename T> class Persistent; | 14 template<typename T> class Persistent; |
15 | 15 |
16 enum TracenessMemberConfiguration { | |
haraken
2016/08/16 13:27:13
Shall we use an enum class?
enum class TracedMemb
keishi
2016/08/17 11:18:29
Done.
| |
17 TracedMemberConfiguration, | |
18 UntracedMemberConfiguration | |
19 }; | |
20 | |
16 // Members are used in classes to contain strong pointers to other oilpan heap | 21 // Members are used in classes to contain strong pointers to other oilpan heap |
17 // allocated objects. | 22 // allocated objects. |
18 // All Member fields of a class must be traced in the class' trace method. | 23 // All Member fields of a class must be traced in the class' trace method. |
19 // During the mark phase of the GC all live objects are marked as live and | 24 // During the mark phase of the GC all live objects are marked as live and |
20 // all Member fields of a live object will be traced marked as live as well. | 25 // all Member fields of a live object will be traced marked as live as well. |
haraken
2016/08/16 13:27:13
Remove this comment.
keishi
2016/08/17 11:18:28
Done.
| |
21 template<typename T> | 26 template<typename T, TracenessMemberConfiguration tracenessConfiguration = Trace dMemberConfiguration> |
22 class Member { | 27 class MemberBase { |
23 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 28 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
24 public: | 29 public: |
25 Member() : m_raw(nullptr) | 30 MemberBase() : m_raw(nullptr) |
26 { | 31 { |
32 saveCreationThreadHeap(); | |
27 } | 33 } |
28 | 34 |
29 Member(std::nullptr_t) : m_raw(nullptr) | 35 MemberBase(std::nullptr_t) : m_raw(nullptr) |
30 { | 36 { |
37 saveCreationThreadHeap(); | |
31 } | 38 } |
32 | 39 |
33 Member(T* raw) : m_raw(raw) | 40 MemberBase(T* raw) : m_raw(raw) |
34 { | 41 { |
42 saveCreationThreadHeap(); | |
35 checkPointer(); | 43 checkPointer(); |
36 } | 44 } |
37 | 45 |
38 explicit Member(T& raw) : m_raw(&raw) | 46 explicit MemberBase(T& raw) : m_raw(&raw) |
39 { | 47 { |
48 saveCreationThreadHeap(); | |
40 checkPointer(); | 49 checkPointer(); |
41 } | 50 } |
42 | 51 |
43 Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1)) | 52 MemberBase(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1)) |
44 { | 53 { |
54 saveCreationThreadHeap(); | |
45 } | 55 } |
46 | 56 |
47 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>( -1); } | 57 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>( -1); } |
48 | 58 |
49 Member(const Member& other) : m_raw(other) | 59 MemberBase(const MemberBase& other) : m_raw(other) |
50 { | 60 { |
61 saveCreationThreadHeap(); | |
51 checkPointer(); | 62 checkPointer(); |
52 } | 63 } |
53 | 64 |
54 template<typename U> | 65 template<typename U> |
55 Member(const Persistent<U>& other) | 66 MemberBase(const Persistent<U>& other) |
56 { | 67 { |
68 saveCreationThreadHeap(); | |
57 m_raw = other; | 69 m_raw = other; |
58 checkPointer(); | 70 checkPointer(); |
59 } | 71 } |
60 | 72 |
61 template<typename U> | 73 template<typename U> |
62 Member(const Member<U>& other) : m_raw(other) | 74 MemberBase(const MemberBase<U>& other) : m_raw(other) |
63 { | 75 { |
76 saveCreationThreadHeap(); | |
64 checkPointer(); | 77 checkPointer(); |
65 } | 78 } |
66 | 79 |
67 T* release() | 80 T* release() |
68 { | 81 { |
69 T* result = m_raw; | 82 T* result = m_raw; |
70 m_raw = nullptr; | 83 m_raw = nullptr; |
71 return result; | 84 return result; |
72 } | 85 } |
73 | 86 |
74 explicit operator bool() const { return m_raw; } | 87 explicit operator bool() const { return m_raw; } |
75 | 88 |
76 operator T*() const { return m_raw; } | 89 operator T*() const { return m_raw; } |
77 | 90 |
78 T* operator->() const { return m_raw; } | 91 T* operator->() const { return m_raw; } |
79 T& operator*() const { return *m_raw; } | 92 T& operator*() const { return *m_raw; } |
80 | 93 |
81 template<typename U> | 94 template<typename U> |
82 Member& operator=(const Persistent<U>& other) | 95 MemberBase& operator=(const Persistent<U>& other) |
83 { | 96 { |
84 m_raw = other; | 97 m_raw = other; |
85 checkPointer(); | 98 checkPointer(); |
86 return *this; | 99 return *this; |
87 } | 100 } |
88 | 101 |
89 template<typename U> | 102 template<typename U> |
90 Member& operator=(const Member<U>& other) | 103 MemberBase& operator=(const MemberBase<U>& other) |
91 { | 104 { |
92 m_raw = other; | 105 m_raw = other; |
93 checkPointer(); | 106 checkPointer(); |
94 return *this; | 107 return *this; |
95 } | 108 } |
96 | 109 |
97 template<typename U> | 110 template<typename U> |
98 Member& operator=(U* other) | 111 MemberBase& operator=(U* other) |
99 { | 112 { |
100 m_raw = other; | 113 m_raw = other; |
101 checkPointer(); | 114 checkPointer(); |
102 return *this; | 115 return *this; |
103 } | 116 } |
104 | 117 |
105 Member& operator=(std::nullptr_t) | 118 MemberBase& operator=(std::nullptr_t) |
106 { | 119 { |
107 m_raw = nullptr; | 120 m_raw = nullptr; |
108 return *this; | 121 return *this; |
109 } | 122 } |
110 | 123 |
111 void swap(Member<T>& other) | 124 void swap(MemberBase<T>& other) |
112 { | 125 { |
113 std::swap(m_raw, other.m_raw); | 126 std::swap(m_raw, other.m_raw); |
114 checkPointer(); | 127 checkPointer(); |
115 } | 128 } |
116 | 129 |
117 T* get() const { return m_raw; } | 130 T* get() const { return m_raw; } |
118 | 131 |
119 void clear() { m_raw = nullptr; } | 132 void clear() { m_raw = nullptr; } |
120 | 133 |
121 | 134 |
122 protected: | 135 protected: |
123 void checkPointer() | 136 void checkPointer() |
124 { | 137 { |
125 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | 138 #if DCHECK_IS_ON() |
126 if (!m_raw) | 139 if (!m_raw) |
127 return; | 140 return; |
128 // HashTable can store a special value (which is not aligned to the | 141 // HashTable can store a special value (which is not aligned to the |
129 // allocation granularity) to Member<> to represent a deleted entry. | 142 // allocation granularity) to Member<> to represent a deleted entry. |
130 // Thus we treat a pointer that is not aligned to the granularity | 143 // Thus we treat a pointer that is not aligned to the granularity |
131 // as a valid pointer. | 144 // as a valid pointer. |
132 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) | 145 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) |
133 return; | 146 return; |
134 | 147 |
148 ThreadState* current = ThreadState::current(); | |
149 if (tracenessConfiguration != UntracedMemberConfiguration && current) { | |
keishi
2016/08/16 13:05:49
Ignoring UntracedMember because in LayoutTests, Gr
haraken
2016/08/16 13:27:13
'tracenessConfiguration != UntracedMemberConfigura
keishi
2016/08/17 11:18:29
Done.
| |
150 if (m_creationThreadHeap) { | |
haraken
2016/08/16 13:27:13
How is it possible that m_creationThreadHeap is nu
keishi
2016/08/17 11:18:28
I think heap collections use memset to initialize
haraken
2016/08/17 11:40:41
OK, let's add a comment about it.
keishi
2016/08/17 12:23:20
Done.
| |
151 DCHECK_EQ(&ThreadState::fromObject(m_raw)->heap(), m_creationThr eadHeap); | |
152 DCHECK_EQ(¤t->heap(), m_creationThreadHeap); | |
153 } else { | |
154 DCHECK(&ThreadState::fromObject(m_raw)->heap() == ¤t->heap ()); | |
haraken
2016/08/16 13:27:13
Use DCHECK_EQ.
keishi
2016/08/17 11:18:29
Done.
| |
155 } | |
156 } | |
157 | |
158 #if defined(ADDRESS_SANITIZER) | |
135 // TODO(haraken): What we really want to check here is that the pointer | 159 // TODO(haraken): What we really want to check here is that the pointer |
136 // is a traceable object. In other words, the pointer is either of: | 160 // is a traceable object. In other words, the pointer is either of: |
137 // | 161 // |
138 // (a) a pointer to the head of an on-heap object. | 162 // (a) a pointer to the head of an on-heap object. |
139 // (b) a pointer to the head of an on-heap mixin object. | 163 // (b) a pointer to the head of an on-heap mixin object. |
140 // | 164 // |
141 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), | 165 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), |
142 // but we cannot call it here because it requires to include T.h. | 166 // but we cannot call it here because it requires to include T.h. |
143 // So we currently only try to implement the check for (a), but do | 167 // So we currently only try to implement the check for (a), but do |
144 // not insist that T's definition is in scope. | 168 // not insist that T's definition is in scope. |
145 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | 169 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) |
146 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | 170 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); |
147 #endif | 171 #endif |
172 #endif | |
173 } | |
174 | |
175 void saveCreationThreadHeap() | |
keishi
2016/08/16 13:05:50
|this| may be on the stack, and if it is we can't
| |
176 { | |
177 #if DCHECK_IS_ON() | |
178 if (ThreadState::current() && tracenessConfiguration != UntracedMemberCo nfiguration) | |
haraken
2016/08/16 13:27:13
Do we really need to check ThreadState::current()?
keishi
2016/08/17 11:18:28
Done.
| |
179 m_creationThreadHeap = &ThreadState::current()->heap(); | |
180 else | |
181 m_creationThreadHeap = nullptr; | |
182 #endif | |
148 } | 183 } |
149 | 184 |
150 T* m_raw; | 185 T* m_raw; |
186 #if DCHECK_IS_ON() | |
187 const ThreadHeap* m_creationThreadHeap; | |
188 #endif | |
151 | 189 |
152 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | 190 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
153 friend class Visitor; | 191 friend class Visitor; |
154 | 192 |
155 }; | 193 }; |
156 | 194 |
195 // Members are used in classes to contain strong pointers to other oilpan heap | |
196 // allocated objects. | |
197 // All Member fields of a class must be traced in the class' trace method. | |
198 // During the mark phase of the GC all live objects are marked as live and | |
199 // all Member fields of a live object will be traced marked as live as well. | |
200 template<typename T> | |
201 class Member : public MemberBase<T, TracedMemberConfiguration> { | |
202 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | |
203 typedef MemberBase<T, TracedMemberConfiguration> Parent; | |
204 public: | |
205 Member() : Parent() { } | |
206 Member(std::nullptr_t) : Parent(nullptr) { } | |
207 Member(T* raw) : Parent(raw) { } | |
208 Member(T& raw) : Parent(raw) { } | |
209 Member(WTF::HashTableDeletedValueType x) : Parent(x) { } | |
210 | |
211 Member(const Member& other) : Parent(other) { } | |
212 template<typename U> | |
213 Member(const Member<U>& other) : Parent(other) { } | |
214 template<typename U> | |
215 Member(const Persistent<U>& other) : Parent(other) { } | |
216 | |
217 template<typename U> | |
218 Member& operator=(const Persistent<U>& other) | |
219 { | |
220 Parent::operator=(other); | |
221 return *this; | |
222 } | |
223 | |
224 template<typename U> | |
225 Member& operator=(const Member<U>& other) | |
226 { | |
227 Parent::operator=(other); | |
228 return *this; | |
229 } | |
230 | |
231 template<typename U> | |
232 Member& operator=(const WeakMember<U>& other) | |
233 { | |
234 Parent::operator=(other); | |
235 return *this; | |
236 } | |
237 | |
238 template<typename U> | |
239 Member& operator=(U* other) | |
240 { | |
241 Parent::operator=(other); | |
242 return *this; | |
243 } | |
244 | |
245 Member& operator=(std::nullptr_t) | |
246 { | |
247 Parent::operator=(nullptr); | |
248 return *this; | |
249 } | |
250 | |
251 protected: | |
252 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | |
253 friend class Visitor; | |
254 }; | |
255 | |
157 // WeakMember is similar to Member in that it is used to point to other oilpan | 256 // WeakMember is similar to Member in that it is used to point to other oilpan |
158 // heap allocated objects. | 257 // heap allocated objects. |
159 // However instead of creating a strong pointer to the object, the WeakMember cr eates | 258 // However instead of creating a strong pointer to the object, the WeakMember cr eates |
160 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to | 259 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to |
161 // to a heap allocated object are weak the object will be garbage collected. At the | 260 // to a heap allocated object are weak the object will be garbage collected. At the |
162 // time of GC the weak pointers will automatically be set to null. | 261 // time of GC the weak pointers will automatically be set to null. |
163 template<typename T> | 262 template<typename T> |
164 class WeakMember : public Member<T> { | 263 class WeakMember : public MemberBase<T, TracedMemberConfiguration> { |
264 typedef MemberBase<T, TracedMemberConfiguration> Parent; | |
165 public: | 265 public: |
166 WeakMember() : Member<T>() { } | 266 WeakMember() : Parent() { } |
167 | 267 |
168 WeakMember(std::nullptr_t) : Member<T>(nullptr) { } | 268 WeakMember(std::nullptr_t) : Parent(nullptr) { } |
169 | 269 |
170 WeakMember(T* raw) : Member<T>(raw) { } | 270 WeakMember(T* raw) : Parent(raw) { } |
171 | 271 |
172 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | 272 WeakMember(WTF::HashTableDeletedValueType x) : Parent(x) { } |
173 | 273 |
174 template<typename U> | 274 template<typename U> |
175 WeakMember(const Persistent<U>& other) : Member<T>(other) { } | 275 WeakMember(const Persistent<U>& other) : Parent(other) { } |
176 | 276 |
177 template<typename U> | 277 template<typename U> |
178 WeakMember(const Member<U>& other) : Member<T>(other) { } | 278 WeakMember(const Member<U>& other) : Parent(other) { } |
179 | 279 |
180 template<typename U> | 280 template<typename U> |
181 WeakMember& operator=(const Persistent<U>& other) | 281 WeakMember& operator=(const Persistent<U>& other) |
182 { | 282 { |
183 this->m_raw = other; | 283 this->m_raw = other; |
184 this->checkPointer(); | 284 this->checkPointer(); |
185 return *this; | 285 return *this; |
186 } | 286 } |
187 | 287 |
188 template<typename U> | 288 template<typename U> |
(...skipping 26 matching lines...) Expand all Loading... | |
215 | 315 |
216 // UntracedMember is a pointer to an on-heap object that is not traced for some | 316 // UntracedMember is a pointer to an on-heap object that is not traced for some |
217 // reason. Please don't use this unless you understand what you're doing. | 317 // reason. Please don't use this unless you understand what you're doing. |
218 // Basically, all pointers to on-heap objects must be stored in either of | 318 // Basically, all pointers to on-heap objects must be stored in either of |
219 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to | 319 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to |
220 // on-heap objects. However, there can be scenarios where you have to use raw | 320 // on-heap objects. However, there can be scenarios where you have to use raw |
221 // pointers for some reason, and in that case you can use UntracedMember. Of | 321 // pointers for some reason, and in that case you can use UntracedMember. Of |
222 // course, it must be guaranteed that the pointing on-heap object is kept alive | 322 // course, it must be guaranteed that the pointing on-heap object is kept alive |
223 // while the raw pointer is pointing to the object. | 323 // while the raw pointer is pointing to the object. |
224 template<typename T> | 324 template<typename T> |
225 class UntracedMember final : public Member<T> { | 325 class UntracedMember final : public MemberBase<T, UntracedMemberConfiguration> { |
326 typedef MemberBase<T, UntracedMemberConfiguration> Parent; | |
226 public: | 327 public: |
227 UntracedMember() : Member<T>() { } | 328 UntracedMember() : Parent() { } |
228 | 329 |
229 UntracedMember(std::nullptr_t) : Member<T>(nullptr) { } | 330 UntracedMember(std::nullptr_t) : Parent(nullptr) { } |
230 | 331 |
231 UntracedMember(T* raw) : Member<T>(raw) { } | 332 UntracedMember(T* raw) : Parent(raw) { } |
232 | 333 |
233 template<typename U> | 334 template<typename U> |
234 UntracedMember(const Persistent<U>& other) : Member<T>(other) { } | 335 UntracedMember(const Persistent<U>& other) : Parent(other) { } |
235 | 336 |
236 template<typename U> | 337 template<typename U> |
237 UntracedMember(const Member<U>& other) : Member<T>(other) { } | 338 UntracedMember(const Member<U>& other) : Parent(other) { } |
238 | 339 |
239 UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | 340 UntracedMember(WTF::HashTableDeletedValueType x) : Parent(x) { } |
240 | 341 |
241 template<typename U> | 342 template<typename U> |
242 UntracedMember& operator=(const Persistent<U>& other) | 343 UntracedMember& operator=(const Persistent<U>& other) |
243 { | 344 { |
244 this->m_raw = other; | 345 this->m_raw = other; |
245 this->checkPointer(); | 346 this->checkPointer(); |
246 return *this; | 347 return *this; |
247 } | 348 } |
248 | 349 |
249 template<typename U> | 350 template<typename U> |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 | 416 |
316 template<typename T> | 417 template<typename T> |
317 struct IsTraceable<blink::WeakMember<T>> { | 418 struct IsTraceable<blink::WeakMember<T>> { |
318 STATIC_ONLY(IsTraceable); | 419 STATIC_ONLY(IsTraceable); |
319 static const bool value = true; | 420 static const bool value = true; |
320 }; | 421 }; |
321 | 422 |
322 } // namespace WTF | 423 } // namespace WTF |
323 | 424 |
324 #endif // Member_h | 425 #endif // Member_h |
OLD | NEW |