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/Member.h" |
| 38 #include "platform/heap/Persistent.h" |
38 #include "platform/heap/ThreadState.h" | 39 #include "platform/heap/ThreadState.h" |
39 #include "platform/heap/TraceTraits.h" | 40 #include "platform/heap/TraceTraits.h" |
40 #include "platform/heap/Visitor.h" | 41 #include "platform/heap/Visitor.h" |
41 #include "wtf/Allocator.h" | 42 #include "wtf/Allocator.h" |
42 #include "wtf/Atomics.h" | |
43 #include "wtf/HashFunctions.h" | |
44 | 43 |
45 #if defined(LEAK_SANITIZER) | 44 #if defined(LEAK_SANITIZER) |
46 #include "wtf/LeakAnnotations.h" | 45 #include "wtf/LeakAnnotations.h" |
47 #endif | 46 #endif |
48 | 47 |
49 namespace blink { | 48 namespace blink { |
50 | 49 |
51 // Marker used to annotate persistent objects and collections with, | |
52 // so as to enable reliable testing for persistent references via | |
53 // a type trait (see TypeTraits.h's IsPersistentReferenceType<>.) | |
54 #define IS_PERSISTENT_REFERENCE_TYPE() \ | |
55 public: \ | |
56 using IsPersistentReferenceTypeMarker = int; \ | |
57 private: | |
58 | |
59 enum WeaknessPersistentConfiguration { | |
60 NonWeakPersistentConfiguration, | |
61 WeakPersistentConfiguration | |
62 }; | |
63 | |
64 enum CrossThreadnessPersistentConfiguration { | |
65 SingleThreadPersistentConfiguration, | |
66 CrossThreadPersistentConfiguration | |
67 }; | |
68 | |
69 template<typename T, WeaknessPersistentConfiguration weaknessConfiguration, Cros
sThreadnessPersistentConfiguration crossThreadnessConfiguration> | |
70 class PersistentBase { | |
71 USING_FAST_MALLOC(PersistentBase); | |
72 IS_PERSISTENT_REFERENCE_TYPE(); | |
73 public: | |
74 PersistentBase() : m_raw(nullptr) | |
75 { | |
76 initialize(); | |
77 } | |
78 | |
79 PersistentBase(std::nullptr_t) : m_raw(nullptr) | |
80 { | |
81 initialize(); | |
82 } | |
83 | |
84 PersistentBase(T* raw) : m_raw(raw) | |
85 { | |
86 initialize(); | |
87 checkPointer(); | |
88 } | |
89 | |
90 PersistentBase(T& raw) : m_raw(&raw) | |
91 { | |
92 initialize(); | |
93 checkPointer(); | |
94 } | |
95 | |
96 PersistentBase(const PersistentBase& other) : m_raw(other) | |
97 { | |
98 initialize(); | |
99 checkPointer(); | |
100 } | |
101 | |
102 template<typename U> | |
103 PersistentBase(const PersistentBase<U, weaknessConfiguration, crossThreadnes
sConfiguration>& other) : m_raw(other) | |
104 { | |
105 initialize(); | |
106 checkPointer(); | |
107 } | |
108 | |
109 template<typename U> | |
110 PersistentBase(const Member<U>& other) : m_raw(other) | |
111 { | |
112 initialize(); | |
113 checkPointer(); | |
114 } | |
115 | |
116 ~PersistentBase() | |
117 { | |
118 uninitialize(); | |
119 m_raw = nullptr; | |
120 } | |
121 | |
122 template<typename VisitorDispatcher> | |
123 void trace(VisitorDispatcher visitor) | |
124 { | |
125 static_assert(sizeof(T), "T must be fully defined"); | |
126 static_assert(IsGarbageCollectedType<T>::value, "T needs to be a garbage
collected object"); | |
127 if (weaknessConfiguration == WeakPersistentConfiguration) { | |
128 visitor->registerWeakCell(&m_raw); | |
129 } else { | |
130 visitor->mark(m_raw); | |
131 } | |
132 } | |
133 | |
134 T* release() | |
135 { | |
136 T* result = m_raw; | |
137 assign(nullptr); | |
138 return result; | |
139 } | |
140 | |
141 void clear() { assign(nullptr); } | |
142 T& operator*() const { return *m_raw; } | |
143 explicit operator bool() const { return m_raw; } | |
144 operator T*() const { return m_raw; } | |
145 T* operator->() const { return *this; } | |
146 T* get() const { return m_raw; } | |
147 | |
148 template<typename U> | |
149 PersistentBase& operator=(U* other) | |
150 { | |
151 assign(other); | |
152 return *this; | |
153 } | |
154 | |
155 PersistentBase& operator=(std::nullptr_t) | |
156 { | |
157 assign(nullptr); | |
158 return *this; | |
159 } | |
160 | |
161 PersistentBase& operator=(const PersistentBase& other) | |
162 { | |
163 assign(other); | |
164 return *this; | |
165 } | |
166 | |
167 template<typename U> | |
168 PersistentBase& operator=(const PersistentBase<U, weaknessConfiguration, cro
ssThreadnessConfiguration>& other) | |
169 { | |
170 assign(other); | |
171 return *this; | |
172 } | |
173 | |
174 template<typename U> | |
175 PersistentBase& operator=(const Member<U>& other) | |
176 { | |
177 assign(other); | |
178 return *this; | |
179 } | |
180 | |
181 // Register the persistent node as a 'static reference', | |
182 // belonging to the current thread and a persistent that must | |
183 // be cleared when the ThreadState itself is cleared out and | |
184 // destructed. | |
185 // | |
186 // Static singletons arrange for this to happen, either to ensure | |
187 // clean LSan leak reports or to register a thread-local persistent | |
188 // needing to be cleared out before the thread is terminated. | |
189 PersistentBase* registerAsStaticReference() | |
190 { | |
191 if (m_persistentNode) { | |
192 ASSERT(ThreadState::current()); | |
193 ThreadState::current()->registerStaticPersistentNode(m_persistentNod
e, nullptr); | |
194 LEAK_SANITIZER_IGNORE_OBJECT(this); | |
195 } | |
196 return this; | |
197 } | |
198 | |
199 protected: | |
200 T* atomicGet() { return reinterpret_cast<T*>(acquireLoad(reinterpret_cast<vo
id* volatile*>(&m_raw))); } | |
201 | |
202 private: | |
203 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
204 void assign(T* ptr) | |
205 { | |
206 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration) | |
207 releaseStore(reinterpret_cast<void* volatile*>(&m_raw), ptr); | |
208 else | |
209 m_raw = ptr; | |
210 checkPointer(); | |
211 if (m_raw) { | |
212 if (!m_persistentNode) | |
213 initialize(); | |
214 return; | |
215 } | |
216 uninitialize(); | |
217 } | |
218 | |
219 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
220 void initialize() | |
221 { | |
222 ASSERT(!m_persistentNode); | |
223 if (!m_raw) | |
224 return; | |
225 | |
226 TraceCallback traceCallback = TraceMethodDelegate<PersistentBase<T, weak
nessConfiguration, crossThreadnessConfiguration>, &PersistentBase<T, weaknessCon
figuration, crossThreadnessConfiguration>::trace>::trampoline; | |
227 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ | |
228 ProcessHeap::crossThreadPersistentRegion().allocatePersistentNode(m_
persistentNode, this, traceCallback); | |
229 return; | |
230 } | |
231 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
232 ASSERT(state->checkThread()); | |
233 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(
this, traceCallback); | |
234 #if ENABLE(ASSERT) | |
235 m_state = state; | |
236 #endif | |
237 } | |
238 | |
239 void uninitialize() | |
240 { | |
241 if (crossThreadnessConfiguration == CrossThreadPersistentConfiguration)
{ | |
242 if (acquireLoad(reinterpret_cast<void* volatile*>(&m_persistentNode)
)) | |
243 ProcessHeap::crossThreadPersistentRegion().freePersistentNode(m_
persistentNode); | |
244 return; | |
245 } | |
246 | |
247 if (!m_persistentNode) | |
248 return; | |
249 ThreadState* state = ThreadStateFor<ThreadingTrait<T>::Affinity>::state(
); | |
250 ASSERT(state->checkThread()); | |
251 // Persistent handle must be created and destructed in the same thread. | |
252 ASSERT(m_state == state); | |
253 state->freePersistentNode(m_persistentNode); | |
254 m_persistentNode = nullptr; | |
255 } | |
256 | |
257 void checkPointer() | |
258 { | |
259 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | |
260 if (!m_raw) | |
261 return; | |
262 | |
263 // ThreadHeap::isHeapObjectAlive(m_raw) checks that m_raw is a traceable | |
264 // object. In other words, it checks that the pointer is either of: | |
265 // | |
266 // (a) a pointer to the head of an on-heap object. | |
267 // (b) a pointer to the head of an on-heap mixin object. | |
268 // | |
269 // Otherwise, ThreadHeap::isHeapObjectAlive will crash when it calls | |
270 // header->checkHeader(). | |
271 ThreadHeap::isHeapObjectAlive(m_raw); | |
272 #endif | |
273 } | |
274 | |
275 // m_raw is accessed most, so put it at the first field. | |
276 T* m_raw; | |
277 PersistentNode* m_persistentNode = nullptr; | |
278 #if ENABLE(ASSERT) | |
279 ThreadState* m_state = nullptr; | |
280 #endif | |
281 }; | |
282 | |
283 // Persistent is a way to create a strong pointer from an off-heap object | |
284 // to another on-heap object. As long as the Persistent handle is alive | |
285 // the GC will keep the object pointed to alive. The Persistent handle is | |
286 // always a GC root from the point of view of the GC. | |
287 // | |
288 // We have to construct and destruct Persistent in the same thread. | |
289 template<typename T> | |
290 class Persistent : public PersistentBase<T, NonWeakPersistentConfiguration, Sing
leThreadPersistentConfiguration> { | |
291 typedef PersistentBase<T, NonWeakPersistentConfiguration, SingleThreadPersis
tentConfiguration> Parent; | |
292 public: | |
293 Persistent() : Parent() { } | |
294 Persistent(std::nullptr_t) : Parent(nullptr) { } | |
295 Persistent(T* raw) : Parent(raw) { } | |
296 Persistent(T& raw) : Parent(raw) { } | |
297 Persistent(const Persistent& other) : Parent(other) { } | |
298 template<typename U> | |
299 Persistent(const Persistent<U>& other) : Parent(other) { } | |
300 template<typename U> | |
301 Persistent(const Member<U>& other) : Parent(other) { } | |
302 | |
303 template<typename U> | |
304 Persistent& operator=(U* other) | |
305 { | |
306 Parent::operator=(other); | |
307 return *this; | |
308 } | |
309 | |
310 Persistent& operator=(std::nullptr_t) | |
311 { | |
312 Parent::operator=(nullptr); | |
313 return *this; | |
314 } | |
315 | |
316 Persistent& operator=(const Persistent& other) | |
317 { | |
318 Parent::operator=(other); | |
319 return *this; | |
320 } | |
321 | |
322 template<typename U> | |
323 Persistent& operator=(const Persistent<U>& other) | |
324 { | |
325 Parent::operator=(other); | |
326 return *this; | |
327 } | |
328 | |
329 template<typename U> | |
330 Persistent& operator=(const Member<U>& other) | |
331 { | |
332 Parent::operator=(other); | |
333 return *this; | |
334 } | |
335 }; | |
336 | |
337 // WeakPersistent is a way to create a weak pointer from an off-heap object | |
338 // to an on-heap object. The m_raw is automatically cleared when the pointee | |
339 // gets collected. | |
340 // | |
341 // We have to construct and destruct WeakPersistent in the same thread. | |
342 // | |
343 // Note that collections of WeakPersistents are not supported. Use a persistent | |
344 // collection of WeakMembers instead. | |
345 // | |
346 // HashSet<WeakPersistent<T>> m_set; // wrong | |
347 // PersistentHeapHashSet<WeakMember<T>> m_set; // correct | |
348 template<typename T> | |
349 class WeakPersistent : public PersistentBase<T, WeakPersistentConfiguration, Sin
gleThreadPersistentConfiguration> { | |
350 typedef PersistentBase<T, WeakPersistentConfiguration, SingleThreadPersisten
tConfiguration> Parent; | |
351 public: | |
352 WeakPersistent() : Parent() { } | |
353 WeakPersistent(std::nullptr_t) : Parent(nullptr) { } | |
354 WeakPersistent(T* raw) : Parent(raw) { } | |
355 WeakPersistent(T& raw) : Parent(raw) { } | |
356 WeakPersistent(const WeakPersistent& other) : Parent(other) { } | |
357 template<typename U> | |
358 WeakPersistent(const WeakPersistent<U>& other) : Parent(other) { } | |
359 template<typename U> | |
360 WeakPersistent(const Member<U>& other) : Parent(other) { } | |
361 | |
362 template<typename U> | |
363 WeakPersistent& operator=(U* other) | |
364 { | |
365 Parent::operator=(other); | |
366 return *this; | |
367 } | |
368 | |
369 WeakPersistent& operator=(std::nullptr_t) | |
370 { | |
371 Parent::operator=(nullptr); | |
372 return *this; | |
373 } | |
374 | |
375 WeakPersistent& operator=(const WeakPersistent& other) | |
376 { | |
377 Parent::operator=(other); | |
378 return *this; | |
379 } | |
380 | |
381 template<typename U> | |
382 WeakPersistent& operator=(const WeakPersistent<U>& other) | |
383 { | |
384 Parent::operator=(other); | |
385 return *this; | |
386 } | |
387 | |
388 template<typename U> | |
389 WeakPersistent& operator=(const Member<U>& other) | |
390 { | |
391 Parent::operator=(other); | |
392 return *this; | |
393 } | |
394 }; | |
395 | |
396 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread | |
397 // different from the construction thread. | |
398 template<typename T> | |
399 class CrossThreadPersistent : public PersistentBase<T, NonWeakPersistentConfigur
ation, CrossThreadPersistentConfiguration> { | |
400 typedef PersistentBase<T, NonWeakPersistentConfiguration, CrossThreadPersist
entConfiguration> Parent; | |
401 public: | |
402 CrossThreadPersistent() : Parent() { } | |
403 CrossThreadPersistent(std::nullptr_t) : Parent(nullptr) { } | |
404 CrossThreadPersistent(T* raw) : Parent(raw) { } | |
405 CrossThreadPersistent(T& raw) : Parent(raw) { } | |
406 CrossThreadPersistent(const CrossThreadPersistent& other) : Parent(other) {
} | |
407 template<typename U> | |
408 CrossThreadPersistent(const CrossThreadPersistent<U>& other) : Parent(other)
{ } | |
409 template<typename U> | |
410 CrossThreadPersistent(const Member<U>& other) : Parent(other) { } | |
411 | |
412 T* atomicGet() { return Parent::atomicGet(); } | |
413 | |
414 template<typename U> | |
415 CrossThreadPersistent& operator=(U* other) | |
416 { | |
417 Parent::operator=(other); | |
418 return *this; | |
419 } | |
420 | |
421 CrossThreadPersistent& operator=(std::nullptr_t) | |
422 { | |
423 Parent::operator=(nullptr); | |
424 return *this; | |
425 } | |
426 | |
427 CrossThreadPersistent& operator=(const CrossThreadPersistent& other) | |
428 { | |
429 Parent::operator=(other); | |
430 return *this; | |
431 } | |
432 | |
433 template<typename U> | |
434 CrossThreadPersistent& operator=(const CrossThreadPersistent<U>& other) | |
435 { | |
436 Parent::operator=(other); | |
437 return *this; | |
438 } | |
439 | |
440 template<typename U> | |
441 CrossThreadPersistent& operator=(const Member<U>& other) | |
442 { | |
443 Parent::operator=(other); | |
444 return *this; | |
445 } | |
446 }; | |
447 | |
448 // Combines the behavior of CrossThreadPersistent and WeakPersistent. | |
449 template<typename T> | |
450 class CrossThreadWeakPersistent : public PersistentBase<T, WeakPersistentConfigu
ration, CrossThreadPersistentConfiguration> { | |
451 typedef PersistentBase<T, WeakPersistentConfiguration, CrossThreadPersistent
Configuration> Parent; | |
452 public: | |
453 CrossThreadWeakPersistent() : Parent() { } | |
454 CrossThreadWeakPersistent(std::nullptr_t) : Parent(nullptr) { } | |
455 CrossThreadWeakPersistent(T* raw) : Parent(raw) { } | |
456 CrossThreadWeakPersistent(T& raw) : Parent(raw) { } | |
457 CrossThreadWeakPersistent(const CrossThreadWeakPersistent& other) : Parent(o
ther) { } | |
458 template<typename U> | |
459 CrossThreadWeakPersistent(const CrossThreadWeakPersistent<U>& other) : Paren
t(other) { } | |
460 template<typename U> | |
461 CrossThreadWeakPersistent(const Member<U>& other) : Parent(other) { } | |
462 | |
463 template<typename U> | |
464 CrossThreadWeakPersistent& operator=(U* other) | |
465 { | |
466 Parent::operator=(other); | |
467 return *this; | |
468 } | |
469 | |
470 CrossThreadWeakPersistent& operator=(std::nullptr_t) | |
471 { | |
472 Parent::operator=(nullptr); | |
473 return *this; | |
474 } | |
475 | |
476 CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent& other) | |
477 { | |
478 Parent::operator=(other); | |
479 return *this; | |
480 } | |
481 | |
482 template<typename U> | |
483 CrossThreadWeakPersistent& operator=(const CrossThreadWeakPersistent<U>& oth
er) | |
484 { | |
485 Parent::operator=(other); | |
486 return *this; | |
487 } | |
488 | |
489 template<typename U> | |
490 CrossThreadWeakPersistent& operator=(const Member<U>& other) | |
491 { | |
492 Parent::operator=(other); | |
493 return *this; | |
494 } | |
495 }; | |
496 | |
497 template<typename Collection> | |
498 class PersistentHeapCollectionBase : public Collection { | |
499 // We overload the various new and delete operators with using the WTF Parti
tionAllocator to ensure persistent | |
500 // heap collections are always allocated off-heap. This allows persistent co
llections to be used in | |
501 // DEFINE_STATIC_LOCAL et. al. | |
502 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::PartitionAllocator); | |
503 IS_PERSISTENT_REFERENCE_TYPE(); | |
504 public: | |
505 PersistentHeapCollectionBase() | |
506 { | |
507 initialize(); | |
508 } | |
509 | |
510 PersistentHeapCollectionBase(const PersistentHeapCollectionBase& other) : Co
llection(other) | |
511 { | |
512 initialize(); | |
513 } | |
514 | |
515 template<typename OtherCollection> | |
516 PersistentHeapCollectionBase(const OtherCollection& other) : Collection(othe
r) | |
517 { | |
518 initialize(); | |
519 } | |
520 | |
521 ~PersistentHeapCollectionBase() | |
522 { | |
523 uninitialize(); | |
524 } | |
525 | |
526 template<typename VisitorDispatcher> | |
527 void trace(VisitorDispatcher visitor) | |
528 { | |
529 static_assert(sizeof(Collection), "Collection must be fully defined"); | |
530 visitor->trace(*static_cast<Collection*>(this)); | |
531 } | |
532 | |
533 // See PersistentBase::registerAsStaticReference() comment. | |
534 PersistentHeapCollectionBase* registerAsStaticReference() | |
535 { | |
536 if (m_persistentNode) { | |
537 ASSERT(ThreadState::current()); | |
538 ThreadState::current()->registerStaticPersistentNode(m_persistentNod
e, &PersistentHeapCollectionBase<Collection>::clearPersistentNode); | |
539 LEAK_SANITIZER_IGNORE_OBJECT(this); | |
540 } | |
541 return this; | |
542 } | |
543 | |
544 private: | |
545 | |
546 // Used when the registered PersistentNode of this object is | |
547 // released during ThreadState shutdown, clearing the association. | |
548 static void clearPersistentNode(void *self) | |
549 { | |
550 PersistentHeapCollectionBase<Collection>* collection = (reinterpret_cast
<PersistentHeapCollectionBase<Collection>*>(self)); | |
551 collection->uninitialize(); | |
552 collection->clear(); | |
553 } | |
554 | |
555 NO_LAZY_SWEEP_SANITIZE_ADDRESS | |
556 void initialize() | |
557 { | |
558 // FIXME: Derive affinity based on the collection. | |
559 ThreadState* state = ThreadState::current(); | |
560 ASSERT(state->checkThread()); | |
561 m_persistentNode = state->getPersistentRegion()->allocatePersistentNode(
this, TraceMethodDelegate<PersistentHeapCollectionBase<Collection>, &PersistentH
eapCollectionBase<Collection>::trace>::trampoline); | |
562 #if ENABLE(ASSERT) | |
563 m_state = state; | |
564 #endif | |
565 } | |
566 | |
567 void uninitialize() | |
568 { | |
569 if (!m_persistentNode) | |
570 return; | |
571 ThreadState* state = ThreadState::current(); | |
572 ASSERT(state->checkThread()); | |
573 // Persistent handle must be created and destructed in the same thread. | |
574 ASSERT(m_state == state); | |
575 state->freePersistentNode(m_persistentNode); | |
576 m_persistentNode = nullptr; | |
577 } | |
578 | |
579 PersistentNode* m_persistentNode; | |
580 #if ENABLE(ASSERT) | |
581 ThreadState* m_state; | |
582 #endif | |
583 }; | |
584 | |
585 template< | |
586 typename KeyArg, | |
587 typename MappedArg, | |
588 typename HashArg = typename DefaultHash<KeyArg>::Hash, | |
589 typename KeyTraitsArg = HashTraits<KeyArg>, | |
590 typename MappedTraitsArg = HashTraits<MappedArg>> | |
591 class PersistentHeapHashMap : public PersistentHeapCollectionBase<HeapHashMap<Ke
yArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg>> { }; | |
592 | |
593 template< | |
594 typename ValueArg, | |
595 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
596 typename TraitsArg = HashTraits<ValueArg>> | |
597 class PersistentHeapHashSet : public PersistentHeapCollectionBase<HeapHashSet<Va
lueArg, HashArg, TraitsArg>> { }; | |
598 | |
599 template< | |
600 typename ValueArg, | |
601 typename HashArg = typename DefaultHash<ValueArg>::Hash, | |
602 typename TraitsArg = HashTraits<ValueArg>> | |
603 class PersistentHeapLinkedHashSet : public PersistentHeapCollectionBase<HeapLink
edHashSet<ValueArg, HashArg, TraitsArg>> { }; | |
604 | |
605 template< | |
606 typename ValueArg, | |
607 size_t inlineCapacity = 0, | |
608 typename HashArg = typename DefaultHash<ValueArg>::Hash> | |
609 class PersistentHeapListHashSet : public PersistentHeapCollectionBase<HeapListHa
shSet<ValueArg, inlineCapacity, HashArg>> { }; | |
610 | |
611 template< | |
612 typename ValueArg, | |
613 typename HashFunctions = typename DefaultHash<ValueArg>::Hash, | |
614 typename Traits = HashTraits<ValueArg>> | |
615 class PersistentHeapHashCountedSet : public PersistentHeapCollectionBase<HeapHas
hCountedSet<ValueArg, HashFunctions, Traits>> { }; | |
616 | |
617 template<typename T, size_t inlineCapacity = 0> | |
618 class PersistentHeapVector : public PersistentHeapCollectionBase<HeapVector<T, i
nlineCapacity>> { | |
619 public: | |
620 PersistentHeapVector() | |
621 { | |
622 initializeUnusedSlots(); | |
623 } | |
624 | |
625 explicit PersistentHeapVector(size_t size) | |
626 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(size) | |
627 { | |
628 initializeUnusedSlots(); | |
629 } | |
630 | |
631 PersistentHeapVector(const PersistentHeapVector& other) | |
632 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(other) | |
633 { | |
634 initializeUnusedSlots(); | |
635 } | |
636 | |
637 template<size_t otherCapacity> | |
638 PersistentHeapVector(const HeapVector<T, otherCapacity>& other) | |
639 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity>>(other) | |
640 { | |
641 initializeUnusedSlots(); | |
642 } | |
643 | |
644 private: | |
645 void initializeUnusedSlots() | |
646 { | |
647 // The PersistentHeapVector is allocated off heap along with its | |
648 // inline buffer (if any.) Maintain the invariant that unused | |
649 // slots are cleared for the off-heap inline buffer also. | |
650 size_t unusedSlots = this->capacity() - this->size(); | |
651 if (unusedSlots) | |
652 this->clearUnusedSlots(this->end(), this->end() + unusedSlots); | |
653 } | |
654 }; | |
655 | |
656 template<typename T, size_t inlineCapacity = 0> | |
657 class PersistentHeapDeque : public PersistentHeapCollectionBase<HeapDeque<T, inl
ineCapacity>> { | |
658 public: | |
659 PersistentHeapDeque() { } | |
660 | |
661 template<size_t otherCapacity> | |
662 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other) | |
663 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity>>(other) | |
664 { | |
665 } | |
666 }; | |
667 | |
668 // Members are used in classes to contain strong pointers to other oilpan heap | |
669 // allocated objects. | |
670 // All Member fields of a class must be traced in the class' trace method. | |
671 // During the mark phase of the GC all live objects are marked as live and | |
672 // all Member fields of a live object will be traced marked as live as well. | |
673 template<typename T> | |
674 class Member { | |
675 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW(); | |
676 public: | |
677 Member() : m_raw(nullptr) | |
678 { | |
679 } | |
680 | |
681 Member(std::nullptr_t) : m_raw(nullptr) | |
682 { | |
683 } | |
684 | |
685 Member(T* raw) : m_raw(raw) | |
686 { | |
687 checkPointer(); | |
688 } | |
689 | |
690 explicit Member(T& raw) : m_raw(&raw) | |
691 { | |
692 checkPointer(); | |
693 } | |
694 | |
695 Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1)) | |
696 { | |
697 } | |
698 | |
699 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(
-1); } | |
700 | |
701 template<typename U> | |
702 Member(const Persistent<U>& other) : m_raw(other) | |
703 { | |
704 checkPointer(); | |
705 } | |
706 | |
707 Member(const Member& other) : m_raw(other) | |
708 { | |
709 checkPointer(); | |
710 } | |
711 | |
712 template<typename U> | |
713 Member(const Member<U>& other) : m_raw(other) | |
714 { | |
715 checkPointer(); | |
716 } | |
717 | |
718 T* release() | |
719 { | |
720 T* result = m_raw; | |
721 m_raw = nullptr; | |
722 return result; | |
723 } | |
724 | |
725 explicit operator bool() const { return m_raw; } | |
726 | |
727 operator T*() const { return m_raw; } | |
728 | |
729 T* operator->() const { return m_raw; } | |
730 T& operator*() const { return *m_raw; } | |
731 | |
732 template<typename U> | |
733 Member& operator=(const Persistent<U>& other) | |
734 { | |
735 m_raw = other; | |
736 checkPointer(); | |
737 return *this; | |
738 } | |
739 | |
740 template<typename U> | |
741 Member& operator=(const Member<U>& other) | |
742 { | |
743 m_raw = other; | |
744 checkPointer(); | |
745 return *this; | |
746 } | |
747 | |
748 template<typename U> | |
749 Member& operator=(U* other) | |
750 { | |
751 m_raw = other; | |
752 checkPointer(); | |
753 return *this; | |
754 } | |
755 | |
756 Member& operator=(std::nullptr_t) | |
757 { | |
758 m_raw = nullptr; | |
759 return *this; | |
760 } | |
761 | |
762 void swap(Member<T>& other) | |
763 { | |
764 std::swap(m_raw, other.m_raw); | |
765 checkPointer(); | |
766 } | |
767 | |
768 T* get() const { return m_raw; } | |
769 | |
770 void clear() { m_raw = nullptr; } | |
771 | |
772 | |
773 protected: | |
774 void checkPointer() | |
775 { | |
776 #if ENABLE(ASSERT) && defined(ADDRESS_SANITIZER) | |
777 if (!m_raw) | |
778 return; | |
779 // HashTable can store a special value (which is not aligned to the | |
780 // allocation granularity) to Member<> to represent a deleted entry. | |
781 // Thus we treat a pointer that is not aligned to the granularity | |
782 // as a valid pointer. | |
783 if (reinterpret_cast<intptr_t>(m_raw) % allocationGranularity) | |
784 return; | |
785 | |
786 // TODO(haraken): What we really want to check here is that the pointer | |
787 // is a traceable object. In other words, the pointer is either of: | |
788 // | |
789 // (a) a pointer to the head of an on-heap object. | |
790 // (b) a pointer to the head of an on-heap mixin object. | |
791 // | |
792 // We can check it by calling ThreadHeap::isHeapObjectAlive(m_raw), | |
793 // but we cannot call it here because it requires to include T.h. | |
794 // So we currently only try to implement the check for (a), but do | |
795 // not insist that T's definition is in scope. | |
796 if (IsFullyDefined<T>::value && !IsGarbageCollectedMixin<T>::value) | |
797 ASSERT(HeapObjectHeader::fromPayload(m_raw)->checkHeader()); | |
798 #endif | |
799 } | |
800 | |
801 T* m_raw; | |
802 | |
803 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStr
ongly z, typename U, typename V> friend struct CollectionBackingTraceTrait; | |
804 friend class Visitor; | |
805 | |
806 }; | |
807 | |
808 // WeakMember is similar to Member in that it is used to point to other oilpan | |
809 // heap allocated objects. | |
810 // However instead of creating a strong pointer to the object, the WeakMember cr
eates | |
811 // a weak pointer, which does not keep the pointee alive. Hence if all pointers
to | |
812 // to a heap allocated object are weak the object will be garbage collected. At
the | |
813 // time of GC the weak pointers will automatically be set to null. | |
814 template<typename T> | |
815 class WeakMember : public Member<T> { | |
816 public: | |
817 WeakMember() : Member<T>() { } | |
818 | |
819 WeakMember(std::nullptr_t) : Member<T>(nullptr) { } | |
820 | |
821 WeakMember(T* raw) : Member<T>(raw) { } | |
822 | |
823 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | |
824 | |
825 template<typename U> | |
826 WeakMember(const Persistent<U>& other) : Member<T>(other) { } | |
827 | |
828 template<typename U> | |
829 WeakMember(const Member<U>& other) : Member<T>(other) { } | |
830 | |
831 template<typename U> | |
832 WeakMember& operator=(const Persistent<U>& other) | |
833 { | |
834 this->m_raw = other; | |
835 this->checkPointer(); | |
836 return *this; | |
837 } | |
838 | |
839 template<typename U> | |
840 WeakMember& operator=(const Member<U>& other) | |
841 { | |
842 this->m_raw = other; | |
843 this->checkPointer(); | |
844 return *this; | |
845 } | |
846 | |
847 template<typename U> | |
848 WeakMember& operator=(U* other) | |
849 { | |
850 this->m_raw = other; | |
851 this->checkPointer(); | |
852 return *this; | |
853 } | |
854 | |
855 WeakMember& operator=(std::nullptr_t) | |
856 { | |
857 this->m_raw = nullptr; | |
858 return *this; | |
859 } | |
860 | |
861 private: | |
862 T** cell() const { return const_cast<T**>(&this->m_raw); } | |
863 | |
864 template<typename Derived> friend class VisitorHelper; | |
865 }; | |
866 | |
867 // UntracedMember is a pointer to an on-heap object that is not traced for some | |
868 // reason. Please don't use this unless you understand what you're doing. | |
869 // Basically, all pointers to on-heap objects must be stored in either of | |
870 // Persistent, Member or WeakMember. It is not allowed to leave raw pointers to | |
871 // on-heap objects. However, there can be scenarios where you have to use raw | |
872 // pointers for some reason, and in that case you can use UntracedMember. Of | |
873 // course, it must be guaranteed that the pointing on-heap object is kept alive | |
874 // while the raw pointer is pointing to the object. | |
875 template<typename T> | |
876 class UntracedMember final : public Member<T> { | |
877 public: | |
878 UntracedMember() : Member<T>() { } | |
879 | |
880 UntracedMember(std::nullptr_t) : Member<T>(nullptr) { } | |
881 | |
882 UntracedMember(T* raw) : Member<T>(raw) { } | |
883 | |
884 template<typename U> | |
885 UntracedMember(const Persistent<U>& other) : Member<T>(other) { } | |
886 | |
887 template<typename U> | |
888 UntracedMember(const Member<U>& other) : Member<T>(other) { } | |
889 | |
890 UntracedMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { } | |
891 | |
892 template<typename U> | |
893 UntracedMember& operator=(const Persistent<U>& other) | |
894 { | |
895 this->m_raw = other; | |
896 this->checkPointer(); | |
897 return *this; | |
898 } | |
899 | |
900 template<typename U> | |
901 UntracedMember& operator=(const Member<U>& other) | |
902 { | |
903 this->m_raw = other; | |
904 this->checkPointer(); | |
905 return *this; | |
906 } | |
907 | |
908 template<typename U> | |
909 UntracedMember& operator=(U* other) | |
910 { | |
911 this->m_raw = other; | |
912 this->checkPointer(); | |
913 return *this; | |
914 } | |
915 | |
916 UntracedMember& operator=(std::nullptr_t) | |
917 { | |
918 this->m_raw = nullptr; | |
919 return *this; | |
920 } | |
921 }; | |
922 | |
923 // Comparison operators between (Weak)Members, Persistents, and UntracedMembers. | |
924 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Member<U>& b) { return a.get() == b.get(); } | |
925 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Member<U>& b) { return a.get() != b.get(); } | |
926 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() == b.get(); } | |
927 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Persistent<U>& b) { return a.get() != b.get(); } | |
928 | |
929 template<typename T, typename U> inline bool operator==(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() == b.get(); } | |
930 template<typename T, typename U> inline bool operator!=(const Member<T>& a, cons
t Persistent<U>& b) { return a.get() != b.get(); } | |
931 template<typename T, typename U> inline bool operator==(const Persistent<T>& a,
const Member<U>& b) { return a.get() == b.get(); } | |
932 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a,
const Member<U>& b) { return a.get() != b.get(); } | |
933 | |
934 template<typename T, bool = IsGarbageCollectedType<T>::value> | |
935 class RawPtrOrMemberTrait { | |
936 STATIC_ONLY(RawPtrOrMemberTrait) | |
937 public: | |
938 using Type = T*; | |
939 }; | |
940 | |
941 template<typename T> | |
942 class RawPtrOrMemberTrait<T, true> { | |
943 STATIC_ONLY(RawPtrOrMemberTrait) | |
944 public: | |
945 using Type = Member<T>; | |
946 }; | |
947 | |
948 // Abstraction for injecting calls to an object's 'dispose()' method | |
949 // on leaving a stack scope, ensuring earlier release of resources | |
950 // than waiting until the object is eventually GCed. | |
951 template<typename T, void (T::*Disposer)() = (&T::dispose)> | |
952 class ScopedDisposal { | |
953 STACK_ALLOCATED(); | |
954 public: | |
955 ScopedDisposal(T* object) | |
956 : m_object(object) | |
957 { | |
958 } | |
959 | |
960 ~ScopedDisposal() | |
961 { | |
962 if (m_object) | |
963 (m_object->*Disposer)(); | |
964 } | |
965 | |
966 void clear() { m_object.clear(); } | |
967 | |
968 private: | |
969 typename RawPtrOrMemberTrait<T>::Type m_object; | |
970 }; | |
971 | |
972 // SelfKeepAlive<Object> is the idiom to use for objects that have to keep | |
973 // themselves temporarily alive and cannot rely on there being some | |
974 // external reference in that interval: | |
975 // | |
976 // class Opener { | |
977 // public: | |
978 // ... | |
979 // void open() | |
980 // { | |
981 // // Retain a self-reference while in an open()ed state: | |
982 // m_keepAlive = this; | |
983 // .... | |
984 // } | |
985 // | |
986 // void close() | |
987 // { | |
988 // // Clear self-reference that ensured we were kept alive while opened. | |
989 // m_keepAlive.clear(); | |
990 // .... | |
991 // } | |
992 // | |
993 // private: | |
994 // ... | |
995 // SelfKeepAlive m_keepAlive; | |
996 // }; | |
997 // | |
998 // The responsibility to call clear() in a timely fashion resides with the imple
mentation | |
999 // of the object. | |
1000 // | |
1001 // | |
1002 template<typename Self> | |
1003 class SelfKeepAlive final { | |
1004 DISALLOW_NEW(); | |
1005 public: | |
1006 SelfKeepAlive() | |
1007 { | |
1008 } | |
1009 | |
1010 explicit SelfKeepAlive(Self* self) | |
1011 { | |
1012 assign(self); | |
1013 } | |
1014 | |
1015 SelfKeepAlive& operator=(Self* self) | |
1016 { | |
1017 assign(self); | |
1018 return *this; | |
1019 } | |
1020 | |
1021 void clear() | |
1022 { | |
1023 m_keepAlive.clear(); | |
1024 } | |
1025 | |
1026 typedef Persistent<Self> (SelfKeepAlive::*UnspecifiedBoolType); | |
1027 operator UnspecifiedBoolType() const { return m_keepAlive ? &SelfKeepAlive::
m_keepAlive : 0; } | |
1028 | |
1029 private: | |
1030 void assign(Self* self) | |
1031 { | |
1032 ASSERT(!m_keepAlive || m_keepAlive.get() == self); | |
1033 m_keepAlive = self; | |
1034 } | |
1035 | |
1036 GC_PLUGIN_IGNORE("420515") | |
1037 Persistent<Self> m_keepAlive; | |
1038 }; | |
1039 | |
1040 // Only a very reduced form of weak heap object references can currently be held | |
1041 // by WTF::Closure<>s. i.e., bound as a 'this' pointer only. | |
1042 // | |
1043 // TODO(sof): once wtf/Functional.h is able to work over platform/heap/ types | |
1044 // (like CrossThreadWeakPersistent<>), drop the restriction on weak persistent | |
1045 // use by function closures (and rename this ad-hoc type.) | |
1046 template<typename T> | |
1047 class WeakPersistentThisPointer { | |
1048 STACK_ALLOCATED(); | |
1049 public: | |
1050 explicit WeakPersistentThisPointer(T* value) : m_value(value) { } | |
1051 WeakPersistent<T> value() const { return m_value; } | |
1052 private: | |
1053 WeakPersistent<T> m_value; | |
1054 }; | |
1055 | |
1056 template<typename T> | |
1057 class CrossThreadWeakPersistentThisPointer { | |
1058 STACK_ALLOCATED(); | |
1059 public: | |
1060 explicit CrossThreadWeakPersistentThisPointer(T* value) : m_value(value) { } | |
1061 CrossThreadWeakPersistent<T> value() const { return m_value; } | |
1062 private: | |
1063 CrossThreadWeakPersistent<T> m_value; | |
1064 }; | |
1065 | |
1066 template <typename T> | |
1067 Persistent<T> wrapPersistent(T* value) | |
1068 { | |
1069 return Persistent<T>(value); | |
1070 } | |
1071 | |
1072 template <typename T> | |
1073 CrossThreadPersistent<T> wrapCrossThreadPersistent(T* value) | |
1074 { | |
1075 return CrossThreadPersistent<T>(value); | |
1076 } | |
1077 | |
1078 // LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the current scope | 50 // LEAK_SANITIZER_DISABLED_SCOPE: all allocations made in the current scope |
1079 // will be exempted from LSan consideration. | 51 // will be exempted from LSan consideration. |
1080 // | 52 // |
1081 // TODO(sof): move this to wtf/LeakAnnotations.h (LeakSanitizer.h?) once | 53 // TODO(sof): move this to wtf/LeakAnnotations.h (LeakSanitizer.h?) once |
1082 // wtf/ can freely call upon Oilpan functionality. | 54 // wtf/ can freely call upon Oilpan functionality. |
1083 #if defined(LEAK_SANITIZER) | 55 #if defined(LEAK_SANITIZER) |
1084 class LeakSanitizerDisableScope { | 56 class LeakSanitizerDisableScope { |
1085 STACK_ALLOCATED(); | 57 STACK_ALLOCATED(); |
1086 WTF_MAKE_NONCOPYABLE(LeakSanitizerDisableScope); | 58 WTF_MAKE_NONCOPYABLE(LeakSanitizerDisableScope); |
1087 public: | 59 public: |
(...skipping 11 matching lines...) Expand all Loading... |
1099 ThreadState::current()->leaveStaticReferenceRegistrationDisabledScop
e(); | 71 ThreadState::current()->leaveStaticReferenceRegistrationDisabledScop
e(); |
1100 } | 72 } |
1101 }; | 73 }; |
1102 #define LEAK_SANITIZER_DISABLED_SCOPE LeakSanitizerDisableScope lsanDisabledScop
e | 74 #define LEAK_SANITIZER_DISABLED_SCOPE LeakSanitizerDisableScope lsanDisabledScop
e |
1103 #else | 75 #else |
1104 #define LEAK_SANITIZER_DISABLED_SCOPE | 76 #define LEAK_SANITIZER_DISABLED_SCOPE |
1105 #endif | 77 #endif |
1106 | 78 |
1107 } // namespace blink | 79 } // namespace blink |
1108 | 80 |
1109 namespace WTF { | |
1110 | |
1111 template <typename T> | |
1112 struct MemberHash : PtrHash<T> { | |
1113 STATIC_ONLY(MemberHash); | |
1114 template <typename U> | |
1115 static unsigned hash(const U& key) { return PtrHash<T>::hash(key); } | |
1116 template <typename U, typename V> | |
1117 static bool equal(const U& a, const V& b) { return a == b; } | |
1118 }; | |
1119 | |
1120 template <typename T> | |
1121 struct WeakMemberHash : MemberHash<T> { | |
1122 STATIC_ONLY(WeakMemberHash); | |
1123 }; | |
1124 | |
1125 template <typename T> | |
1126 struct UntracedMemberHash : MemberHash<T> { | |
1127 STATIC_ONLY(UntracedMemberHash); | |
1128 }; | |
1129 | |
1130 // PtrHash is the default hash for hash tables with members. | |
1131 template <typename T> | |
1132 struct DefaultHash<blink::Member<T>> { | |
1133 STATIC_ONLY(DefaultHash); | |
1134 using Hash = MemberHash<T>; | |
1135 }; | |
1136 | |
1137 template <typename T> | |
1138 struct DefaultHash<blink::WeakMember<T>> { | |
1139 STATIC_ONLY(DefaultHash); | |
1140 using Hash = WeakMemberHash<T>; | |
1141 }; | |
1142 | |
1143 template <typename T> | |
1144 struct DefaultHash<blink::UntracedMember<T>> { | |
1145 STATIC_ONLY(DefaultHash); | |
1146 using Hash = UntracedMemberHash<T>; | |
1147 }; | |
1148 | |
1149 template<typename T> | |
1150 struct NeedsTracing<blink::Member<T>> { | |
1151 STATIC_ONLY(NeedsTracing); | |
1152 static const bool value = true; | |
1153 }; | |
1154 | |
1155 template<typename T> | |
1156 struct IsWeak<blink::WeakMember<T>> { | |
1157 STATIC_ONLY(IsWeak); | |
1158 static const bool value = true; | |
1159 }; | |
1160 | |
1161 template<typename T> | |
1162 struct ParamStorageTraits<blink::WeakPersistentThisPointer<T>> { | |
1163 STATIC_ONLY(ParamStorageTraits); | |
1164 static_assert(sizeof(T), "T must be fully defined"); | |
1165 using StorageType = blink::WeakPersistent<T>; | |
1166 | |
1167 static StorageType wrap(const blink::WeakPersistentThisPointer<T>& value) {
return value.value(); } | |
1168 | |
1169 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent | |
1170 // into it. | |
1171 // | |
1172 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty
pe like | |
1173 // WeakPersistent<>. | |
1174 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR
eference<T>::create(value.get())); } | |
1175 }; | |
1176 | |
1177 template<typename T> | |
1178 struct ParamStorageTraits<blink::CrossThreadWeakPersistentThisPointer<T>> { | |
1179 STATIC_ONLY(ParamStorageTraits); | |
1180 static_assert(sizeof(T), "T must be fully defined"); | |
1181 using StorageType = blink::CrossThreadWeakPersistent<T>; | |
1182 | |
1183 static StorageType wrap(const blink::CrossThreadWeakPersistentThisPointer<T>
& value) { return value.value(); } | |
1184 | |
1185 // WTF::FunctionWrapper<> handles WeakPtr<>, so recast this weak persistent | |
1186 // into it. | |
1187 // | |
1188 // TODO(sof): remove this hack once wtf/Functional.h can also work with a ty
pe like | |
1189 // CrossThreadWeakPersistent<>. | |
1190 static WeakPtr<T> unwrap(const StorageType& value) { return WeakPtr<T>(WeakR
eference<T>::create(value.get())); } | |
1191 }; | |
1192 | |
1193 } // namespace WTF | |
1194 | |
1195 #endif | 81 #endif |
OLD | NEW |