Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Side by Side Diff: third_party/WebKit/Source/platform/heap/Handle.h

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

Powered by Google App Engine
This is Rietveld 408576698