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 // 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 |