1 /*
2 * Copyright (C) 2014 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
29 */
30
31 #ifndef Handle_h
32 #define Handle_h
33
34 #include "platform/heap/Heap.h"
35 #include "platform/heap/ThreadState.h"
36 #include "platform/heap/Visitor.h"
37 #include "wtf/Functional.h"
38 #include "wtf/HashFunctions.h"
39 #include "wtf/Locker.h"
40 #include "wtf/RawPtr.h"
41 #include "wtf/RefCounted.h"
42 #include "wtf/TypeTraits.h"
43
44 namespace blink {
45
46 template<typename T> class HeapTerminatedArray;
47
48 // Template to determine if a class is a GarbageCollectedMixin by checking if it
49 // has adjustAndMark and isAlive. We can't check directly if the class is a
50 // GarbageCollectedMixin because casting to it is potentially ambiguous.
51 template<typename T>
52 struct IsGarbageCollectedMixin {
53 typedef char TrueType;
54 struct FalseType {
55 char dummy[2];
56 };
57
58 #if COMPILER(MSVC)
59 template<typename U> static TrueType hasAdjustAndMark(char[&U::adjustAndMark != 0]);
60 template<typename U> static TrueType hasIsAlive(char[&U::isAlive != 0]);
61 #else
62 template<size_t> struct F;
63 template<typename U> static TrueType hasAdjustAndMark(F<sizeof(&U::adjustAndMark)>*);
64 template<typename U> static TrueType hasIsAlive(F<sizeof(&U::isAlive)>*);
65 #endif
66 template<typename U> static FalseType hasIsAlive(...);
67 template<typename U> static FalseType hasAdjustAndMark(...);
68
69 static bool const value = (sizeof(TrueType) == sizeof(hasAdjustAndMark<T>(0))) && (sizeof(TrueType) == sizeof(hasIsAlive<T>(0)));
70 };
71
72 template <typename T>
73 struct IsGarbageCollectedType {
74 typedef char TrueType;
75 struct FalseType {
76 char dummy[2];
77 };
78
79 typedef typename WTF::RemoveConst<T>::Type NonConstType;
80 typedef WTF::IsSubclassOfTemplate<NonConstType, GarbageCollected> GarbageCollectedSubclass;
81 typedef IsGarbageCollectedMixin<NonConstType> GarbageCollectedMixinSubclass;
82 typedef WTF::IsSubclassOfTemplate3<NonConstType, HeapHashSet> HeapHashSetSubclass;
83 typedef WTF::IsSubclassOfTemplate3<NonConstType, HeapLinkedHashSet> HeapLinkedHashSetSubclass;
84 typedef WTF::IsSubclassOfTemplateTypenameSizeTypename<NonConstType, HeapListHashSet> HeapListHashSetSubclass;
85 typedef WTF::IsSubclassOfTemplate5<NonConstType, HeapHashMap> HeapHashMapSubclass;
86 typedef WTF::IsSubclassOfTemplateTypenameSize<NonConstType, HeapVector> HeapVectorSubclass;
87 typedef WTF::IsSubclassOfTemplateTypenameSize<NonConstType, HeapDeque> HeapDequeSubclass;
88 typedef WTF::IsSubclassOfTemplate3<NonConstType, HeapHashCountedSet> HeapHashCountedSetSubclass;
89 typedef WTF::IsSubclassOfTemplate<NonConstType, HeapTerminatedArray> HeapTerminatedArraySubclass;
90
91 template<typename U, size_t inlineCapacity> static TrueType listHashSetNodeIsHeapAllocated(WTF::ListHashSetNode<U, HeapListHashSetAllocator<U, inlineCapacity> >*);
92 static FalseType listHashSetNodeIsHeapAllocated(...);
93 static const bool isHeapAllocatedListHashSetNode = sizeof(TrueType) == sizeof(listHashSetNodeIsHeapAllocated(reinterpret_cast<NonConstType*>(0)));
94
95 static const bool value =
96 GarbageCollectedSubclass::value
97 || GarbageCollectedMixinSubclass::value
98 || HeapHashSetSubclass::value
99 || HeapLinkedHashSetSubclass::value
100 || HeapListHashSetSubclass::value
101 || HeapHashMapSubclass::value
102 || HeapVectorSubclass::value
103 || HeapDequeSubclass::value
104 || HeapHashCountedSetSubclass::value
105 || HeapTerminatedArraySubclass::value
106 || isHeapAllocatedListHashSetNode;
107 };
108
109 #define COMPILE_ASSERT_IS_GARBAGE_COLLECTED(T, ErrorMessage) \
110 COMPILE_ASSERT(IsGarbageCollectedType<T>::value, ErrorMessage)
111
112 template<typename T> class Member;
113
114 class PersistentNode {
115 public:
PersistentNode(TraceCallback trace)116 explicit PersistentNode(TraceCallback trace)
117 : m_trace(trace)
118 {
119 }
120
isAlive()121 bool isAlive() { return m_trace; }
122
~PersistentNode()123 virtual ~PersistentNode()
124 {
125 ASSERT(isAlive());
126 m_trace = 0;
127 }
128
129 // Ideally the trace method should be virtual and automatically dispatch
130 // to the most specific implementation. However having a virtual method
131 // on PersistentNode leads to too eager template instantiation with MSVC
132 // which leads to include cycles.
133 // Instead we call the constructor with a TraceCallback which knows the
134 // type of the most specific child and calls trace directly. See
135 // TraceMethodDelegate in Visitor.h for how this is done.
trace(Visitor * visitor)136 void trace(Visitor* visitor)
137 {
138 m_trace(visitor, this);
139 }
140
141 protected:
142 TraceCallback m_trace;
143
144 private:
145 PersistentNode* m_next;
146 PersistentNode* m_prev;
147
148 template<typename RootsAccessor, typename Owner> friend class PersistentBase;
149 friend class PersistentAnchor;
150 friend class ThreadState;
151 };
152
153
154 const int wrapperPersistentsPerRegion = 256;
155 const size_t wrapperPersistentOffsetMask = ~static_cast<size_t>(3);
156 const size_t wrapperPersistentLiveBitMask = 1;
157
158 class WrapperPersistentNode {
159 ALLOW_ONLY_INLINE_ALLOCATION();
160 WTF_MAKE_NONCOPYABLE(WrapperPersistentNode);
161 public:
isAlive()162 bool isAlive() { return m_regionOffset & wrapperPersistentLiveBitMask; }
163
region()164 WrapperPersistentRegion* region()
165 {
166 return reinterpret_cast<WrapperPersistentRegion*>(
167 reinterpret_cast<Address>(this) - regionOffset());
168 }
169
trace(Visitor * visitor)170 virtual void trace(Visitor* visitor) { }
171
172 static inline void destroy(const WrapperPersistentNode*);
173
174 protected:
WrapperPersistentNode()175 WrapperPersistentNode() : m_raw(0), m_regionOffset(0) { }
WrapperPersistentNode(void * raw,size_t regionOffset)176 WrapperPersistentNode(void *raw, size_t regionOffset) : m_raw(raw), m_regionOffset(regionOffset) { }
177
178 private:
regionOffset()179 size_t regionOffset() { return m_regionOffset & wrapperPersistentOffsetMask; }
180
takeSlot()181 WrapperPersistentNode* takeSlot()
182 {
183 // The slot should not be alive at the point where it is allocated.
184 ASSERT(!isAlive());
185 WrapperPersistentNode* nextFree = reinterpret_cast<WrapperPersistentNode*>(m_raw);
186 m_raw = 0;
187 return nextFree;
188 }
189
freeSlot(WrapperPersistentNode * nextFree)190 WrapperPersistentNode* freeSlot(WrapperPersistentNode* nextFree)
191 {
192 m_regionOffset &= ~wrapperPersistentLiveBitMask;
193 m_raw = nextFree;
194 return this;
195 }
196
197 // Don't allow delete being called on wrapper persistent nodes. We
198 // do use placement new to initialize the slot with the right vtable. See
199 // WrapperPersistent<T> below.
200 void operator delete(void*);
201
202 protected:
203 // m_raw is used both to point to the object when the WrapperPersistentNode is used/alive
204 // and to point to the next free wrapperPersistentNode in the region when the node is
205 // unused/dead.
206 void* m_raw;
207
208 // The m_regionOffset field encodes liveness of the slot as well as being an
209 // offset from this node to the base of the containing WrapperPersistentRegion.
210 size_t m_regionOffset;
211
212 friend class WrapperPersistentRegion;
213 };
214
215 template<typename T>
216 class WrapperPersistent FINAL : public WrapperPersistentNode {
217 ALLOW_ONLY_INLINE_ALLOCATION();
218 public:
219 static WrapperPersistent<T>* create(T* raw);
220
trace(Visitor * visitor)221 virtual void trace(Visitor* visitor) OVERRIDE
222 {
223 ASSERT(isAlive());
224 visitor->mark(static_cast<T*>(m_raw));
225 }
226
227 private:
WrapperPersistent()228 WrapperPersistent() { }
229
230 // We need to use a constructor to initialize the allocated slot since it
231 // has a vtable which must be set to the WrapperPersistent<T> type.
WrapperPersistent(T * raw,size_t regionOffset)232 WrapperPersistent(T* raw, size_t regionOffset) : WrapperPersistentNode(raw, regionOffset) { }
233
234 // Don't allow delete being called on wrapper persistents.
235 void operator delete(void*);
236 };
237
238 class PLATFORM_EXPORT WrapperPersistentRegion {
239 WTF_MAKE_NONCOPYABLE(WrapperPersistentRegion);
240 public:
WrapperPersistentRegion()241 WrapperPersistentRegion()
242 {
243 WrapperPersistentNode* nextFree = 0;
244 for (int i = wrapperPersistentsPerRegion - 1; i >= 0; --i) {
245 size_t regionOffset = reinterpret_cast<Address>(&m_entries[i]) - reinterpret_cast<Address>(this);
246 // Setup the free slot with an offset to the containing region's base and a pointer to the next
247 // free slot in the region.
248 ASSERT(!(regionOffset & ~wrapperPersistentOffsetMask));
249 new (&m_entries[i]) WrapperPersistentNode(nextFree, regionOffset);
250 nextFree = &m_entries[i];
251 }
252 m_prev = 0;
253 m_next = 0;
254 m_freeHead = nextFree;
255 m_count = 0;
256 }
257
allocate()258 Address allocate()
259 {
260 if (!m_freeHead) {
261 ASSERT(m_count == wrapperPersistentsPerRegion);
262 return 0;
263 }
264 // We have a free persistent slot in this region.
265 WrapperPersistentNode* freeSlot = m_freeHead;
266 // Take the slot and advance m_freeHead to the next free slot.
267 m_freeHead = freeSlot->takeSlot();
268 ASSERT(m_count < wrapperPersistentsPerRegion);
269 m_count++;
270 return reinterpret_cast<Address>(freeSlot);
271 }
272
free(WrapperPersistentNode * object)273 void free(WrapperPersistentNode* object)
274 {
275 ASSERT(object);
276 m_freeHead = object->freeSlot(m_freeHead);
277 ASSERT(m_count > 0);
278 m_count--;
279 if (!m_count)
280 ThreadState::current()->freeWrapperPersistentRegion(this);
281 }
282
283 bool removeIfNotLast(WrapperPersistentRegion** headPtr);
284 static void insertHead(WrapperPersistentRegion** headPtr, WrapperPersistentRegion* newHead);
285 static WrapperPersistentRegion* removeHead(WrapperPersistentRegion** headPtr);
286 static Address outOfLineAllocate(ThreadState*, WrapperPersistentRegion**);
trace(WrapperPersistentRegion * head,Visitor * visitor)287 static void trace(WrapperPersistentRegion* head, Visitor* visitor)
288 {
289 for (WrapperPersistentRegion* current = head; current; current = current->m_next)
290 current->traceRegion(visitor);
291 }
292
293 private:
traceRegion(Visitor * visitor)294 void traceRegion(Visitor* visitor)
295 {
296 size_t live = 0;
297
298 #ifdef NDEBUG
299 for (int i = 0; i < wrapperPersistentsPerRegion && live < m_count; ++i) {
300 #else
301 // In DEBUG mode we scan all entries to validate we only have m_count
302 // live entries.
303 for (int i = 0; i < wrapperPersistentsPerRegion; ++i) {
304 #endif
305 if (m_entries[i].isAlive()) {
306 m_entries[i].trace(visitor);
307 live++;
308 }
309 }
310 ASSERT(live == m_count);
311 }
312
313 WrapperPersistentRegion* m_prev;
314 WrapperPersistentRegion* m_next;
315 WrapperPersistentNode* m_freeHead;
316 size_t m_count;
317 WrapperPersistentNode m_entries[wrapperPersistentsPerRegion];
318 };
319
320 template<typename T>
create(T * raw)321 WrapperPersistent<T>* WrapperPersistent<T>::create(T* raw)
322 {
323 ThreadState* state = ThreadState::current();
324 WrapperPersistentRegion* region = state->wrapperRoots();
325 ASSERT(region);
326 Address persistentSlot = region->allocate();
327 if (!persistentSlot)
328 persistentSlot = WrapperPersistentRegion::outOfLineAllocate(state, ®ion);
329 ASSERT(persistentSlot);
330 ASSERT(!reinterpret_cast<WrapperPersistentNode*>(persistentSlot)->isAlive());
331
332 size_t regionOffset = persistentSlot - reinterpret_cast<Address>(region);
333 regionOffset |= wrapperPersistentLiveBitMask;
334
335 // We use placement new to call the constructor to ensure that we setup the
336 // vtable correctly.
337 return new (persistentSlot) WrapperPersistent<T>(raw, regionOffset);
338 }
339
destroy(const WrapperPersistentNode * node)340 void WrapperPersistentNode::destroy(const WrapperPersistentNode* node)
341 {
342 WrapperPersistentNode* persistent = const_cast<WrapperPersistentNode*>(node);
343 persistent->region()->free(persistent);
344 }
345
346 // RootsAccessor for Persistent that provides access to thread-local list
347 // of persistent handles. Can only be used to create handles that
348 // are constructed and destructed on the same thread.
349 template<ThreadAffinity Affinity>
350 class ThreadLocalPersistents {
351 public:
roots()352 static PersistentNode* roots() { return state()->roots(); }
353
354 // No locking required. Just check that we are at the right thread.
355 class Lock {
356 public:
Lock()357 Lock() { state()->checkThread(); }
358 };
359
360 private:
state()361 static ThreadState* state() { return ThreadStateFor<Affinity>::state(); }
362 };
363
364 // RootsAccessor for Persistent that provides synchronized access to global
365 // list of persistent handles. Can be used for persistent handles that are
366 // passed between threads.
367 class GlobalPersistents {
368 public:
roots()369 static PersistentNode* roots() { return ThreadState::globalRoots(); }
370
371 class Lock {
372 public:
Lock()373 Lock() : m_locker(ThreadState::globalRootsMutex()) { }
374 private:
375 MutexLocker m_locker;
376 };
377 };
378
379 // Base class for persistent handles. RootsAccessor specifies which list to
380 // link resulting handle into. Owner specifies the class containing trace
381 // method.
382 template<typename RootsAccessor, typename Owner>
383 class PersistentBase : public PersistentNode {
384 public:
~PersistentBase()385 ~PersistentBase()
386 {
387 typename RootsAccessor::Lock lock;
388 ASSERT(m_roots == RootsAccessor::roots()); // Check that the thread is using the same roots list.
389 ASSERT(isAlive());
390 ASSERT(m_next->isAlive());
391 ASSERT(m_prev->isAlive());
392 m_next->m_prev = m_prev;
393 m_prev->m_next = m_next;
394 }
395
396 protected:
PersistentBase()397 inline PersistentBase()
398 : PersistentNode(TraceMethodDelegate<Owner, &Owner::trace>::trampoline)
399 #if ENABLE(ASSERT)
400 , m_roots(RootsAccessor::roots())
401 #endif
402 {
403 typename RootsAccessor::Lock lock;
404 m_prev = RootsAccessor::roots();
405 m_next = m_prev->m_next;
406 m_prev->m_next = this;
407 m_next->m_prev = this;
408 }
409
PersistentBase(const PersistentBase & otherref)410 inline explicit PersistentBase(const PersistentBase& otherref)
411 : PersistentNode(otherref.m_trace)
412 #if ENABLE(ASSERT)
413 , m_roots(RootsAccessor::roots())
414 #endif
415 {
416 // We don't support allocation of thread local Persistents while doing
417 // thread shutdown/cleanup.
418 ASSERT(!ThreadState::current()->isTerminating());
419 typename RootsAccessor::Lock lock;
420 ASSERT(otherref.m_roots == m_roots); // Handles must belong to the same list.
421 PersistentBase* other = const_cast<PersistentBase*>(&otherref);
422 m_prev = other;
423 m_next = other->m_next;
424 other->m_next = this;
425 m_next->m_prev = this;
426 }
427
428 inline PersistentBase& operator=(const PersistentBase& otherref) { return *this; }
429
430 #if ENABLE(ASSERT)
431 private:
432 PersistentNode* m_roots;
433 #endif
434 };
435
436 // A dummy Persistent handle that ensures the list of persistents is never null.
437 // This removes a test from a hot path.
438 class PersistentAnchor : public PersistentNode {
439 public:
trace(Visitor * visitor)440 void trace(Visitor* visitor)
441 {
442 for (PersistentNode* current = m_next; current != this; current = current->m_next)
443 current->trace(visitor);
444 }
445
numberOfPersistents()446 int numberOfPersistents()
447 {
448 int numberOfPersistents = 0;
449 for (PersistentNode* current = m_next; current != this; current = current->m_next)
450 ++numberOfPersistents;
451 return numberOfPersistents;
452 }
453
~PersistentAnchor()454 virtual ~PersistentAnchor()
455 {
456 // FIXME: oilpan: Ideally we should have no left-over persistents at this point. However currently there is a
457 // large number of objects leaked when we tear down the main thread. Since some of these might contain a
458 // persistent or e.g. be RefCountedGarbageCollected we cannot guarantee there are no remaining Persistents at
459 // this point.
460 }
461
462 private:
PersistentAnchor()463 PersistentAnchor() : PersistentNode(TraceMethodDelegate<PersistentAnchor, &PersistentAnchor::trace>::trampoline)
464 {
465 m_next = this;
466 m_prev = this;
467 }
468
469 friend class ThreadState;
470 };
471
472 #if ENABLE(ASSERT)
473 // For global persistent handles we cannot check that the
474 // pointer is in the heap because that would involve
475 // inspecting the heap of running threads.
476 #define ASSERT_IS_VALID_PERSISTENT_POINTER(pointer) \
477 bool isGlobalPersistent = WTF::IsSubclass<RootsAccessor, GlobalPersistents>::value; \
478 ASSERT(!pointer || isGlobalPersistent || ThreadStateFor<ThreadingTrait<T>::Affinity>::state()->contains(pointer))
479 #else
480 #define ASSERT_IS_VALID_PERSISTENT_POINTER(pointer)
481 #endif
482
483 template<typename T>
484 class CrossThreadPersistent;
485
486 // Persistent handles are used to store pointers into the
487 // managed heap. As long as the Persistent handle is alive
488 // the GC will keep the object pointed to alive. Persistent
489 // handles can be stored in objects and they are not scoped.
490 // Persistent handles must not be used to contain pointers
491 // between objects that are in the managed heap. They are only
492 // meant to point to managed heap objects from variables/members
493 // outside the managed heap.
494 //
495 // A Persistent is always a GC root from the point of view of
496 // the garbage collector.
497 //
498 // We have to construct and destruct Persistent with default RootsAccessor in
499 // the same thread.
500 template<typename T, typename RootsAccessor /* = ThreadLocalPersistents<ThreadingTrait<T>::Affinity > */ >
501 class Persistent : public PersistentBase<RootsAccessor, Persistent<T, RootsAccessor> > {
502 WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(Persistent);
503 WTF_DISALLOW_ZERO_ASSIGNMENT(Persistent);
504 public:
Persistent()505 Persistent() : m_raw(0) { }
506
Persistent(std::nullptr_t)507 Persistent(std::nullptr_t) : m_raw(0) { }
508
Persistent(T * raw)509 Persistent(T* raw) : m_raw(raw)
510 {
511 ASSERT_IS_VALID_PERSISTENT_POINTER(m_raw);
512 recordBacktrace();
513 }
514
Persistent(T & raw)515 explicit Persistent(T& raw) : m_raw(&raw)
516 {
517 ASSERT_IS_VALID_PERSISTENT_POINTER(m_raw);
518 recordBacktrace();
519 }
520
Persistent(const Persistent & other)521 Persistent(const Persistent& other) : m_raw(other) { recordBacktrace(); }
522
523 template<typename U>
Persistent(const Persistent<U,RootsAccessor> & other)524 Persistent(const Persistent<U, RootsAccessor>& other) : m_raw(other) { recordBacktrace(); }
525
526 template<typename U>
Persistent(const Member<U> & other)527 Persistent(const Member<U>& other) : m_raw(other) { recordBacktrace(); }
528
529 template<typename U>
Persistent(const RawPtr<U> & other)530 Persistent(const RawPtr<U>& other) : m_raw(other.get()) { recordBacktrace(); }
531
532 template<typename U>
533 Persistent& operator=(U* other)
534 {
535 m_raw = other;
536 recordBacktrace();
537 return *this;
538 }
539
540 Persistent& operator=(std::nullptr_t)
541 {
542 m_raw = 0;
543 return *this;
544 }
545
clear()546 void clear() { m_raw = 0; }
547
~Persistent()548 virtual ~Persistent()
549 {
550 m_raw = 0;
551 }
552
553 template<typename U>
as()554 U* as() const
555 {
556 return static_cast<U*>(m_raw);
557 }
558
trace(Visitor * visitor)559 void trace(Visitor* visitor)
560 {
561 COMPILE_ASSERT_IS_GARBAGE_COLLECTED(T, NonGarbageCollectedObjectInPersistent);
562 #if ENABLE(GC_PROFILE_MARKING)
563 visitor->setHostInfo(this, m_tracingName.isEmpty() ? "Persistent" : m_tracingName);
564 #endif
565 visitor->mark(m_raw);
566 }
567
release()568 RawPtr<T> release()
569 {
570 RawPtr<T> result = m_raw;
571 m_raw = 0;
572 return result;
573 }
574
575 T& operator*() const { return *m_raw; }
576
577 bool operator!() const { return !m_raw; }
578
579 operator T*() const { return m_raw; }
580 operator RawPtr<T>() const { return m_raw; }
581
582 T* operator->() const { return *this; }
583
584 Persistent& operator=(const Persistent& other)
585 {
586 m_raw = other;
587 recordBacktrace();
588 return *this;
589 }
590
591 template<typename U>
592 Persistent& operator=(const Persistent<U, RootsAccessor>& other)
593 {
594 m_raw = other;
595 recordBacktrace();
596 return *this;
597 }
598
599 template<typename U>
600 Persistent& operator=(const Member<U>& other)
601 {
602 m_raw = other;
603 recordBacktrace();
604 return *this;
605 }
606
607 template<typename U>
608 Persistent& operator=(const RawPtr<U>& other)
609 {
610 m_raw = other;
611 recordBacktrace();
612 return *this;
613 }
614
get()615 T* get() const { return m_raw; }
616
617 private:
618 #if ENABLE(GC_PROFILE_MARKING)
recordBacktrace()619 void recordBacktrace()
620 {
621 if (m_raw)
622 m_tracingName = Heap::createBacktraceString();
623 }
624
625 String m_tracingName;
626 #else
627 inline void recordBacktrace() const { }
628 #endif
629 T* m_raw;
630
631 friend class CrossThreadPersistent<T>;
632 };
633
634 // Unlike Persistent, we can destruct a CrossThreadPersistent in a thread
635 // different from the construction thread.
636 template<typename T>
637 class CrossThreadPersistent : public Persistent<T, GlobalPersistents> {
638 WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(CrossThreadPersistent);
639 WTF_DISALLOW_ZERO_ASSIGNMENT(CrossThreadPersistent);
640 public:
CrossThreadPersistent(T * raw)641 CrossThreadPersistent(T* raw) : Persistent<T, GlobalPersistents>(raw) { }
642
643 using Persistent<T, GlobalPersistents>::operator=;
644 };
645
646 // FIXME: derive affinity based on the collection.
647 template<typename Collection, ThreadAffinity Affinity = AnyThread>
648 class PersistentHeapCollectionBase
649 : public Collection
650 , public PersistentBase<ThreadLocalPersistents<Affinity>, PersistentHeapCollectionBase<Collection, Affinity> > {
651 // We overload the various new and delete operators with using the WTF DefaultAllocator to ensure persistent
652 // heap collections are always allocated off-heap. This allows persistent collections to be used in
653 // DEFINE_STATIC_LOCAL et. al.
654 WTF_USE_ALLOCATOR(PersistentHeapCollectionBase, WTF::DefaultAllocator);
655 public:
PersistentHeapCollectionBase()656 PersistentHeapCollectionBase() { }
657
658 template<typename OtherCollection>
PersistentHeapCollectionBase(const OtherCollection & other)659 PersistentHeapCollectionBase(const OtherCollection& other) : Collection(other) { }
660
trace(Visitor * visitor)661 void trace(Visitor* visitor)
662 {
663 #if ENABLE(GC_PROFILE_MARKING)
664 visitor->setHostInfo(this, "PersistentHeapCollectionBase");
665 #endif
666 visitor->trace(*static_cast<Collection*>(this));
667 }
668 };
669
670 template<
671 typename KeyArg,
672 typename MappedArg,
673 typename HashArg = typename DefaultHash<KeyArg>::Hash,
674 typename KeyTraitsArg = HashTraits<KeyArg>,
675 typename MappedTraitsArg = HashTraits<MappedArg> >
676 class PersistentHeapHashMap : public PersistentHeapCollectionBase<HeapHashMap<KeyArg, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> > { };
677
678 template<
679 typename ValueArg,
680 typename HashArg = typename DefaultHash<ValueArg>::Hash,
681 typename TraitsArg = HashTraits<ValueArg> >
682 class PersistentHeapHashSet : public PersistentHeapCollectionBase<HeapHashSet<ValueArg, HashArg, TraitsArg> > { };
683
684 template<
685 typename ValueArg,
686 typename HashArg = typename DefaultHash<ValueArg>::Hash,
687 typename TraitsArg = HashTraits<ValueArg> >
688 class PersistentHeapLinkedHashSet : public PersistentHeapCollectionBase<HeapLinkedHashSet<ValueArg, HashArg, TraitsArg> > { };
689
690 template<
691 typename ValueArg,
692 size_t inlineCapacity = 0,
693 typename HashArg = typename DefaultHash<ValueArg>::Hash>
694 class PersistentHeapListHashSet : public PersistentHeapCollectionBase<HeapListHashSet<ValueArg, inlineCapacity, HashArg> > { };
695
696 template<typename T, typename U, typename V>
697 class PersistentHeapHashCountedSet : public PersistentHeapCollectionBase<HeapHashCountedSet<T, U, V> > { };
698
699 template<typename T, size_t inlineCapacity = 0>
700 class PersistentHeapVector : public PersistentHeapCollectionBase<HeapVector<T, inlineCapacity> > {
701 public:
PersistentHeapVector()702 PersistentHeapVector() { }
703
704 template<size_t otherCapacity>
PersistentHeapVector(const HeapVector<T,otherCapacity> & other)705 PersistentHeapVector(const HeapVector<T, otherCapacity>& other)
706 : PersistentHeapCollectionBase<HeapVector<T, inlineCapacity> >(other)
707 {
708 }
709 };
710
711 template<typename T, size_t inlineCapacity = 0>
712 class PersistentHeapDeque : public PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity> > {
713 public:
PersistentHeapDeque()714 PersistentHeapDeque() { }
715
716 template<size_t otherCapacity>
PersistentHeapDeque(const HeapDeque<T,otherCapacity> & other)717 PersistentHeapDeque(const HeapDeque<T, otherCapacity>& other)
718 : PersistentHeapCollectionBase<HeapDeque<T, inlineCapacity> >(other)
719 {
720 }
721 };
722
723 // Members are used in classes to contain strong pointers to other oilpan heap
724 // allocated objects.
725 // All Member fields of a class must be traced in the class' trace method.
726 // During the mark phase of the GC all live objects are marked as live and
727 // all Member fields of a live object will be traced marked as live as well.
728 template<typename T>
729 class Member {
730 WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(Member);
731 WTF_DISALLOW_ZERO_ASSIGNMENT(Member);
732 public:
Member()733 Member() : m_raw(0)
734 {
735 }
736
Member(std::nullptr_t)737 Member(std::nullptr_t) : m_raw(0)
738 {
739 }
740
Member(T * raw)741 Member(T* raw) : m_raw(raw)
742 {
743 }
744
Member(T & raw)745 explicit Member(T& raw) : m_raw(&raw)
746 {
747 }
748
749 template<typename U>
Member(const RawPtr<U> & other)750 Member(const RawPtr<U>& other) : m_raw(other.get())
751 {
752 }
753
Member(WTF::HashTableDeletedValueType)754 Member(WTF::HashTableDeletedValueType) : m_raw(reinterpret_cast<T*>(-1))
755 {
756 }
757
isHashTableDeletedValue()758 bool isHashTableDeletedValue() const { return m_raw == reinterpret_cast<T*>(-1); }
759
760 template<typename U>
Member(const Persistent<U> & other)761 Member(const Persistent<U>& other) : m_raw(other) { }
762
Member(const Member & other)763 Member(const Member& other) : m_raw(other) { }
764
765 template<typename U>
Member(const Member<U> & other)766 Member(const Member<U>& other) : m_raw(other) { }
767
release()768 T* release()
769 {
770 T* result = m_raw;
771 m_raw = 0;
772 return result;
773 }
774
775 template<typename U>
as()776 U* as() const
777 {
778 return static_cast<U*>(m_raw);
779 }
780
781 bool operator!() const { return !m_raw; }
782
783 operator T*() const { return m_raw; }
784
785 T* operator->() const { return m_raw; }
786 T& operator*() const { return *m_raw; }
787 template<typename U>
788 operator RawPtr<U>() const { return m_raw; }
789
790 template<typename U>
791 Member& operator=(const Persistent<U>& other)
792 {
793 m_raw = other;
794 return *this;
795 }
796
797 template<typename U>
798 Member& operator=(const Member<U>& other)
799 {
800 m_raw = other;
801 return *this;
802 }
803
804 template<typename U>
805 Member& operator=(U* other)
806 {
807 m_raw = other;
808 return *this;
809 }
810
811 template<typename U>
812 Member& operator=(RawPtr<U> other)
813 {
814 m_raw = other;
815 return *this;
816 }
817
818 Member& operator=(std::nullptr_t)
819 {
820 m_raw = 0;
821 return *this;
822 }
823
swap(Member<T> & other)824 void swap(Member<T>& other) { std::swap(m_raw, other.m_raw); }
825
get()826 T* get() const { return m_raw; }
827
clear()828 void clear() { m_raw = 0; }
829
830
831 protected:
verifyTypeIsGarbageCollected()832 void verifyTypeIsGarbageCollected() const
833 {
834 COMPILE_ASSERT_IS_GARBAGE_COLLECTED(T, NonGarbageCollectedObjectInMember);
835 }
836
837 T* m_raw;
838
839 template<bool x, WTF::WeakHandlingFlag y, WTF::ShouldWeakPointersBeMarkedStrongly z, typename U, typename V> friend struct CollectionBackingTraceTrait;
840 friend class Visitor;
841 };
842
843 template<typename T>
844 class TraceTrait<Member<T> > {
845 public:
trace(Visitor * visitor,void * self)846 static void trace(Visitor* visitor, void* self)
847 {
848 TraceTrait<T>::mark(visitor, *static_cast<Member<T>*>(self));
849 }
850 };
851
852 // TraceTrait to allow compilation of trace method bodies when oilpan is disabled.
853 // This should never be called, but is needed to compile.
854 template<typename T>
855 class TraceTrait<RefPtr<T> > {
856 public:
trace(Visitor *,void *)857 static void trace(Visitor*, void*)
858 {
859 ASSERT_NOT_REACHED();
860 }
861 };
862
863 template<typename T>
864 class TraceTrait<OwnPtr<T> > {
865 public:
trace(Visitor * visitor,OwnPtr<T> * ptr)866 static void trace(Visitor* visitor, OwnPtr<T>* ptr)
867 {
868 ASSERT_NOT_REACHED();
869 }
870 };
871
872 template<typename T, bool needsTracing>
873 struct TraceIfEnabled;
874
875 template<typename T>
876 struct TraceIfEnabled<T, false> {
877 static void trace(Visitor*, T*) { }
878 };
879
880 template<typename T>
881 struct TraceIfEnabled<T, true> {
882 static void trace(Visitor* visitor, T* t)
883 {
884 visitor->trace(*t);
885 }
886 };
887
888 template <typename T> struct RemoveHeapPointerWrapperTypes {
889 typedef typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<typename WTF::RemoveTemplate<T, Member>::Type, WeakMember>::Type, RawPtr>::Type Type;
890 };
891
892 // FIXME: Oilpan: TraceIfNeeded should be implemented ala:
893 // NeedsTracing<T>::value || IsWeakMember<T>::value. It should not need to test
894 // raw pointer types. To remove these tests, we may need support for
895 // instantiating a template with a RawPtrOrMember'ish template.
896 template<typename T>
897 struct TraceIfNeeded : public TraceIfEnabled<T, WTF::NeedsTracing<T>::value || blink::IsGarbageCollectedType<typename RemoveHeapPointerWrapperTypes<typename WTF::RemovePointer<T>::Type>::Type>::value> { };
898
899 // This trace trait for std::pair will null weak members if their referent is
900 // collected. If you have a collection that contain weakness it does not remove
901 // entries from the collection that contain nulled weak members.
902 template<typename T, typename U>
903 class TraceTrait<std::pair<T, U> > {
904 public:
905 static const bool firstNeedsTracing = WTF::NeedsTracing<T>::value || WTF::IsWeak<T>::value;
906 static const bool secondNeedsTracing = WTF::NeedsTracing<U>::value || WTF::IsWeak<U>::value;
907 static void trace(Visitor* visitor, std::pair<T, U>* pair)
908 {
909 TraceIfEnabled<T, firstNeedsTracing>::trace(visitor, &pair->first);
910 TraceIfEnabled<U, secondNeedsTracing>::trace(visitor, &pair->second);
911 }
912 };
913
914 // WeakMember is similar to Member in that it is used to point to other oilpan
915 // heap allocated objects.
916 // However instead of creating a strong pointer to the object, the WeakMember creates
917 // a weak pointer, which does not keep the pointee alive. Hence if all pointers to
918 // to a heap allocated object are weak the object will be garbage collected. At the
919 // time of GC the weak pointers will automatically be set to null.
920 template<typename T>
921 class WeakMember : public Member<T> {
922 WTF_DISALLOW_CONSTRUCTION_FROM_ZERO(WeakMember);
923 WTF_DISALLOW_ZERO_ASSIGNMENT(WeakMember);
924 public:
925 WeakMember() : Member<T>() { }
926
927 WeakMember(std::nullptr_t) : Member<T>(nullptr) { }
928
929 WeakMember(T* raw) : Member<T>(raw) { }
930
931 WeakMember(WTF::HashTableDeletedValueType x) : Member<T>(x) { }
932
933 template<typename U>
934 WeakMember(const Persistent<U>& other) : Member<T>(other) { }
935
936 template<typename U>
937 WeakMember(const Member<U>& other) : Member<T>(other) { }
938
939 template<typename U>
940 WeakMember& operator=(const Persistent<U>& other)
941 {
942 this->m_raw = other;
943 return *this;
944 }
945
946 template<typename U>
947 WeakMember& operator=(const Member<U>& other)
948 {
949 this->m_raw = other;
950 return *this;
951 }
952
953 template<typename U>
954 WeakMember& operator=(U* other)
955 {
956 this->m_raw = other;
957 return *this;
958 }
959
960 template<typename U>
961 WeakMember& operator=(const RawPtr<U>& other)
962 {
963 this->m_raw = other;
964 return *this;
965 }
966
967 WeakMember& operator=(std::nullptr_t)
968 {
969 this->m_raw = 0;
970 return *this;
971 }
972
973 private:
974 T** cell() const { return const_cast<T**>(&this->m_raw); }
975
976 friend class Visitor;
977 };
978
979 // Comparison operators between (Weak)Members and Persistents
980 template<typename T, typename U> inline bool operator==(const Member<T>& a, const Member<U>& b) { return a.get() == b.get(); }
981 template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Member<U>& b) { return a.get() != b.get(); }
982 template<typename T, typename U> inline bool operator==(const Member<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
983 template<typename T, typename U> inline bool operator!=(const Member<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
984 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Member<U>& b) { return a.get() == b.get(); }
985 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Member<U>& b) { return a.get() != b.get(); }
986 template<typename T, typename U> inline bool operator==(const Persistent<T>& a, const Persistent<U>& b) { return a.get() == b.get(); }
987 template<typename T, typename U> inline bool operator!=(const Persistent<T>& a, const Persistent<U>& b) { return a.get() != b.get(); }
988
989 // CPP-defined type names for the transition period where we want to
990 // support both reference counting and garbage collection based on a
991 // compile-time flag.
992 //
993 // C++11 template aliases were initially used (with clang only, not
994 // with GCC nor MSVC.) However, supporting both CPP defines and
995 // template aliases is problematic from outside a WebCore namespace
996 // when Oilpan is disabled: e.g.,
997 // blink::RefCountedWillBeGarbageCollected as a template alias would
998 // uniquely resolve from within any namespace, but if it is backed by
999 // a CPP #define, it would expand to blink::RefCounted, and not the
1000 // required WTF::RefCounted.
1001 //
1002 // Having the CPP expansion instead be fully namespace qualified, and the
1003 // transition type be unqualified, would dually not work for template
1004 // aliases. So, slightly unfortunately, fall back/down to the lowest
1005 // commmon denominator of using CPP macros only.
1006 #if ENABLE(OILPAN)
1007 #define PassRefPtrWillBeRawPtr WTF::RawPtr
1008 #define RefCountedWillBeGarbageCollected blink::GarbageCollected
1009 #define RefCountedWillBeGarbageCollectedFinalized blink::GarbageCollectedFinalized
1010 #define RefCountedWillBeRefCountedGarbageCollected blink::RefCountedGarbageCollected
1011 #define RefCountedGarbageCollectedWillBeGarbageCollectedFinalized blink::GarbageCollectedFinalized
1012 #define ThreadSafeRefCountedWillBeGarbageCollected blink::GarbageCollected
1013 #define ThreadSafeRefCountedWillBeGarbageCollectedFinalized blink::GarbageCollectedFinalized
1014 #define ThreadSafeRefCountedWillBeThreadSafeRefCountedGarbageCollected blink::ThreadSafeRefCountedGarbageCollected
1015 #define PersistentWillBeMember blink::Member
1016 #define CrossThreadPersistentWillBeMember blink::Member
1017 #define RefPtrWillBePersistent blink::Persistent
1018 #define RefPtrWillBeRawPtr WTF::RawPtr
1019 #define RefPtrWillBeMember blink::Member
1020 #define RefPtrWillBeWeakMember blink::WeakMember
1021 #define RefPtrWillBeCrossThreadPersistent blink::CrossThreadPersistent
1022 #define RawPtrWillBeMember blink::Member
1023 #define RawPtrWillBePersistent blink::Persistent
1024 #define RawPtrWillBeWeakMember blink::WeakMember
1025 #define OwnPtrWillBeMember blink::Member
1026 #define OwnPtrWillBePersistent blink::Persistent
1027 #define OwnPtrWillBeRawPtr WTF::RawPtr
1028 #define PassOwnPtrWillBeRawPtr WTF::RawPtr
1029 #define WeakPtrWillBeMember blink::Member
1030 #define WeakPtrWillBeRawPtr WTF::RawPtr
1031 #define WeakPtrWillBeMember blink::Member
1032 #define WeakPtrWillBeWeakMember blink::WeakMember
1033 #define NoBaseWillBeGarbageCollected blink::GarbageCollected
1034 #define NoBaseWillBeGarbageCollectedFinalized blink::GarbageCollectedFinalized
1035 #define NoBaseWillBeRefCountedGarbageCollected blink::RefCountedGarbageCollected
1036 #define WillBeHeapHashMap blink::HeapHashMap
1037 #define WillBePersistentHeapHashMap blink::PersistentHeapHashMap
1038 #define WillBeHeapHashSet blink::HeapHashSet
1039 #define WillBePersistentHeapHashSet blink::PersistentHeapHashSet
1040 #define WillBeHeapLinkedHashSet blink::HeapLinkedHashSet
1041 #define WillBePersistentHeapLinkedHashSet blink::PersistentHeapLinkedHashSet
1042 #define WillBeHeapListHashSet blink::HeapListHashSet
1043 #define WillBePersistentHeapListHashSet blink::PersistentHeapListHashSet
1044 #define WillBeHeapVector blink::HeapVector
1045 #define WillBePersistentHeapVector blink::PersistentHeapVector
1046 #define WillBeHeapDeque blink::HeapDeque
1047 #define WillBePersistentHeapDeque blink::PersistentHeapDeque
1048 #define WillBeHeapHashCountedSet blink::HeapHashCountedSet
1049 #define WillBePersistentHeapHashCountedSet blink::PersistentHeapHashCountedSet
1050 #define WillBeGarbageCollectedMixin blink::GarbageCollectedMixin
1051 #define WillBeHeapSupplement blink::HeapSupplement
1052 #define WillBeHeapSupplementable blink::HeapSupplementable
1053 #define WillBeHeapTerminatedArray blink::HeapTerminatedArray
1054 #define WillBeHeapTerminatedArrayBuilder blink::HeapTerminatedArrayBuilder
1055 #define WillBeHeapLinkedStack blink::HeapLinkedStack
1056 #define PersistentHeapHashSetWillBeHeapHashSet blink::HeapHashSet
1057 #define PersistentHeapDequeWillBeHeapDeque blink::HeapDeque
1058 #define PersistentHeapVectorWillBeHeapVector blink::HeapVector
1059
1060 template<typename T> PassRefPtrWillBeRawPtr<T> adoptRefWillBeNoop(T* ptr)
1061 {
1062 static const bool notRefCountedGarbageCollected = !WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCountedGarbageCollected>::value;
1063 static const bool notRefCounted = !WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCounted>::value;
1064 COMPILE_ASSERT(notRefCountedGarbageCollected, useAdoptRefCountedWillBeRefCountedGarbageCollected);
1065 COMPILE_ASSERT(notRefCounted, youMustAdopt);
1066 return PassRefPtrWillBeRawPtr<T>(ptr);
1067 }
1068
1069 template<typename T> PassRefPtrWillBeRawPtr<T> adoptRefWillBeRefCountedGarbageCollected(T* ptr)
1070 {
1071 static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCountedGarbageCollected>::value;
1072 COMPILE_ASSERT(isRefCountedGarbageCollected, useAdoptRefWillBeNoop);
1073 return PassRefPtrWillBeRawPtr<T>(adoptRefCountedGarbageCollected(ptr));
1074 }
1075
1076 template<typename T> PassRefPtrWillBeRawPtr<T> adoptRefWillBeThreadSafeRefCountedGarbageCollected(T* ptr)
1077 {
1078 static const bool isThreadSafeRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, ThreadSafeRefCountedGarbageCollected>::value;
1079 COMPILE_ASSERT(isThreadSafeRefCountedGarbageCollected, useAdoptRefWillBeNoop);
1080 return PassRefPtrWillBeRawPtr<T>(adoptRefCountedGarbageCollected(ptr));
1081 }
1082
1083 template<typename T> PassOwnPtrWillBeRawPtr<T> adoptPtrWillBeNoop(T* ptr)
1084 {
1085 static const bool notRefCountedGarbageCollected = !WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCountedGarbageCollected>::value;
1086 static const bool notRefCounted = !WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCounted>::value;
1087 COMPILE_ASSERT(notRefCountedGarbageCollected, useAdoptRefCountedWillBeRefCountedGarbageCollected);
1088 COMPILE_ASSERT(notRefCounted, youMustAdopt);
1089 return PassOwnPtrWillBeRawPtr<T>(ptr);
1090 }
1091
1092 template<typename T> T* adoptPtrWillBeRefCountedGarbageCollected(T* ptr)
1093 {
1094 static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCountedGarbageCollected>::value;
1095 COMPILE_ASSERT(isRefCountedGarbageCollected, useAdoptRefWillBeNoop);
1096 return adoptRefCountedGarbageCollected(ptr);
1097 }
1098
1099 template<typename T> T* adoptRefCountedGarbageCollectedWillBeNoop(T* ptr)
1100 {
1101 static const bool notRefCountedGarbageCollected = !WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCountedGarbageCollected>::value;
1102 static const bool notRefCounted = !WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCounted>::value;
1103 COMPILE_ASSERT(notRefCountedGarbageCollected, useAdoptRefCountedWillBeRefCountedGarbageCollected);
1104 COMPILE_ASSERT(notRefCounted, youMustAdopt);
1105 return ptr;
1106 }
1107
1108 #define WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED // do nothing when oilpan is enabled.
1109 #define DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(type) // do nothing
1110 #define DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(type) // do nothing
1111 #define DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(type) // do nothing
1112
1113 #define DEFINE_STATIC_REF_WILL_BE_PERSISTENT(type, name, arguments) \
1114 static type* name = (new Persistent<type>(arguments))->get();
1115
1116 #else // !ENABLE(OILPAN)
1117
1118 template<typename T>
1119 class DummyBase {
1120 public:
1121 DummyBase() { }
1122 ~DummyBase() { }
1123 };
1124
1125 #define PassRefPtrWillBeRawPtr WTF::PassRefPtr
1126 #define RefCountedWillBeGarbageCollected WTF::RefCounted
1127 #define RefCountedWillBeGarbageCollectedFinalized WTF::RefCounted
1128 #define RefCountedWillBeRefCountedGarbageCollected WTF::RefCounted
1129 #define RefCountedGarbageCollectedWillBeGarbageCollectedFinalized blink::RefCountedGarbageCollected
1130 #define ThreadSafeRefCountedWillBeGarbageCollected WTF::ThreadSafeRefCounted
1131 #define ThreadSafeRefCountedWillBeGarbageCollectedFinalized WTF::ThreadSafeRefCounted
1132 #define ThreadSafeRefCountedWillBeThreadSafeRefCountedGarbageCollected WTF::ThreadSafeRefCounted
1133 #define PersistentWillBeMember blink::Persistent
1134 #define CrossThreadPersistentWillBeMember blink::CrossThreadPersistent
1135 #define RefPtrWillBePersistent WTF::RefPtr
1136 #define RefPtrWillBeRawPtr WTF::RefPtr
1137 #define RefPtrWillBeMember WTF::RefPtr
1138 #define RefPtrWillBeWeakMember WTF::RefPtr
1139 #define RefPtrWillBeCrossThreadPersistent WTF::RefPtr
1140 #define RawPtrWillBeMember WTF::RawPtr
1141 #define RawPtrWillBePersistent WTF::RawPtr
1142 #define RawPtrWillBeWeakMember WTF::RawPtr
1143 #define OwnPtrWillBeMember WTF::OwnPtr
1144 #define OwnPtrWillBePersistent WTF::OwnPtr
1145 #define OwnPtrWillBeRawPtr WTF::OwnPtr
1146 #define PassOwnPtrWillBeRawPtr WTF::PassOwnPtr
1147 #define WeakPtrWillBeMember WTF::WeakPtr
1148 #define WeakPtrWillBeRawPtr WTF::WeakPtr
1149 #define WeakPtrWillBeMember WTF::WeakPtr
1150 #define WeakPtrWillBeWeakMember WTF::WeakPtr
1151 #define NoBaseWillBeGarbageCollected blink::DummyBase
1152 #define NoBaseWillBeGarbageCollectedFinalized blink::DummyBase
1153 #define NoBaseWillBeRefCountedGarbageCollected blink::DummyBase
1154 #define WillBeHeapHashMap WTF::HashMap
1155 #define WillBePersistentHeapHashMap WTF::HashMap
1156 #define WillBeHeapHashSet WTF::HashSet
1157 #define WillBePersistentHeapHashSet WTF::HashSet
1158 #define WillBeHeapLinkedHashSet WTF::LinkedHashSet
1159 #define WillBePersistentLinkedHeapHashSet WTF::LinkedHashSet
1160 #define WillBeHeapListHashSet WTF::ListHashSet
1161 #define WillBePersistentListHeapHashSet WTF::ListHashSet
1162 #define WillBeHeapVector WTF::Vector
1163 #define WillBePersistentHeapVector WTF::Vector
1164 #define WillBeHeapDeque WTF::Deque
1165 #define WillBePersistentHeapDeque WTF::Deque
1166 #define WillBeHeapHashCountedSet WTF::HashCountedSet
1167 #define WillBePersistentHeapHashCountedSet WTF::HashCountedSet
1168 #define WillBeGarbageCollectedMixin blink::DummyBase<void>
1169 #define WillBeHeapSupplement blink::Supplement
1170 #define WillBeHeapSupplementable blink::Supplementable
1171 #define WillBeHeapTerminatedArray WTF::TerminatedArray
1172 #define WillBeHeapTerminatedArrayBuilder WTF::TerminatedArrayBuilder
1173 #define WillBeHeapLinkedStack WTF::LinkedStack
1174 #define PersistentHeapHashSetWillBeHeapHashSet blink::PersistentHeapHashSet
1175 #define PersistentHeapDequeWillBeHeapDeque blink::PersistentHeapDeque
1176 #define PersistentHeapVectorWillBeHeapVector blink::PersistentHeapVector
1177
1178 template<typename T> PassRefPtrWillBeRawPtr<T> adoptRefWillBeNoop(T* ptr) { return adoptRef(ptr); }
1179 template<typename T> PassRefPtrWillBeRawPtr<T> adoptRefWillBeRefCountedGarbageCollected(T* ptr) { return adoptRef(ptr); }
1180 template<typename T> PassRefPtrWillBeRawPtr<T> adoptRefWillBeThreadSafeRefCountedGarbageCollected(T* ptr) { return adoptRef(ptr); }
1181 template<typename T> PassOwnPtrWillBeRawPtr<T> adoptPtrWillBeNoop(T* ptr) { return adoptPtr(ptr); }
1182 template<typename T> PassOwnPtrWillBeRawPtr<T> adoptPtrWillBeRefCountedGarbageCollected(T* ptr) { return adoptPtr(ptr); }
1183
1184 template<typename T> T* adoptRefCountedGarbageCollectedWillBeNoop(T* ptr)
1185 {
1186 static const bool isRefCountedGarbageCollected = WTF::IsSubclassOfTemplate<typename WTF::RemoveConst<T>::Type, RefCountedGarbageCollected>::value;
1187 COMPILE_ASSERT(isRefCountedGarbageCollected, useAdoptRefWillBeNoop);
1188 return adoptRefCountedGarbageCollected(ptr);
1189 }
1190
1191
1192 #define WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED WTF_MAKE_FAST_ALLOCATED
1193 #define DECLARE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(type) \
1194 public: \
1195 ~type(); \
1196 private:
1197 #define DECLARE_EMPTY_VIRTUAL_DESTRUCTOR_WILL_BE_REMOVED(type) \
1198 public: \
1199 virtual ~type(); \
1200 private:
1201
1202 #define DEFINE_EMPTY_DESTRUCTOR_WILL_BE_REMOVED(type) \
1203 type::~type() { }
1204
1205 #define DEFINE_STATIC_REF_WILL_BE_PERSISTENT(type, name, arguments) \
1206 DEFINE_STATIC_REF(type, name, arguments)
1207
1208 #endif // ENABLE(OILPAN)
1209
1210 } // namespace blink
1211
1212 namespace WTF {
1213
1214 template <typename T> struct VectorTraits<blink::Member<T> > : VectorTraitsBase<blink::Member<T> > {
1215 static const bool needsDestruction = false;
1216 static const bool canInitializeWithMemset = true;
1217 static const bool canMoveWithMemcpy = true;
1218 };
1219
1220 template <typename T> struct VectorTraits<blink::WeakMember<T> > : VectorTraitsBase<blink::WeakMember<T> > {
1221 static const bool needsDestruction = false;
1222 static const bool canInitializeWithMemset = true;
1223 static const bool canMoveWithMemcpy = true;
1224 };
1225
1226 template <typename T> struct VectorTraits<blink::HeapVector<T, 0> > : VectorTraitsBase<blink::HeapVector<T, 0> > {
1227 static const bool needsDestruction = false;
1228 static const bool canInitializeWithMemset = true;
1229 static const bool canMoveWithMemcpy = true;
1230 };
1231
1232 template <typename T> struct VectorTraits<blink::HeapDeque<T, 0> > : VectorTraitsBase<blink::HeapDeque<T, 0> > {
1233 static const bool needsDestruction = false;
1234 static const bool canInitializeWithMemset = true;
1235 static const bool canMoveWithMemcpy = true;
1236 };
1237
1238 template <typename T, size_t inlineCapacity> struct VectorTraits<blink::HeapVector<T, inlineCapacity> > : VectorTraitsBase<blink::HeapVector<T, inlineCapacity> > {
1239 static const bool needsDestruction = VectorTraits<T>::needsDestruction;
1240 static const bool canInitializeWithMemset = VectorTraits<T>::canInitializeWithMemset;
1241 static const bool canMoveWithMemcpy = VectorTraits<T>::canMoveWithMemcpy;
1242 };
1243
1244 template <typename T, size_t inlineCapacity> struct VectorTraits<blink::HeapDeque<T, inlineCapacity> > : VectorTraitsBase<blink::HeapDeque<T, inlineCapacity> > {
1245 static const bool needsDestruction = VectorTraits<T>::needsDestruction;
1246 static const bool canInitializeWithMemset = VectorTraits<T>::canInitializeWithMemset;
1247 static const bool canMoveWithMemcpy = VectorTraits<T>::canMoveWithMemcpy;
1248 };
1249
1250 template<typename T> struct HashTraits<blink::Member<T> > : SimpleClassHashTraits<blink::Member<T> > {
1251 static const bool needsDestruction = false;
1252 // FIXME: The distinction between PeekInType and PassInType is there for
1253 // the sake of the reference counting handles. When they are gone the two
1254 // types can be merged into PassInType.
1255 // FIXME: Implement proper const'ness for iterator types. Requires support
1256 // in the marking Visitor.
1257 typedef RawPtr<T> PeekInType;
1258 typedef RawPtr<T> PassInType;
1259 typedef blink::Member<T>* IteratorGetType;
1260 typedef const blink::Member<T>* IteratorConstGetType;
1261 typedef blink::Member<T>& IteratorReferenceType;
1262 typedef T* const IteratorConstReferenceType;
1263 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
1264 static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x->get(); }
1265 // FIXME: Similarly, there is no need for a distinction between PeekOutType
1266 // and PassOutType without reference counting.
1267 typedef T* PeekOutType;
1268 typedef T* PassOutType;
1269
1270 template<typename U>
1271 static void store(const U& value, blink::Member<T>& storage) { storage = value; }
1272
1273 static PeekOutType peek(const blink::Member<T>& value) { return value; }
1274 static PassOutType passOut(const blink::Member<T>& value) { return value; }
1275 };
1276
1277 template<typename T> struct HashTraits<blink::WeakMember<T> > : SimpleClassHashTraits<blink::WeakMember<T> > {
1278 static const bool needsDestruction = false;
1279 // FIXME: The distinction between PeekInType and PassInType is there for
1280 // the sake of the reference counting handles. When they are gone the two
1281 // types can be merged into PassInType.
1282 // FIXME: Implement proper const'ness for iterator types. Requires support
1283 // in the marking Visitor.
1284 typedef RawPtr<T> PeekInType;
1285 typedef RawPtr<T> PassInType;
1286 typedef blink::WeakMember<T>* IteratorGetType;
1287 typedef const blink::WeakMember<T>* IteratorConstGetType;
1288 typedef blink::WeakMember<T>& IteratorReferenceType;
1289 typedef T* const IteratorConstReferenceType;
1290 static IteratorReferenceType getToReferenceConversion(IteratorGetType x) { return *x; }
1291 static IteratorConstReferenceType getToReferenceConstConversion(IteratorConstGetType x) { return x->get(); }
1292 // FIXME: Similarly, there is no need for a distinction between PeekOutType
1293 // and PassOutType without reference counting.
1294 typedef T* PeekOutType;
1295 typedef T* PassOutType;
1296
1297 template<typename U>
1298 static void store(const U& value, blink::WeakMember<T>& storage) { storage = value; }
1299
1300 static PeekOutType peek(const blink::WeakMember<T>& value) { return value; }
1301 static PassOutType passOut(const blink::WeakMember<T>& value) { return value; }
1302 static bool traceInCollection(blink::Visitor* visitor, blink::WeakMember<T>& weakMember, ShouldWeakPointersBeMarkedStrongly strongify)
1303 {
1304 if (strongify == WeakPointersActStrong) {
1305 visitor->trace(reinterpret_cast<blink::Member<T>&>(weakMember)); // Strongified visit.
1306 return false;
1307 }
1308 return !visitor->isAlive(weakMember);
1309 }
1310 };
1311
1312 template<typename T> struct PtrHash<blink::Member<T> > : PtrHash<T*> {
1313 template<typename U>
1314 static unsigned hash(const U& key) { return PtrHash<T*>::hash(key); }
1315 static bool equal(T* a, const blink::Member<T>& b) { return a == b; }
1316 static bool equal(const blink::Member<T>& a, T* b) { return a == b; }
1317 template<typename U, typename V>
1318 static bool equal(const U& a, const V& b) { return a == b; }
1319 };
1320
1321 template<typename T> struct PtrHash<blink::WeakMember<T> > : PtrHash<blink::Member<T> > {
1322 };
1323
1324 template<typename P> struct PtrHash<blink::Persistent<P> > : PtrHash<P*> {
1325 using PtrHash<P*>::hash;
1326 static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); }
1327 using PtrHash<P*>::equal;
1328 static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; }
1329 static bool equal(P* a, const RefPtr<P>& b) { return a == b; }
1330 static bool equal(const RefPtr<P>& a, P* b) { return a == b; }
1331 };
1332
1333 // PtrHash is the default hash for hash tables with members.
1334 template<typename T> struct DefaultHash<blink::Member<T> > {
1335 typedef PtrHash<blink::Member<T> > Hash;
1336 };
1337
1338 template<typename T> struct DefaultHash<blink::WeakMember<T> > {
1339 typedef PtrHash<blink::WeakMember<T> > Hash;
1340 };
1341
1342 template<typename T> struct DefaultHash<blink::Persistent<T> > {
1343 typedef PtrHash<blink::Persistent<T> > Hash;
1344 };
1345
1346 template<typename T>
1347 struct NeedsTracing<blink::Member<T> > {
1348 static const bool value = true;
1349 };
1350
1351 template<typename T>
1352 struct IsWeak<blink::WeakMember<T> > {
1353 static const bool value = true;
1354 };
1355
1356 template<typename T> inline T* getPtr(const blink::Member<T>& p)
1357 {
1358 return p.get();
1359 }
1360
1361 template<typename T> inline T* getPtr(const blink::Persistent<T>& p)
1362 {
1363 return p.get();
1364 }
1365
1366 template<typename T, size_t inlineCapacity>
1367 struct NeedsTracing<ListHashSetNode<T, blink::HeapListHashSetAllocator<T, inlineCapacity> > *> {
1368 // All heap allocated node pointers need visiting to keep the nodes alive,
1369 // regardless of whether they contain pointers to other heap allocated
1370 // objects.
1371 static const bool value = true;
1372 };
1373
1374 // For wtf/Functional.h
1375 template<typename T, bool isGarbageCollected> struct PointerParamStorageTraits;
1376
1377 template<typename T>
1378 struct PointerParamStorageTraits<T*, false> {
1379 typedef T* StorageType;
1380
1381 static StorageType wrap(T* value) { return value; }
1382 static T* unwrap(const StorageType& value) { return value; }
1383 };
1384
1385 template<typename T>
1386 struct PointerParamStorageTraits<T*, true> {
1387 typedef blink::CrossThreadPersistent<T> StorageType;
1388
1389 static StorageType wrap(T* value) { return value; }
1390 static T* unwrap(const StorageType& value) { return value.get(); }
1391 };
1392
1393 template<typename T>
1394 struct ParamStorageTraits<T*> : public PointerParamStorageTraits<T*, blink::IsGarbageCollectedType<T>::value> {
1395 };
1396
1397 template<typename T>
1398 struct ParamStorageTraits<RawPtr<T> > : public PointerParamStorageTraits<T*, blink::IsGarbageCollectedType<T>::value> {
1399 };
1400
1401 } // namespace WTF
1402
1403 #endif
1404