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 saveCreationThreadHeap(); | |
27 } | 28 } |
28 | 29 |
29 Member(std::nullptr_t) : m_raw(nullptr) | 30 MemberBase(std::nullptr_t) : m_raw(nullptr) |
30 { | 31 { |
32 saveCreationThreadHeap(); | |
31 } | 33 } |
32 | 34 |
33 Member(T* raw) : m_raw(raw) | 35 MemberBase(T* raw) : m_raw(raw) |
34 { | 36 { |
37 saveCreationThreadHeap(); | |
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 saveCreationThreadHeap(); | |
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 saveCreationThreadHeap(); | |
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 saveCreationThreadHeap(); | |
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 saveCreationThreadHeap(); | |
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 saveCreationThreadHeap(); | |
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(); | |
haraken
2016/08/17 11:40:41
Add DCHECK(current).
keishi
2016/08/17 12:23:20
Done.
| |
145 if (m_creationThreadState) { | |
146 DCHECK_EQ(&ThreadState::fromObject(m_raw)->heap(), &m_creationTh readState->heap()); | |
haraken
2016/08/17 11:40:41
Add a developer-friendly comment to help them unde
keishi
2016/08/17 12:23:20
Done.
| |
147 DCHECK_EQ(¤t->heap(), &m_creationThreadState->heap()); | |
148 } else { | |
149 DCHECK_EQ(&ThreadState::fromObject(m_raw)->heap(), ¤t->hea p()); | |
150 } | |
151 } | |
152 | |
153 #if defined(ADDRESS_SANITIZER) | |
135 // TODO(haraken): What we really want to check here is that the pointer | 154 // 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: | 155 // is a traceable object. In other words, the pointer is either of: |
137 // | 156 // |
138 // (a) a pointer to the head of an on-heap object. | 157 // (a) a pointer to the head of an on-heap object. |
139 // (b) a pointer to the head of an on-heap mixin object. | 158 // (b) a pointer to the head of an on-heap mixin object. |
140 // | 159 // |
141 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), | 160 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), |
142 // but we cannot call it here because it requires to include T.h. | 161 // 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 | 162 // So we currently only try to implement the check for (a), but do |
144 // not insist that T's definition is in scope. | 163 // not insist that T's definition is in scope. |
145 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | 164 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) |
146 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | 165 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); |
147 #endif | 166 #endif |
167 #endif | |
168 } | |
169 | |
170 void saveCreationThreadHeap() | |
171 { | |
172 #if DCHECK_IS_ON() | |
173 if (tracenessConfiguration == TracenessMemberConfiguration::Untraced) | |
174 m_creationThreadState = nullptr; | |
175 else | |
176 m_creationThreadState = ThreadState::current(); | |
haraken
2016/08/17 11:40:41
Add DCHECK(ThreadState::current()).
keishi
2016/08/17 12:23:20
Done.
| |
177 #endif | |
148 } | 178 } |
149 | 179 |
150 T* m_raw; | 180 T* m_raw; |
181 #if DCHECK_IS_ON() | |
182 const ThreadState* m_creationThreadState; | |
183 #endif | |
151 | 184 |
152 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | 185 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; |
153 friend class Visitor; | 186 friend class Visitor; |
154 | 187 |
155 }; | 188 }; |
156 | 189 |
190 // Members are used in classes to contain strong pointers to other oilpan heap | |
191 // allocated objects. | |
192 // All Member fields of a class must be traced in the class' trace method. | |
193 // During the mark phase of the GC all live objects are marked as live and | |
194 // all Member fields of a live object will be traced marked as live as well. | |
195 template<typename T> | |
196 class Member : public MemberBase<T, TracenessMemberConfiguration::Traced> { | |
197 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | |
198 typedef MemberBase<T, TracenessMemberConfiguration::Traced> Parent; | |
199 public: | |
200 Member() : Parent() { } | |
201 Member(std::nullptr_t) : Parent(nullptr) { } | |
202 Member(T* raw) : Parent(raw) { } | |
203 Member(T& raw) : Parent(raw) { } | |
204 Member(WTF::HashTableDeletedValueType x) : Parent(x) { } | |
205 | |
206 Member(const Member& other) : Parent(other) { } | |
207 template<typename U> | |
208 Member(const Member<U>& other) : Parent(other) { } | |
209 template<typename U> | |
210 Member(const Persistent<U>& other) : Parent(other) { } | |
211 | |
212 template<typename U> | |
213 Member& operator=(const Persistent<U>& other) | |
214 { | |
215 Parent::operator=(other); | |
216 return *this; | |
217 } | |
218 | |
219 template<typename U> | |
220 Member& operator=(const Member<U>& other) | |
221 { | |
222 Parent::operator=(other); | |
223 return *this; | |
224 } | |
225 | |
226 template<typename U> | |
227 Member& operator=(const WeakMember<U>& other) | |
228 { | |
229 Parent::operator=(other); | |
230 return *this; | |
231 } | |
232 | |
233 template<typename U> | |
234 Member& operator=(U* other) | |
235 { | |
236 Parent::operator=(other); | |
237 return *this; | |
238 } | |
239 | |
240 Member& operator=(std::nullptr_t) | |
241 { | |
242 Parent::operator=(nullptr); | |
243 return *this; | |
244 } | |
245 | |
246 protected: | |
247 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | |
248 friend class Visitor; | |
249 }; | |
250 | |
157 // WeakMember is similar to Member in that it is used to point to other oilpan | 251 // WeakMember is similar to Member in that it is used to point to other oilpan |
158 // heap allocated objects. | 252 // heap allocated objects. |
159 // However instead of creating a strong pointer to the object, the WeakMember cr eates | 253 // 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 | 254 // 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 | 255 // 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. | 256 // time of GC the weak pointers will automatically be set to null. |
163 template<typename T> | 257 template<typename T> |
164 class WeakMember : public Member<T> { | 258 class WeakMember : public MemberBase<T, TracenessMemberConfiguration::Traced> { |
259 typedef MemberBase<T, TracenessMemberConfiguration::Traced> Parent; | |
165 public: | 260 public: |
166 WeakMember() : Member<T>() { } | 261 WeakMember() : Parent() { } |
167 | 262 |
168 WeakMember(std::nullptr_t) : Member<T>(nullptr) { } | 263 WeakMember(std::nullptr_t) : Parent(nullptr) { } |
169 | 264 |
170 WeakMember(T* raw) : Member<T>(raw) { } | 265 WeakMember(T* raw) : Parent(raw) { } |
171 | 266 |
172 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | 267 WeakMember(WTF::HashTableDeletedValueType x) : Parent(x) { } |
173 | 268 |
174 template<typename U> | 269 template<typename U> |
175 WeakMember(const Persistent<U>& other) : Member<T>(other) { } | 270 WeakMember(const Persistent<U>& other) : Parent(other) { } |
176 | 271 |
177 template<typename U> | 272 template<typename U> |
178 WeakMember(const Member<U>& other) : Member<T>(other) { } | 273 WeakMember(const Member<U>& other) : Parent(other) { } |
179 | 274 |
180 template<typename U> | 275 template<typename U> |
181 WeakMember& operator=(const Persistent<U>& other) | 276 WeakMember& operator=(const Persistent<U>& other) |
182 { | 277 { |
183 this->m_raw = other; | 278 this->m_raw = other; |
184 this->checkPointer(); | 279 this->checkPointer(); |
185 return *this; | 280 return *this; |
186 } | 281 } |
187 | 282 |
188 template<typename U> | 283 template<typename U> |
(...skipping 26 matching lines...) Expand all Loading... | |
215 | 310 |
216 // UntracedMember is a pointer to an on-heap object that is not traced for some | 311 // 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. | 312 // 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 | 313 // 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 | 314 // 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 | 315 // 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 | 316 // 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 | 317 // course, it must be guaranteed that the pointing on-heap object is kept alive |
223 // while the raw pointer is pointing to the object. | 318 // while the raw pointer is pointing to the object. |
224 template<typename T> | 319 template<typename T> |
225 class UntracedMember final : public Member<T> { | 320 class UntracedMember final : public MemberBase<T, TracenessMemberConfiguration:: Untraced> { |
321 typedef MemberBase<T, TracenessMemberConfiguration::Untraced> Parent; | |
226 public: | 322 public: |
227 UntracedMember() : Member<T>() { } | 323 UntracedMember() : Parent() { } |
228 | 324 |
229 UntracedMember(std::nullptr_t) : Member<T>(nullptr) { } | 325 UntracedMember(std::nullptr_t) : Parent(nullptr) { } |
230 | 326 |
231 UntracedMember(T* raw) : Member<T>(raw) { } | 327 UntracedMember(T* raw) : Parent(raw) { } |
232 | 328 |
233 template<typename U> | 329 template<typename U> |
234 UntracedMember(const Persistent<U>& other) : Member<T>(other) { } | 330 UntracedMember(const Persistent<U>& other) : Parent(other) { } |
235 | 331 |
236 template<typename U> | 332 template<typename U> |
237 UntracedMember(const Member<U>& other) : Member<T>(other) { } | 333 UntracedMember(const Member<U>& other) : Parent(other) { } |
238 | 334 |
239 UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | 335 UntracedMember(WTF::HashTableDeletedValueType x) : Parent(x) { } |
240 | 336 |
241 template<typename U> | 337 template<typename U> |
242 UntracedMember& operator=(const Persistent<U>& other) | 338 UntracedMember& operator=(const Persistent<U>& other) |
243 { | 339 { |
244 this->m_raw = other; | 340 this->m_raw = other; |
245 this->checkPointer(); | 341 this->checkPointer(); |
246 return *this; | 342 return *this; |
247 } | 343 } |
248 | 344 |
249 template<typename U> | 345 template<typename U> |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 | 411 |
316 template<typename T> | 412 template<typename T> |
317 struct IsTraceable<blink::WeakMember<T>> { | 413 struct IsTraceable<blink::WeakMember<T>> { |
318 STATIC_ONLY(IsTraceable); | 414 STATIC_ONLY(IsTraceable); |
319 static const bool value = true; | 415 static const bool value = true; |
320 }; | 416 }; |
321 | 417 |
322 } // namespace WTF | 418 } // namespace WTF |
323 | 419 |
324 #endif // Member_h | 420 #endif // Member_h |
OLD | NEW |