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

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

Issue 1999363002: Split out Members, Persistents and SelfKeepAlive in separate headers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sof-gc-type
Patch Set: rebased 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/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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/BUILD.gn ('k') | third_party/WebKit/Source/platform/heap/HeapTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698