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 // Members are used in classes to contain strong pointers to other oilpan heap | 16 enum class TracenessMemberConfiguration { |
17 // allocated objects. | 17 Traced, |
18 // All Member fields of a class must be traced in the class' trace method. | 18 Untraced, |
19 // During the mark phase of the GC all live objects are marked as live and | 19 }; |
20 // all Member fields of a live object will be traced marked as live as well. | 20 |
21 template<typename T> | 21 template<typename T, TracenessMemberConfiguration tracenessConfiguration = Trace
nessMemberConfiguration::Traced> |
22 class Member { | 22 class MemberBase { |
23 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | 23 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
24 public: | 24 public: |
25 Member() : m_raw(nullptr) | 25 MemberBase() : m_raw(nullptr) |
26 { | 26 { |
| 27 saveCreationThreadState(); |
27 } | 28 } |
28 | 29 |
29 Member(std::nullptr_t) : m_raw(nullptr) | 30 MemberBase(std::nullptr_t) : m_raw(nullptr) |
30 { | 31 { |
| 32 saveCreationThreadState(); |
31 } | 33 } |
32 | 34 |
33 Member(T* raw) : m_raw(raw) | 35 MemberBase(T* raw) : m_raw(raw) |
34 { | 36 { |
| 37 saveCreationThreadState(); |
35 checkPointer(); | 38 checkPointer(); |
36 } | 39 } |
37 | 40 |
38 explicit Member(T& raw) : m_raw(&raw) | 41 explicit MemberBase(T& raw) : m_raw(&raw) |
39 { | 42 { |
| 43 saveCreationThreadState(); |
40 checkPointer(); | 44 checkPointer(); |
41 } | 45 } |
42 | 46 |
43 Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1)) | 47 MemberBase(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1)) |
44 { | 48 { |
| 49 saveCreationThreadState(); |
45 } | 50 } |
46 | 51 |
47 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(
-1); } | 52 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(
-1); } |
48 | 53 |
49 Member(const Member& other) : m_raw(other) | 54 MemberBase(const MemberBase& other) : m_raw(other) |
50 { | 55 { |
| 56 saveCreationThreadState(); |
51 checkPointer(); | 57 checkPointer(); |
52 } | 58 } |
53 | 59 |
54 template<typename U> | 60 template<typename U> |
55 Member(const Persistent<U>& other) | 61 MemberBase(const Persistent<U>& other) |
56 { | 62 { |
| 63 saveCreationThreadState(); |
57 m_raw = other; | 64 m_raw = other; |
58 checkPointer(); | 65 checkPointer(); |
59 } | 66 } |
60 | 67 |
61 template<typename U> | 68 template<typename U> |
62 Member(const Member<U>& other) : m_raw(other) | 69 MemberBase(const MemberBase<U>& other) : m_raw(other) |
63 { | 70 { |
| 71 saveCreationThreadState(); |
64 checkPointer(); | 72 checkPointer(); |
65 } | 73 } |
66 | 74 |
67 T* release() | 75 T* release() |
68 { | 76 { |
69 T* result = m_raw; | 77 T* result = m_raw; |
70 m_raw = nullptr; | 78 m_raw = nullptr; |
71 return result; | 79 return result; |
72 } | 80 } |
73 | 81 |
74 explicit operator bool() const { return m_raw; } | 82 explicit operator bool() const { return m_raw; } |
75 | 83 |
76 operator T*() const { return m_raw; } | 84 operator T*() const { return m_raw; } |
77 | 85 |
78 T* operator->() const { return m_raw; } | 86 T* operator->() const { return m_raw; } |
79 T& operator*() const { return *m_raw; } | 87 T& operator*() const { return *m_raw; } |
80 | 88 |
81 template<typename U> | 89 template<typename U> |
82 Member& operator=(const Persistent<U>& other) | 90 MemberBase& operator=(const Persistent<U>& other) |
83 { | 91 { |
84 m_raw = other; | 92 m_raw = other; |
85 checkPointer(); | 93 checkPointer(); |
86 return *this; | 94 return *this; |
87 } | 95 } |
88 | 96 |
89 template<typename U> | 97 template<typename U> |
90 Member& operator=(const Member<U>& other) | 98 MemberBase& operator=(const MemberBase<U>& other) |
91 { | 99 { |
92 m_raw = other; | 100 m_raw = other; |
93 checkPointer(); | 101 checkPointer(); |
94 return *this; | 102 return *this; |
95 } | 103 } |
96 | 104 |
97 template<typename U> | 105 template<typename U> |
98 Member& operator=(U* other) | 106 MemberBase& operator=(U* other) |
99 { | 107 { |
100 m_raw = other; | 108 m_raw = other; |
101 checkPointer(); | 109 checkPointer(); |
102 return *this; | 110 return *this; |
103 } | 111 } |
104 | 112 |
105 Member& operator=(std::nullptr_t) | 113 MemberBase& operator=(std::nullptr_t) |
106 { | 114 { |
107 m_raw = nullptr; | 115 m_raw = nullptr; |
108 return *this; | 116 return *this; |
109 } | 117 } |
110 | 118 |
111 void swap(Member<T>& other) | 119 void swap(MemberBase<T>& other) |
112 { | 120 { |
113 std::swap(m_raw, other.m_raw); | 121 std::swap(m_raw, other.m_raw); |
114 checkPointer(); | 122 checkPointer(); |
115 } | 123 } |
116 | 124 |
117 T* get() const { return m_raw; } | 125 T* get() const { return m_raw; } |
118 | 126 |
119 void clear() { m_raw = nullptr; } | 127 void clear() { m_raw = nullptr; } |
120 | 128 |
121 | 129 |
122 protected: | 130 protected: |
123 void checkPointer() | 131 void checkPointer() |
124 { | 132 { |
125 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | 133 #if DCHECK_IS_ON() |
126 if (!m_raw) | 134 if (!m_raw) |
127 return; | 135 return; |
128 // HashTable can store a special value (which is not aligned to the | 136 // HashTable can store a special value (which is not aligned to the |
129 // allocation granularity) to Member<> to represent a deleted entry. | 137 // allocation granularity) to Member<> to represent a deleted entry. |
130 // Thus we treat a pointer that is not aligned to the granularity | 138 // Thus we treat a pointer that is not aligned to the granularity |
131 // as a valid pointer. | 139 // as a valid pointer. |
132 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) | 140 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) |
133 return; | 141 return; |
134 | 142 |
| 143 if (tracenessConfiguration != TracenessMemberConfiguration::Untraced) { |
| 144 ThreadState* current = ThreadState::current(); |
| 145 DCHECK(current); |
| 146 // m_creationThreadState may be null when this is used in a heap |
| 147 // collection which initialized the Member with memset and the |
| 148 // constructor wasn't called. |
| 149 if (m_creationThreadState) { |
| 150 // Member should point to objects that belong in the same Thread
Heap. |
| 151 DCHECK_EQ(&ThreadState::fromObject(m_raw)->heap(), &m_creationTh
readState->heap()); |
| 152 // Member should point to objects that belong in the same Thread
Heap. |
| 153 DCHECK_EQ(¤t->heap(), &m_creationThreadState->heap()); |
| 154 } else { |
| 155 DCHECK_EQ(&ThreadState::fromObject(m_raw)->heap(), ¤t->hea
p()); |
| 156 } |
| 157 } |
| 158 |
| 159 #if defined(ADDRESS_SANITIZER) |
135 // TODO(haraken): What we really want to check here is that the pointer | 160 // 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: | 161 // is a traceable object. In other words, the pointer is either of: |
137 // | 162 // |
138 // (a) a pointer to the head of an on-heap object. | 163 // (a) a pointer to the head of an on-heap object. |
139 // (b) a pointer to the head of an on-heap mixin object. | 164 // (b) a pointer to the head of an on-heap mixin object. |
140 // | 165 // |
141 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), | 166 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), |
142 // but we cannot call it here because it requires to include T.h. | 167 // 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 | 168 // So we currently only try to implement the check for (a), but do |
144 // not insist that T's definition is in scope. | 169 // not insist that T's definition is in scope. |
145 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | 170 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) |
146 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | 171 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); |
147 #endif | 172 #endif |
| 173 #endif |
| 174 } |
| 175 |
| 176 void saveCreationThreadState() |
| 177 { |
| 178 #if DCHECK_IS_ON() |
| 179 if (tracenessConfiguration == TracenessMemberConfiguration::Untraced) { |
| 180 m_creationThreadState = nullptr; |
| 181 } else { |
| 182 m_creationThreadState = ThreadState::current(); |
| 183 // Members should be created in an attached thread. But an empty |
| 184 // value Member may be created on an unattached thread by a heap |
| 185 // collection iterator. |
| 186 DCHECK(m_creationThreadState || !m_raw); |
| 187 } |
| 188 #endif |
148 } | 189 } |
149 | 190 |
150 T* m_raw; | 191 T* m_raw; |
| 192 #if DCHECK_IS_ON() |
| 193 const ThreadState* m_creationThreadState; |
| 194 #endif |
151 | 195 |
152 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | 196 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
153 friend class Visitor; | 197 friend class Visitor; |
154 | 198 |
155 }; | 199 }; |
156 | 200 |
| 201 // Members are used in classes to contain strong pointers to other oilpan heap |
| 202 // allocated objects. |
| 203 // All Member fields of a class must be traced in the class' trace method. |
| 204 // During the mark phase of the GC all live objects are marked as live and |
| 205 // all Member fields of a live object will be traced marked as live as well. |
| 206 template<typename T> |
| 207 class Member : public MemberBase<T, TracenessMemberConfiguration::Traced> { |
| 208 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); |
| 209 typedef MemberBase<T, TracenessMemberConfiguration::Traced> Parent; |
| 210 public: |
| 211 Member() : Parent() { } |
| 212 Member(std::nullptr_t) : Parent(nullptr) { } |
| 213 Member(T* raw) : Parent(raw) { } |
| 214 Member(T& raw) : Parent(raw) { } |
| 215 Member(WTF::HashTableDeletedValueType x) : Parent(x) { } |
| 216 |
| 217 Member(const Member& other) : Parent(other) { } |
| 218 template<typename U> |
| 219 Member(const Member<U>& other) : Parent(other) { } |
| 220 template<typename U> |
| 221 Member(const Persistent<U>& other) : Parent(other) { } |
| 222 |
| 223 template<typename U> |
| 224 Member& operator=(const Persistent<U>& other) |
| 225 { |
| 226 Parent::operator=(other); |
| 227 return *this; |
| 228 } |
| 229 |
| 230 template<typename U> |
| 231 Member& operator=(const Member<U>& other) |
| 232 { |
| 233 Parent::operator=(other); |
| 234 return *this; |
| 235 } |
| 236 |
| 237 template<typename U> |
| 238 Member& operator=(const WeakMember<U>& other) |
| 239 { |
| 240 Parent::operator=(other); |
| 241 return *this; |
| 242 } |
| 243 |
| 244 template<typename U> |
| 245 Member& operator=(U* other) |
| 246 { |
| 247 Parent::operator=(other); |
| 248 return *this; |
| 249 } |
| 250 |
| 251 Member& operator=(std::nullptr_t) |
| 252 { |
| 253 Parent::operator=(nullptr); |
| 254 return *this; |
| 255 } |
| 256 |
| 257 protected: |
| 258 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
| 259 friend class Visitor; |
| 260 }; |
| 261 |
157 // WeakMember is similar to Member in that it is used to point to other oilpan | 262 // WeakMember is similar to Member in that it is used to point to other oilpan |
158 // heap allocated objects. | 263 // heap allocated objects. |
159 // However instead of creating a strong pointer to the object, the WeakMember cr
eates | 264 // 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 | 265 // 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 | 266 // 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. | 267 // time of GC the weak pointers will automatically be set to null. |
163 template<typename T> | 268 template<typename T> |
164 class WeakMember : public Member<T> { | 269 class WeakMember : public MemberBase<T, TracenessMemberConfiguration::Traced> { |
| 270 typedef MemberBase<T, TracenessMemberConfiguration::Traced> Parent; |
165 public: | 271 public: |
166 WeakMember() : Member<T>() { } | 272 WeakMember() : Parent() { } |
167 | 273 |
168 WeakMember(std::nullptr_t) : Member<T>(nullptr) { } | 274 WeakMember(std::nullptr_t) : Parent(nullptr) { } |
169 | 275 |
170 WeakMember(T* raw) : Member<T>(raw) { } | 276 WeakMember(T* raw) : Parent(raw) { } |
171 | 277 |
172 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | 278 WeakMember(WTF::HashTableDeletedValueType x) : Parent(x) { } |
173 | 279 |
174 template<typename U> | 280 template<typename U> |
175 WeakMember(const Persistent<U>& other) : Member<T>(other) { } | 281 WeakMember(const Persistent<U>& other) : Parent(other) { } |
176 | 282 |
177 template<typename U> | 283 template<typename U> |
178 WeakMember(const Member<U>& other) : Member<T>(other) { } | 284 WeakMember(const Member<U>& other) : Parent(other) { } |
179 | 285 |
180 template<typename U> | 286 template<typename U> |
181 WeakMember& operator=(const Persistent<U>& other) | 287 WeakMember& operator=(const Persistent<U>& other) |
182 { | 288 { |
183 this->m_raw = other; | 289 this->m_raw = other; |
184 this->checkPointer(); | 290 this->checkPointer(); |
185 return *this; | 291 return *this; |
186 } | 292 } |
187 | 293 |
188 template<typename U> | 294 template<typename U> |
(...skipping 26 matching lines...) Expand all Loading... |
215 | 321 |
216 // UntracedMember is a pointer to an on-heap object that is not traced for some | 322 // 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. | 323 // 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 | 324 // 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 | 325 // 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 | 326 // 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 | 327 // 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 | 328 // course, it must be guaranteed that the pointing on-heap object is kept alive |
223 // while the raw pointer is pointing to the object. | 329 // while the raw pointer is pointing to the object. |
224 template<typename T> | 330 template<typename T> |
225 class UntracedMember final : public Member<T> { | 331 class UntracedMember final : public MemberBase<T, TracenessMemberConfiguration::
Untraced> { |
| 332 typedef MemberBase<T, TracenessMemberConfiguration::Untraced> Parent; |
226 public: | 333 public: |
227 UntracedMember() : Member<T>() { } | 334 UntracedMember() : Parent() { } |
228 | 335 |
229 UntracedMember(std::nullptr_t) : Member<T>(nullptr) { } | 336 UntracedMember(std::nullptr_t) : Parent(nullptr) { } |
230 | 337 |
231 UntracedMember(T* raw) : Member<T>(raw) { } | 338 UntracedMember(T* raw) : Parent(raw) { } |
232 | 339 |
233 template<typename U> | 340 template<typename U> |
234 UntracedMember(const Persistent<U>& other) : Member<T>(other) { } | 341 UntracedMember(const Persistent<U>& other) : Parent(other) { } |
235 | 342 |
236 template<typename U> | 343 template<typename U> |
237 UntracedMember(const Member<U>& other) : Member<T>(other) { } | 344 UntracedMember(const Member<U>& other) : Parent(other) { } |
238 | 345 |
239 UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | 346 UntracedMember(WTF::HashTableDeletedValueType x) : Parent(x) { } |
240 | 347 |
241 template<typename U> | 348 template<typename U> |
242 UntracedMember& operator=(const Persistent<U>& other) | 349 UntracedMember& operator=(const Persistent<U>& other) |
243 { | 350 { |
244 this->m_raw = other; | 351 this->m_raw = other; |
245 this->checkPointer(); | 352 this->checkPointer(); |
246 return *this; | 353 return *this; |
247 } | 354 } |
248 | 355 |
249 template<typename U> | 356 template<typename U> |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 | 422 |
316 template<typename T> | 423 template<typename T> |
317 struct IsTraceable<blink::WeakMember<T>> { | 424 struct IsTraceable<blink::WeakMember<T>> { |
318 STATIC_ONLY(IsTraceable); | 425 STATIC_ONLY(IsTraceable); |
319 static const bool value = true; | 426 static const bool value = true; |
320 }; | 427 }; |
321 | 428 |
322 } // namespace WTF | 429 } // namespace WTF |
323 | 430 |
324 #endif // Member_h | 431 #endif // Member_h |
OLD | NEW |