Chromium Code Reviews| 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 |