Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2014 Google Inc. All rights reserved. | 2 * Copyright (C) 2014 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #ifndef Handle_h | 31 #ifndef Handle_h |
| 32 #define Handle_h | 32 #define Handle_h |
| 33 | 33 |
| 34 #include "heap/Heap.h" | 34 #include "heap/Heap.h" |
| 35 #include "heap/ThreadState.h" | 35 #include "heap/ThreadState.h" |
| 36 #include "heap/Visitor.h" | 36 #include "heap/Visitor.h" |
| 37 | 37 |
| 38 #include "wtf/Locker.h" | |
| 38 #include "wtf/RawPtr.h" | 39 #include "wtf/RawPtr.h" |
| 39 #include "wtf/RefCounted.h" | 40 #include "wtf/RefCounted.h" |
| 40 | 41 |
| 41 namespace WebCore { | 42 namespace WebCore { |
| 42 | 43 |
| 43 template<typename T> class Member; | 44 template<typename T> class Member; |
| 44 | 45 |
| 45 class PersistentNode { | 46 class PersistentNode { |
| 46 public: | 47 public: |
| 47 explicit PersistentNode(TraceCallback trace) | 48 explicit PersistentNode(TraceCallback trace) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 69 m_trace(visitor, this); | 70 m_trace(visitor, this); |
| 70 } | 71 } |
| 71 | 72 |
| 72 protected: | 73 protected: |
| 73 TraceCallback m_trace; | 74 TraceCallback m_trace; |
| 74 | 75 |
| 75 private: | 76 private: |
| 76 PersistentNode* m_next; | 77 PersistentNode* m_next; |
| 77 PersistentNode* m_prev; | 78 PersistentNode* m_prev; |
| 78 | 79 |
| 79 template<ThreadAffinity affinity, typename Owner> friend class PersistentBas e; | 80 template<typename RootsAccessor, typename Owner> friend class PersistentBase ; |
| 80 friend class PersistentAnchor; | 81 friend class PersistentAnchor; |
| 81 friend class ThreadState; | 82 friend class ThreadState; |
| 82 }; | 83 }; |
| 83 | 84 |
| 84 template<ThreadAffinity Affinity, typename Owner> | 85 // RootsAccessor for Persistent that provides access to thread-local list |
| 86 // of persistent handles. Can only be used to create handles that | |
| 87 // are constructed and destructed on the same thread. | |
| 88 template<ThreadAffinity Affinity> | |
| 89 class ThreadLocalPersistents { | |
| 90 public: | |
| 91 static PersistentNode* roots() { return state()->roots(); } | |
| 92 | |
| 93 // No locking requires. Just checks that we are at the right thread. | |
|
Mads Ager (chromium)
2014/02/17 15:00:13
required
Vyacheslav Egorov (Chromium)
2014/02/17 15:52:35
Done.
| |
| 94 class Lock { | |
| 95 public: | |
| 96 Lock() { state()->checkThread(); } | |
| 97 }; | |
| 98 | |
| 99 private: | |
| 100 static ThreadState* state() { return ThreadStateFor<Affinity>::state(); } | |
| 101 }; | |
| 102 | |
| 103 // RootsAccessor for Persistent that provides synchronized access to global | |
| 104 // list of persistent handles. Can be used for persistent handles that are | |
| 105 // passed between threads. | |
| 106 class GlobalPersistents { | |
| 107 public: | |
| 108 static PersistentNode* roots() { return ThreadState::globalRoots(); } | |
| 109 | |
| 110 class Lock { | |
| 111 public: | |
| 112 Lock() : m_locker(ThreadState::globalRootsMutex()) { } | |
| 113 private: | |
| 114 MutexLocker m_locker; | |
| 115 }; | |
| 116 }; | |
| 117 | |
| 118 // Base class for persistent handles. RootsAccessor specifies which list to | |
| 119 // link resulting handle into. Owner specifies the class containing trace | |
| 120 // method. | |
| 121 template<typename RootsAccessor, typename Owner> | |
| 85 class PersistentBase : public PersistentNode { | 122 class PersistentBase : public PersistentNode { |
| 86 public: | 123 public: |
| 87 ~PersistentBase() | 124 ~PersistentBase() |
| 88 { | 125 { |
| 89 #ifndef NDEBUG | 126 #ifndef NDEBUG |
| 90 ASSERT(isAlive()); | 127 ASSERT(isAlive()); |
| 91 ASSERT(m_next->isAlive()); | 128 ASSERT(m_next->isAlive()); |
| 92 ASSERT(m_prev->isAlive()); | 129 ASSERT(m_prev->isAlive()); |
| 93 m_threadState->checkThread(); | 130 ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is u sing the same roots list. |
| 94 #endif | 131 #endif |
| 132 typename RootsAccessor::Lock lock; | |
|
Mads Ager (chromium)
2014/02/17 15:00:13
Shouldn't you lock before the debug-mode code? The
Vyacheslav Egorov (Chromium)
2014/02/17 15:52:35
Good catch. Fixed.
| |
| 95 m_next->m_prev = m_prev; | 133 m_next->m_prev = m_prev; |
| 96 m_prev->m_next = m_next; | 134 m_prev->m_next = m_next; |
| 97 } | 135 } |
| 98 | 136 |
| 99 protected: | 137 protected: |
| 100 inline PersistentBase() | 138 inline PersistentBase() |
| 101 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) | 139 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) |
| 102 #ifndef NDEBUG | 140 #ifndef NDEBUG |
| 103 , m_threadState(state()) | 141 , m_roots(RootsAccessor::roots()) |
| 104 #endif | 142 #endif |
| 105 { | 143 { |
| 106 #ifndef NDEBUG | 144 typename RootsAccessor::Lock lock; |
| 107 m_threadState->checkThread(); | 145 m_prev = RootsAccessor::roots(); |
| 108 #endif | 146 m_next = m_prev->m_next; |
| 109 ThreadState* threadState = state(); | 147 m_prev->m_next = this; |
| 110 m_prev = threadState->roots(); | |
| 111 m_next = threadState->roots()->m_next; | |
| 112 threadState->roots()->m_next = this; | |
| 113 m_next->m_prev = this; | 148 m_next->m_prev = this; |
| 114 } | 149 } |
| 115 | 150 |
| 116 inline explicit PersistentBase(const PersistentBase& otherref) | 151 inline explicit PersistentBase(const PersistentBase& otherref) |
| 117 : PersistentNode(otherref.m_trace) | 152 : PersistentNode(otherref.m_trace) |
| 118 #ifndef NDEBUG | 153 #ifndef NDEBUG |
| 119 , m_threadState(state()) | 154 , m_roots(RootsAccessor::roots()) |
| 120 #endif | 155 #endif |
| 121 { | 156 { |
| 122 #ifndef NDEBUG | 157 typename RootsAccessor::Lock lock; |
| 123 m_threadState->checkThread(); | 158 ASSERT(otherref.m_roots == m_roots); // Handles must belong to the same list. |
| 124 #endif | |
| 125 ASSERT(otherref.m_threadState == m_threadState); | |
| 126 PersistentBase* other = const_cast<PersistentBase*>(&otherref); | 159 PersistentBase* other = const_cast<PersistentBase*>(&otherref); |
| 127 m_prev = other; | 160 m_prev = other; |
| 128 m_next = other->m_next; | 161 m_next = other->m_next; |
| 129 other->m_next = this; | 162 other->m_next = this; |
| 130 m_next->m_prev = this; | 163 m_next->m_prev = this; |
| 131 } | 164 } |
| 132 | 165 |
| 133 inline PersistentBase& operator=(const PersistentBase& otherref) | 166 inline PersistentBase& operator=(const PersistentBase& otherref) { return *t his; } |
| 134 { | |
| 135 return *this; | |
| 136 } | |
| 137 | |
| 138 static ThreadState* state() { return ThreadStateFor<Affinity>::state(); } | |
| 139 | 167 |
| 140 #ifndef NDEBUG | 168 #ifndef NDEBUG |
| 141 private: | 169 private: |
| 142 ThreadState* m_threadState; | 170 PersistentNode* m_roots; |
| 143 #endif | 171 #endif |
| 144 }; | 172 }; |
| 145 | 173 |
| 146 // A dummy Persistent handle that ensures the list of persistents is never null. | 174 // A dummy Persistent handle that ensures the list of persistents is never null. |
| 147 // This removes a test from a hot path. | 175 // This removes a test from a hot path. |
| 148 class PersistentAnchor : public PersistentNode { | 176 class PersistentAnchor : public PersistentNode { |
| 149 public: | 177 public: |
| 150 void trace(Visitor*) { } | 178 void trace(Visitor* visitor) |
| 179 { | |
| 180 for (PersistentNode* current = m_next; current != this; current = curren t->m_next) | |
| 181 current->trace(visitor); | |
| 182 } | |
| 151 | 183 |
| 152 private: | 184 private: |
| 153 virtual ~PersistentAnchor() | 185 virtual ~PersistentAnchor() |
| 154 { | 186 { |
| 155 // FIXME: oilpan: Ideally we should have no left-over persistents at thi s point. However currently there is a | 187 // FIXME: oilpan: Ideally we should have no left-over persistents at thi s point. However currently there is a |
| 156 // large number of objects leaked when we tear down the main thread. Sin ce some of these might contain a | 188 // large number of objects leaked when we tear down the main thread. Sin ce some of these might contain a |
| 157 // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee there are no remaining Persistents at | 189 // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee there are no remaining Persistents at |
| 158 // this point. | 190 // this point. |
| 159 } | 191 } |
| 160 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P ersistentAnchor::trace>::trampoline) | 192 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P ersistentAnchor::trace>::trampoline) |
| 161 { | 193 { |
| 162 m_next = this; | 194 m_next = this; |
| 163 m_prev = this; | 195 m_prev = this; |
| 164 } | 196 } |
| 165 | 197 |
| 166 friend class ThreadState; | 198 friend class ThreadState; |
| 167 }; | 199 }; |
| 168 | 200 |
| 169 // Persistent handles are used to store pointers into the | 201 // Persistent handles are used to store pointers into the |
| 170 // managed heap. As long as the Persistent handle is alive | 202 // managed heap. As long as the Persistent handle is alive |
| 171 // the GC will keep the object pointed to alive. Persistent | 203 // the GC will keep the object pointed to alive. Persistent |
| 172 // handles can be stored in objects and they are not scoped. | 204 // handles can be stored in objects and they are not scoped. |
| 173 // Persistent handles must not be used to contain pointers | 205 // Persistent handles must not be used to contain pointers |
| 174 // between objects that are in the managed heap. They are only | 206 // between objects that are in the managed heap. They are only |
| 175 // meant to point to managed heap objects from variables/members | 207 // meant to point to managed heap objects from variables/members |
| 176 // outside the managed heap. | 208 // outside the managed heap. |
| 177 // | 209 // |
| 178 // A Persistent is always a GC root from the point of view of | 210 // A Persistent is always a GC root from the point of view of |
| 179 // the garbage collector. | 211 // the garbage collector. |
| 180 template<typename T> | 212 template<typename T, typename RootsAccessor> |
|
Mads Ager (chromium)
2014/02/17 15:03:43
Should we have a default template argument here?
Vyacheslav Egorov (Chromium)
2014/02/17 15:52:35
Forward declaration from Heap.h provides default a
| |
| 181 class Persistent : public PersistentBase<ThreadingTrait<T>::Affinity, Persistent <T> > { | 213 class Persistent : public PersistentBase<RootsAccessor, Persistent<T> > { |
| 182 public: | 214 public: |
| 183 Persistent() : m_raw(0) { } | 215 Persistent() : m_raw(0) { } |
| 184 | 216 |
| 185 Persistent(T* raw) : m_raw(raw) { } | 217 Persistent(T* raw) : m_raw(raw) { } |
| 186 | 218 |
| 187 Persistent(const Persistent& other) : m_raw(other) { } | 219 Persistent(const Persistent& other) : m_raw(other) { } |
| 188 | 220 |
| 189 template<typename U> | 221 template<typename U> |
| 190 Persistent(const Persistent<U>& other) : m_raw(other) { } | 222 Persistent(const Persistent<U>& other) : m_raw(other) { } |
| 191 | 223 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 T* get() const { return m_raw; } | 294 T* get() const { return m_raw; } |
| 263 | 295 |
| 264 private: | 296 private: |
| 265 T* m_raw; | 297 T* m_raw; |
| 266 }; | 298 }; |
| 267 | 299 |
| 268 // FIXME: derive affinity based on the collection. | 300 // FIXME: derive affinity based on the collection. |
| 269 template<typename Collection, ThreadAffinity Affinity = AnyThread> | 301 template<typename Collection, ThreadAffinity Affinity = AnyThread> |
| 270 class PersistentHeapCollectionBase | 302 class PersistentHeapCollectionBase |
| 271 : public Collection | 303 : public Collection |
| 272 , public PersistentBase<Affinity, PersistentHeapCollectionBase<Collection, A ffinity> > { | 304 , public PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapColl ectionBase<Collection, Affinity> > { |
| 273 // Never allocate these objects with new. Use Persistent<Collection> instead . | 305 // Never allocate these objects with new. Use Persistent<Collection> instead . |
| 274 DISALLOW_ALLOCATION(); | 306 DISALLOW_ALLOCATION(); |
| 275 public: | 307 public: |
| 276 void trace(Visitor* visitor) { visitor->trace(*static_cast<Collection*>(this )); } | 308 void trace(Visitor* visitor) { visitor->trace(*static_cast<Collection*>(this )); } |
| 277 }; | 309 }; |
| 278 | 310 |
| 279 template< | 311 template< |
| 280 typename KeyArg, | 312 typename KeyArg, |
| 281 typename MappedArg, | 313 typename MappedArg, |
| 282 typename HashArg = typename DefaultHash<KeyArg>::Hash, | 314 typename HashArg = typename DefaultHash<KeyArg>::Hash, |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 template<typename T, size_t inlineCapacity> | 501 template<typename T, size_t inlineCapacity> |
| 470 class IndexingBehavior<CollectionPersistent<Vector<T, inlineCapacity, WTF::Defau ltAllocator> > > { | 502 class IndexingBehavior<CollectionPersistent<Vector<T, inlineCapacity, WTF::Defau ltAllocator> > > { |
| 471 typedef CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator > > CollectionPersistentType; | 503 typedef CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator > > CollectionPersistentType; |
| 472 public: | 504 public: |
| 473 T& operator[] (size_t i) { return (**static_cast<CollectionPersistentType*>( this))[i]; } | 505 T& operator[] (size_t i) { return (**static_cast<CollectionPersistentType*>( this))[i]; } |
| 474 const T& operator[] (size_t i) const { return (**static_cast<const Collectio nPersistentType*>(this))[i]; } | 506 const T& operator[] (size_t i) const { return (**static_cast<const Collectio nPersistentType*>(this))[i]; } |
| 475 }; | 507 }; |
| 476 | 508 |
| 477 template<typename Collection, ThreadAffinity Affinity> | 509 template<typename Collection, ThreadAffinity Affinity> |
| 478 class CollectionPersistent | 510 class CollectionPersistent |
| 479 : public PersistentBase<Affinity, CollectionPersistent<Collection, Affinity> > | 511 : public PersistentBase<ThreadLocalPersistents<Affinity>, CollectionPersiste nt<Collection, Affinity> > |
| 480 , public IndexingBehavior<CollectionPersistent<Collection, Affinity> > { | 512 , public IndexingBehavior<CollectionPersistent<Collection, Affinity> > { |
| 481 public: | 513 public: |
| 482 typedef Collection CollectionType; | 514 typedef Collection CollectionType; |
| 483 typedef typename Collection::iterator iterator; | 515 typedef typename Collection::iterator iterator; |
| 484 typedef typename Collection::const_iterator const_iterator; | 516 typedef typename Collection::const_iterator const_iterator; |
| 485 | 517 |
| 486 CollectionPersistent() { } | 518 CollectionPersistent() { } |
| 487 explicit CollectionPersistent(size_t size) : m_collection(Collection(size)) { } | 519 explicit CollectionPersistent(size_t size) : m_collection(Collection(size)) { } |
| 488 explicit CollectionPersistent(const Collection& collection) : m_collection(c ollection) { } | 520 explicit CollectionPersistent(const Collection& collection) : m_collection(c ollection) { } |
| 489 CollectionPersistent& operator=(const Collection& collection) { m_collection = collection; return *this; } | 521 CollectionPersistent& operator=(const Collection& collection) { m_collection = collection; return *this; } |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 800 }; | 832 }; |
| 801 | 833 |
| 802 template<typename T> inline T* getPtr(const WebCore::Member<T>& p) | 834 template<typename T> inline T* getPtr(const WebCore::Member<T>& p) |
| 803 { | 835 { |
| 804 return p.get(); | 836 return p.get(); |
| 805 } | 837 } |
| 806 | 838 |
| 807 } // namespace WTF | 839 } // namespace WTF |
| 808 | 840 |
| 809 #endif | 841 #endif |
| OLD | NEW |