2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
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
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.
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.
33 #include "platform/Task.h"
34 #include "platform/heap/Handle.h"
35 #include "platform/heap/Heap.h"
36 #include "platform/heap/HeapLinkedStack.h"
37 #include "platform/heap/HeapTerminatedArrayBuilder.h"
38 #include "platform/heap/ThreadState.h"
39 #include "platform/heap/Visitor.h"
40 #include "public/platform/Platform.h"
41 #include "wtf/HashTraits.h"
42 #include "wtf/LinkedHashSet.h"
44 #include <gtest/gtest.h>
48 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
50 static IntWrapper* create(int x)
52 return new IntWrapper(x);
60 static int s_destructorCalls;
61 static void trace(Visitor*) { }
63 int value() const { return m_x; }
65 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
67 unsigned hash() { return IntHash<int>::hash(m_x); }
69 IntWrapper(int x) : m_x(x) { }
76 USED_FROM_MULTIPLE_THREADS(IntWrapper);
80 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(0) { }
81 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i) { }
82 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(reinterpret_cast<ThreadState*>(-1)), m_num(0) { }
85 EXPECT_TRUE((m_creatingThread == ThreadState::current())
86 || (m_creatingThread == reinterpret_cast<ThreadState*>(0))
87 || (m_creatingThread == reinterpret_cast<ThreadState*>(-1)));
89 bool isHashTableDeletedValue() const { return m_creatingThread == reinterpret_cast<ThreadState*>(-1); }
90 bool operator==(const ThreadMarker& other) const { return other.m_creatingThread == m_creatingThread && other.m_num == m_num; }
91 ThreadState* m_creatingThread;
95 struct ThreadMarkerHash {
96 static unsigned hash(const ThreadMarker& key)
98 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(key.m_creatingThread) + key.m_num);
101 static bool equal(const ThreadMarker& a, const ThreadMarker& b)
106 static const bool safeToCompareToEmptyOrDeleted = false;
109 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeakPair;
111 struct PairWithWeakHandling : public StrongWeakPair {
112 ALLOW_ONLY_INLINE_ALLOCATION();
115 // Regular constructor.
116 PairWithWeakHandling(IntWrapper* one, IntWrapper* two)
117 : StrongWeakPair(one, two)
119 ASSERT(one); // We use null first field to indicate empty slots in the hash table.
122 // The HashTable (via the HashTrait) calls this constructor with a
123 // placement new to mark slots in the hash table as being deleted. We will
124 // never call trace or the destructor on these slots. We mark ourselves deleted
125 // with a pointer to -1 in the first field.
126 PairWithWeakHandling(WTF::HashTableDeletedValueType)
127 : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr)
131 // Used by the HashTable (via the HashTrait) to skip deleted slots in the
132 // table. Recognizes objects that were 'constructed' using the above
134 bool isHashTableDeletedValue() const { return first == reinterpret_cast<IntWrapper*>(-1); }
136 // Since we don't allocate independent objects of this type, we don't need
137 // a regular trace method. Instead, we use a traceInCollection method. If
138 // the entry should be deleted from the collection we return true and don't
139 // trace the strong pointer.
140 bool traceInCollection(Visitor* visitor, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
142 visitor->traceInCollection(second, strongify);
143 if (!visitor->isAlive(second))
145 visitor->trace(first);
154 template<typename T> struct DefaultHash;
155 template<> struct DefaultHash<blink::ThreadMarker> {
156 typedef blink::ThreadMarkerHash Hash;
159 // ThreadMarkerHash is the default hash for ThreadMarker
160 template<> struct HashTraits<blink::ThreadMarker> : GenericHashTraits<blink::ThreadMarker> {
161 static const bool emptyValueIsZero = true;
162 static void constructDeletedValue(blink::ThreadMarker& slot, bool) { new (NotNull, &slot) blink::ThreadMarker(HashTableDeletedValue); }
163 static bool isDeletedValue(const blink::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
166 // The hash algorithm for our custom pair class is just the standard double
167 // hash for pairs. Note that this means you can't mutate either of the parts of
168 // the pair while they are in the hash table, as that would change their hash
169 // code and thus their preferred placement in the table.
170 template<> struct DefaultHash<blink::PairWithWeakHandling> {
171 typedef PairHash<blink::Member<blink::IntWrapper>, blink::WeakMember<blink::IntWrapper> > Hash;
174 // Custom traits for the pair. These are weakness handling traits, which means
175 // PairWithWeakHandling must implement the traceInCollection method.
176 // In addition, these traits are concerned with the two magic values for the
177 // object, that represent empty and deleted slots in the hash table. The
178 // SimpleClassHashTraits allow empty slots in the table to be initialzed with
179 // memset to zero, and we use -1 in the first part of the pair to represent
181 template<> struct HashTraits<blink::PairWithWeakHandling> : blink::WeakHandlingHashTraits<blink::PairWithWeakHandling> {
182 static const bool needsDestruction = false;
183 static const bool hasIsEmptyValueFunction = true;
184 static bool isEmptyValue(const blink::PairWithWeakHandling& value) { return !value.first; }
185 static void constructDeletedValue(blink::PairWithWeakHandling& slot, bool) { new (NotNull, &slot) blink::PairWithWeakHandling(HashTableDeletedValue); }
186 static bool isDeletedValue(const blink::PairWithWeakHandling& value) { return value.isHashTableDeletedValue(); }
195 explicit TestGCScope(ThreadState::StackState state)
196 : m_state(ThreadState::current())
197 , m_safePointScope(state)
198 , m_parkedAllThreads(false)
200 m_state->checkThread();
201 EXPECT_FALSE(m_state->isInGC());
202 if (LIKELY(ThreadState::stopThreads())) {
204 m_parkedAllThreads = true;
208 bool allThreadsParked() { return m_parkedAllThreads; }
212 // Only cleanup if we parked all threads in which case the GC happened
213 // and we need to resume the other threads.
214 if (LIKELY(m_parkedAllThreads)) {
216 EXPECT_FALSE(m_state->isInGC());
217 ThreadState::resumeThreads();
222 ThreadState* m_state;
223 ThreadState::SafePointScope m_safePointScope;
224 bool m_parkedAllThreads; // False if we fail to park all threads
227 static void getHeapStats(HeapStats* stats)
229 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
230 EXPECT_TRUE(scope.allThreadsParked());
231 Heap::getStats(stats);
234 #define DEFINE_VISITOR_METHODS(Type) \
235 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
240 virtual bool isMarked(const Type*) OVERRIDE { return false; }
242 class CountingVisitor : public Visitor {
249 virtual void mark(const void* object, TraceCallback) OVERRIDE
255 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
257 ASSERT(header->payload());
261 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
263 ASSERT(header->payload());
267 virtual void registerDelayedMarkNoTracing(const void*) OVERRIDE { }
268 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
269 virtual void registerWeakTable(const void*, EphemeronCallback, EphemeronCallback) OVERRIDE { }
271 virtual bool weakTableRegistered(const void*) OVERRIDE { return false; }
273 virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
274 virtual bool isMarked(const void*) OVERRIDE { return false; }
276 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
278 size_t count() { return m_count; }
279 void reset() { m_count = 0; }
285 class SimpleObject : public GarbageCollected<SimpleObject> {
287 static SimpleObject* create() { return new SimpleObject(); }
288 void trace(Visitor*) { }
289 char getPayload(int i) { return payload[i]; }
290 // This virtual method is unused but it is here to make sure
291 // that this object has a vtable. This object is used
292 // as the super class for objects that also have garbage
293 // collected mixins and having a virtual here makes sure
294 // that adjustment is needed both for marking and for isAlive
296 virtual void virtualMethod() { }
302 #undef DEFINE_VISITOR_METHODS
304 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
306 static HeapTestSuperClass* create()
308 return new HeapTestSuperClass();
311 virtual ~HeapTestSuperClass()
316 static int s_destructorCalls;
317 void trace(Visitor*) { }
320 HeapTestSuperClass() { }
323 int HeapTestSuperClass::s_destructorCalls = 0;
325 class HeapTestOtherSuperClass {
330 static const size_t classMagic = 0xABCDDBCA;
332 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
334 static HeapTestSubClass* create()
336 return new HeapTestSubClass();
339 virtual ~HeapTestSubClass()
341 EXPECT_EQ(classMagic, m_magic);
345 static int s_destructorCalls;
349 HeapTestSubClass() : m_magic(classMagic) { }
351 const size_t m_magic;
354 int HeapTestSubClass::s_destructorCalls = 0;
356 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
360 for (int i = 0; i < s_arraySize; ++i) {
361 m_array[i] = i % 128;
365 int8_t at(size_t i) { return m_array[i]; }
366 void trace(Visitor*) { }
368 static const int s_arraySize = 1000;
369 int8_t m_array[s_arraySize];
372 // Do several GCs to make sure that later GCs don't free up old memory from
373 // previously run tests in this process.
374 static void clearOutOldGarbage(HeapStats* heapStats)
377 getHeapStats(heapStats);
378 size_t used = heapStats->totalObjectSpace();
379 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
380 getHeapStats(heapStats);
381 if (heapStats->totalObjectSpace() >= used)
386 class OffHeapInt : public RefCounted<OffHeapInt> {
388 static RefPtr<OffHeapInt> create(int x)
390 return adoptRef(new OffHeapInt(x));
393 virtual ~OffHeapInt()
398 static int s_destructorCalls;
400 int value() const { return m_x; }
402 bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
404 unsigned hash() { return IntHash<int>::hash(m_x); }
405 void voidFunction() { }
408 OffHeapInt(int x) : m_x(x) { }
415 int IntWrapper::s_destructorCalls = 0;
416 int OffHeapInt::s_destructorCalls = 0;
418 class ThreadedTesterBase {
420 static void test(ThreadedTesterBase* tester)
422 Vector<OwnPtr<WebThread>, numberOfThreads> m_threads;
423 for (int i = 0; i < numberOfThreads; i++) {
424 m_threads.append(adoptPtr(Platform::current()->createThread("blink gc testing thread")));
425 m_threads.last()->postTask(new Task(WTF::bind(threadFunc, tester)));
427 while (tester->m_threadsToFinish) {
428 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
429 Platform::current()->yieldCurrentThread();
434 virtual void runThread() = 0;
437 static const int numberOfThreads = 10;
438 static const int gcPerThread = 5;
439 static const int numberOfAllocations = 50;
441 ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
445 virtual ~ThreadedTesterBase()
449 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
451 volatile int m_gcCount;
452 volatile int m_threadsToFinish;
455 static void threadFunc(void* data)
457 reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
461 class ThreadedHeapTester : public ThreadedTesterBase {
465 ThreadedTesterBase::test(new ThreadedHeapTester);
469 virtual void runThread() OVERRIDE
471 ThreadState::attach();
475 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
477 Persistent<IntWrapper> wrapper;
479 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
480 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
482 for (int i = 0; i < numberOfAllocations; i++) {
483 wrapper = IntWrapper::create(0x0bbac0de);
485 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
487 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
488 Platform::current()->yieldCurrentThread();
491 if (gcCount < gcPerThread) {
492 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
494 atomicIncrement(&m_gcCount);
497 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
498 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
499 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
501 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
502 Platform::current()->yieldCurrentThread();
504 ThreadState::detach();
505 atomicDecrement(&m_threadsToFinish);
509 class ThreadedWeaknessTester : public ThreadedTesterBase {
513 ThreadedTesterBase::test(new ThreadedWeaknessTester);
517 virtual void runThread() OVERRIDE
519 ThreadState::attach();
523 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
525 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
526 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
528 for (int i = 0; i < numberOfAllocations; i++) {
529 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
530 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
531 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
532 Platform::current()->yieldCurrentThread();
535 if (gcCount < gcPerThread) {
536 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
538 atomicIncrement(&m_gcCount);
541 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
542 EXPECT_TRUE(weakMap->isEmpty());
543 EXPECT_TRUE(weakMap2.isEmpty());
545 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
546 Platform::current()->yieldCurrentThread();
548 ThreadState::detach();
549 atomicDecrement(&m_threadsToFinish);
553 // The accounting for memory includes the memory used by rounding up object
554 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
555 // have some slack in the tests.
557 void CheckWithSlack(T expected, T actual, int slack)
559 EXPECT_LE(expected, actual);
560 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
563 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
565 static TraceCounter* create()
567 return new TraceCounter();
570 void trace(Visitor*) { m_traceCount++; }
572 int traceCount() { return m_traceCount; }
583 class ClassWithMember : public GarbageCollected<ClassWithMember> {
585 static ClassWithMember* create()
587 return new ClassWithMember();
590 void trace(Visitor* visitor)
592 EXPECT_TRUE(visitor->isMarked(this));
594 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
596 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
598 visitor->trace(m_traceCounter);
601 int traceCount() { return m_traceCounter->traceCount(); }
605 : m_traceCounter(TraceCounter::create())
608 Member<TraceCounter> m_traceCounter;
611 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
613 static SimpleFinalizedObject* create()
615 return new SimpleFinalizedObject();
618 ~SimpleFinalizedObject()
623 static int s_destructorCalls;
625 void trace(Visitor*) { }
628 SimpleFinalizedObject() { }
631 int SimpleFinalizedObject::s_destructorCalls = 0;
633 class Node : public GarbageCollected<Node> {
635 static Node* create(int i)
640 void trace(Visitor*) { }
642 int value() { return m_value; }
645 Node(int i) : m_value(i) { }
649 class Bar : public GarbageCollectedFinalized<Bar> {
656 void finalizeGarbageCollectedObject()
658 EXPECT_TRUE(m_magic == magic);
662 bool hasBeenFinalized() const { return !m_magic; }
664 virtual void trace(Visitor* visitor) { }
665 static unsigned s_live;
668 static const int magic = 1337;
678 unsigned Bar::s_live = 0;
680 class Baz : public GarbageCollected<Baz> {
682 static Baz* create(Bar* bar)
687 void trace(Visitor* visitor)
689 visitor->trace(m_bar);
692 void clear() { m_bar.release(); }
694 // willFinalize is called by FinalizationObserver.
697 EXPECT_TRUE(!m_bar->hasBeenFinalized());
701 explicit Baz(Bar* bar)
709 class Foo : public Bar {
711 static Foo* create(Bar* bar)
716 static Foo* create(Foo* foo)
721 virtual void trace(Visitor* visitor) OVERRIDE
724 visitor->mark(static_cast<Foo*>(m_bar));
726 visitor->mark(m_bar);
733 , m_pointsToFoo(false)
740 , m_pointsToFoo(true)
748 class Bars : public Bar {
750 static Bars* create()
755 virtual void trace(Visitor* visitor) OVERRIDE
757 for (unsigned i = 0; i < m_width; i++)
758 visitor->trace(m_bars[i]);
761 unsigned getWidth() const
766 static const unsigned width = 7500;
770 for (unsigned i = 0; i < width; i++) {
771 m_bars[i] = Bar::create();
777 Member<Bar> m_bars[width];
780 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
782 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
784 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
787 ConstructorAllocation()
789 m_intWrapper = IntWrapper::create(42);
792 Member<IntWrapper> m_intWrapper;
795 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
801 static LargeObject* create() { return new LargeObject(); }
802 char get(size_t i) { return m_data[i]; }
803 void set(size_t i, char c) { m_data[i] = c; }
804 size_t length() { return s_length; }
805 void trace(Visitor* visitor)
807 visitor->trace(m_intWrapper);
809 static int s_destructorCalls;
812 static const size_t s_length = 1024*1024;
815 m_intWrapper = IntWrapper::create(23);
817 Member<IntWrapper> m_intWrapper;
818 char m_data[s_length];
821 int LargeObject::s_destructorCalls = 0;
823 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
825 static PassRefPtr<RefCountedAndGarbageCollected> create()
827 return adoptRef(new RefCountedAndGarbageCollected());
830 ~RefCountedAndGarbageCollected()
835 // These are here with their default implementations so you can break in
836 // them in the debugger.
837 void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref(); }
838 void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::deref(); }
840 void trace(Visitor*) { }
842 static int s_destructorCalls;
845 RefCountedAndGarbageCollected()
850 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
852 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
854 static RefCountedAndGarbageCollected2* create()
856 return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
859 ~RefCountedAndGarbageCollected2()
864 void trace(Visitor*) { }
866 static int s_destructorCalls;
869 RefCountedAndGarbageCollected2()
874 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
876 #define DEFINE_VISITOR_METHODS(Type) \
877 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
882 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
884 RefCountedGarbageCollectedVisitor(int expected, void** objects)
886 , m_expectedCount(expected)
887 , m_expectedObjects(objects)
891 void mark(const void* ptr) { markNoTrace(ptr); }
893 virtual void markNoTrace(const void* ptr)
897 if (m_count < m_expectedCount)
898 EXPECT_TRUE(expectedObject(ptr));
900 EXPECT_FALSE(expectedObject(ptr));
904 virtual void mark(const void* ptr, TraceCallback) OVERRIDE
909 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
911 mark(header->payload());
914 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
916 mark(header->payload());
919 bool validate() { return m_count >= m_expectedCount; }
920 void reset() { m_count = 0; }
922 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
925 bool expectedObject(const void* ptr)
927 for (int i = 0; i < m_expectedCount; i++) {
928 if (m_expectedObjects[i] == ptr)
936 void** m_expectedObjects;
939 #undef DEFINE_VISITOR_METHODS
941 class Weak : public Bar {
943 static Weak* create(Bar* strong, Bar* weak)
945 return new Weak(strong, weak);
948 virtual void trace(Visitor* visitor) OVERRIDE
950 visitor->trace(m_strongBar);
951 visitor->registerWeakMembers(this, zapWeakMembers);
954 static void zapWeakMembers(Visitor* visitor, void* self)
956 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
959 bool strongIsThere() { return !!m_strongBar; }
960 bool weakIsThere() { return !!m_weakBar; }
963 Weak(Bar* strongBar, Bar* weakBar)
965 , m_strongBar(strongBar)
970 void zapWeakMembers(Visitor* visitor)
972 if (!visitor->isAlive(m_weakBar))
976 Member<Bar> m_strongBar;
980 class WithWeakMember : public Bar {
982 static WithWeakMember* create(Bar* strong, Bar* weak)
984 return new WithWeakMember(strong, weak);
987 virtual void trace(Visitor* visitor) OVERRIDE
989 visitor->trace(m_strongBar);
990 visitor->trace(m_weakBar);
993 bool strongIsThere() { return !!m_strongBar; }
994 bool weakIsThere() { return !!m_weakBar; }
997 WithWeakMember(Bar* strongBar, Bar* weakBar)
999 , m_strongBar(strongBar)
1000 , m_weakBar(weakBar)
1004 Member<Bar> m_strongBar;
1005 WeakMember<Bar> m_weakBar;
1008 class Observable : public GarbageCollectedFinalized<Observable> {
1010 static Observable* create(Bar* bar) { return new Observable(bar); }
1011 ~Observable() { m_wasDestructed = true; }
1012 void trace(Visitor* visitor) { visitor->trace(m_bar); }
1014 // willFinalize is called by FinalizationObserver. willFinalize can touch
1015 // other on-heap objects.
1018 EXPECT_FALSE(m_wasDestructed);
1019 EXPECT_FALSE(m_bar->hasBeenFinalized());
1023 explicit Observable(Bar* bar)
1025 , m_wasDestructed(false)
1030 bool m_wasDestructed;
1033 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
1035 static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
1036 bool didCallWillFinalize() const { return m_didCallWillFinalize; }
1038 void trace(Visitor* visitor)
1040 visitor->registerWeakMembers(this, zapWeakMembers);
1044 FinalizationObserver(T* data)
1046 , m_didCallWillFinalize(false)
1050 static void zapWeakMembers(Visitor* visitor, void* self)
1052 FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
1053 if (o->m_data && !visitor->isAlive(o->m_data)) {
1054 o->m_data->willFinalize();
1055 o->m_data = nullptr;
1056 o->m_didCallWillFinalize = true;
1060 WeakMember<T> m_data;
1061 bool m_didCallWillFinalize;
1064 class FinalizationObserverWithHashMap {
1066 typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
1068 explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
1069 ~FinalizationObserverWithHashMap()
1071 m_target.willFinalize();
1072 s_didCallWillFinalize = true;
1075 static ObserverMap& observe(Observable& target)
1077 ObserverMap& map = observers();
1078 ObserverMap::AddResult result = map.add(&target, nullptr);
1079 if (result.isNewEntry)
1080 result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
1082 ASSERT(result.storedValue->value);
1086 static bool s_didCallWillFinalize;
1089 static ObserverMap& observers()
1091 DEFINE_STATIC_LOCAL(Persistent<ObserverMap>, observerMap, ());
1093 observerMap = new ObserverMap();
1094 return *observerMap;
1097 Observable& m_target;
1100 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
1104 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
1106 static PassRefPtrWillBeRawPtr<PointsBack> create()
1108 return adoptRefWillBeNoop(new PointsBack());
1116 void setBackPointer(SuperClass* backPointer)
1118 m_backPointer = backPointer;
1121 SuperClass* backPointer() const { return m_backPointer; }
1123 void trace(Visitor* visitor)
1126 visitor->trace(m_backPointer);
1130 static int s_aliveCount;
1132 PointsBack() : m_backPointer(nullptr)
1137 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1140 int PointsBack::s_aliveCount = 0;
1142 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1144 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1146 return adoptRefWillBeNoop(new SuperClass(pointsBack));
1149 virtual ~SuperClass()
1152 m_pointsBack->setBackPointer(0);
1157 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1159 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1160 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1161 EXPECT_EQ(pointsBack, target->pointsBack());
1162 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1165 virtual void trace(Visitor* visitor)
1168 visitor->trace(m_pointsBack);
1172 PointsBack* pointsBack() const { return m_pointsBack.get(); }
1174 static int s_aliveCount;
1176 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1177 : m_pointsBack(pointsBack)
1179 m_pointsBack->setBackPointer(this);
1184 RefPtrWillBeMember<PointsBack> m_pointsBack;
1187 int SuperClass::s_aliveCount = 0;
1188 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1190 SubData() { ++s_aliveCount; }
1191 ~SubData() { --s_aliveCount; }
1193 void trace(Visitor*) { }
1195 static int s_aliveCount;
1198 int SubData::s_aliveCount = 0;
1200 class SubClass : public SuperClass {
1202 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1204 return adoptRefWillBeNoop(new SubClass(pointsBack));
1212 virtual void trace(Visitor* visitor)
1215 SuperClass::trace(visitor);
1216 visitor->trace(m_data);
1220 static int s_aliveCount;
1222 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1223 : SuperClass(pointsBack)
1224 , m_data(adoptPtrWillBeNoop(new SubData()))
1230 OwnPtrWillBeMember<SubData> m_data;
1233 int SubClass::s_aliveCount = 0;
1235 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1237 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1239 return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
1242 ~TransitionRefCounted()
1247 void trace(Visitor* visitor) { }
1249 static int s_aliveCount;
1252 TransitionRefCounted()
1258 int TransitionRefCounted::s_aliveCount = 0;
1260 class Mixin : public GarbageCollectedMixin {
1262 virtual void trace(Visitor* visitor) { }
1264 virtual char getPayload(int i) { return m_padding[i]; }
1270 class UseMixin : public SimpleObject, public Mixin {
1271 USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1273 static UseMixin* create()
1275 return new UseMixin();
1278 static int s_traceCount;
1279 virtual void trace(Visitor* visitor)
1281 SimpleObject::trace(visitor);
1282 Mixin::trace(visitor);
1293 int UseMixin::s_traceCount = 0;
1295 class VectorObject {
1296 ALLOW_ONLY_INLINE_ALLOCATION();
1300 m_value = SimpleFinalizedObject::create();
1303 void trace(Visitor* visitor)
1305 visitor->trace(m_value);
1309 Member<SimpleFinalizedObject> m_value;
1312 class VectorObjectInheritedTrace : public VectorObject { };
1314 class VectorObjectNoTrace {
1315 ALLOW_ONLY_INLINE_ALLOCATION();
1317 VectorObjectNoTrace()
1319 m_value = SimpleFinalizedObject::create();
1323 Member<SimpleFinalizedObject> m_value;
1326 class TerminatedArrayItem {
1327 ALLOW_ONLY_INLINE_ALLOCATION();
1329 TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1331 void trace(Visitor* visitor) { visitor->trace(m_payload); }
1333 bool isLastInArray() const { return m_isLast; }
1334 void setLastInArray(bool value) { m_isLast = value; }
1336 IntWrapper* payload() const { return m_payload; }
1339 Member<IntWrapper> m_payload;
1343 } // namespace blink
1345 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObject);
1346 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectInheritedTrace);
1347 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectNoTrace);
1351 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1353 ~OneKiloByteObject() { s_destructorCalls++; }
1354 char* data() { return m_data; }
1355 void trace(Visitor* visitor) { }
1356 static int s_destructorCalls;
1359 static const size_t s_length = 1024;
1360 char m_data[s_length];
1363 int OneKiloByteObject::s_destructorCalls = 0;
1365 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1367 static DynamicallySizedObject* create(size_t size)
1369 void* slot = Heap::allocate<DynamicallySizedObject>(size);
1370 return new (slot) DynamicallySizedObject();
1373 void* operator new(std::size_t, void* location)
1380 return *(reinterpret_cast<uint8_t*>(this) + i);
1383 void trace(Visitor*) { }
1386 DynamicallySizedObject() { }
1389 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1391 FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1392 : m_wrapper(wrapper)
1396 ~FinalizationAllocator()
1398 for (int i = 0; i < 10; ++i)
1399 *m_wrapper = IntWrapper::create(42);
1400 for (int i = 0; i < 512; ++i)
1401 new OneKiloByteObject();
1404 void trace(Visitor*) { }
1407 Persistent<IntWrapper>* m_wrapper;
1410 TEST(HeapTest, Transition)
1413 RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1414 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1415 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1416 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1418 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1419 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1421 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1422 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1423 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1424 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1425 EXPECT_EQ(2, PointsBack::s_aliveCount);
1426 EXPECT_EQ(2, SuperClass::s_aliveCount);
1427 EXPECT_EQ(1, SubClass::s_aliveCount);
1428 EXPECT_EQ(1, SubData::s_aliveCount);
1430 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1431 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1432 EXPECT_EQ(2, PointsBack::s_aliveCount);
1433 EXPECT_EQ(2, SuperClass::s_aliveCount);
1434 EXPECT_EQ(1, SubClass::s_aliveCount);
1435 EXPECT_EQ(1, SubData::s_aliveCount);
1437 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1438 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1439 EXPECT_EQ(2, PointsBack::s_aliveCount);
1440 EXPECT_EQ(1, SuperClass::s_aliveCount);
1441 EXPECT_EQ(1, SubClass::s_aliveCount);
1442 EXPECT_EQ(1, SubData::s_aliveCount);
1443 EXPECT_EQ(0, pointsBack1->backPointer());
1445 pointsBack1.release();
1446 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1447 EXPECT_EQ(1, PointsBack::s_aliveCount);
1448 EXPECT_EQ(1, SuperClass::s_aliveCount);
1449 EXPECT_EQ(1, SubClass::s_aliveCount);
1450 EXPECT_EQ(1, SubData::s_aliveCount);
1452 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1453 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1454 EXPECT_EQ(1, PointsBack::s_aliveCount);
1455 EXPECT_EQ(0, SuperClass::s_aliveCount);
1456 EXPECT_EQ(0, SubClass::s_aliveCount);
1457 EXPECT_EQ(0, SubData::s_aliveCount);
1458 EXPECT_EQ(0, pointsBack2->backPointer());
1460 pointsBack2.release();
1461 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1462 EXPECT_EQ(0, PointsBack::s_aliveCount);
1463 EXPECT_EQ(0, SuperClass::s_aliveCount);
1464 EXPECT_EQ(0, SubClass::s_aliveCount);
1465 EXPECT_EQ(0, SubData::s_aliveCount);
1467 EXPECT_TRUE(superClass == subClass);
1470 TEST(HeapTest, Threading)
1472 ThreadedHeapTester::test();
1475 TEST(HeapTest, ThreadedWeakness)
1477 ThreadedWeaknessTester::test();
1480 TEST(HeapTest, BasicFunctionality)
1482 HeapStats heapStats;
1483 clearOutOldGarbage(&heapStats);
1487 // When the test starts there may already have been leaked some memory
1488 // on the heap, so we establish a base line.
1489 size_t baseLevel = heapStats.totalObjectSpace();
1490 bool testPagesAllocated = !baseLevel;
1491 if (testPagesAllocated)
1492 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1494 // This allocates objects on the general heap which should add a page of memory.
1495 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1497 memset(alloc32, 40, 32);
1498 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1500 memset(alloc64, 27, 64);
1504 getHeapStats(&heapStats);
1505 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1506 if (testPagesAllocated)
1507 EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1509 CheckWithSlack(alloc32 + 32 + sizeof(FinalizedHeapObjectHeader), alloc64, slack);
1511 EXPECT_EQ(alloc32->get(0), 40);
1512 EXPECT_EQ(alloc32->get(31), 40);
1513 EXPECT_EQ(alloc64->get(0), 27);
1514 EXPECT_EQ(alloc64->get(63), 27);
1516 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1518 EXPECT_EQ(alloc32->get(0), 40);
1519 EXPECT_EQ(alloc32->get(31), 40);
1520 EXPECT_EQ(alloc64->get(0), 27);
1521 EXPECT_EQ(alloc64->get(63), 27);
1524 clearOutOldGarbage(&heapStats);
1527 size_t baseLevel = heapStats.totalObjectSpace();
1528 bool testPagesAllocated = !baseLevel;
1529 if (testPagesAllocated)
1530 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1533 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1537 size_t persistentCount = 0;
1538 const size_t numPersistents = 100000;
1539 Persistent<DynamicallySizedObject>* persistents[numPersistents];
1541 for (int i = 0; i < 1000; i++) {
1542 size_t size = 128 + i * 8;
1544 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1546 getHeapStats(&heapStats);
1547 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1548 if (testPagesAllocated)
1549 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1553 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1555 memset(alloc32b, 40, 32);
1556 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1558 memset(alloc64b, 27, 64);
1559 EXPECT_TRUE(alloc32b != alloc64b);
1562 getHeapStats(&heapStats);
1563 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1564 if (testPagesAllocated)
1565 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1568 clearOutOldGarbage(&heapStats);
1571 if (testPagesAllocated)
1572 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1574 DynamicallySizedObject* bigAreaRaw = bigArea;
1575 // Clear the persistent, so that the big area will be garbage collected.
1577 clearOutOldGarbage(&heapStats);
1581 getHeapStats(&heapStats);
1582 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1583 if (testPagesAllocated)
1584 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1586 // Endless loop unless we eventually get the memory back that we just freed.
1588 Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
1590 persistents[persistentCount++] = alloc;
1591 EXPECT_LT(persistentCount, numPersistents);
1593 if (bigAreaRaw == alloc->get())
1597 getHeapStats(&heapStats);
1598 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1599 if (testPagesAllocated)
1600 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1602 for (size_t i = 0; i < persistentCount; i++) {
1603 delete persistents[i];
1607 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1608 for (int i = 0; i < 100; i++)
1610 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1611 for (int i = 0; i < 100; i++)
1612 EXPECT_EQ(address[i], i);
1613 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1614 for (int i = 0; i < 50; i++)
1615 EXPECT_EQ(address[i], i);
1616 // This should be equivalent to free(address).
1617 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1618 // This should be equivalent to malloc(0).
1619 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1622 TEST(HeapTest, SimpleAllocation)
1624 HeapStats initialHeapStats;
1625 clearOutOldGarbage(&initialHeapStats);
1626 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1628 // Allocate an object in the heap.
1629 HeapAllocatedArray* array = new HeapAllocatedArray();
1630 HeapStats statsAfterAllocation;
1631 getHeapStats(&statsAfterAllocation);
1632 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1634 // Sanity check of the contents in the heap.
1635 EXPECT_EQ(0, array->at(0));
1636 EXPECT_EQ(42, array->at(42));
1637 EXPECT_EQ(0, array->at(128));
1638 EXPECT_EQ(999 % 128, array->at(999));
1641 TEST(HeapTest, SimplePersistent)
1643 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1644 EXPECT_EQ(0, traceCounter->traceCount());
1646 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1647 EXPECT_EQ(1, traceCounter->traceCount());
1649 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1650 EXPECT_EQ(0, classWithMember->traceCount());
1652 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1653 EXPECT_EQ(1, classWithMember->traceCount());
1654 EXPECT_EQ(2, traceCounter->traceCount());
1657 TEST(HeapTest, SimpleFinalization)
1660 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1661 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1662 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1663 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1666 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1667 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1670 TEST(HeapTest, Finalization)
1673 HeapTestSubClass* t1 = HeapTestSubClass::create();
1674 HeapTestSubClass* t2 = HeapTestSubClass::create();
1675 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1676 // FIXME(oilpan): Ignore unused variables.
1681 // Nothing is marked so the GC should free everything and call
1682 // the finalizer on all three objects.
1683 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1684 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1685 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1686 // Destructors not called again when GCing again.
1687 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1688 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1689 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1692 TEST(HeapTest, TypedHeapSanity)
1694 // We use TraceCounter for allocating an object on the general heap.
1695 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1696 Persistent<Node> typedHeapObject = Node::create(0);
1697 EXPECT_NE(pageHeaderFromObject(generalHeapObject.get()),
1698 pageHeaderFromObject(typedHeapObject.get()));
1701 TEST(HeapTest, NoAllocation)
1703 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1705 // Disallow allocation
1706 NoAllocationScope<AnyThread> noAllocationScope;
1707 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1709 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1712 TEST(HeapTest, Members)
1719 h1 = Baz::create(Bar::create());
1720 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1721 EXPECT_EQ(1u, Bar::s_live);
1722 h2 = Baz::create(Bar::create());
1723 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1724 EXPECT_EQ(2u, Bar::s_live);
1726 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1727 EXPECT_EQ(2u, Bar::s_live);
1729 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1730 EXPECT_EQ(1u, Bar::s_live);
1732 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1733 EXPECT_EQ(0u, Bar::s_live);
1736 TEST(HeapTest, MarkTest)
1740 Persistent<Bar> bar = Bar::create();
1741 EXPECT_TRUE(ThreadState::current()->contains(bar));
1742 EXPECT_EQ(1u, Bar::s_live);
1744 Foo* foo = Foo::create(bar);
1745 EXPECT_TRUE(ThreadState::current()->contains(foo));
1746 EXPECT_EQ(2u, Bar::s_live);
1747 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1748 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1749 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1750 EXPECT_EQ(2u, Bar::s_live);
1752 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1753 EXPECT_EQ(1u, Bar::s_live);
1755 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1756 EXPECT_EQ(0u, Bar::s_live);
1759 TEST(HeapTest, DeepTest)
1761 const unsigned depth = 100000;
1764 Bar* bar = Bar::create();
1765 EXPECT_TRUE(ThreadState::current()->contains(bar));
1766 Foo* foo = Foo::create(bar);
1767 EXPECT_TRUE(ThreadState::current()->contains(foo));
1768 EXPECT_EQ(2u, Bar::s_live);
1769 for (unsigned i = 0; i < depth; i++) {
1770 Foo* foo2 = Foo::create(foo);
1772 EXPECT_TRUE(ThreadState::current()->contains(foo));
1774 EXPECT_EQ(depth + 2, Bar::s_live);
1775 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1776 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1777 EXPECT_EQ(depth + 2, Bar::s_live);
1779 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1780 EXPECT_EQ(0u, Bar::s_live);
1783 TEST(HeapTest, WideTest)
1787 Bars* bars = Bars::create();
1788 unsigned width = Bars::width;
1789 EXPECT_EQ(width + 1, Bar::s_live);
1790 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1791 EXPECT_EQ(width + 1, Bar::s_live);
1792 // Use bars here to make sure that it will be on the stack
1793 // for the conservative stack scan to find.
1794 EXPECT_EQ(width, bars->getWidth());
1796 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1797 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1798 EXPECT_EQ(0u, Bar::s_live);
1801 TEST(HeapTest, HashMapOfMembers)
1803 HeapStats initialHeapSize;
1804 IntWrapper::s_destructorCalls = 0;
1806 clearOutOldGarbage(&initialHeapSize);
1808 typedef HeapHashMap<
1811 DefaultHash<Member<IntWrapper> >::Hash,
1812 HashTraits<Member<IntWrapper> >,
1813 HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1815 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1818 HeapStats afterSetWasCreated;
1819 getHeapStats(&afterSetWasCreated);
1820 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1822 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1824 getHeapStats(&afterGC);
1825 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1827 // If the additions below cause garbage collections, these
1828 // pointers should be found by conservative stack scanning.
1829 IntWrapper* one(IntWrapper::create(1));
1830 IntWrapper* anotherOne(IntWrapper::create(1));
1834 HeapStats afterOneAdd;
1835 getHeapStats(&afterOneAdd);
1836 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1838 HeapObjectIdentityMap::iterator it(map->begin());
1839 HeapObjectIdentityMap::iterator it2(map->begin());
1843 map->add(anotherOne, one);
1845 // The addition above can cause an allocation of a new
1846 // backing store. We therefore garbage collect before
1847 // taking the heap stats in order to get rid of the old
1848 // backing store. We make sure to not use conservative
1849 // stack scanning as that could find a pointer to the
1851 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1852 HeapStats afterAddAndGC;
1853 getHeapStats(&afterAddAndGC);
1854 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1856 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1858 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1859 EXPECT_TRUE(map->contains(one));
1860 EXPECT_TRUE(map->contains(anotherOne));
1862 IntWrapper* gotten(map->get(one));
1863 EXPECT_EQ(gotten->value(), one->value());
1864 EXPECT_EQ(gotten, one);
1867 getHeapStats(&afterGC2);
1868 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1870 IntWrapper* dozen = 0;
1872 for (int i = 1; i < 1000; i++) { // 999 iterations.
1873 IntWrapper* iWrapper(IntWrapper::create(i));
1874 IntWrapper* iSquared(IntWrapper::create(i * i));
1875 map->add(iWrapper, iSquared);
1879 HeapStats afterAdding1000;
1880 getHeapStats(&afterAdding1000);
1881 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1883 IntWrapper* gross(map->get(dozen));
1884 EXPECT_EQ(gross->value(), 144);
1886 // This should clear out any junk backings created by all the adds.
1887 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1889 getHeapStats(&afterGC3);
1890 EXPECT_TRUE(afterGC3.totalObjectSpace() <= afterAdding1000.totalObjectSpace());
1893 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1894 // The objects 'one', anotherOne, and the 999 other pairs.
1895 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1897 getHeapStats(&afterGC4);
1898 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1901 TEST(HeapTest, NestedAllocation)
1903 HeapStats initialHeapSize;
1904 clearOutOldGarbage(&initialHeapSize);
1906 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1908 HeapStats afterFree;
1909 clearOutOldGarbage(&afterFree);
1910 EXPECT_TRUE(initialHeapSize == afterFree);
1913 TEST(HeapTest, LargeObjects)
1915 HeapStats initialHeapSize;
1916 clearOutOldGarbage(&initialHeapSize);
1917 IntWrapper::s_destructorCalls = 0;
1918 LargeObject::s_destructorCalls = 0;
1920 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1921 Persistent<LargeObject> object = LargeObject::create();
1922 EXPECT_TRUE(ThreadState::current()->contains(object));
1923 EXPECT_TRUE(ThreadState::current()->contains(reinterpret_cast<char*>(object.get()) + sizeof(LargeObject) - 1));
1924 #if ENABLE(GC_PROFILE_MARKING)
1925 const GCInfo* info = ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()));
1926 EXPECT_NE(reinterpret_cast<const GCInfo*>(0), info);
1927 EXPECT_EQ(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject) - 1));
1928 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject)));
1929 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) - 1));
1931 HeapStats afterAllocation;
1932 clearOutOldGarbage(&afterAllocation);
1934 object->set(0, 'a');
1935 EXPECT_EQ('a', object->get(0));
1936 object->set(object->length() - 1, 'b');
1937 EXPECT_EQ('b', object->get(object->length() - 1));
1938 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1939 size_t actualObjectSpace =
1940 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1941 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1942 // There is probably space for the IntWrapper in a heap page without
1943 // allocating extra pages. However, the IntWrapper allocation might cause
1944 // the addition of a heap page.
1945 size_t largeObjectAllocationSize =
1946 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1947 size_t allocatedSpaceLowerBound =
1948 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1949 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1950 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1951 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1952 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1953 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1954 for (int i = 0; i < 10; i++)
1955 object = LargeObject::create();
1957 HeapStats oneLargeObject;
1958 clearOutOldGarbage(&oneLargeObject);
1959 EXPECT_TRUE(oneLargeObject == afterAllocation);
1960 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1961 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1963 HeapStats backToInitial;
1964 clearOutOldGarbage(&backToInitial);
1965 EXPECT_TRUE(initialHeapSize == backToInitial);
1966 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1967 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1968 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1971 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1972 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1973 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1974 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1975 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1976 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1978 class Container : public GarbageCollected<Container> {
1980 static Container* create() { return new Container(); }
1981 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1982 HeapHashSet<Member<IntWrapper> > set;
1983 HeapHashSet<Member<IntWrapper> > set2;
1984 HeapHashCountedSet<Member<IntWrapper> > set3;
1985 HeapVector<Member<IntWrapper>, 2> vector;
1986 HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1987 HeapVector<PairUnwrappedWrapped, 2> vectorUW;
1988 HeapDeque<Member<IntWrapper>, 0> deque;
1989 HeapDeque<PairWrappedUnwrapped, 0> dequeWU;
1990 HeapDeque<PairUnwrappedWrapped, 0> dequeUW;
1991 void trace(Visitor* visitor)
1993 visitor->trace(map);
1994 visitor->trace(set);
1995 visitor->trace(set2);
1996 visitor->trace(set3);
1997 visitor->trace(vector);
1998 visitor->trace(vectorWU);
1999 visitor->trace(vectorUW);
2000 visitor->trace(deque);
2001 visitor->trace(dequeWU);
2002 visitor->trace(dequeUW);
2006 struct ShouldBeTraced {
2007 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
2008 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
2009 Member<IntWrapper> m_wrapper;
2012 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
2014 static OffHeapContainer* create() { return new OffHeapContainer(); }
2016 static const int iterations = 300;
2017 static const int deadWrappers = 1200;
2021 for (int i = 0; i < iterations; i++) {
2022 m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
2023 m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
2024 m_deque2.append(IntWrapper::create(i));
2025 m_vector2.append(IntWrapper::create(i));
2028 Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
2029 Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
2030 Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
2031 Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
2033 for (int i = 0; i < iterations; i++) {
2034 EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
2035 EXPECT_EQ(i, m_vector2[i]->value());
2036 EXPECT_EQ(i, d1Iterator->m_wrapper->value());
2037 EXPECT_EQ(i, v1Iterator->m_wrapper->value());
2038 EXPECT_EQ(i, d2Iterator->get()->value());
2039 EXPECT_EQ(i, v2Iterator->get()->value());
2045 EXPECT_EQ(d1Iterator, m_deque1.end());
2046 EXPECT_EQ(v1Iterator, m_vector1.end());
2047 EXPECT_EQ(d2Iterator, m_deque2.end());
2048 EXPECT_EQ(v2Iterator, m_vector2.end());
2051 void trace(Visitor* visitor)
2053 visitor->trace(m_deque1);
2054 visitor->trace(m_vector1);
2055 visitor->trace(m_deque2);
2056 visitor->trace(m_vector2);
2059 Deque<ShouldBeTraced> m_deque1;
2060 Vector<ShouldBeTraced> m_vector1;
2061 Deque<Member<IntWrapper> > m_deque2;
2062 Vector<Member<IntWrapper> > m_vector2;
2065 const int OffHeapContainer::iterations;
2066 const int OffHeapContainer::deadWrappers;
2068 // These class definitions test compile-time asserts with transition
2069 // types. They are therefore unused in test code and just need to
2070 // compile. This is intentional; do not delete the A and B classes below.
2071 class A : public WillBeGarbageCollectedMixin {
2074 class B : public NoBaseWillBeGarbageCollected<B>, public A {
2075 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
2077 void trace(Visitor*) { }
2080 TEST(HeapTest, HeapVectorFilledWithValue)
2082 IntWrapper* val = IntWrapper::create(1);
2083 HeapVector<Member<IntWrapper> > vector(10, val);
2084 EXPECT_EQ(10u, vector.size());
2085 for (size_t i = 0; i < vector.size(); i++)
2086 EXPECT_EQ(val, vector[i]);
2089 TEST(HeapTest, HeapVectorWithInlineCapacity)
2091 IntWrapper* one = IntWrapper::create(1);
2092 IntWrapper* two = IntWrapper::create(2);
2093 IntWrapper* three = IntWrapper::create(3);
2094 IntWrapper* four = IntWrapper::create(4);
2095 IntWrapper* five = IntWrapper::create(5);
2096 IntWrapper* six = IntWrapper::create(6);
2098 HeapVector<Member<IntWrapper>, 2> vector;
2101 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2102 EXPECT_TRUE(vector.contains(one));
2103 EXPECT_TRUE(vector.contains(two));
2105 vector.append(three);
2106 vector.append(four);
2107 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2108 EXPECT_TRUE(vector.contains(one));
2109 EXPECT_TRUE(vector.contains(two));
2110 EXPECT_TRUE(vector.contains(three));
2111 EXPECT_TRUE(vector.contains(four));
2114 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2115 EXPECT_TRUE(vector.contains(one));
2116 EXPECT_FALSE(vector.contains(two));
2117 EXPECT_FALSE(vector.contains(three));
2118 EXPECT_FALSE(vector.contains(four));
2121 HeapVector<Member<IntWrapper>, 2> vector1;
2122 HeapVector<Member<IntWrapper>, 2> vector2;
2124 vector1.append(one);
2125 vector2.append(two);
2126 vector1.swap(vector2);
2127 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2128 EXPECT_TRUE(vector1.contains(two));
2129 EXPECT_TRUE(vector2.contains(one));
2132 HeapVector<Member<IntWrapper>, 2> vector1;
2133 HeapVector<Member<IntWrapper>, 2> vector2;
2135 vector1.append(one);
2136 vector1.append(two);
2137 vector2.append(three);
2138 vector2.append(four);
2139 vector2.append(five);
2140 vector2.append(six);
2141 vector1.swap(vector2);
2142 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2143 EXPECT_TRUE(vector1.contains(three));
2144 EXPECT_TRUE(vector1.contains(four));
2145 EXPECT_TRUE(vector1.contains(five));
2146 EXPECT_TRUE(vector1.contains(six));
2147 EXPECT_TRUE(vector2.contains(one));
2148 EXPECT_TRUE(vector2.contains(two));
2152 template<typename T, size_t inlineCapacity, typename U>
2153 bool dequeContains(HeapDeque<T, inlineCapacity>& deque, U u)
2155 typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
2156 for (iterator it = deque.begin(); it != deque.end(); ++it) {
2163 TEST(HeapTest, HeapCollectionTypes)
2165 HeapStats initialHeapSize;
2166 IntWrapper::s_destructorCalls = 0;
2168 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
2169 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2170 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
2172 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2173 typedef HeapHashCountedSet<Member<IntWrapper> > MemberCountedSet;
2175 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2176 typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
2178 typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2179 typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2180 typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
2181 typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
2183 Persistent<MemberMember> memberMember = new MemberMember();
2184 Persistent<MemberMember> memberMember2 = new MemberMember();
2185 Persistent<MemberMember> memberMember3 = new MemberMember();
2186 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2187 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2188 Persistent<MemberSet> set = new MemberSet();
2189 Persistent<MemberSet> set2 = new MemberSet();
2190 Persistent<MemberCountedSet> set3 = new MemberCountedSet();
2191 Persistent<MemberVector> vector = new MemberVector();
2192 Persistent<MemberVector> vector2 = new MemberVector();
2193 Persistent<VectorWU> vectorWU = new VectorWU();
2194 Persistent<VectorWU> vectorWU2 = new VectorWU();
2195 Persistent<VectorUW> vectorUW = new VectorUW();
2196 Persistent<VectorUW> vectorUW2 = new VectorUW();
2197 Persistent<MemberDeque> deque = new MemberDeque();
2198 Persistent<MemberDeque> deque2 = new MemberDeque();
2199 Persistent<DequeWU> dequeWU = new DequeWU();
2200 Persistent<DequeWU> dequeWU2 = new DequeWU();
2201 Persistent<DequeUW> dequeUW = new DequeUW();
2202 Persistent<DequeUW> dequeUW2 = new DequeUW();
2203 Persistent<Container> container = Container::create();
2205 clearOutOldGarbage(&initialHeapSize);
2207 Persistent<IntWrapper> one(IntWrapper::create(1));
2208 Persistent<IntWrapper> two(IntWrapper::create(2));
2209 Persistent<IntWrapper> oneB(IntWrapper::create(1));
2210 Persistent<IntWrapper> twoB(IntWrapper::create(2));
2211 Persistent<IntWrapper> oneC(IntWrapper::create(1));
2212 Persistent<IntWrapper> oneD(IntWrapper::create(1));
2213 Persistent<IntWrapper> oneE(IntWrapper::create(1));
2214 Persistent<IntWrapper> oneF(IntWrapper::create(1));
2216 IntWrapper* threeB(IntWrapper::create(3));
2217 IntWrapper* threeC(IntWrapper::create(3));
2218 IntWrapper* threeD(IntWrapper::create(3));
2219 IntWrapper* threeE(IntWrapper::create(3));
2220 IntWrapper* threeF(IntWrapper::create(3));
2221 IntWrapper* three(IntWrapper::create(3));
2222 IntWrapper* fourB(IntWrapper::create(4));
2223 IntWrapper* fourC(IntWrapper::create(4));
2224 IntWrapper* fourD(IntWrapper::create(4));
2225 IntWrapper* fourE(IntWrapper::create(4));
2226 IntWrapper* fourF(IntWrapper::create(4));
2227 IntWrapper* four(IntWrapper::create(4));
2228 IntWrapper* fiveC(IntWrapper::create(5));
2229 IntWrapper* fiveD(IntWrapper::create(5));
2230 IntWrapper* fiveE(IntWrapper::create(5));
2231 IntWrapper* fiveF(IntWrapper::create(5));
2233 // Member Collections.
2234 memberMember2->add(one, two);
2235 memberMember2->add(two, three);
2236 memberMember2->add(three, four);
2237 memberMember2->add(four, one);
2238 primitiveMember->add(1, two);
2239 primitiveMember->add(2, three);
2240 primitiveMember->add(3, four);
2241 primitiveMember->add(4, one);
2242 memberPrimitive->add(one, 2);
2243 memberPrimitive->add(two, 3);
2244 memberPrimitive->add(three, 4);
2245 memberPrimitive->add(four, 1);
2253 vector->append(oneB);
2254 deque->append(oneB);
2255 vector2->append(threeB);
2256 vector2->append(fourB);
2257 deque2->append(threeE);
2258 deque2->append(fourE);
2259 vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2260 dequeWU->append(PairWrappedUnwrapped(&*oneE, 42));
2261 vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2262 vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2263 vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2264 dequeWU2->append(PairWrappedUnwrapped(&*threeE, 43));
2265 dequeWU2->append(PairWrappedUnwrapped(&*fourE, 44));
2266 dequeWU2->append(PairWrappedUnwrapped(&*fiveE, 45));
2267 vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2268 vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2269 vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2270 vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2271 dequeUW->append(PairUnwrappedWrapped(1, &*oneF));
2272 dequeUW2->append(PairUnwrappedWrapped(103, &*threeF));
2273 dequeUW2->append(PairUnwrappedWrapped(104, &*fourF));
2274 dequeUW2->append(PairUnwrappedWrapped(105, &*fiveF));
2276 EXPECT_TRUE(dequeContains(*deque, oneB));
2278 // Collect garbage. This should change nothing since we are keeping
2279 // alive the IntWrapper objects with on-stack pointers.
2280 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2282 EXPECT_TRUE(dequeContains(*deque, oneB));
2284 EXPECT_EQ(0u, memberMember->size());
2285 EXPECT_EQ(4u, memberMember2->size());
2286 EXPECT_EQ(4u, primitiveMember->size());
2287 EXPECT_EQ(4u, memberPrimitive->size());
2288 EXPECT_EQ(1u, set->size());
2289 EXPECT_EQ(4u, set2->size());
2290 EXPECT_EQ(1u, set3->size());
2291 EXPECT_EQ(1u, vector->size());
2292 EXPECT_EQ(2u, vector2->size());
2293 EXPECT_EQ(1u, vectorWU->size());
2294 EXPECT_EQ(3u, vectorWU2->size());
2295 EXPECT_EQ(1u, vectorUW->size());
2296 EXPECT_EQ(3u, vectorUW2->size());
2297 EXPECT_EQ(1u, deque->size());
2298 EXPECT_EQ(2u, deque2->size());
2299 EXPECT_EQ(1u, dequeWU->size());
2300 EXPECT_EQ(3u, dequeWU2->size());
2301 EXPECT_EQ(1u, dequeUW->size());
2302 EXPECT_EQ(3u, dequeUW2->size());
2304 MemberVector& cvec = container->vector;
2305 cvec.swap(*vector.get());
2306 vector2->swap(cvec);
2309 VectorWU& cvecWU = container->vectorWU;
2310 cvecWU.swap(*vectorWU.get());
2311 vectorWU2->swap(cvecWU);
2312 vectorWU->swap(cvecWU);
2314 VectorUW& cvecUW = container->vectorUW;
2315 cvecUW.swap(*vectorUW.get());
2316 vectorUW2->swap(cvecUW);
2317 vectorUW->swap(cvecUW);
2319 MemberDeque& cDeque = container->deque;
2320 cDeque.swap(*deque.get());
2321 deque2->swap(cDeque);
2322 deque->swap(cDeque);
2324 DequeWU& cDequeWU = container->dequeWU;
2325 cDequeWU.swap(*dequeWU.get());
2326 dequeWU2->swap(cDequeWU);
2327 dequeWU->swap(cDequeWU);
2329 DequeUW& cDequeUW = container->dequeUW;
2330 cDequeUW.swap(*dequeUW.get());
2331 dequeUW2->swap(cDequeUW);
2332 dequeUW->swap(cDequeUW);
2334 // Swap set and set2 in a roundabout way.
2335 MemberSet& cset1 = container->set;
2336 MemberSet& cset2 = container->set2;
2343 MemberCountedSet& cCountedSet = container->set3;
2344 set3->swap(cCountedSet);
2345 EXPECT_EQ(0u, set3->size());
2346 set3->swap(cCountedSet);
2349 container->map.swap(memberMember2);
2350 MemberMember& containedMap = container->map;
2351 memberMember3->swap(containedMap);
2352 memberMember3->swap(memberMember);
2354 EXPECT_TRUE(memberMember->get(one) == two);
2355 EXPECT_TRUE(memberMember->get(two) == three);
2356 EXPECT_TRUE(memberMember->get(three) == four);
2357 EXPECT_TRUE(memberMember->get(four) == one);
2358 EXPECT_TRUE(primitiveMember->get(1) == two);
2359 EXPECT_TRUE(primitiveMember->get(2) == three);
2360 EXPECT_TRUE(primitiveMember->get(3) == four);
2361 EXPECT_TRUE(primitiveMember->get(4) == one);
2362 EXPECT_EQ(1, memberPrimitive->get(four));
2363 EXPECT_EQ(2, memberPrimitive->get(one));
2364 EXPECT_EQ(3, memberPrimitive->get(two));
2365 EXPECT_EQ(4, memberPrimitive->get(three));
2366 EXPECT_TRUE(set->contains(one));
2367 EXPECT_TRUE(set->contains(two));
2368 EXPECT_TRUE(set->contains(three));
2369 EXPECT_TRUE(set->contains(four));
2370 EXPECT_TRUE(set2->contains(oneB));
2371 EXPECT_TRUE(set3->contains(oneB));
2372 EXPECT_TRUE(vector->contains(threeB));
2373 EXPECT_TRUE(vector->contains(fourB));
2374 EXPECT_TRUE(dequeContains(*deque, threeE));
2375 EXPECT_TRUE(dequeContains(*deque, fourE));
2376 EXPECT_TRUE(vector2->contains(oneB));
2377 EXPECT_FALSE(vector2->contains(threeB));
2378 EXPECT_TRUE(dequeContains(*deque2, oneB));
2379 EXPECT_FALSE(dequeContains(*deque2, threeE));
2380 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2381 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2382 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2383 EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2384 EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2385 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2386 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2387 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2388 EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2389 EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2390 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*threeE, 43)));
2391 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fourE, 44)));
2392 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fiveE, 45)));
2393 EXPECT_TRUE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*oneE, 42)));
2394 EXPECT_FALSE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*threeE, 43)));
2395 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(103, &*threeF)));
2396 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(104, &*fourF)));
2397 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(105, &*fiveF)));
2398 EXPECT_TRUE(dequeContains(*dequeUW2, PairUnwrappedWrapped(1, &*oneF)));
2399 EXPECT_FALSE(dequeContains(*dequeUW2, PairUnwrappedWrapped(103, &*threeF)));
2402 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2404 EXPECT_EQ(4u, memberMember->size());
2405 EXPECT_EQ(0u, memberMember2->size());
2406 EXPECT_EQ(4u, primitiveMember->size());
2407 EXPECT_EQ(4u, memberPrimitive->size());
2408 EXPECT_EQ(4u, set->size());
2409 EXPECT_EQ(1u, set2->size());
2410 EXPECT_EQ(1u, set3->size());
2411 EXPECT_EQ(2u, vector->size());
2412 EXPECT_EQ(1u, vector2->size());
2413 EXPECT_EQ(3u, vectorUW->size());
2414 EXPECT_EQ(1u, vector2->size());
2415 EXPECT_EQ(2u, deque->size());
2416 EXPECT_EQ(1u, deque2->size());
2417 EXPECT_EQ(3u, dequeUW->size());
2418 EXPECT_EQ(1u, deque2->size());
2420 EXPECT_TRUE(memberMember->get(one) == two);
2421 EXPECT_TRUE(primitiveMember->get(1) == two);
2422 EXPECT_TRUE(primitiveMember->get(4) == one);
2423 EXPECT_EQ(2, memberPrimitive->get(one));
2424 EXPECT_EQ(3, memberPrimitive->get(two));
2425 EXPECT_TRUE(set->contains(one));
2426 EXPECT_TRUE(set->contains(two));
2427 EXPECT_FALSE(set->contains(oneB));
2428 EXPECT_TRUE(set2->contains(oneB));
2429 EXPECT_TRUE(set3->contains(oneB));
2430 EXPECT_EQ(2u, set3->find(oneB)->value);
2431 EXPECT_EQ(3, vector->at(0)->value());
2432 EXPECT_EQ(4, vector->at(1)->value());
2433 EXPECT_EQ(3, deque->begin()->get()->value());
2436 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2437 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2439 EXPECT_EQ(4u, memberMember->size());
2440 EXPECT_EQ(4u, primitiveMember->size());
2441 EXPECT_EQ(4u, memberPrimitive->size());
2442 EXPECT_EQ(4u, set->size());
2443 EXPECT_EQ(1u, set2->size());
2444 EXPECT_EQ(2u, vector->size());
2445 EXPECT_EQ(1u, vector2->size());
2446 EXPECT_EQ(3u, vectorWU->size());
2447 EXPECT_EQ(1u, vectorWU2->size());
2448 EXPECT_EQ(3u, vectorUW->size());
2449 EXPECT_EQ(1u, vectorUW2->size());
2450 EXPECT_EQ(2u, deque->size());
2451 EXPECT_EQ(1u, deque2->size());
2452 EXPECT_EQ(3u, dequeWU->size());
2453 EXPECT_EQ(1u, dequeWU2->size());
2454 EXPECT_EQ(3u, dequeUW->size());
2455 EXPECT_EQ(1u, dequeUW2->size());
2458 template<typename T>
2459 void MapIteratorCheck(T& it, const T& end, int expected)
2464 int key = it->key->value();
2465 int value = it->value->value();
2466 EXPECT_TRUE(key >= 0 && key < 1100);
2467 EXPECT_TRUE(value >= 0 && value < 1100);
2470 EXPECT_EQ(expected, found);
2473 template<typename T>
2474 void SetIteratorCheck(T& it, const T& end, int expected)
2479 int value = (*it)->value();
2480 EXPECT_TRUE(value >= 0 && value < 1100);
2483 EXPECT_EQ(expected, found);
2486 TEST(HeapTest, HeapWeakCollectionSimple)
2488 HeapStats initialHeapStats;
2489 clearOutOldGarbage(&initialHeapStats);
2490 IntWrapper::s_destructorCalls = 0;
2492 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2494 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2495 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2496 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2497 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2498 typedef HeapHashCountedSet<WeakMember<IntWrapper> > WeakCountedSet;
2500 Persistent<WeakStrong> weakStrong = new WeakStrong();
2501 Persistent<StrongWeak> strongWeak = new StrongWeak();
2502 Persistent<WeakWeak> weakWeak = new WeakWeak();
2503 Persistent<WeakSet> weakSet = new WeakSet();
2504 Persistent<WeakCountedSet> weakCountedSet = new WeakCountedSet();
2506 Persistent<IntWrapper> two = IntWrapper::create(2);
2508 keepNumbersAlive.append(IntWrapper::create(103));
2509 keepNumbersAlive.append(IntWrapper::create(10));
2512 weakStrong->add(IntWrapper::create(1), two);
2513 strongWeak->add(two, IntWrapper::create(1));
2514 weakWeak->add(two, IntWrapper::create(42));
2515 weakWeak->add(IntWrapper::create(42), two);
2516 weakSet->add(IntWrapper::create(0));
2518 weakSet->add(keepNumbersAlive[0]);
2519 weakSet->add(keepNumbersAlive[1]);
2520 weakCountedSet->add(IntWrapper::create(0));
2521 weakCountedSet->add(two);
2522 weakCountedSet->add(two);
2523 weakCountedSet->add(two);
2524 weakCountedSet->add(keepNumbersAlive[0]);
2525 weakCountedSet->add(keepNumbersAlive[1]);
2526 EXPECT_EQ(1u, weakStrong->size());
2527 EXPECT_EQ(1u, strongWeak->size());
2528 EXPECT_EQ(2u, weakWeak->size());
2529 EXPECT_EQ(4u, weakSet->size());
2530 EXPECT_EQ(4u, weakCountedSet->size());
2531 EXPECT_EQ(3u, weakCountedSet->find(two)->value);
2532 weakCountedSet->remove(two);
2533 EXPECT_EQ(2u, weakCountedSet->find(two)->value);
2536 keepNumbersAlive[0] = nullptr;
2538 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2540 EXPECT_EQ(0u, weakStrong->size());
2541 EXPECT_EQ(0u, strongWeak->size());
2542 EXPECT_EQ(0u, weakWeak->size());
2543 EXPECT_EQ(2u, weakSet->size());
2544 EXPECT_EQ(2u, weakCountedSet->size());
2547 template<typename Set>
2548 void orderedSetHelper(bool strong)
2550 HeapStats initialHeapStats;
2551 clearOutOldGarbage(&initialHeapStats);
2552 IntWrapper::s_destructorCalls = 0;
2554 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2556 Persistent<Set> set1 = new Set();
2557 Persistent<Set> set2 = new Set();
2559 const Set& constSet = *set1.get();
2561 keepNumbersAlive.append(IntWrapper::create(2));
2562 keepNumbersAlive.append(IntWrapper::create(103));
2563 keepNumbersAlive.append(IntWrapper::create(10));
2565 set1->add(IntWrapper::create(0));
2566 set1->add(keepNumbersAlive[0]);
2567 set1->add(keepNumbersAlive[1]);
2568 set1->add(keepNumbersAlive[2]);
2571 set2->add(IntWrapper::create(42));
2574 EXPECT_EQ(4u, set1->size());
2575 typename Set::iterator it(set1->begin());
2576 typename Set::reverse_iterator reverse(set1->rbegin());
2577 typename Set::const_iterator cit(constSet.begin());
2578 typename Set::const_reverse_iterator creverse(constSet.rbegin());
2580 EXPECT_EQ(0, (*it)->value());
2581 EXPECT_EQ(0, (*cit)->value());
2584 EXPECT_EQ(2, (*it)->value());
2585 EXPECT_EQ(2, (*cit)->value());
2588 EXPECT_EQ(0, (*it)->value());
2589 EXPECT_EQ(0, (*cit)->value());
2594 EXPECT_EQ(103, (*it)->value());
2595 EXPECT_EQ(103, (*cit)->value());
2598 EXPECT_EQ(10, (*it)->value());
2599 EXPECT_EQ(10, (*cit)->value());
2603 EXPECT_EQ(10, (*reverse)->value());
2604 EXPECT_EQ(10, (*creverse)->value());
2607 EXPECT_EQ(103, (*reverse)->value());
2608 EXPECT_EQ(103, (*creverse)->value());
2611 EXPECT_EQ(10, (*reverse)->value());
2612 EXPECT_EQ(10, (*creverse)->value());
2617 EXPECT_EQ(2, (*reverse)->value());
2618 EXPECT_EQ(2, (*creverse)->value());
2621 EXPECT_EQ(0, (*reverse)->value());
2622 EXPECT_EQ(0, (*creverse)->value());
2626 EXPECT_EQ(set1->end(), it);
2627 EXPECT_EQ(constSet.end(), cit);
2628 EXPECT_EQ(set1->rend(), reverse);
2629 EXPECT_EQ(constSet.rend(), creverse);
2631 typename Set::iterator iX(set2->begin());
2632 EXPECT_EQ(set2->end(), iX);
2635 set1->remove(keepNumbersAlive[0]);
2637 keepNumbersAlive[0] = nullptr;
2639 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2641 EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
2643 EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
2645 typename Set::iterator i2(set1->begin());
2647 EXPECT_EQ(0, (*i2)->value());
2649 EXPECT_NE(set1->end(), i2);
2651 EXPECT_EQ(103, (*i2)->value());
2653 EXPECT_NE(set1->end(), i2);
2654 EXPECT_EQ(10, (*i2)->value());
2656 EXPECT_EQ(set1->end(), i2);
2659 TEST(HeapTest, HeapWeakLinkedHashSet)
2661 orderedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
2662 orderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
2663 orderedSetHelper<HeapListHashSet<Member<IntWrapper> > >(true);
2666 class ThingWithDestructor {
2668 ThingWithDestructor()
2671 s_liveThingsWithDestructor++;
2674 ThingWithDestructor(int x)
2677 s_liveThingsWithDestructor++;
2680 ThingWithDestructor(const ThingWithDestructor&other)
2683 s_liveThingsWithDestructor++;
2686 ~ThingWithDestructor()
2688 s_liveThingsWithDestructor--;
2691 int value() { return m_x; }
2693 static int s_liveThingsWithDestructor;
2695 unsigned hash() { return IntHash<int>::hash(m_x); }
2698 static const int emptyValue = 0;
2702 int ThingWithDestructor::s_liveThingsWithDestructor;
2704 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2705 static const bool needsDestruction = true;
2708 static void heapMapDestructorHelper(bool clearMaps)
2710 HeapStats initialHeapStats;
2711 clearOutOldGarbage(&initialHeapStats);
2712 ThingWithDestructor::s_liveThingsWithDestructor = 0;
2714 typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageCollected> > RefMap;
2716 typedef HeapHashMap<
2717 WeakMember<IntWrapper>,
2718 ThingWithDestructor,
2719 DefaultHash<WeakMember<IntWrapper> >::Hash,
2720 HashTraits<WeakMember<IntWrapper> >,
2721 ThingWithDestructorTraits> Map;
2723 Persistent<Map> map(new Map());
2724 Persistent<RefMap> refMap(new RefMap());
2726 Persistent<IntWrapper> luck(IntWrapper::create(103));
2728 int baseLine, refBaseLine;
2734 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2735 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2737 stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2738 stackMap.add(luck, ThingWithDestructor(8128));
2739 stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2740 stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2742 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2743 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2745 // Although the heap maps are on-stack, we can't expect prompt
2746 // finalization of the elements, so when they go out of scope here we
2747 // will not necessarily have called the relevant destructors.
2750 // The RefCountedAndGarbageCollected things need an extra GC to discover
2751 // that they are no longer ref counted.
2752 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2753 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2754 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2755 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2757 // Now use maps kept alive with persistents. Here we don't expect any
2758 // destructors to be called before there have been GCs.
2760 map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2761 map->add(luck, ThingWithDestructor(8128));
2762 refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2763 refMap->add(luck, RefCountedAndGarbageCollected::create());
2765 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2766 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2770 map->clear(); // Clear map.
2771 refMap->clear(); // Clear map.
2773 map.clear(); // Clear Persistent handle, not map.
2774 refMap.clear(); // Clear Persistent handle, not map.
2775 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2776 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2779 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2781 // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2782 // noticies it's been decremented to zero.
2783 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2784 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2787 TEST(HeapTest, HeapMapDestructor)
2789 heapMapDestructorHelper(true);
2790 heapMapDestructorHelper(false);
2793 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2794 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2795 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2796 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2797 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
2798 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
2799 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
2800 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
2801 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
2802 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
2803 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
2804 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
2806 template<typename T>
2807 T& iteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair)
2812 template<typename T>
2813 T& iteratorExtractor(T& notAPair)
2818 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2820 Persistent<WSSet>& weakStrong,
2821 Persistent<SWSet>& strongWeak,
2822 Persistent<WUSet>& weakUnwrapped,
2823 Persistent<UWSet>& unwrappedWeak,
2825 Persistent<IntWrapper>& two)
2827 typename WSSet::iterator itWS = weakStrong->begin();
2828 typename SWSet::iterator itSW = strongWeak->begin();
2829 typename WUSet::iterator itWU = weakUnwrapped->begin();
2830 typename UWSet::iterator itUW = unwrappedWeak->begin();
2832 EXPECT_EQ(2u, weakStrong->size());
2833 EXPECT_EQ(2u, strongWeak->size());
2834 EXPECT_EQ(2u, weakUnwrapped->size());
2835 EXPECT_EQ(2u, unwrappedWeak->size());
2837 PairWeakStrong p = iteratorExtractor(*itWS);
2838 PairStrongWeak p2 = iteratorExtractor(*itSW);
2839 PairWeakUnwrapped p3 = iteratorExtractor(*itWU);
2840 PairUnwrappedWeak p4 = iteratorExtractor(*itUW);
2841 if (p.first == two && p.second == two)
2843 if (p2.first == two && p2.second == two)
2845 if (p3.first == two && p3.second == 2)
2847 if (p4.first == 2 && p4.second == two)
2849 p = iteratorExtractor(*itWS);
2850 p2 = iteratorExtractor(*itSW);
2851 p3 = iteratorExtractor(*itWU);
2852 p4 = iteratorExtractor(*itUW);
2853 IntWrapper* nullWrapper = 0;
2855 EXPECT_EQ(p.first->value(), 1);
2856 EXPECT_EQ(p2.second->value(), 1);
2857 EXPECT_EQ(p3.first->value(), 1);
2858 EXPECT_EQ(p4.second->value(), 1);
2860 EXPECT_EQ(p.first, nullWrapper);
2861 EXPECT_EQ(p2.second, nullWrapper);
2862 EXPECT_EQ(p3.first, nullWrapper);
2863 EXPECT_EQ(p4.second, nullWrapper);
2866 EXPECT_EQ(p.second->value(), 2);
2867 EXPECT_EQ(p2.first->value(), 2);
2868 EXPECT_EQ(p3.second, 2);
2869 EXPECT_EQ(p4.first, 2);
2871 EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2872 EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2873 EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2874 EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2877 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2878 void weakPairsHelper()
2880 IntWrapper::s_destructorCalls = 0;
2882 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2884 Persistent<WSSet> weakStrong = new WSSet();
2885 Persistent<SWSet> strongWeak = new SWSet();
2886 Persistent<WUSet> weakUnwrapped = new WUSet();
2887 Persistent<UWSet> unwrappedWeak = new UWSet();
2889 Persistent<IntWrapper> two = IntWrapper::create(2);
2891 weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2892 weakStrong->add(PairWeakStrong(&*two, &*two));
2893 strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2894 strongWeak->add(PairStrongWeak(&*two, &*two));
2895 weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2896 weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2897 unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2898 unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2900 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2902 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2903 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2906 TEST(HeapTest, HeapWeakPairs)
2909 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2910 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2911 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2912 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2913 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2917 typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
2918 typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2919 typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
2920 typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2921 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2925 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
2926 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2927 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
2928 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2929 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2933 TEST(HeapTest, HeapWeakCollectionTypes)
2935 HeapStats initialHeapSize;
2936 IntWrapper::s_destructorCalls = 0;
2938 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2939 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2940 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2941 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2942 typedef HeapLinkedHashSet<WeakMember<IntWrapper> > WeakOrderedSet;
2944 clearOutOldGarbage(&initialHeapSize);
2946 const int weakStrongIndex = 0;
2947 const int strongWeakIndex = 1;
2948 const int weakWeakIndex = 2;
2949 const int numberOfMapIndices = 3;
2950 const int weakSetIndex = 3;
2951 const int weakOrderedSetIndex = 4;
2952 const int numberOfCollections = 5;
2954 for (int testRun = 0; testRun < 4; testRun++) {
2955 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2956 bool deleteAfterwards = (testRun == 1);
2957 bool addAfterwards = (testRun == 2);
2958 bool testThatIteratorsMakeStrong = (testRun == 3);
2960 // The test doesn't work for strongWeak with deleting because we lost
2961 // the key from the keepNumbersAlive array, so we can't do the lookup.
2962 if (deleteAfterwards && collectionNumber == strongWeakIndex)
2965 unsigned added = addAfterwards ? 100 : 0;
2967 Persistent<WeakStrong> weakStrong = new WeakStrong();
2968 Persistent<StrongWeak> strongWeak = new StrongWeak();
2969 Persistent<WeakWeak> weakWeak = new WeakWeak();
2971 Persistent<WeakSet> weakSet = new WeakSet();
2972 Persistent<WeakOrderedSet> weakOrderedSet = new WeakOrderedSet();
2974 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2975 for (int i = 0; i < 128; i += 2) {
2976 IntWrapper* wrapped = IntWrapper::create(i);
2977 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
2978 keepNumbersAlive.append(wrapped);
2979 keepNumbersAlive.append(wrapped2);
2980 weakStrong->add(wrapped, wrapped2);
2981 strongWeak->add(wrapped2, wrapped);
2982 weakWeak->add(wrapped, wrapped2);
2983 weakSet->add(wrapped);
2984 weakOrderedSet->add(wrapped);
2987 EXPECT_EQ(64u, weakStrong->size());
2988 EXPECT_EQ(64u, strongWeak->size());
2989 EXPECT_EQ(64u, weakWeak->size());
2990 EXPECT_EQ(64u, weakSet->size());
2991 EXPECT_EQ(64u, weakOrderedSet->size());
2993 // Collect garbage. This should change nothing since we are keeping
2994 // alive the IntWrapper objects.
2995 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2997 EXPECT_EQ(64u, weakStrong->size());
2998 EXPECT_EQ(64u, strongWeak->size());
2999 EXPECT_EQ(64u, weakWeak->size());
3000 EXPECT_EQ(64u, weakSet->size());
3001 EXPECT_EQ(64u, weakOrderedSet->size());
3003 for (int i = 0; i < 128; i += 2) {
3004 IntWrapper* wrapped = keepNumbersAlive[i];
3005 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
3006 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
3007 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
3008 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
3009 EXPECT_TRUE(weakSet->contains(wrapped));
3010 EXPECT_TRUE(weakOrderedSet->contains(wrapped));
3013 for (int i = 0; i < 128; i += 3)
3014 keepNumbersAlive[i] = nullptr;
3016 if (collectionNumber != weakStrongIndex)
3017 weakStrong->clear();
3018 if (collectionNumber != strongWeakIndex)
3019 strongWeak->clear();
3020 if (collectionNumber != weakWeakIndex)
3022 if (collectionNumber != weakSetIndex)
3024 if (collectionNumber != weakOrderedSetIndex)
3025 weakOrderedSet->clear();
3027 if (testThatIteratorsMakeStrong) {
3028 WeakStrong::iterator it1 = weakStrong->begin();
3029 StrongWeak::iterator it2 = strongWeak->begin();
3030 WeakWeak::iterator it3 = weakWeak->begin();
3031 WeakSet::iterator it4 = weakSet->begin();
3032 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3033 // Collect garbage. This should change nothing since the
3034 // iterators make the collections strong.
3035 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3036 if (collectionNumber == weakStrongIndex) {
3037 EXPECT_EQ(64u, weakStrong->size());
3038 MapIteratorCheck(it1, weakStrong->end(), 64);
3039 } else if (collectionNumber == strongWeakIndex) {
3040 EXPECT_EQ(64u, strongWeak->size());
3041 MapIteratorCheck(it2, strongWeak->end(), 64);
3042 } else if (collectionNumber == weakWeakIndex) {
3043 EXPECT_EQ(64u, weakWeak->size());
3044 MapIteratorCheck(it3, weakWeak->end(), 64);
3045 } else if (collectionNumber == weakSetIndex) {
3046 EXPECT_EQ(64u, weakSet->size());
3047 SetIteratorCheck(it4, weakSet->end(), 64);
3048 } else if (collectionNumber == weakOrderedSetIndex) {
3049 EXPECT_EQ(64u, weakOrderedSet->size());
3050 SetIteratorCheck(it5, weakOrderedSet->end(), 64);
3053 // Collect garbage. This causes weak processing to remove
3054 // things from the collections.
3055 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3057 for (int i = 0; i < 128; i += 2) {
3058 bool firstAlive = keepNumbersAlive[i];
3059 bool secondAlive = keepNumbersAlive[i + 1];
3060 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
3062 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
3063 if (collectionNumber == weakStrongIndex) {
3064 if (deleteAfterwards)
3065 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
3066 } else if (collectionNumber == strongWeakIndex) {
3067 if (deleteAfterwards)
3068 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
3069 } else if (collectionNumber == weakWeakIndex) {
3070 if (deleteAfterwards)
3071 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
3073 if (!deleteAfterwards)
3075 } else if (collectionNumber == weakSetIndex && firstAlive) {
3076 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
3077 if (deleteAfterwards)
3078 weakSet->remove(keepNumbersAlive[i]);
3081 } else if (collectionNumber == weakOrderedSetIndex && firstAlive) {
3082 ASSERT_TRUE(weakOrderedSet->contains(keepNumbersAlive[i]));
3083 if (deleteAfterwards)
3084 weakOrderedSet->remove(keepNumbersAlive[i]);
3089 if (addAfterwards) {
3090 for (int i = 1000; i < 1100; i++) {
3091 IntWrapper* wrapped = IntWrapper::create(i);
3092 keepNumbersAlive.append(wrapped);
3093 weakStrong->add(wrapped, wrapped);
3094 strongWeak->add(wrapped, wrapped);
3095 weakWeak->add(wrapped, wrapped);
3096 weakSet->add(wrapped);
3097 weakOrderedSet->add(wrapped);
3100 if (collectionNumber == weakStrongIndex)
3101 EXPECT_EQ(count + added, weakStrong->size());
3102 else if (collectionNumber == strongWeakIndex)
3103 EXPECT_EQ(count + added, strongWeak->size());
3104 else if (collectionNumber == weakWeakIndex)
3105 EXPECT_EQ(count + added, weakWeak->size());
3106 else if (collectionNumber == weakSetIndex)
3107 EXPECT_EQ(count + added, weakSet->size());
3108 else if (collectionNumber == weakOrderedSetIndex)
3109 EXPECT_EQ(count + added, weakOrderedSet->size());
3110 WeakStrong::iterator it1 = weakStrong->begin();
3111 StrongWeak::iterator it2 = strongWeak->begin();
3112 WeakWeak::iterator it3 = weakWeak->begin();
3113 WeakSet::iterator it4 = weakSet->begin();
3114 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3115 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
3116 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
3117 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
3118 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
3119 SetIteratorCheck(it5, weakOrderedSet->end(), (collectionNumber == weakOrderedSetIndex ? count : 0) + added);
3121 for (unsigned i = 0; i < 128 + added; i++)
3122 keepNumbersAlive[i] = nullptr;
3123 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3124 EXPECT_EQ(0u, weakStrong->size());
3125 EXPECT_EQ(0u, strongWeak->size());
3126 EXPECT_EQ(0u, weakWeak->size());
3127 EXPECT_EQ(0u, weakSet->size());
3128 EXPECT_EQ(0u, weakOrderedSet->size());
3133 TEST(HeapTest, RefCountedGarbageCollected)
3135 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3137 RefPtr<RefCountedAndGarbageCollected> refPtr3;
3139 Persistent<RefCountedAndGarbageCollected> persistent;
3141 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
3142 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
3143 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3144 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3145 persistent = refPtr1.get();
3147 // Reference count is zero for both objects but one of
3148 // them is kept alive by a persistent handle.
3149 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3150 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3151 refPtr3 = persistent.get();
3153 // The persistent handle is gone but the ref count has been
3155 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3156 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3158 // Both persistent handle is gone and ref count is zero so the
3159 // object can be collected.
3160 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3161 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
3164 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
3166 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3167 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
3169 RefCountedAndGarbageCollected* pointer1 = 0;
3170 RefCountedAndGarbageCollected2* pointer2 = 0;
3172 RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
3173 RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
3174 pointer1 = object1.get();
3175 pointer2 = object2.get();
3176 void* objects[2] = { object1.get(), object2.get() };
3177 RefCountedGarbageCollectedVisitor visitor(2, objects);
3178 ThreadState::current()->visitPersistents(&visitor);
3179 EXPECT_TRUE(visitor.validate());
3181 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3182 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3183 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3185 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3186 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3187 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3189 // At this point, the reference counts of object1 and object2 are 0.
3190 // Only pointer1 and pointer2 keep references to object1 and object2.
3191 void* objects[] = { 0 };
3192 RefCountedGarbageCollectedVisitor visitor(0, objects);
3193 ThreadState::current()->visitPersistents(&visitor);
3194 EXPECT_TRUE(visitor.validate());
3197 RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
3198 RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
3199 void* objects[2] = { object1.get(), object2.get() };
3200 RefCountedGarbageCollectedVisitor visitor(2, objects);
3201 ThreadState::current()->visitPersistents(&visitor);
3202 EXPECT_TRUE(visitor.validate());
3204 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3205 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3206 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3209 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3210 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3211 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3214 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3215 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3216 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
3219 TEST(HeapTest, WeakMembers)
3223 Persistent<Bar> h1 = Bar::create();
3224 Persistent<Weak> h4;
3225 Persistent<WithWeakMember> h5;
3226 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3227 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
3229 Bar* h2 = Bar::create();
3230 Bar* h3 = Bar::create();
3231 h4 = Weak::create(h2, h3);
3232 h5 = WithWeakMember::create(h2, h3);
3233 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3234 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
3235 EXPECT_TRUE(h4->strongIsThere());
3236 EXPECT_TRUE(h4->weakIsThere());
3237 EXPECT_TRUE(h5->strongIsThere());
3238 EXPECT_TRUE(h5->weakIsThere());
3240 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3241 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3242 EXPECT_EQ(4u, Bar::s_live);
3243 EXPECT_TRUE(h4->strongIsThere());
3244 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
3245 EXPECT_TRUE(h5->strongIsThere());
3246 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
3247 h1.release(); // Zero out h1.
3248 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3249 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
3250 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
3251 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
3253 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3254 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3255 EXPECT_EQ(0u, Bar::s_live); // All gone.
3258 TEST(HeapTest, FinalizationObserver)
3260 Persistent<FinalizationObserver<Observable> > o;
3262 Observable* foo = Observable::create(Bar::create());
3263 // |o| observes |foo|.
3264 o = FinalizationObserver<Observable>::create(foo);
3266 // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3267 // and its member will be collected.
3268 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3269 EXPECT_EQ(0u, Bar::s_live);
3270 EXPECT_TRUE(o->didCallWillFinalize());
3272 FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
3273 Observable* foo = Observable::create(Bar::create());
3274 FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
3275 EXPECT_EQ(1u, map.size());
3277 // FinalizationObserverWithHashMap doesn't have a strong reference to
3278 // |foo|. So |foo| and its member will be collected.
3279 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3280 EXPECT_EQ(0u, Bar::s_live);
3281 EXPECT_EQ(0u, map.size());
3282 EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
3285 TEST(HeapTest, Comparisons)
3287 Persistent<Bar> barPersistent = Bar::create();
3288 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
3289 EXPECT_TRUE(barPersistent != fooPersistent);
3290 barPersistent = fooPersistent;
3291 EXPECT_TRUE(barPersistent == fooPersistent);
3294 TEST(HeapTest, CheckAndMarkPointer)
3296 HeapStats initialHeapStats;
3297 clearOutOldGarbage(&initialHeapStats);
3299 Vector<Address> objectAddresses;
3300 Vector<Address> endAddresses;
3301 Address largeObjectAddress;
3302 Address largeObjectEndAddress;
3303 CountingVisitor visitor;
3304 for (int i = 0; i < 10; i++) {
3305 SimpleObject* object = SimpleObject::create();
3306 Address objectAddress = reinterpret_cast<Address>(object);
3307 objectAddresses.append(objectAddress);
3308 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
3310 LargeObject* largeObject = LargeObject::create();
3311 largeObjectAddress = reinterpret_cast<Address>(largeObject);
3312 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
3314 // This is a low-level test where we call checkAndMarkPointer. This method
3315 // causes the object start bitmap to be computed which requires the heap
3316 // to be in a consistent state (e.g. the free allocation area must be put
3317 // into a free list header). However when we call makeConsistentForSweeping it
3318 // also clears out the freelists so we have to rebuild those before trying
3319 // to allocate anything again. We do this by forcing a GC after doing the
3320 // checkAndMarkPointer tests.
3322 TestGCScope scope(ThreadState::HeapPointersOnStack);
3323 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3324 Heap::makeConsistentForSweeping();
3325 for (size_t i = 0; i < objectAddresses.size(); i++) {
3326 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3327 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3329 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3331 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3332 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3333 EXPECT_EQ(2ul, visitor.count());
3336 // This forces a GC without stack scanning which results in the objects
3337 // being collected. This will also rebuild the above mentioned freelists,
3338 // however we don't rely on that below since we don't have any allocations.
3339 clearOutOldGarbage(&initialHeapStats);
3341 TestGCScope scope(ThreadState::HeapPointersOnStack);
3342 EXPECT_TRUE(scope.allThreadsParked());
3343 Heap::makeConsistentForSweeping();
3344 for (size_t i = 0; i < objectAddresses.size(); i++) {
3345 // We would like to assert that checkAndMarkPointer returned false
3346 // here because the pointers no longer point into a valid object
3347 // (it's been freed by the GCs. But checkAndMarkPointer will return
3348 // true for any pointer that points into a heap page, regardless of
3349 // whether it points at a valid object (this ensures the
3350 // correctness of the page-based on-heap address caches), so we
3351 // can't make that assert.
3352 Heap::checkAndMarkPointer(&visitor, objectAddresses[i]);
3353 Heap::checkAndMarkPointer(&visitor, endAddresses[i]);
3355 EXPECT_EQ(0ul, visitor.count());
3356 Heap::checkAndMarkPointer(&visitor, largeObjectAddress);
3357 Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress);
3358 EXPECT_EQ(0ul, visitor.count());
3360 // This round of GC is important to make sure that the object start
3361 // bitmap are cleared out and that the free lists are rebuild.
3362 clearOutOldGarbage(&initialHeapStats);
3365 TEST(HeapTest, VisitOffHeapCollections)
3367 HeapStats initialHeapStats;
3368 clearOutOldGarbage(&initialHeapStats);
3369 IntWrapper::s_destructorCalls = 0;
3370 Persistent<OffHeapContainer> container = OffHeapContainer::create();
3371 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3372 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3373 container = nullptr;
3374 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3375 EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
3378 TEST(HeapTest, PersistentHeapCollectionTypes)
3380 HeapStats initialHeapSize;
3381 IntWrapper::s_destructorCalls = 0;
3383 typedef HeapVector<Member<IntWrapper> > Vec;
3384 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
3385 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
3386 typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet;
3387 typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet;
3388 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
3389 typedef PersistentHeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakPMap;
3390 typedef PersistentHeapDeque<Member<IntWrapper> > PDeque;
3392 clearOutOldGarbage(&initialHeapSize);
3398 PLinkedSet pLinkedSet;
3402 IntWrapper* one(IntWrapper::create(1));
3403 IntWrapper* two(IntWrapper::create(2));
3404 IntWrapper* three(IntWrapper::create(3));
3405 IntWrapper* four(IntWrapper::create(4));
3406 IntWrapper* five(IntWrapper::create(5));
3407 IntWrapper* six(IntWrapper::create(6));
3408 IntWrapper* seven(IntWrapper::create(7));
3409 IntWrapper* eight(IntWrapper::create(8));
3410 IntWrapper* nine(IntWrapper::create(9));
3411 Persistent<IntWrapper> ten(IntWrapper::create(10));
3412 IntWrapper* eleven(IntWrapper::create(11));
3417 pDeque.append(seven);
3420 Vec* vec = new Vec();
3427 pListSet.add(eight);
3428 pLinkedSet.add(nine);
3429 pMap.add(five, six);
3430 wpMap.add(ten, eleven);
3432 // Collect |vec| and |one|.
3434 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3435 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3437 EXPECT_EQ(2u, pVec.size());
3438 EXPECT_EQ(two, pVec.at(0));
3439 EXPECT_EQ(three, pVec.at(1));
3441 EXPECT_EQ(2u, pDeque.size());
3442 EXPECT_EQ(seven, pDeque.first());
3443 EXPECT_EQ(seven, pDeque.takeFirst());
3444 EXPECT_EQ(two, pDeque.first());
3446 EXPECT_EQ(1u, pDeque.size());
3448 EXPECT_EQ(1u, pSet.size());
3449 EXPECT_TRUE(pSet.contains(four));
3451 EXPECT_EQ(1u, pListSet.size());
3452 EXPECT_TRUE(pListSet.contains(eight));
3454 EXPECT_EQ(1u, pLinkedSet.size());
3455 EXPECT_TRUE(pLinkedSet.contains(nine));
3457 EXPECT_EQ(1u, pMap.size());
3458 EXPECT_EQ(six, pMap.get(five));
3460 EXPECT_EQ(1u, wpMap.size());
3461 EXPECT_EQ(eleven, wpMap.get(ten));
3463 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3464 EXPECT_EQ(0u, wpMap.size());
3467 // Collect previous roots.
3468 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3469 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
3472 TEST(HeapTest, CollectionNesting)
3474 HeapStats initialStats;
3475 clearOutOldGarbage(&initialStats);
3476 int* key = &IntWrapper::s_destructorCalls;
3477 IntWrapper::s_destructorCalls = 0;
3478 typedef HeapVector<Member<IntWrapper> > IntVector;
3479 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3480 HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
3481 HeapHashMap<void*, IntDeque>* map2 = new HeapHashMap<void*, IntDeque>();
3483 map->add(key, IntVector());
3484 map2->add(key, IntDeque());
3486 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3487 EXPECT_EQ(0u, map->get(key).size());
3489 HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3490 EXPECT_EQ(0u, map2->get(key).size());
3492 it->value.append(IntWrapper::create(42));
3493 EXPECT_EQ(1u, map->get(key).size());
3495 it2->value.append(IntWrapper::create(42));
3496 EXPECT_EQ(1u, map2->get(key).size());
3498 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
3499 Persistent<HeapHashMap<void*, IntDeque> > keepAlive2(map2);
3501 for (int i = 0; i < 100; i++) {
3502 map->add(key + 1 + i, IntVector());
3503 map2->add(key + 1 + i, IntDeque());
3506 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3508 EXPECT_EQ(1u, map->get(key).size());
3509 EXPECT_EQ(1u, map2->get(key).size());
3510 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3512 keepAlive = nullptr;
3513 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3514 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3517 TEST(HeapTest, GarbageCollectedMixin)
3519 HeapStats initialHeapStats;
3520 clearOutOldGarbage(&initialHeapStats);
3522 Persistent<UseMixin> usemixin = UseMixin::create();
3523 EXPECT_EQ(0, UseMixin::s_traceCount);
3524 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3525 EXPECT_EQ(1, UseMixin::s_traceCount);
3527 Persistent<Mixin> mixin = usemixin;
3529 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3530 EXPECT_EQ(2, UseMixin::s_traceCount);
3532 PersistentHeapHashSet<WeakMember<Mixin> > weakMap;
3533 weakMap.add(UseMixin::create());
3534 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3535 EXPECT_EQ(0u, weakMap.size());
3538 TEST(HeapTest, CollectionNesting2)
3540 HeapStats initialStats;
3541 clearOutOldGarbage(&initialStats);
3542 void* key = &IntWrapper::s_destructorCalls;
3543 IntWrapper::s_destructorCalls = 0;
3544 typedef HeapHashSet<Member<IntWrapper> > IntSet;
3545 HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
3547 map->add(key, IntSet());
3549 HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3550 EXPECT_EQ(0u, map->get(key).size());
3552 it->value.add(IntWrapper::create(42));
3553 EXPECT_EQ(1u, map->get(key).size());
3555 Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
3556 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3557 EXPECT_EQ(1u, map->get(key).size());
3558 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3561 TEST(HeapTest, CollectionNesting3)
3563 HeapStats initialStats;
3564 clearOutOldGarbage(&initialStats);
3565 IntWrapper::s_destructorCalls = 0;
3566 typedef HeapVector<Member<IntWrapper> > IntVector;
3567 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3568 HeapVector<IntVector>* vector = new HeapVector<IntVector>();
3569 HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
3571 vector->append(IntVector());
3572 deque->append(IntDeque());
3574 HeapVector<IntVector>::iterator it = vector->begin();
3575 HeapDeque<IntDeque>::iterator it2 = deque->begin();
3576 EXPECT_EQ(0u, it->size());
3577 EXPECT_EQ(0u, it2->size());
3579 it->append(IntWrapper::create(42));
3580 it2->append(IntWrapper::create(42));
3581 EXPECT_EQ(1u, it->size());
3582 EXPECT_EQ(1u, it2->size());
3584 Persistent<HeapVector<IntVector> > keepAlive(vector);
3585 Persistent<HeapDeque<IntDeque> > keepAlive2(deque);
3586 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3587 EXPECT_EQ(1u, it->size());
3588 EXPECT_EQ(1u, it2->size());
3589 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3592 TEST(HeapTest, EmbeddedInVector)
3594 HeapStats initialStats;
3595 clearOutOldGarbage(&initialStats);
3596 SimpleFinalizedObject::s_destructorCalls = 0;
3598 PersistentHeapVector<VectorObject, 2> inlineVector;
3599 PersistentHeapVector<VectorObject> outlineVector;
3600 VectorObject i1, i2;
3601 inlineVector.append(i1);
3602 inlineVector.append(i2);
3604 VectorObject o1, o2;
3605 outlineVector.append(o1);
3606 outlineVector.append(o2);
3608 PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
3609 VectorObjectInheritedTrace it1, it2;
3610 vectorInheritedTrace.append(it1);
3611 vectorInheritedTrace.append(it2);
3613 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3614 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3616 // Since VectorObjectNoTrace has no trace method it will
3617 // not be traced and hence be collected when doing GC.
3618 // We trace items in a collection braced on the item's
3619 // having a trace method. This is determined via the
3620 // NeedsTracing trait in wtf/TypeTraits.h.
3621 PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
3622 VectorObjectNoTrace n1, n2;
3623 vectorNoTrace.append(n1);
3624 vectorNoTrace.append(n2);
3625 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3626 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3628 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3629 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3632 TEST(HeapTest, EmbeddedInDeque)
3634 HeapStats initialStats;
3635 clearOutOldGarbage(&initialStats);
3636 SimpleFinalizedObject::s_destructorCalls = 0;
3638 PersistentHeapDeque<VectorObject, 2> inlineDeque;
3639 PersistentHeapDeque<VectorObject> outlineDeque;
3640 VectorObject i1, i2;
3641 inlineDeque.append(i1);
3642 inlineDeque.append(i2);
3644 VectorObject o1, o2;
3645 outlineDeque.append(o1);
3646 outlineDeque.append(o2);
3648 PersistentHeapDeque<VectorObjectInheritedTrace> dequeInheritedTrace;
3649 VectorObjectInheritedTrace it1, it2;
3650 dequeInheritedTrace.append(it1);
3651 dequeInheritedTrace.append(it2);
3653 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3654 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3656 // Since VectorObjectNoTrace has no trace method it will
3657 // not be traced and hence be collected when doing GC.
3658 // We trace items in a collection braced on the item's
3659 // having a trace method. This is determined via the
3660 // NeedsTracing trait in wtf/TypeTraits.h.
3661 PersistentHeapDeque<VectorObjectNoTrace> dequeNoTrace;
3662 VectorObjectNoTrace n1, n2;
3663 dequeNoTrace.append(n1);
3664 dequeNoTrace.append(n2);
3665 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3666 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3668 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3669 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3672 template<typename Set>
3673 void rawPtrInHashHelper()
3676 set.add(new int(42));
3677 set.add(new int(42));
3678 EXPECT_EQ(2u, set.size());
3679 for (typename Set::iterator it = set.begin(); it != set.end(); ++it) {
3680 EXPECT_EQ(42, **it);
3685 TEST(HeapTest, RawPtrInHash)
3687 rawPtrInHashHelper<HashSet<RawPtr<int> > >();
3688 rawPtrInHashHelper<ListHashSet<RawPtr<int> > >();
3689 rawPtrInHashHelper<LinkedHashSet<RawPtr<int> > >();
3692 TEST(HeapTest, HeapTerminatedArray)
3694 HeapStats initialHeapSize;
3695 clearOutOldGarbage(&initialHeapSize);
3696 IntWrapper::s_destructorCalls = 0;
3698 HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
3700 const size_t prefixSize = 4;
3701 const size_t suffixSize = 4;
3704 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3705 builder.grow(prefixSize);
3706 for (size_t i = 0; i < prefixSize; i++)
3707 builder.append(TerminatedArrayItem(IntWrapper::create(i)));
3708 arr = builder.release();
3711 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3712 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3713 EXPECT_EQ(prefixSize, arr->size());
3714 for (size_t i = 0; i < prefixSize; i++)
3715 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3718 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3719 builder.grow(suffixSize);
3720 for (size_t i = 0; i < suffixSize; i++)
3721 builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
3722 arr = builder.release();
3725 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3726 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3727 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3728 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3729 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3732 Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3734 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3735 arr = persistentArr.get();
3736 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3737 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3738 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3739 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3743 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3744 EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3747 TEST(HeapTest, HeapLinkedStack)
3749 HeapStats initialHeapSize;
3750 clearOutOldGarbage(&initialHeapSize);
3751 IntWrapper::s_destructorCalls = 0;
3753 HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3755 const size_t stackSize = 10;
3757 for (size_t i = 0; i < stackSize; i++)
3758 stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3760 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3761 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3762 EXPECT_EQ(stackSize, stack->size());
3763 while (!stack->isEmpty()) {
3764 EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3768 Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3770 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3771 EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3772 EXPECT_EQ(0u, pStack->size());
3775 TEST(HeapTest, AllocationDuringFinalization)
3777 HeapStats initialHeapSize;
3778 clearOutOldGarbage(&initialHeapSize);
3779 IntWrapper::s_destructorCalls = 0;
3780 OneKiloByteObject::s_destructorCalls = 0;
3782 Persistent<IntWrapper> wrapper;
3783 new FinalizationAllocator(&wrapper);
3785 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3786 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3787 // Check that the wrapper allocated during finalization is not
3788 // swept away and zapped later in the same sweeping phase.
3789 EXPECT_EQ(42, wrapper->value());
3792 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3793 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3794 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3797 class SimpleClassWithDestructor {
3799 SimpleClassWithDestructor() { }
3800 ~SimpleClassWithDestructor()
3802 s_wasDestructed = true;
3804 static bool s_wasDestructed;
3807 bool SimpleClassWithDestructor::s_wasDestructed;
3809 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
3811 RefCountedWithDestructor() { }
3812 ~RefCountedWithDestructor()
3814 s_wasDestructed = true;
3816 static bool s_wasDestructed;
3819 bool RefCountedWithDestructor::s_wasDestructed;
3821 template<typename Set>
3822 void destructorsCalledOnGC(bool addLots)
3824 RefCountedWithDestructor::s_wasDestructed = false;
3827 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3828 set.add(adoptRef(hasDestructor));
3829 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3832 for (int i = 0; i < 1000; i++) {
3833 set.add(adoptRef(new RefCountedWithDestructor()));
3837 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3838 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3839 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3841 // The destructors of the sets don't call the destructors of the elements
3842 // in the heap sets. You have to actually remove the elments, call clear()
3843 // or have a GC to get the destructors called.
3844 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3845 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3846 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3849 template<typename Set>
3850 void destructorsCalledOnClear(bool addLots)
3852 RefCountedWithDestructor::s_wasDestructed = false;
3854 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3855 set.add(adoptRef(hasDestructor));
3856 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3859 for (int i = 0; i < 1000; i++) {
3860 set.add(adoptRef(new RefCountedWithDestructor()));
3864 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3866 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3869 TEST(HeapTest, DestructorsCalled)
3871 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3872 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3873 map.add(hasDestructor, adoptPtr(hasDestructor));
3874 SimpleClassWithDestructor::s_wasDestructed = false;
3876 EXPECT_TRUE(SimpleClassWithDestructor::s_wasDestructed);
3878 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3879 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3880 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3881 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3882 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3883 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3885 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3886 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3887 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3888 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3889 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3890 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3893 class MixinA : public GarbageCollectedMixin {
3895 MixinA() : m_obj(IntWrapper::create(100)) { }
3896 virtual void trace(Visitor* visitor)
3898 visitor->trace(m_obj);
3900 Member<IntWrapper> m_obj;
3903 class MixinB : public GarbageCollectedMixin {
3905 MixinB() : m_obj(IntWrapper::create(101)) { }
3906 virtual void trace(Visitor* visitor)
3908 visitor->trace(m_obj);
3910 Member<IntWrapper> m_obj;
3913 class MultipleMixins : public GarbageCollected<MultipleMixins>, public MixinA, public MixinB {
3914 USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
3916 MultipleMixins() : m_obj(IntWrapper::create(102)) { }
3917 virtual void trace(Visitor* visitor)
3919 visitor->trace(m_obj);
3920 MixinA::trace(visitor);
3921 MixinB::trace(visitor);
3923 Member<IntWrapper> m_obj;
3926 static const bool s_isMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
3927 static const bool s_isMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
3929 TEST(HeapTest, MultipleMixins)
3931 EXPECT_TRUE(s_isMixinTrue);
3932 EXPECT_FALSE(s_isMixinFalse);
3934 HeapStats initialHeapSize;
3935 clearOutOldGarbage(&initialHeapSize);
3936 IntWrapper::s_destructorCalls = 0;
3937 MultipleMixins* obj = new MultipleMixins();
3939 Persistent<MixinA> a = obj;
3940 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3941 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3944 Persistent<MixinB> b = obj;
3945 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3946 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3948 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3949 EXPECT_EQ(3, IntWrapper::s_destructorCalls);
3952 class GCParkingThreadTester {
3956 OwnPtr<WebThread> sleepingThread = adoptPtr(Platform::current()->createThread("SleepingThread"));
3957 sleepingThread->postTask(new Task(WTF::bind(sleeperMainFunc)));
3959 // Wait for the sleeper to run.
3960 while (!s_sleeperRunning) {
3961 Platform::current()->yieldCurrentThread();
3965 // Expect the first attempt to park the sleeping thread to fail
3966 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3967 EXPECT_FALSE(scope.allThreadsParked());
3970 s_sleeperDone = true;
3972 // Wait for the sleeper to finish.
3973 while (s_sleeperRunning) {
3974 // We enter the safepoint here since the sleeper thread will detach
3975 // causing it to GC.
3976 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
3977 Platform::current()->yieldCurrentThread();
3981 // Since the sleeper thread has detached this is the only thread.
3982 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3983 EXPECT_TRUE(scope.allThreadsParked());
3988 static void sleeperMainFunc()
3990 ThreadState::attach();
3991 s_sleeperRunning = true;
3993 // Simulate a long running op that is not entering a safepoint.
3994 while (!s_sleeperDone) {
3995 Platform::current()->yieldCurrentThread();
3998 ThreadState::detach();
3999 s_sleeperRunning = false;
4002 static volatile bool s_sleeperRunning;
4003 static volatile bool s_sleeperDone;
4006 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
4007 volatile bool GCParkingThreadTester::s_sleeperDone = false;
4009 TEST(HeapTest, GCParkingTimeout)
4011 GCParkingThreadTester::test();
4014 TEST(HeapTest, NeedsAdjustAndMark)
4016 // class Mixin : public GarbageCollectedMixin {};
4017 EXPECT_TRUE(NeedsAdjustAndMark<Mixin>::value);
4018 EXPECT_TRUE(NeedsAdjustAndMark<const Mixin>::value);
4020 // class SimpleObject : public GarbageCollected<SimpleObject> {};
4021 EXPECT_FALSE(NeedsAdjustAndMark<SimpleObject>::value);
4022 EXPECT_FALSE(NeedsAdjustAndMark<const SimpleObject>::value);
4024 // class UseMixin : public SimpleObject, public Mixin {};
4025 EXPECT_FALSE(NeedsAdjustAndMark<UseMixin>::value);
4026 EXPECT_FALSE(NeedsAdjustAndMark<const UseMixin>::value);
4029 template<typename Set>
4030 void setWithCustomWeaknessHandling()
4032 typedef typename Set::iterator Iterator;
4033 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4034 Persistent<Set> set1(new Set());
4037 Set* set3 = new Set();
4038 set2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4039 set3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4040 set1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4041 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4042 // The first set is pointed to from a persistent, so it's referenced, but
4043 // the weak processing may have taken place.
4045 Iterator i1 = set1->begin();
4046 EXPECT_EQ(4, i1->first->value());
4047 EXPECT_EQ(5, i1->second->value());
4049 // The second set is on-stack, so its backing store must be referenced from
4050 // the stack. That makes the weak references strong.
4051 Iterator i2 = set2.begin();
4052 EXPECT_EQ(0, i2->first->value());
4053 EXPECT_EQ(1, i2->second->value());
4054 // The third set is pointed to from the stack, so it's referenced, but the
4055 // weak processing may have taken place.
4057 Iterator i3 = set3->begin();
4058 EXPECT_EQ(2, i3->first->value());
4059 EXPECT_EQ(3, i3->second->value());
4062 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4063 EXPECT_EQ(0u, set1->size());
4064 set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt));
4065 set1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4066 set1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4067 set1->add(PairWithWeakHandling(livingInt, livingInt));
4068 set1->add(PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4069 EXPECT_EQ(4u, set1->size());
4070 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4071 EXPECT_EQ(2u, set1->size());
4072 Iterator i1 = set1->begin();
4073 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4074 EXPECT_EQ(livingInt, i1->second);
4076 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4077 EXPECT_EQ(livingInt, i1->second);
4080 TEST(HeapTest, SetWithCustomWeaknessHandling)
4082 setWithCustomWeaknessHandling<HeapHashSet<PairWithWeakHandling> >();
4083 setWithCustomWeaknessHandling<HeapLinkedHashSet<PairWithWeakHandling> >();
4086 TEST(HeapTest, MapWithCustomWeaknessHandling)
4088 typedef HeapHashMap<PairWithWeakHandling, RefPtr<OffHeapInt> > Map;
4089 typedef Map::iterator Iterator;
4090 HeapStats initialHeapSize;
4091 clearOutOldGarbage(&initialHeapSize);
4092 OffHeapInt::s_destructorCalls = 0;
4094 Persistent<Map> map1(new Map());
4095 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4098 Map* map3 = new Map();
4099 map2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)), OffHeapInt::create(1001));
4100 map3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)), OffHeapInt::create(1002));
4101 map1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)), OffHeapInt::create(1003));
4102 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4104 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4105 // The first map2 is pointed to from a persistent, so it's referenced, but
4106 // the weak processing may have taken place.
4108 Iterator i1 = map1->begin();
4109 EXPECT_EQ(4, i1->key.first->value());
4110 EXPECT_EQ(5, i1->key.second->value());
4111 EXPECT_EQ(1003, i1->value->value());
4113 // The second map2 is on-stack, so its backing store must be referenced from
4114 // the stack. That makes the weak references strong.
4115 Iterator i2 = map2.begin();
4116 EXPECT_EQ(0, i2->key.first->value());
4117 EXPECT_EQ(1, i2->key.second->value());
4118 EXPECT_EQ(1001, i2->value->value());
4119 // The third map2 is pointed to from the stack, so it's referenced, but the
4120 // weak processing may have taken place.
4122 Iterator i3 = map3->begin();
4123 EXPECT_EQ(2, i3->key.first->value());
4124 EXPECT_EQ(3, i3->key.second->value());
4125 EXPECT_EQ(1002, i3->value->value());
4128 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4130 EXPECT_EQ(0u, map1->size());
4131 EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4133 OffHeapInt::s_destructorCalls = 0;
4135 map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), OffHeapInt::create(2000));
4136 map1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103)), OffHeapInt::create(2001)); // This one gets zapped at GC time because nothing holds the 103 alive.
4137 map1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), OffHeapInt::create(2002)); // This one gets zapped too.
4138 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4139 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt);
4140 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); // This one is identical to the previous and doesn't add anything.
4143 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4144 EXPECT_EQ(4u, map1->size());
4145 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4146 EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4147 EXPECT_EQ(2u, map1->size());
4148 Iterator i1 = map1->begin();
4149 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4150 EXPECT_EQ(livingInt, i1->key.second);
4152 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4153 EXPECT_EQ(livingInt, i1->key.second);
4156 TEST(HeapTest, MapWithCustomWeaknessHandling2)
4158 typedef HeapHashMap<RefPtr<OffHeapInt>, PairWithWeakHandling> Map;
4159 typedef Map::iterator Iterator;
4160 HeapStats initialHeapSize;
4161 clearOutOldGarbage(&initialHeapSize);
4162 OffHeapInt::s_destructorCalls = 0;
4164 Persistent<Map> map1(new Map());
4165 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4169 Map* map3 = new Map();
4170 map2.add(OffHeapInt::create(1001), PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4171 map3->add(OffHeapInt::create(1002), PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4172 map1->add(OffHeapInt::create(1003), PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4173 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4175 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4176 // The first map2 is pointed to from a persistent, so it's referenced, but
4177 // the weak processing may have taken place.
4179 Iterator i1 = map1->begin();
4180 EXPECT_EQ(4, i1->value.first->value());
4181 EXPECT_EQ(5, i1->value.second->value());
4182 EXPECT_EQ(1003, i1->key->value());
4184 // The second map2 is on-stack, so its backing store must be referenced from
4185 // the stack. That makes the weak references strong.
4186 Iterator i2 = map2.begin();
4187 EXPECT_EQ(0, i2->value.first->value());
4188 EXPECT_EQ(1, i2->value.second->value());
4189 EXPECT_EQ(1001, i2->key->value());
4190 // The third map2 is pointed to from the stack, so it's referenced, but the
4191 // weak processing may have taken place.
4193 Iterator i3 = map3->begin();
4194 EXPECT_EQ(2, i3->value.first->value());
4195 EXPECT_EQ(3, i3->value.second->value());
4196 EXPECT_EQ(1002, i3->key->value());
4199 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4201 EXPECT_EQ(0u, map1->size());
4202 EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4204 OffHeapInt::s_destructorCalls = 0;
4206 map1->add(OffHeapInt::create(2000), PairWithWeakHandling(IntWrapper::create(103), livingInt));
4207 map1->add(OffHeapInt::create(2001), PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4208 map1->add(OffHeapInt::create(2002), PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4209 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4210 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt));
4211 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4214 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4215 EXPECT_EQ(4u, map1->size());
4216 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4217 EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4218 EXPECT_EQ(2u, map1->size());
4219 Iterator i1 = map1->begin();
4220 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4221 EXPECT_EQ(livingInt, i1->value.second);
4223 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4224 EXPECT_EQ(livingInt, i1->value.second);
4227 static void addElementsToWeakMap(HeapHashMap<int, WeakMember<IntWrapper> >* map)
4229 // Key cannot be zero in hashmap.
4230 for (int i = 1; i < 11; i++)
4231 map->add(i, IntWrapper::create(i));
4235 // If it doesn't assert a concurrent modification to the map, then it's passing.
4236 TEST(HeapTest, RegressNullIsStrongified)
4238 Persistent<HeapHashMap<int, WeakMember<IntWrapper> > > map = new HeapHashMap<int, WeakMember<IntWrapper> >();
4239 addElementsToWeakMap(map);
4240 HeapHashMap<int, WeakMember<IntWrapper> >::AddResult result = map->add(800, nullptr);
4241 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4242 result.storedValue->value = IntWrapper::create(42);
4245 TEST(HeapTest, Bind)
4247 Closure closure = bind(&Bar::trace, Bar::create(), static_cast<Visitor*>(0));
4248 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4249 // The closure should have a persistent handle to the Bar.
4250 EXPECT_EQ(1u, Bar::s_live);
4252 Closure closure2 = bind(&Bar::trace, RawPtr<Bar>(Bar::create()), static_cast<Visitor*>(0));
4253 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4254 // The closure should have a persistent handle to the Bar.
4255 EXPECT_EQ(2u, Bar::s_live);
4256 // RawPtr<OffHeapInt> should not make Persistent.
4257 Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHeapInt::create(1).get()));
4259 UseMixin::s_traceCount = 0;
4260 Mixin* mixin = UseMixin::create();
4261 Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0));
4262 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4263 // The closure should have a persistent handle to the mixin.
4264 EXPECT_EQ(1, UseMixin::s_traceCount);
4267 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
4269 // These special traits will remove a set from a map when the set is empty.
4270 struct EmptyClearingHashSetTraits : HashTraits<WeakSet> {
4271 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
4272 static bool traceInCollection(Visitor* visitor, WeakSet& set, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
4274 bool liveEntriesFound = false;
4275 WeakSet::iterator end = set.end();
4276 for (WeakSet::iterator it = set.begin(); it != end; ++it) {
4277 if (visitor->isAlive(*it)) {
4278 liveEntriesFound = true;
4282 // If there are live entries in the set then the set cannot be removed
4283 // from the map it is contained in, and we need to mark it (and its
4284 // backing) live. We just trace normally, which will invoke the normal
4285 // weak handling for any entries that are not live.
4286 if (liveEntriesFound)
4288 return !liveEntriesFound;
4292 // This is an example to show how you can remove entries from a T->WeakSet map
4293 // when the weak sets become empty. For this example we are using a type that
4294 // is given to use (HeapHashSet) rather than a type of our own. This means:
4295 // 1) We can't just override the HashTrait for the type since this would affect
4296 // all collections that use this kind of weak set. Instead we have our own
4297 // traits and use a map with custom traits for the value type. These traits
4298 // are the 5th template parameter, so we have to supply default values for
4299 // the 3rd and 4th template parameters
4300 // 2) We can't just inherit from WeakHandlingHashTraits, since that trait
4301 // assumes we can add methods to the type, but we can't add methods to
4303 TEST(HeapTest, RemoveEmptySets)
4305 HeapStats initialHeapSize;
4306 clearOutOldGarbage(&initialHeapSize);
4307 OffHeapInt::s_destructorCalls = 0;
4309 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4311 typedef RefPtr<OffHeapInt> Key;
4312 typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash, HashTraits<Key>, EmptyClearingHashSetTraits> Map;
4313 Persistent<Map> map(new Map());
4314 map->add(OffHeapInt::create(1), WeakSet());
4316 WeakSet& set = map->begin()->value;
4317 set.add(IntWrapper::create(103)); // Weak set can't hold this long.
4318 set.add(livingInt); // This prevents the set from being emptied.
4319 EXPECT_EQ(2u, set.size());
4322 // The set we add here is empty, so the entry will be removed from the map
4324 map->add(OffHeapInt::create(2), WeakSet());
4325 EXPECT_EQ(2u, map->size());
4327 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4328 EXPECT_EQ(1u, map->size()); // The one with key 2 was removed.
4329 EXPECT_EQ(1, OffHeapInt::s_destructorCalls);
4331 WeakSet& set = map->begin()->value;
4332 EXPECT_EQ(1u, set.size());
4335 livingInt.clear(); // The weak set can no longer keep the '42' alive now.
4336 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4337 EXPECT_EQ(0u, map->size());
4340 TEST(HeapTest, EphemeronsInEphemerons)
4342 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > InnerMap;
4343 typedef HeapHashMap<WeakMember<IntWrapper>, InnerMap> OuterMap;
4345 for (int keepOuterAlive = 0; keepOuterAlive <= 1; keepOuterAlive++) {
4346 for (int keepInnerAlive = 0; keepInnerAlive <=1; keepInnerAlive++) {
4347 Persistent<OuterMap> outer = new OuterMap();
4348 Persistent<IntWrapper> one = IntWrapper::create(1);
4349 Persistent<IntWrapper> two = IntWrapper::create(2);
4350 outer->add(one, InnerMap());
4351 outer->begin()->value.add(two, IntWrapper::create(3));
4352 EXPECT_EQ(1u, outer->get(one).size());
4353 if (!keepOuterAlive)
4355 if (!keepInnerAlive)
4357 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4358 if (keepOuterAlive) {
4359 const InnerMap& inner = outer->get(one);
4360 if (keepInnerAlive) {
4361 EXPECT_EQ(1u, inner.size());
4362 IntWrapper* three = inner.get(two);
4363 EXPECT_EQ(3, three->value());
4365 EXPECT_EQ(0u, inner.size());
4368 EXPECT_EQ(0u, outer->size());
4371 Persistent<IntWrapper> deep = IntWrapper::create(42);
4372 Persistent<IntWrapper> home = IntWrapper::create(103);
4373 Persistent<IntWrapper> composite = IntWrapper::create(91);
4374 Persistent<HeapVector<Member<IntWrapper> > > keepAlive = new HeapVector<Member<IntWrapper> >();
4375 for (int i = 0; i < 10000; i++) {
4376 IntWrapper* value = IntWrapper::create(i);
4377 keepAlive->append(value);
4378 OuterMap::AddResult newEntry = outer->add(value, InnerMap());
4379 newEntry.storedValue->value.add(deep, home);
4380 newEntry.storedValue->value.add(composite, home);
4383 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4384 EXPECT_EQ(10000u, outer->size());
4385 for (int i = 0; i < 10000; i++) {
4386 IntWrapper* value = keepAlive->at(i);
4387 EXPECT_EQ(1u, outer->get(value).size()); // Other one was deleted by weak handling.
4389 keepAlive->at(i) = nullptr;
4391 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4392 EXPECT_EQ(5000u, outer->size());
4397 class EphemeronWrapper : public GarbageCollected<EphemeronWrapper> {
4399 void trace(Visitor* visitor)
4401 visitor->trace(m_map);
4404 typedef HeapHashMap<WeakMember<IntWrapper>, Member<EphemeronWrapper> > Map;
4405 Map& map() { return m_map; }
4411 TEST(HeapTest, EphemeronsPointToEphemerons)
4413 Persistent<IntWrapper> key = IntWrapper::create(42);
4414 Persistent<IntWrapper> key2 = IntWrapper::create(103);
4416 Persistent<EphemeronWrapper> chain;
4417 for (int i = 0; i < 100; i++) {
4418 EphemeronWrapper* oldHead = chain;
4419 chain = new EphemeronWrapper();
4421 chain->map().add(key2, oldHead);
4423 chain->map().add(key, oldHead);
4424 chain->map().add(IntWrapper::create(103), new EphemeronWrapper());
4427 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4429 EphemeronWrapper* wrapper = chain;
4430 for (int i = 0; i< 100; i++) {
4431 EXPECT_EQ(1u, wrapper->map().size());
4433 wrapper = wrapper->map().get(key2);
4435 wrapper = wrapper->map().get(key);
4437 EXPECT_EQ(nullptr, wrapper);
4440 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4443 for (int i = 0; i < 50; i++) {
4444 EXPECT_EQ(i == 49 ? 0u : 1u, wrapper->map().size());
4445 wrapper = wrapper->map().get(key);
4447 EXPECT_EQ(nullptr, wrapper);
4450 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4451 EXPECT_EQ(0u, chain->map().size());
4454 TEST(HeapTest, Ephemeron)
4456 typedef HeapHashMap<WeakMember<IntWrapper>, PairWithWeakHandling> WeakPairMap;
4457 typedef HeapHashMap<PairWithWeakHandling, WeakMember<IntWrapper> > PairWeakMap;
4458 typedef HeapHashSet<WeakMember<IntWrapper> > Set;
4460 Persistent<WeakPairMap> weakPairMap = new WeakPairMap();
4461 Persistent<WeakPairMap> weakPairMap2 = new WeakPairMap();
4462 Persistent<WeakPairMap> weakPairMap3 = new WeakPairMap();
4463 Persistent<WeakPairMap> weakPairMap4 = new WeakPairMap();
4465 Persistent<PairWeakMap> pairWeakMap = new PairWeakMap();
4466 Persistent<PairWeakMap> pairWeakMap2 = new PairWeakMap();
4468 Persistent<Set> set = new Set();
4470 Persistent<IntWrapper> wp1 = IntWrapper::create(1);
4471 Persistent<IntWrapper> wp2 = IntWrapper::create(2);
4472 Persistent<IntWrapper> pw1 = IntWrapper::create(3);
4473 Persistent<IntWrapper> pw2 = IntWrapper::create(4);
4475 weakPairMap->add(wp1, PairWithWeakHandling(wp1, wp1));
4476 weakPairMap->add(wp2, PairWithWeakHandling(wp1, wp1));
4477 weakPairMap2->add(wp1, PairWithWeakHandling(wp1, wp2));
4478 weakPairMap2->add(wp2, PairWithWeakHandling(wp1, wp2));
4479 // The map from wp1 to (wp2, wp1) would mark wp2 live, so we skip that.
4480 weakPairMap3->add(wp2, PairWithWeakHandling(wp2, wp1));
4481 weakPairMap4->add(wp1, PairWithWeakHandling(wp2, wp2));
4482 weakPairMap4->add(wp2, PairWithWeakHandling(wp2, wp2));
4484 pairWeakMap->add(PairWithWeakHandling(pw1, pw1), pw1);
4485 pairWeakMap->add(PairWithWeakHandling(pw1, pw2), pw1);
4486 // The map from (pw2, pw1) to pw1 would make pw2 live, so we skip that.
4487 pairWeakMap->add(PairWithWeakHandling(pw2, pw2), pw1);
4488 pairWeakMap2->add(PairWithWeakHandling(pw1, pw1), pw2);
4489 pairWeakMap2->add(PairWithWeakHandling(pw1, pw2), pw2);
4490 pairWeakMap2->add(PairWithWeakHandling(pw2, pw1), pw2);
4491 pairWeakMap2->add(PairWithWeakHandling(pw2, pw2), pw2);
4499 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4501 EXPECT_EQ(2u, weakPairMap->size());
4502 EXPECT_EQ(2u, weakPairMap2->size());
4503 EXPECT_EQ(1u, weakPairMap3->size());
4504 EXPECT_EQ(2u, weakPairMap4->size());
4506 EXPECT_EQ(3u, pairWeakMap->size());
4507 EXPECT_EQ(4u, pairWeakMap2->size());
4509 EXPECT_EQ(4u, set->size());
4511 wp2.clear(); // Kills all entries in the weakPairMaps except the first.
4512 pw2.clear(); // Kills all entries in the pairWeakMaps except the first.
4514 for (int i = 0; i < 2; i++) {
4515 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4517 EXPECT_EQ(1u, weakPairMap->size());
4518 EXPECT_EQ(0u, weakPairMap2->size());
4519 EXPECT_EQ(0u, weakPairMap3->size());
4520 EXPECT_EQ(0u, weakPairMap4->size());
4522 EXPECT_EQ(1u, pairWeakMap->size());
4523 EXPECT_EQ(0u, pairWeakMap2->size());
4525 EXPECT_EQ(2u, set->size()); // wp1 and pw1.
4531 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4533 EXPECT_EQ(0u, weakPairMap->size());
4534 EXPECT_EQ(0u, pairWeakMap->size());
4535 EXPECT_EQ(0u, set->size());
4538 class Link1 : public GarbageCollected<Link1> {
4540 Link1(IntWrapper* link) : m_link(link) { }
4542 void trace(Visitor* visitor)
4544 visitor->trace(m_link);
4547 IntWrapper* link() { return m_link; }
4550 Member<IntWrapper> m_link;
4553 TEST(HeapTest, IndirectStrongToWeak)
4555 typedef HeapHashMap<WeakMember<IntWrapper>, Member<Link1> > Map;
4556 Persistent<Map> map = new Map();
4557 Persistent<IntWrapper> deadObject = IntWrapper::create(100); // Named for "Drowning by Numbers" (1988).
4558 Persistent<IntWrapper> lifeObject = IntWrapper::create(42);
4559 map->add(deadObject, new Link1(deadObject));
4560 map->add(lifeObject, new Link1(lifeObject));
4561 EXPECT_EQ(2u, map->size());
4562 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4563 EXPECT_EQ(2u, map->size());
4564 EXPECT_EQ(deadObject, map->get(deadObject)->link());
4565 EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4566 deadObject.clear(); // Now it can live up to its name.
4567 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4568 EXPECT_EQ(1u, map->size());
4569 EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4570 lifeObject.clear(); // Despite its name.
4571 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4572 EXPECT_EQ(0u, map->size());
4575 static Mutex& mainThreadMutex()
4577 AtomicallyInitializedStatic(Mutex&, mainMutex = *new Mutex);
4581 static ThreadCondition& mainThreadCondition()
4583 AtomicallyInitializedStatic(ThreadCondition&, mainCondition = *new ThreadCondition);
4584 return mainCondition;
4587 static void parkMainThread()
4589 mainThreadCondition().wait(mainThreadMutex());
4592 static void wakeMainThread()
4594 MutexLocker locker(mainThreadMutex());
4595 mainThreadCondition().signal();
4598 static Mutex& workerThreadMutex()
4600 AtomicallyInitializedStatic(Mutex&, workerMutex = *new Mutex);
4604 static ThreadCondition& workerThreadCondition()
4606 AtomicallyInitializedStatic(ThreadCondition&, workerCondition = *new ThreadCondition);
4607 return workerCondition;
4610 static void parkWorkerThread()
4612 workerThreadCondition().wait(workerThreadMutex());
4615 static void wakeWorkerThread()
4617 MutexLocker locker(workerThreadMutex());
4618 workerThreadCondition().signal();
4621 class CrossThreadObject : public GarbageCollectedFinalized<CrossThreadObject> {
4623 static CrossThreadObject* create(IntWrapper* workerObjectPointer)
4625 return new CrossThreadObject(workerObjectPointer);
4628 virtual ~CrossThreadObject()
4630 ++s_destructorCalls;
4633 static int s_destructorCalls;
4634 void trace(Visitor* visitor) { visitor->trace(m_workerObject); }
4637 CrossThreadObject(IntWrapper* workerObjectPointer) : m_workerObject(workerObjectPointer) { }
4640 Member<IntWrapper> m_workerObject;
4643 int CrossThreadObject::s_destructorCalls = 0;
4645 class CrossThreadPointerTester {
4649 CrossThreadObject::s_destructorCalls = 0;
4650 IntWrapper::s_destructorCalls = 0;
4652 MutexLocker locker(mainThreadMutex());
4653 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4654 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4658 uintptr_t stackPtrValue = 0;
4660 // Create an object with a pointer to the other heap's IntWrapper.
4661 Persistent<CrossThreadObject> cto = CrossThreadObject::create(const_cast<IntWrapper*>(s_workerObjectPointer));
4662 s_workerObjectPointer = 0;
4664 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4666 // Nothing should have been collected/destructed.
4667 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4668 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4670 // Put cto into a stack value. This is used to check that a conservative
4671 // GC succeeds even though we are tracing the other thread heap after
4672 // shutting it down.
4673 stackPtrValue = reinterpret_cast<uintptr_t>(cto.get());
4675 // At this point it is "programatically" okay to shut down the worker thread
4676 // since the cto object should be dead. However out stackPtrValue will cause a
4677 // trace of the object when doing a conservative GC.
4678 // The worker thread's thread local GC's should just add the worker thread's
4679 // pages to the heap after finalizing IntWrapper.
4682 // Wait for the worker to shutdown.
4685 // After the worker thread has detached it should have finalized the
4686 // IntWrapper object on its heaps. Since there has been no global GC
4687 // the cto object should not have been finalized.
4688 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4689 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4691 // Now do a conservative GC. The stackPtrValue should keep cto alive
4692 // and will also cause the orphaned page of the other thread to be
4693 // traced. At this point cto should still not be finalized.
4694 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4695 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4696 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4698 // This release assert is here to ensure the stackValuePtr is not
4699 // optimized away before doing the above conservative GC. If the
4700 // EXPECT_EQ(0, CrossThreadObject::s_destructorCalls) call above
4701 // starts failing it means we have to find a better way to ensure
4702 // the stackPtrValue is not optimized away.
4703 RELEASE_ASSERT(stackPtrValue);
4705 // Do a GC with no pointers on the stack to see the cto being collected.
4706 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4707 EXPECT_EQ(1, CrossThreadObject::s_destructorCalls);
4708 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4712 static void workerThreadMain()
4714 MutexLocker locker(workerThreadMutex());
4715 ThreadState::attach();
4718 // Create a worker object that is only kept alive by a cross thread
4719 // pointer (from CrossThreadObject).
4720 IntWrapper* workerObject = IntWrapper::create(42);
4721 s_workerObjectPointer = workerObject;
4724 // Wake up the main thread which is waiting for the worker to do its
4725 // allocation and passing the pointer.
4728 // Wait for main thread to signal the worker to shutdown.
4730 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4734 ThreadState::detach();
4736 // Tell the main thread the worker has done its shutdown.
4740 static volatile IntWrapper* s_workerObjectPointer;
4743 volatile IntWrapper* CrossThreadPointerTester::s_workerObjectPointer = 0;
4745 TEST(HeapTest, CrossThreadPointerToOrphanedPage)
4747 CrossThreadPointerTester::test();
4750 class DeadBitTester {
4754 IntWrapper::s_destructorCalls = 0;
4756 MutexLocker locker(mainThreadMutex());
4757 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4758 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4760 // Wait for the worker thread to have done its initialization,
4761 // IE. the worker allocates an object and then throw aways any
4765 // Now do a GC. This will not find the worker threads object since it
4766 // is not referred from any of the threads. Even a conservative
4767 // GC will not find it.
4768 // Also at this point the worker is waiting for the main thread
4769 // to be parked and will not do any sweep of its heap.
4770 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4772 // Since the worker thread is not sweeping the worker object should
4773 // not have been finalized.
4774 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4776 // Put the worker thread's object address on the stack and do a
4777 // conservative GC. This should find the worker object, but since
4778 // it was dead in the previous GC it should not be traced in this
4780 uintptr_t stackPtrValue = s_workerObjectPointer;
4781 s_workerObjectPointer = 0;
4782 ASSERT_UNUSED(stackPtrValue, stackPtrValue);
4783 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4785 // Since the worker thread is not sweeping the worker object should
4786 // not have been finalized.
4787 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4789 // Wake up the worker thread so it can continue with its sweeping.
4790 // This should finalized the worker object which we test below.
4791 // The worker thread will go back to sleep once sweeping to ensure
4792 // we don't have thread local GCs until after validating the destructor
4796 // Wait for the worker thread to sweep its heaps before checking.
4798 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4800 // Wake up the worker to allow it thread to continue with thread
4807 static void workerThreadMain()
4809 MutexLocker locker(workerThreadMutex());
4811 ThreadState::attach();
4814 // Create a worker object that is not kept alive except the
4815 // main thread will keep it as an integer value on its stack.
4816 IntWrapper* workerObject = IntWrapper::create(42);
4817 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject);
4820 // Signal the main thread that the worker is done with its allocation.
4824 // Wait for the main thread to do two GCs without sweeping this thread
4825 // heap. The worker waits within a safepoint, but there is no sweeping
4826 // until leaving the safepoint scope.
4827 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4831 // Wake up the main thread when done sweeping.
4834 // Wait with detach until the main thread says so. This is not strictly
4835 // necessary, but it means the worker thread will not do its thread local
4836 // GCs just yet, making it easier to reason about that no new GC has occurred
4837 // and the above sweep was the one finalizing the worker object.
4840 ThreadState::detach();
4843 static volatile uintptr_t s_workerObjectPointer;
4846 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0;
4848 TEST(HeapTest, ObjectDeadBit)
4850 DeadBitTester::test();
4853 class ThreadedStrongificationTester {
4857 IntWrapper::s_destructorCalls = 0;
4859 MutexLocker locker(mainThreadMutex());
4860 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4861 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4863 // Wait for the worker thread initialization. The worker
4864 // allocates a weak collection where both collection and
4865 // contents are kept alive via persistent pointers.
4868 // Perform two garbage collections where the worker thread does
4869 // not wake up in between. This will cause us to remove marks
4870 // and mark unmarked objects dead. The collection on the worker
4871 // heap is found through the persistent and the backing should
4873 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4874 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4876 // Wake up the worker thread so it can continue. It will sweep
4877 // and perform another GC where the backing store of its
4878 // collection should be strongified.
4881 // Wait for the worker thread to sweep its heaps before checking.
4883 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4890 static HeapHashSet<WeakMember<IntWrapper> >* allocateCollection()
4892 // Create a weak collection that is kept alive by a persistent
4893 // and keep the contents alive with a persistents as
4895 Persistent<IntWrapper> wrapper1 = IntWrapper::create(32);
4896 Persistent<IntWrapper> wrapper2 = IntWrapper::create(32);
4897 Persistent<IntWrapper> wrapper3 = IntWrapper::create(32);
4898 Persistent<IntWrapper> wrapper4 = IntWrapper::create(32);
4899 Persistent<IntWrapper> wrapper5 = IntWrapper::create(32);
4900 Persistent<IntWrapper> wrapper6 = IntWrapper::create(32);
4901 Persistent<HeapHashSet<WeakMember<IntWrapper> > > weakCollection = new HeapHashSet<WeakMember<IntWrapper> >;
4902 weakCollection->add(wrapper1);
4903 weakCollection->add(wrapper2);
4904 weakCollection->add(wrapper3);
4905 weakCollection->add(wrapper4);
4906 weakCollection->add(wrapper5);
4907 weakCollection->add(wrapper6);
4909 // Signal the main thread that the worker is done with its allocation.
4913 // Wait for the main thread to do two GCs without sweeping
4914 // this thread heap. The worker waits within a safepoint,
4915 // but there is no sweeping until leaving the safepoint
4916 // scope. If the weak collection backing is marked dead
4917 // because of this we will not get strongification in the
4918 // GC we force when we continue.
4919 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4923 return weakCollection;
4926 static void workerThreadMain()
4928 MutexLocker locker(workerThreadMutex());
4930 ThreadState::attach();
4933 Persistent<HeapHashSet<WeakMember<IntWrapper> > > collection = allocateCollection();
4935 // Prevent weak processing with an iterator and GC.
4936 HeapHashSet<WeakMember<IntWrapper> >::iterator it = collection->begin();
4937 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4939 // The backing should be strongified because of the iterator.
4940 EXPECT_EQ(6u, collection->size());
4941 EXPECT_EQ(32, (*it)->value());
4944 // Disregarding the iterator but keeping the collection alive
4945 // with a persistent should lead to weak processing.
4946 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4947 EXPECT_EQ(0u, collection->size());
4951 ThreadState::detach();
4954 static volatile uintptr_t s_workerObjectPointer;
4957 TEST(HeapTest, ThreadedStrongification)
4959 ThreadedStrongificationTester::test();
4962 static bool allocateAndReturnBool()
4964 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4968 class MixinWithGarbageCollectionInConstructor : public GarbageCollectedMixin {
4970 MixinWithGarbageCollectionInConstructor() : m_dummy(allocateAndReturnBool())
4977 class ClassWithGarbageCollectingMixinConstructor
4978 : public GarbageCollected<ClassWithGarbageCollectingMixinConstructor>
4979 , public MixinWithGarbageCollectionInConstructor {
4980 USING_GARBAGE_COLLECTED_MIXIN(ClassWithGarbageCollectingMixinConstructor);
4982 ClassWithGarbageCollectingMixinConstructor() : m_wrapper(IntWrapper::create(32))
4986 virtual void trace(Visitor* visitor)
4988 visitor->trace(m_wrapper);
4993 EXPECT_EQ(32, m_wrapper->value());
4997 Member<IntWrapper> m_wrapper;
5000 // Regression test for out of bounds call through vtable.
5001 // Passes if it doesn't crash.
5002 TEST(HeapTest, GarbageCollectionDuringMixinConstruction)
5004 ClassWithGarbageCollectingMixinConstructor* a =
5005 new ClassWithGarbageCollectingMixinConstructor();
5009 static RecursiveMutex& recursiveMutex()
5011 AtomicallyInitializedStatic(RecursiveMutex&, recursiveMutex = *new RecursiveMutex);
5012 return recursiveMutex;
5015 class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLockingObject> {
5017 static DestructorLockingObject* create()
5019 return new DestructorLockingObject();
5022 virtual ~DestructorLockingObject()
5024 SafePointAwareMutexLocker lock(recursiveMutex());
5025 ++s_destructorCalls;
5028 static int s_destructorCalls;
5029 void trace(Visitor* visitor) { }
5032 DestructorLockingObject() { }
5035 int DestructorLockingObject::s_destructorCalls = 0;
5037 class RecursiveLockingTester {
5041 DestructorLockingObject::s_destructorCalls = 0;
5043 MutexLocker locker(mainThreadMutex());
5044 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
5045 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
5047 // Park the main thread until the worker thread has initialized.
5051 SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
5053 // Let the worker try to acquire the above mutex. It won't get it
5054 // until the main thread has done its GC.
5057 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5059 // The worker thread should not have swept yet since it is waiting
5060 // to get the global mutex.
5061 EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
5063 // At this point the main thread releases the global lock and the worker
5064 // can acquire it and do its sweep of its heaps. Just wait for the worker
5065 // to complete its sweep and check the result.
5067 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
5071 static void workerThreadMain()
5073 MutexLocker locker(workerThreadMutex());
5074 ThreadState::attach();
5076 DestructorLockingObject* dlo = DestructorLockingObject::create();
5077 ASSERT_UNUSED(dlo, dlo);
5079 // Wake up the main thread which is waiting for the worker to do its
5083 // Wait for the main thread to get the global lock to ensure it has
5084 // it before the worker tries to acquire it. We want the worker to
5085 // block in the SafePointAwareMutexLocker until the main thread
5086 // has done a GC. The GC will not mark the "dlo" object since the worker
5087 // is entering the safepoint with NoHeapPointersOnStack. When the worker
5088 // subsequently gets the global lock and leaves the safepoint it will
5089 // sweep its heap and finalize "dlo". The destructor of "dlo" will try
5090 // to acquire the same global lock that the thread just got and deadlock
5091 // unless the global lock is recursive.
5093 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState::NoHeapPointersOnStack);
5095 // We won't get here unless the lock is recursive since the sweep done
5096 // in the constructor of SafePointAwareMutexLocker after
5097 // getting the lock will not complete given the "dlo" destructor is
5098 // waiting to get the same lock.
5099 // Tell the main thread the worker has done its sweep.
5102 ThreadState::detach();
5105 static volatile IntWrapper* s_workerObjectPointer;
5108 TEST(HeapTest, RecursiveMutex)
5110 RecursiveLockingTester::test();
5113 template<typename T>
5114 class TraceIfNeededTester : public GarbageCollectedFinalized<TraceIfNeededTester<T> > {
5116 static TraceIfNeededTester<T>* create() { return new TraceIfNeededTester<T>(); }
5117 static TraceIfNeededTester<T>* create(const T& obj) { return new TraceIfNeededTester<T>(obj); }
5118 void trace(Visitor* visitor) { TraceIfNeeded<T>::trace(visitor, &m_obj); }
5119 T& obj() { return m_obj; }
5120 ~TraceIfNeededTester() { }
5122 TraceIfNeededTester() { }
5123 explicit TraceIfNeededTester(const T& obj) : m_obj(obj) { }
5128 DISALLOW_ALLOCATION();
5130 PartObject() : m_obj(SimpleObject::create()) { }
5131 void trace(Visitor* visitor) { visitor->trace(m_obj); }
5133 Member<SimpleObject> m_obj;
5136 TEST(HeapTest, TraceIfNeeded)
5138 CountingVisitor visitor;
5141 TraceIfNeededTester<RefPtr<OffHeapInt> >* m_offHeap = TraceIfNeededTester<RefPtr<OffHeapInt> >::create(OffHeapInt::create(42));
5143 m_offHeap->trace(&visitor);
5144 EXPECT_EQ(0u, visitor.count());
5148 TraceIfNeededTester<PartObject>* m_part = TraceIfNeededTester<PartObject>::create();
5150 m_part->trace(&visitor);
5151 EXPECT_EQ(1u, visitor.count());
5155 TraceIfNeededTester<Member<SimpleObject> >* m_obj = TraceIfNeededTester<Member<SimpleObject> >::create(Member<SimpleObject>(SimpleObject::create()));
5157 m_obj->trace(&visitor);
5158 EXPECT_EQ(1u, visitor.count());
5162 TraceIfNeededTester<HeapVector<Member<SimpleObject> > >* m_vec = TraceIfNeededTester<HeapVector<Member<SimpleObject> > >::create();
5163 m_vec->obj().append(SimpleObject::create());
5165 m_vec->trace(&visitor);
5166 EXPECT_EQ(2u, visitor.count());
5170 class AllocatesOnAssignment {
5172 AllocatesOnAssignment(std::nullptr_t)
5175 AllocatesOnAssignment(int x)
5176 : m_value(new IntWrapper(x))
5178 AllocatesOnAssignment(IntWrapper* x)
5182 AllocatesOnAssignment& operator=(const AllocatesOnAssignment x)
5184 m_value = x.m_value;
5188 enum DeletedMarker {
5192 AllocatesOnAssignment(const AllocatesOnAssignment& other)
5194 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
5195 m_value = new IntWrapper(other.m_value->value());
5198 AllocatesOnAssignment(DeletedMarker)
5199 : m_value(reinterpret_cast<IntWrapper*>(-1)) { }
5201 inline bool isDeleted() const { return m_value == reinterpret_cast<IntWrapper*>(-1); }
5203 virtual void trace(Visitor* visitor)
5205 visitor->trace(m_value);
5208 int value() { return m_value->value(); }
5211 Member<IntWrapper> m_value;
5213 friend bool operator==(const AllocatesOnAssignment&, const AllocatesOnAssignment&);
5214 friend void swap(AllocatesOnAssignment&, AllocatesOnAssignment&);
5217 bool operator==(const AllocatesOnAssignment& a, const AllocatesOnAssignment& b)
5220 return b.m_value && a.m_value->value() == b.m_value->value();
5224 void swap(AllocatesOnAssignment& a, AllocatesOnAssignment& b)
5226 std::swap(a.m_value, b.m_value);
5229 struct DegenerateHash {
5230 static unsigned hash(const AllocatesOnAssignment&) { return 0; }
5231 static bool equal(const AllocatesOnAssignment& a, const AllocatesOnAssignment& b) { return !a.isDeleted() && a == b; }
5232 static const bool safeToCompareToEmptyOrDeleted = true;
5235 struct AllocatesOnAssignmentHashTraits : WTF::GenericHashTraits<AllocatesOnAssignment> {
5236 typedef AllocatesOnAssignment T;
5237 typedef std::nullptr_t EmptyValueType;
5238 static EmptyValueType emptyValue() { return nullptr; }
5239 static const bool emptyValueIsZero = false; // Can't be zero if it has a vtable.
5240 static const bool needsDestruction = false;
5241 static void constructDeletedValue(T& slot, bool) { slot = T(AllocatesOnAssignment::DeletedValue); }
5242 static bool isDeletedValue(const T& value) { return value.isDeleted(); }
5245 } // namespace blink
5249 template<> struct DefaultHash<blink::AllocatesOnAssignment> {
5250 typedef blink::DegenerateHash Hash;
5253 template <> struct HashTraits<blink::AllocatesOnAssignment> : blink::AllocatesOnAssignmentHashTraits { };
5259 TEST(HeapTest, GCInHashMapOperations)
5261 typedef HeapHashMap<AllocatesOnAssignment, AllocatesOnAssignment> Map;
5262 Map* map = new Map();
5263 IntWrapper* key = new IntWrapper(42);
5264 map->add(key, AllocatesOnAssignment(103));
5266 for (int i = 0; i < 10; i++)
5267 map->add(AllocatesOnAssignment(i), AllocatesOnAssignment(i));
5268 for (Map::iterator it = map->begin(); it != map->end(); ++it)
5269 EXPECT_EQ(it->key.value(), it->value.value());
5272 class PartObjectWithVirtualMethod {
5274 virtual void trace(Visitor*) { }
5277 class ObjectWithVirtualPartObject : public GarbageCollected<ObjectWithVirtualPartObject> {
5279 ObjectWithVirtualPartObject() : m_dummy(allocateAndReturnBool()) { }
5280 void trace(Visitor* visitor) { visitor->trace(m_part); }
5283 PartObjectWithVirtualMethod m_part;
5286 TEST(HeapTest, PartObjectWithVirtualMethod)
5288 ObjectWithVirtualPartObject* object = new ObjectWithVirtualPartObject();
5289 EXPECT_TRUE(object);
5292 class AllocInSuperConstructorArgumentSuper : public GarbageCollectedFinalized<AllocInSuperConstructorArgumentSuper> {
5294 AllocInSuperConstructorArgumentSuper(bool value) : m_value(value) { }
5295 virtual void trace(Visitor*) { }
5296 bool value() { return m_value; }
5301 class AllocInSuperConstructorArgument : public AllocInSuperConstructorArgumentSuper {
5303 AllocInSuperConstructorArgument()
5304 : AllocInSuperConstructorArgumentSuper(allocateAndReturnBool())
5309 // Regression test for crbug.com/404511. Tests conservative marking of
5310 // an object with an uninitialized vtable.
5311 TEST(HeapTest, AllocationInSuperConstructorArgument)
5313 AllocInSuperConstructorArgument* object = new AllocInSuperConstructorArgument();
5314 EXPECT_TRUE(object);
5315 Heap::collectAllGarbage();
5318 class NonNodeAllocatingNodeInDestructor : public GarbageCollectedFinalized<NonNodeAllocatingNodeInDestructor> {
5320 ~NonNodeAllocatingNodeInDestructor()
5322 s_node = new Persistent<Node>(Node::create(10));
5325 void trace(Visitor*) { }
5327 static Persistent<Node>* s_node;
5330 Persistent<Node>* NonNodeAllocatingNodeInDestructor::s_node = 0;
5332 TEST(HeapTest, NonNodeAllocatingNodeInDestructor)
5334 new NonNodeAllocatingNodeInDestructor();
5335 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5336 EXPECT_EQ(10, (*NonNodeAllocatingNodeInDestructor::s_node)->value());
5337 delete NonNodeAllocatingNodeInDestructor::s_node;
5338 NonNodeAllocatingNodeInDestructor::s_node = 0;
5341 } // namespace blink