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 16 matching lines...) Expand all Loading... | |
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
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 "platform/heap/Heap.h" | 34 #include "platform/heap/Heap.h" |
35 #include "platform/heap/HeapAllocator.h" | 35 #include "platform/heap/HeapAllocator.h" |
36 #include "platform/heap/InlinedGlobalMarkingVisitor.h" | 36 #include "platform/heap/InlinedGlobalMarkingVisitor.h" |
37 #include "platform/heap/PersistentNode.h" | |
37 #include "platform/heap/ThreadState.h" | 38 #include "platform/heap/ThreadState.h" |
38 #include "platform/heap/TraceTraits.h" | 39 #include "platform/heap/TraceTraits.h" |
39 #include "platform/heap/Visitor.h" | 40 #include "platform/heap/Visitor.h" |
40 #include "wtf/Functional.h" | 41 #include "wtf/Functional.h" |
41 #include "wtf/HashFunctions.h" | 42 #include "wtf/HashFunctions.h" |
42 #include "wtf/Locker.h" | 43 #include "wtf/Locker.h" |
44 #include "wtf/MainThread.h" | |
43 #include "wtf/RawPtr.h" | 45 #include "wtf/RawPtr.h" |
44 #include "wtf/RefCounted.h" | 46 #include "wtf/RefCounted.h" |
45 #include "wtf/TypeTraits.h" | 47 #include "wtf/TypeTraits.h" |
46 | 48 |
47 namespace blink { | 49 namespace blink { |
48 | 50 |
49 template<typename T> class HeapTerminatedArray; | 51 template<typename T> class HeapTerminatedArray; |
50 | 52 |
51 class PersistentNode { | |
52 public: | |
53 explicit PersistentNode(TraceCallback trace) | |
54 : m_trace(trace) | |
55 { | |
56 } | |
57 | |
58 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
59 bool isHeapObjectAlive() { return m_trace; } | |
60 | |
61 // This operator= is important. Without having the operator=, m_next and | |
62 // m_prev are inproperly copied and it breaks the link list of the | |
63 // persistent handles. | |
64 inline PersistentNode& operator=(const PersistentNode& otherref) { return *t his; } | |
65 | |
66 private: | |
67 // Ideally the trace method should be virtual and automatically dispatch | |
68 // to the most specific implementation. However having a virtual method | |
69 // on PersistentNode leads to too eager template instantiation with MSVC | |
70 // which leads to include cycles. | |
71 // Instead we call the constructor with a TraceCallback which knows the | |
72 // type of the most specific child and calls trace directly. See | |
73 // TraceMethodDelegate in Visitor.h for how this is done. | |
74 void tracePersistentNode(Visitor* visitor) | |
75 { | |
76 m_trace(visitor, this); | |
77 } | |
78 | |
79 ~PersistentNode() | |
80 { | |
81 } | |
82 | |
83 TraceCallback m_trace; | |
84 PersistentNode* m_next; | |
85 PersistentNode* m_prev; | |
86 | |
87 template<typename T> friend class CrossThreadPersistent; | |
88 template<typename T> friend class Persistent; | |
89 template<typename Collection> friend class PersistentHeapCollectionBase; | |
90 friend class PersistentAnchor; | |
91 friend class ThreadState; | |
92 }; | |
93 | |
94 // A dummy Persistent handle that ensures the list of persistents is never null. | |
95 // This removes a test from a hot path. | |
96 class PersistentAnchor : public PersistentNode { | |
97 public: | |
98 void tracePersistentNodes(Visitor* visitor) | |
99 { | |
100 for (PersistentNode* current = m_next; current != this; current = curren t->m_next) | |
101 current->tracePersistentNode(visitor); | |
102 } | |
103 | |
104 int numberOfPersistents() | |
105 { | |
106 int numberOfPersistents = 0; | |
107 for (PersistentNode* current = m_next; current != this; current = curren t->m_next) | |
108 ++numberOfPersistents; | |
109 return numberOfPersistents; | |
110 } | |
111 | |
112 ~PersistentAnchor() | |
113 { | |
114 m_trace = nullptr; | |
115 } | |
116 | |
117 template<typename VisitorDispatcher> | |
118 void trace(VisitorDispatcher visitor) | |
119 { | |
120 ASSERT_NOT_REACHED(); | |
121 } | |
122 | |
123 private: | |
124 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &P ersistentAnchor::trace>::trampoline) | |
125 { | |
126 m_next = this; | |
127 m_prev = this; | |
128 } | |
129 | |
130 friend class ThreadState; | |
131 }; | |
132 | |
133 // Persistent handles are used to store pointers into the | 53 // Persistent handles are used to store pointers into the |
134 // managed heap. As long as the Persistent handle is alive | 54 // managed heap. As long as the Persistent handle is alive |
135 // the GC will keep the object pointed to alive. Persistent | 55 // the GC will keep the object pointed to alive. Persistent |
136 // handles can be stored in objects and they are not scoped. | 56 // handles can be stored in objects and they are not scoped. |
137 // Persistent handles must not be used to contain pointers | 57 // Persistent handles must not be used to contain pointers |
138 // between objects that are in the managed heap. They are only | 58 // between objects that are in the managed heap. They are only |
139 // meant to point to managed heap objects from variables/members | 59 // meant to point to managed heap objects from variables/members |
140 // outside the managed heap. | 60 // outside the managed heap. |
141 // | 61 // |
142 // A Persistent is always a GC root from the point of view of | 62 // A Persistent is always a GC root from the point of view of |
143 // the garbage collector. | 63 // the garbage collector. |
144 // | 64 // |
145 // We have to construct and destruct Persistent in the same thread. | 65 // We have to construct and destruct Persistent in the same thread. |
146 template<typename T> | 66 template<typename T> |
147 class Persistent : public PersistentNode { | 67 class Persistent final { |
148 public: | 68 public: |
149 Persistent() : PersistentNode(TraceMethodDelegate<Persistent<T>, &Persistent <T>::trace>::trampoline), m_raw(nullptr) | 69 Persistent() : m_raw(nullptr) |
150 { | 70 { |
151 initialize(); | 71 initialize(); |
152 } | 72 } |
153 | 73 |
154 Persistent(std::nullptr_t) : PersistentNode(TraceMethodDelegate<Persistent<T >, &Persistent<T>::trace>::trampoline), m_raw(nullptr) | 74 Persistent(std::nullptr_t) : m_raw(nullptr) |
155 { | 75 { |
156 initialize(); | 76 initialize(); |
157 } | 77 } |
158 | 78 |
159 Persistent(T* raw) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Pers istent<T>::trace>::trampoline), m_raw(raw) | 79 Persistent(T* raw) : m_raw(raw) |
160 { | 80 { |
161 initialize(); | 81 initialize(); |
162 checkPointer(); | 82 checkPointer(); |
163 recordBacktrace(); | 83 recordBacktrace(); |
164 } | 84 } |
165 | 85 |
166 Persistent(T& raw) : PersistentNode(TraceMethodDelegate<Persistent<T>, &Pers istent<T>::trace>::trampoline), m_raw(&raw) | 86 Persistent(T& raw) : m_raw(&raw) |
167 { | 87 { |
168 initialize(); | 88 initialize(); |
169 checkPointer(); | 89 checkPointer(); |
170 recordBacktrace(); | 90 recordBacktrace(); |
171 } | 91 } |
172 | 92 |
173 Persistent(const Persistent& other) : PersistentNode(TraceMethodDelegate<Per sistent<T>, &Persistent<T>::trace>::trampoline), m_raw(other) | 93 Persistent(const Persistent& other) : m_raw(other) |
174 { | 94 { |
175 initialize(); | 95 initialize(); |
176 checkPointer(); | 96 checkPointer(); |
177 recordBacktrace(); | 97 recordBacktrace(); |
178 } | 98 } |
179 | 99 |
180 template<typename U> | 100 template<typename U> |
181 Persistent(const Persistent<U>& other) : PersistentNode(TraceMethodDelegate< Persistent<T>, &Persistent<T>::trace>::trampoline), m_raw(other) | 101 Persistent(const Persistent<U>& other) : m_raw(other) |
182 { | 102 { |
183 initialize(); | 103 initialize(); |
184 checkPointer(); | 104 checkPointer(); |
185 recordBacktrace(); | 105 recordBacktrace(); |
186 } | 106 } |
187 | 107 |
188 template<typename U> | 108 template<typename U> |
189 Persistent(const Member<U>& other) : PersistentNode(TraceMethodDelegate<Pers istent<T>, &Persistent<T>::trace>::trampoline), m_raw(other) | 109 Persistent(const Member<U>& other) : m_raw(other) |
190 { | 110 { |
191 initialize(); | 111 initialize(); |
192 checkPointer(); | 112 checkPointer(); |
193 recordBacktrace(); | 113 recordBacktrace(); |
194 } | 114 } |
195 | 115 |
196 template<typename U> | 116 template<typename U> |
197 Persistent(const RawPtr<U>& other) : PersistentNode(TraceMethodDelegate<Pers istent<T>, &Persistent<T>::trace>::trampoline), m_raw(other.get()) | 117 Persistent(const RawPtr<U>& other) : m_raw(other.get()) |
198 { | 118 { |
199 initialize(); | 119 initialize(); |
200 checkPointer(); | 120 checkPointer(); |
201 recordBacktrace(); | 121 recordBacktrace(); |
202 } | 122 } |
203 | 123 |
204 void clear() { m_raw = nullptr; } | 124 void clear() { m_raw = nullptr; } |
205 | 125 |
206 ~Persistent() | 126 ~Persistent() |
207 { | 127 { |
208 uninitialize(); | 128 uninitialize(); |
209 m_raw = nullptr; | 129 m_raw = nullptr; |
210 m_trace = nullptr; | |
211 } | 130 } |
212 | 131 |
213 template<typename VisitorDispatcher> | 132 template<typename VisitorDispatcher> |
214 void trace(VisitorDispatcher visitor) | 133 void trace(VisitorDispatcher visitor) |
215 { | 134 { |
216 static_assert(sizeof(T), "T must be fully defined"); | 135 static_assert(sizeof(T), "T must be fully defined"); |
217 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage collected object"); | 136 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage collected object"); |
218 visitor->mark(m_raw); | 137 visitor->mark(m_raw); |
219 } | 138 } |
220 | 139 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 return *this; | 203 return *this; |
285 } | 204 } |
286 | 205 |
287 T* get() const { return m_raw; } | 206 T* get() const { return m_raw; } |
288 | 207 |
289 private: | 208 private: |
290 void initialize() | 209 void initialize() |
291 { | 210 { |
292 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state( ); | 211 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state( ); |
293 state->checkThread(); | 212 state->checkThread(); |
294 m_prev = state->roots(); | 213 m_persistentNode = state->persistentRegion()->allocatePersistentNode(thi s, TraceMethodDelegate<Persistent<T>, &Persistent<T>::trace>::trampoline); |
295 m_next = m_prev->m_next; | |
296 m_prev->m_next = this; | |
297 m_next->m_prev = this; | |
298 } | 214 } |
299 | 215 |
300 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
301 void uninitialize() | 216 void uninitialize() |
302 { | 217 { |
303 ASSERT(isHeapObjectAlive()); | 218 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state( ); |
304 ASSERT(m_next->isHeapObjectAlive()); | 219 state->checkThread(); |
305 ASSERT(m_prev->isHeapObjectAlive()); | 220 state->persistentRegion()->freePersistentNode(m_persistentNode); |
sof
2015/06/30 10:08:11
Is this ASan friendly with lazy-sweeping enabled?
| |
306 m_next->m_prev = m_prev; | |
307 m_prev->m_next = m_next; | |
308 } | 221 } |
309 | 222 |
310 void checkPointer() | 223 void checkPointer() |
311 { | 224 { |
312 #if ENABLE(ASSERT) | 225 #if ENABLE(ASSERT) |
313 if (!m_raw) | 226 if (!m_raw) |
314 return; | 227 return; |
315 | 228 |
316 // Heap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | 229 // Heap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable |
317 // object. In other words, it checks that the pointer is either of: | 230 // object. In other words, it checks that the pointer is either of: |
(...skipping 11 matching lines...) Expand all Loading... | |
329 void recordBacktrace() | 242 void recordBacktrace() |
330 { | 243 { |
331 if (m_raw) | 244 if (m_raw) |
332 m_tracingName = Heap::createBacktraceString(); | 245 m_tracingName = Heap::createBacktraceString(); |
333 } | 246 } |
334 | 247 |
335 String m_tracingName; | 248 String m_tracingName; |
336 #else | 249 #else |
337 inline void recordBacktrace() const { } | 250 inline void recordBacktrace() const { } |
338 #endif | 251 #endif |
252 // m_raw is accessed most, so put it at the first field. | |
339 T* m_raw; | 253 T* m_raw; |
254 PersistentNode* m_persistentNode; | |
340 }; | 255 }; |
341 | 256 |
342 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread | 257 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread |
343 // different from the construction thread. | 258 // different from the construction thread. |
344 template<typename T> | 259 template<typename T> |
345 class CrossThreadPersistent : public PersistentNode { | 260 class CrossThreadPersistent final { |
346 public: | 261 public: |
347 CrossThreadPersistent() : PersistentNode(TraceMethodDelegate<CrossThreadPers istent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(nullptr) | 262 CrossThreadPersistent() : m_raw(nullptr) |
348 { | 263 { |
349 initialize(); | 264 initialize(); |
350 } | 265 } |
351 | 266 |
352 CrossThreadPersistent(std::nullptr_t) : PersistentNode(TraceMethodDelegate<C rossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(n ullptr) | 267 CrossThreadPersistent(std::nullptr_t) : m_raw(nullptr) |
353 { | 268 { |
354 initialize(); | 269 initialize(); |
355 } | 270 } |
356 | 271 |
357 CrossThreadPersistent(T* raw) : PersistentNode(TraceMethodDelegate<CrossThre adPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(raw) | 272 CrossThreadPersistent(T* raw) : m_raw(raw) |
358 { | 273 { |
359 initialize(); | 274 initialize(); |
360 checkPointer(); | 275 checkPointer(); |
361 recordBacktrace(); | 276 recordBacktrace(); |
362 } | 277 } |
363 | 278 |
364 CrossThreadPersistent(T& raw) : PersistentNode(TraceMethodDelegate<CrossThre adPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(&raw) | 279 CrossThreadPersistent(T& raw) : m_raw(&raw) |
365 { | 280 { |
366 initialize(); | 281 initialize(); |
367 checkPointer(); | 282 checkPointer(); |
368 recordBacktrace(); | 283 recordBacktrace(); |
369 } | 284 } |
370 | 285 |
371 CrossThreadPersistent(const CrossThreadPersistent& other) : PersistentNode(T raceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>:: trampoline), m_raw(other) | 286 CrossThreadPersistent(const CrossThreadPersistent& other) : m_raw(other) |
372 { | 287 { |
373 initialize(); | 288 initialize(); |
374 checkPointer(); | 289 checkPointer(); |
375 recordBacktrace(); | 290 recordBacktrace(); |
376 } | 291 } |
377 | 292 |
378 template<typename U> | 293 template<typename U> |
379 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : PersistentNod e(TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace >::trampoline), m_raw(other) | 294 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : m_raw(other) |
380 { | 295 { |
381 initialize(); | 296 initialize(); |
382 checkPointer(); | 297 checkPointer(); |
383 recordBacktrace(); | 298 recordBacktrace(); |
384 } | 299 } |
385 | 300 |
386 template<typename U> | 301 template<typename U> |
387 CrossThreadPersistent(const Member<U>& other) : PersistentNode(TraceMethodDe legate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(other) | 302 CrossThreadPersistent(const Member<U>& other) : m_raw(other) |
388 { | 303 { |
389 initialize(); | 304 initialize(); |
390 checkPointer(); | 305 checkPointer(); |
391 recordBacktrace(); | 306 recordBacktrace(); |
392 } | 307 } |
393 | 308 |
394 template<typename U> | 309 template<typename U> |
395 CrossThreadPersistent(const RawPtr<U>& other) : PersistentNode(TraceMethodDe legate<CrossThreadPersistent<T>, &CrossThreadPersistent<T>::trace>::trampoline), m_raw(other.get()) | 310 CrossThreadPersistent(const RawPtr<U>& other) : m_raw(other.get()) |
396 { | 311 { |
397 initialize(); | 312 initialize(); |
398 checkPointer(); | 313 checkPointer(); |
399 recordBacktrace(); | 314 recordBacktrace(); |
400 } | 315 } |
401 | 316 |
402 void clear() { m_raw = nullptr; } | 317 void clear() { m_raw = nullptr; } |
403 | 318 |
404 ~CrossThreadPersistent() | 319 ~CrossThreadPersistent() |
405 { | 320 { |
406 uninitialize(); | 321 uninitialize(); |
407 m_raw = nullptr; | 322 m_raw = nullptr; |
408 m_trace = nullptr; | |
409 } | 323 } |
410 | 324 |
411 template<typename VisitorDispatcher> | 325 template<typename VisitorDispatcher> |
412 void trace(VisitorDispatcher visitor) | 326 void trace(VisitorDispatcher visitor) |
413 { | 327 { |
414 static_assert(sizeof(T), "T must be fully defined"); | 328 static_assert(sizeof(T), "T must be fully defined"); |
415 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage collected object"); | 329 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage collected object"); |
416 visitor->mark(m_raw); | 330 visitor->mark(m_raw); |
417 } | 331 } |
418 | 332 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
480 checkPointer(); | 394 checkPointer(); |
481 recordBacktrace(); | 395 recordBacktrace(); |
482 return *this; | 396 return *this; |
483 } | 397 } |
484 | 398 |
485 T* get() const { return m_raw; } | 399 T* get() const { return m_raw; } |
486 | 400 |
487 private: | 401 private: |
488 void initialize() | 402 void initialize() |
489 { | 403 { |
490 MutexLocker m_locker(ThreadState::globalRootsMutex()); | 404 m_persistentNode = ThreadState::crossThreadPersistentRegion().allocatePe rsistentNode(this, TraceMethodDelegate<CrossThreadPersistent<T>, &CrossThreadPer sistent<T>::trace>::trampoline); |
491 m_prev = &ThreadState::globalRoots(); | |
492 m_next = m_prev->m_next; | |
493 m_prev->m_next = this; | |
494 m_next->m_prev = this; | |
495 } | 405 } |
496 | 406 |
497 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
498 void uninitialize() | 407 void uninitialize() |
499 { | 408 { |
500 MutexLocker m_locker(ThreadState::globalRootsMutex()); | 409 ThreadState::crossThreadPersistentRegion().freePersistentNode(m_persiste ntNode); |
sof
2015/06/30 10:08:11
Is this ASan friendly?
| |
501 ASSERT(isHeapObjectAlive()); | |
502 ASSERT(m_next->isHeapObjectAlive()); | |
503 ASSERT(m_prev->isHeapObjectAlive()); | |
504 m_next->m_prev = m_prev; | |
505 m_prev->m_next = m_next; | |
506 } | 410 } |
507 | 411 |
508 void checkPointer() | 412 void checkPointer() |
509 { | 413 { |
510 #if ENABLE(ASSERT) | 414 #if ENABLE(ASSERT) |
511 if (!m_raw) | 415 if (!m_raw) |
512 return; | 416 return; |
513 // Heap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | 417 // Heap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable |
514 // object. In other words, it checks that the pointer is either of: | 418 // object. In other words, it checks that the pointer is either of: |
515 // | 419 // |
(...skipping 10 matching lines...) Expand all Loading... | |
526 void recordBacktrace() | 430 void recordBacktrace() |
527 { | 431 { |
528 if (m_raw) | 432 if (m_raw) |
529 m_tracingName = Heap::createBacktraceString(); | 433 m_tracingName = Heap::createBacktraceString(); |
530 } | 434 } |
531 | 435 |
532 String m_tracingName; | 436 String m_tracingName; |
533 #else | 437 #else |
534 inline void recordBacktrace() const { } | 438 inline void recordBacktrace() const { } |
535 #endif | 439 #endif |
440 // m_raw is accessed most, so put it at the first field. | |
536 T* m_raw; | 441 T* m_raw; |
442 PersistentNode* m_persistentNode; | |
537 }; | 443 }; |
538 | 444 |
539 // PersistentNode must be the left-most class to let the | 445 // PersistentNode must be the left-most class to let the |
540 // visitor->trace(static_cast<Collection*>(this)) trace the correct position. | 446 // visitor->trace(static_cast<Collection*>(this)) trace the correct position. |
541 // FIXME: derive affinity based on the collection. | 447 // FIXME: derive affinity based on the collection. |
542 template<typename Collection> | 448 template<typename Collection> |
543 class PersistentHeapCollectionBase : public PersistentNode, public Collection { | 449 class PersistentHeapCollectionBase : public Collection { |
544 // We overload the various new and delete operators with using the WTF Defau ltAllocator to ensure persistent | 450 // We overload the various new and delete operators with using the WTF Defau ltAllocator to ensure persistent |
545 // heap collections are always allocated off-heap. This allows persistent co llections to be used in | 451 // heap collections are always allocated off-heap. This allows persistent co llections to be used in |
546 // DEFINE_STATIC_LOCAL et. al. | 452 // DEFINE_STATIC_LOCAL et. al. |
547 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::DefaultAllocator); | 453 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::DefaultAllocator); |
548 public: | 454 public: |
549 PersistentHeapCollectionBase() : PersistentNode(TraceMethodDelegate<Persiste ntHeapCollectionBase<Collection>, &PersistentHeapCollectionBase<Collection>::tra ce>::trampoline) | 455 PersistentHeapCollectionBase() |
550 { | 456 { |
551 initialize(); | 457 initialize(); |
552 } | 458 } |
553 | 459 |
554 PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Pe rsistentNode(TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &Pers istentHeapCollectionBase<Collection>::trace>::trampoline), Collection(other) | 460 PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Co llection(other) |
555 { | 461 { |
556 initialize(); | 462 initialize(); |
557 } | 463 } |
558 | 464 |
559 template<typename OtherCollection> | 465 template<typename OtherCollection> |
560 PersistentHeapCollectionBase(const OtherCollection& other) : PersistentNode( TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentHeapCol lectionBase<Collection>::trace>::trampoline), Collection(other) | 466 PersistentHeapCollectionBase(const OtherCollection& other) : Collection(othe r) |
561 { | 467 { |
562 initialize(); | 468 initialize(); |
563 } | 469 } |
564 | 470 |
565 ~PersistentHeapCollectionBase() | 471 ~PersistentHeapCollectionBase() |
566 { | 472 { |
567 uninitialize(); | 473 uninitialize(); |
568 m_trace = nullptr; | |
569 } | 474 } |
570 | 475 |
571 template<typename VisitorDispatcher> | 476 template<typename VisitorDispatcher> |
572 void trace(VisitorDispatcher visitor) | 477 void trace(VisitorDispatcher visitor) |
573 { | 478 { |
574 static_assert(sizeof(Collection), "Collection must be fully defined"); | 479 static_assert(sizeof(Collection), "Collection must be fully defined"); |
575 visitor->trace(*static_cast<Collection*>(this)); | 480 visitor->trace(*static_cast<Collection*>(this)); |
576 } | 481 } |
577 | 482 |
578 private: | 483 private: |
579 void initialize() | 484 void initialize() |
580 { | 485 { |
581 ThreadState* state = ThreadState::current(); | 486 ThreadState* state = ThreadState::current(); |
582 m_prev = state->roots(); | 487 state->checkThread(); |
583 m_next = m_prev->m_next; | 488 m_persistentNode = state->persistentRegion()->allocatePersistentNode(thi s, TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentHeap CollectionBase<Collection>::trace>::trampoline); |
584 m_prev->m_next = this; | |
585 m_next->m_prev = this; | |
586 } | 489 } |
587 | 490 |
588 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
589 void uninitialize() | 491 void uninitialize() |
590 { | 492 { |
591 ASSERT(isHeapObjectAlive()); | 493 ThreadState* state = ThreadState::current(); |
592 ASSERT(m_next->isHeapObjectAlive()); | 494 state->checkThread(); |
593 ASSERT(m_prev->isHeapObjectAlive()); | 495 state->persistentRegion()->freePersistentNode(m_persistentNode); |
sof
2015/06/30 10:08:11
Ditto.
| |
594 m_next->m_prev = m_prev; | |
595 m_prev->m_next = m_next; | |
596 } | 496 } |
497 | |
498 PersistentNode* m_persistentNode; | |
597 }; | 499 }; |
598 | 500 |
599 template< | 501 template< |
600 typename KeyArg, | 502 typename KeyArg, |
601 typename MappedArg, | 503 typename MappedArg, |
602 typename HashArg = typename DefaultHash<KeyArg>::Hash, | 504 typename HashArg = typename DefaultHash<KeyArg>::Hash, |
603 typename KeyTraitsArg = HashTraits<KeyArg>, | 505 typename KeyTraitsArg = HashTraits<KeyArg>, |
604 typename MappedTraitsArg = HashTraits<MappedArg>> | 506 typename MappedTraitsArg = HashTraits<MappedArg>> |
605 class PersistentHeapHashMap : public PersistentHeapCollectionBase<HeapHashMap<Ke yArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { }; | 507 class PersistentHeapHashMap : public PersistentHeapCollectionBase<HeapHashMap<Ke yArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { }; |
606 | 508 |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1287 struct ParamStorageTraits<RawPtr<T>> : public PointerParamStorageTraits<T*, blin k::IsGarbageCollectedType<T>::value> { | 1189 struct ParamStorageTraits<RawPtr<T>> : public PointerParamStorageTraits<T*, blin k::IsGarbageCollectedType<T>::value> { |
1288 static_assert(sizeof(T), "T must be fully defined"); | 1190 static_assert(sizeof(T), "T must be fully defined"); |
1289 }; | 1191 }; |
1290 | 1192 |
1291 template<typename T> | 1193 template<typename T> |
1292 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; | 1194 PassRefPtr<T> adoptRef(blink::RefCountedGarbageCollected<T>*) = delete; |
1293 | 1195 |
1294 } // namespace WTF | 1196 } // namespace WTF |
1295 | 1197 |
1296 #endif | 1198 #endif |
OLD | NEW |