| 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 required. Just check that we are at the right thread. |
| 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 typename RootsAccessor::Lock lock; |
| 127 ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is u
sing the same roots list. |
| 90 ASSERT(isAlive()); | 128 ASSERT(isAlive()); |
| 91 ASSERT(m_next->isAlive()); | 129 ASSERT(m_next->isAlive()); |
| 92 ASSERT(m_prev->isAlive()); | 130 ASSERT(m_prev->isAlive()); |
| 93 m_threadState->checkThread(); | |
| 94 #endif | |
| 95 m_next->m_prev = m_prev; | 131 m_next->m_prev = m_prev; |
| 96 m_prev->m_next = m_next; | 132 m_prev->m_next = m_next; |
| 97 } | 133 } |
| 98 | 134 |
| 99 protected: | 135 protected: |
| 100 inline PersistentBase() | 136 inline PersistentBase() |
| 101 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) | 137 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline) |
| 102 #ifndef NDEBUG | 138 #ifndef NDEBUG |
| 103 , m_threadState(state()) | 139 , m_roots(RootsAccessor::roots()) |
| 104 #endif | 140 #endif |
| 105 { | 141 { |
| 106 #ifndef NDEBUG | 142 typename RootsAccessor::Lock lock; |
| 107 m_threadState->checkThread(); | 143 m_prev = RootsAccessor::roots(); |
| 108 #endif | 144 m_next = m_prev->m_next; |
| 109 ThreadState* threadState = state(); | 145 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; | 146 m_next->m_prev = this; |
| 114 } | 147 } |
| 115 | 148 |
| 116 inline explicit PersistentBase(const PersistentBase& otherref) | 149 inline explicit PersistentBase(const PersistentBase& otherref) |
| 117 : PersistentNode(otherref.m_trace) | 150 : PersistentNode(otherref.m_trace) |
| 118 #ifndef NDEBUG | 151 #ifndef NDEBUG |
| 119 , m_threadState(state()) | 152 , m_roots(RootsAccessor::roots()) |
| 120 #endif | 153 #endif |
| 121 { | 154 { |
| 122 #ifndef NDEBUG | 155 typename RootsAccessor::Lock lock; |
| 123 m_threadState->checkThread(); | 156 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); | 157 PersistentBase* other = const_cast<PersistentBase*>(&otherref); |
| 127 m_prev = other; | 158 m_prev = other; |
| 128 m_next = other->m_next; | 159 m_next = other->m_next; |
| 129 other->m_next = this; | 160 other->m_next = this; |
| 130 m_next->m_prev = this; | 161 m_next->m_prev = this; |
| 131 } | 162 } |
| 132 | 163 |
| 133 inline PersistentBase& operator=(const PersistentBase& otherref) | 164 inline PersistentBase& operator=(const PersistentBase& otherref) { return *t
his; } |
| 134 { | |
| 135 return *this; | |
| 136 } | |
| 137 | |
| 138 static ThreadState* state() { return ThreadStateFor<Affinity>::state(); } | |
| 139 | 165 |
| 140 #ifndef NDEBUG | 166 #ifndef NDEBUG |
| 141 private: | 167 private: |
| 142 ThreadState* m_threadState; | 168 PersistentNode* m_roots; |
| 143 #endif | 169 #endif |
| 144 }; | 170 }; |
| 145 | 171 |
| 146 // A dummy Persistent handle that ensures the list of persistents is never null. | 172 // A dummy Persistent handle that ensures the list of persistents is never null. |
| 147 // This removes a test from a hot path. | 173 // This removes a test from a hot path. |
| 148 class PersistentAnchor : public PersistentNode { | 174 class PersistentAnchor : public PersistentNode { |
| 149 public: | 175 public: |
| 150 void trace(Visitor*) { } | 176 void trace(Visitor* visitor) |
| 177 { |
| 178 for (PersistentNode* current = m_next; current != this; current = curren
t->m_next) |
| 179 current->trace(visitor); |
| 180 } |
| 151 | 181 |
| 152 private: | 182 private: |
| 153 virtual ~PersistentAnchor() | 183 virtual ~PersistentAnchor() |
| 154 { | 184 { |
| 155 // FIXME: oilpan: Ideally we should have no left-over persistents at thi
s point. However currently there is a | 185 // 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 | 186 // 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 | 187 // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee
there are no remaining Persistents at |
| 158 // this point. | 188 // this point. |
| 159 } | 189 } |
| 160 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P
ersistentAnchor::trace>::trampoline) | 190 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P
ersistentAnchor::trace>::trampoline) |
| 161 { | 191 { |
| 162 m_next = this; | 192 m_next = this; |
| 163 m_prev = this; | 193 m_prev = this; |
| 164 } | 194 } |
| 165 | 195 |
| 166 friend class ThreadState; | 196 friend class ThreadState; |
| 167 }; | 197 }; |
| 168 | 198 |
| 169 // Persistent handles are used to store pointers into the | 199 // Persistent handles are used to store pointers into the |
| 170 // managed heap. As long as the Persistent handle is alive | 200 // managed heap. As long as the Persistent handle is alive |
| 171 // the GC will keep the object pointed to alive. Persistent | 201 // the GC will keep the object pointed to alive. Persistent |
| 172 // handles can be stored in objects and they are not scoped. | 202 // handles can be stored in objects and they are not scoped. |
| 173 // Persistent handles must not be used to contain pointers | 203 // Persistent handles must not be used to contain pointers |
| 174 // between objects that are in the managed heap. They are only | 204 // between objects that are in the managed heap. They are only |
| 175 // meant to point to managed heap objects from variables/members | 205 // meant to point to managed heap objects from variables/members |
| 176 // outside the managed heap. | 206 // outside the managed heap. |
| 177 // | 207 // |
| 178 // A Persistent is always a GC root from the point of view of | 208 // A Persistent is always a GC root from the point of view of |
| 179 // the garbage collector. | 209 // the garbage collector. |
| 180 template<typename T> | 210 template<typename T, typename RootsAccessor /* = ThreadLocalPersistents<Threadin
gTrait<T>::Affinity > */ > |
| 181 class Persistent : public PersistentBase<ThreadingTrait<T>::Affinity, Persistent
<T> > { | 211 class Persistent : public PersistentBase<RootsAccessor, Persistent<T, RootsAcces
sor> > { |
| 182 public: | 212 public: |
| 183 Persistent() : m_raw(0) { } | 213 Persistent() : m_raw(0) { } |
| 184 | 214 |
| 185 Persistent(T* raw) : m_raw(raw) { } | 215 Persistent(T* raw) : m_raw(raw) { } |
| 186 | 216 |
| 187 Persistent(const Persistent& other) : m_raw(other) { } | 217 Persistent(const Persistent& other) : m_raw(other) { } |
| 188 | 218 |
| 189 template<typename U> | 219 template<typename U> |
| 190 Persistent(const Persistent<U>& other) : m_raw(other) { } | 220 Persistent(const Persistent<U, RootsAccessor>& other) : m_raw(other) { } |
| 191 | 221 |
| 192 template<typename U> | 222 template<typename U> |
| 193 Persistent(const Member<U>& other) : m_raw(other) { } | 223 Persistent(const Member<U>& other) : m_raw(other) { } |
| 194 | 224 |
| 195 template<typename U> | 225 template<typename U> |
| 196 Persistent(const RawPtr<U>& other) : m_raw(other.get()) { } | 226 Persistent(const RawPtr<U>& other) : m_raw(other.get()) { } |
| 197 | 227 |
| 198 template<typename U> | 228 template<typename U> |
| 199 Persistent& operator=(U* other) | 229 Persistent& operator=(U* other) |
| 200 { | 230 { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 232 | 262 |
| 233 T* operator->() const { return *this; } | 263 T* operator->() const { return *this; } |
| 234 | 264 |
| 235 Persistent& operator=(const Persistent& other) | 265 Persistent& operator=(const Persistent& other) |
| 236 { | 266 { |
| 237 m_raw = other; | 267 m_raw = other; |
| 238 return *this; | 268 return *this; |
| 239 } | 269 } |
| 240 | 270 |
| 241 template<typename U> | 271 template<typename U> |
| 242 Persistent& operator=(const Persistent<U>& other) | 272 Persistent& operator=(const Persistent<U, RootsAccessor>& other) |
| 243 { | 273 { |
| 244 m_raw = other; | 274 m_raw = other; |
| 245 return *this; | 275 return *this; |
| 246 } | 276 } |
| 247 | 277 |
| 248 template<typename U> | 278 template<typename U> |
| 249 Persistent& operator=(const Member<U>& other) | 279 Persistent& operator=(const Member<U>& other) |
| 250 { | 280 { |
| 251 m_raw = other; | 281 m_raw = other; |
| 252 return *this; | 282 return *this; |
| 253 } | 283 } |
| 254 | 284 |
| 255 template<typename U> | 285 template<typename U> |
| 256 Persistent& operator=(const RawPtr<U>& other) | 286 Persistent& operator=(const RawPtr<U>& other) |
| 257 { | 287 { |
| 258 m_raw = other; | 288 m_raw = other; |
| 259 return *this; | 289 return *this; |
| 260 } | 290 } |
| 261 | 291 |
| 262 T* get() const { return m_raw; } | 292 T* get() const { return m_raw; } |
| 263 | 293 |
| 264 private: | 294 private: |
| 265 T* m_raw; | 295 T* m_raw; |
| 266 }; | 296 }; |
| 267 | 297 |
| 268 // FIXME: derive affinity based on the collection. | 298 // FIXME: derive affinity based on the collection. |
| 269 template<typename Collection, ThreadAffinity Affinity = AnyThread> | 299 template<typename Collection, ThreadAffinity Affinity = AnyThread> |
| 270 class PersistentHeapCollectionBase | 300 class PersistentHeapCollectionBase |
| 271 : public Collection | 301 : public Collection |
| 272 , public PersistentBase<Affinity, PersistentHeapCollectionBase<Collection, A
ffinity> > { | 302 , public PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapColl
ectionBase<Collection, Affinity> > { |
| 273 // Never allocate these objects with new. Use Persistent<Collection> instead
. | 303 // Never allocate these objects with new. Use Persistent<Collection> instead
. |
| 274 DISALLOW_ALLOCATION(); | 304 DISALLOW_ALLOCATION(); |
| 275 public: | 305 public: |
| 276 void trace(Visitor* visitor) { visitor->trace(*static_cast<Collection*>(this
)); } | 306 void trace(Visitor* visitor) { visitor->trace(*static_cast<Collection*>(this
)); } |
| 277 }; | 307 }; |
| 278 | 308 |
| 279 template< | 309 template< |
| 280 typename KeyArg, | 310 typename KeyArg, |
| 281 typename MappedArg, | 311 typename MappedArg, |
| 282 typename HashArg = typename DefaultHash<KeyArg>::Hash, | 312 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> | 499 template<typename T, size_t inlineCapacity> |
| 470 class IndexingBehavior<CollectionPersistent<Vector<T, inlineCapacity, WTF::Defau
ltAllocator> > > { | 500 class IndexingBehavior<CollectionPersistent<Vector<T, inlineCapacity, WTF::Defau
ltAllocator> > > { |
| 471 typedef CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator
> > CollectionPersistentType; | 501 typedef CollectionPersistent<Vector<T, inlineCapacity, WTF::DefaultAllocator
> > CollectionPersistentType; |
| 472 public: | 502 public: |
| 473 T& operator[] (size_t i) { return (**static_cast<CollectionPersistentType*>(
this))[i]; } | 503 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]; } | 504 const T& operator[] (size_t i) const { return (**static_cast<const Collectio
nPersistentType*>(this))[i]; } |
| 475 }; | 505 }; |
| 476 | 506 |
| 477 template<typename Collection, ThreadAffinity Affinity> | 507 template<typename Collection, ThreadAffinity Affinity> |
| 478 class CollectionPersistent | 508 class CollectionPersistent |
| 479 : public PersistentBase<Affinity, CollectionPersistent<Collection, Affinity>
> | 509 : public PersistentBase<ThreadLocalPersistents<Affinity>, CollectionPersiste
nt<Collection, Affinity> > |
| 480 , public IndexingBehavior<CollectionPersistent<Collection, Affinity> > { | 510 , public IndexingBehavior<CollectionPersistent<Collection, Affinity> > { |
| 481 public: | 511 public: |
| 482 typedef Collection CollectionType; | 512 typedef Collection CollectionType; |
| 483 typedef typename Collection::iterator iterator; | 513 typedef typename Collection::iterator iterator; |
| 484 typedef typename Collection::const_iterator const_iterator; | 514 typedef typename Collection::const_iterator const_iterator; |
| 485 | 515 |
| 486 CollectionPersistent() { } | 516 CollectionPersistent() { } |
| 487 explicit CollectionPersistent(size_t size) : m_collection(Collection(size))
{ } | 517 explicit CollectionPersistent(size_t size) : m_collection(Collection(size))
{ } |
| 488 explicit CollectionPersistent(const Collection& collection) : m_collection(c
ollection) { } | 518 explicit CollectionPersistent(const Collection& collection) : m_collection(c
ollection) { } |
| 489 CollectionPersistent& operator=(const Collection& collection) { m_collection
= collection; return *this; } | 519 CollectionPersistent& operator=(const Collection& collection) { m_collection
= collection; return *this; } |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 804 }; | 834 }; |
| 805 | 835 |
| 806 template<typename T> inline T* getPtr(const WebCore::Member<T>& p) | 836 template<typename T> inline T* getPtr(const WebCore::Member<T>& p) |
| 807 { | 837 { |
| 808 return p.get(); | 838 return p.get(); |
| 809 } | 839 } |
| 810 | 840 |
| 811 } // namespace WTF | 841 } // namespace WTF |
| 812 | 842 |
| 813 #endif | 843 #endif |
| OLD | NEW |