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/heap/Handle.h"
34 #include "platform/heap/Heap.h"
35 #include "platform/heap/HeapLinkedStack.h"
36 #include "platform/heap/HeapTerminatedArrayBuilder.h"
37 #include "platform/heap/ThreadState.h"
38 #include "platform/heap/Visitor.h"
39 #include "public/platform/Platform.h"
40 #include "wtf/HashTraits.h"
41 #include "wtf/LinkedHashSet.h"
43 #include <gtest/gtest.h>
47 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
49 static IntWrapper* create(int x)
51 return new IntWrapper(x);
59 static int s_destructorCalls;
60 static void trace(Visitor*) { }
62 int value() const { return m_x; }
64 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
66 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) { 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) { 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 registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
268 virtual void registerWeakTable(const void*, EphemeronCallback, EphemeronCallback) OVERRIDE { }
270 virtual bool weakTableRegistered(const void*) OVERRIDE { return false; }
272 virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
273 virtual bool isMarked(const void*) OVERRIDE { return false; }
275 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
277 size_t count() { return m_count; }
278 void reset() { m_count = 0; }
284 class SimpleObject : public GarbageCollected<SimpleObject> {
286 static SimpleObject* create() { return new SimpleObject(); }
287 void trace(Visitor*) { }
288 char getPayload(int i) { return payload[i]; }
289 // This virtual method is unused but it is here to make sure
290 // that this object has a vtable. This object is used
291 // as the super class for objects that also have garbage
292 // collected mixins and having a virtual here makes sure
293 // that adjustment is needed both for marking and for isAlive
295 virtual void virtualMethod() { }
301 #undef DEFINE_VISITOR_METHODS
303 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
305 static HeapTestSuperClass* create()
307 return new HeapTestSuperClass();
310 virtual ~HeapTestSuperClass()
315 static int s_destructorCalls;
316 void trace(Visitor*) { }
319 HeapTestSuperClass() { }
322 int HeapTestSuperClass::s_destructorCalls = 0;
324 class HeapTestOtherSuperClass {
329 static const size_t classMagic = 0xABCDDBCA;
331 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
333 static HeapTestSubClass* create()
335 return new HeapTestSubClass();
338 virtual ~HeapTestSubClass()
340 EXPECT_EQ(classMagic, m_magic);
344 static int s_destructorCalls;
348 HeapTestSubClass() : m_magic(classMagic) { }
350 const size_t m_magic;
353 int HeapTestSubClass::s_destructorCalls = 0;
355 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
359 for (int i = 0; i < s_arraySize; ++i) {
360 m_array[i] = i % 128;
364 int8_t at(size_t i) { return m_array[i]; }
365 void trace(Visitor*) { }
367 static const int s_arraySize = 1000;
368 int8_t m_array[s_arraySize];
371 // Do several GCs to make sure that later GCs don't free up old memory from
372 // previously run tests in this process.
373 static void clearOutOldGarbage(HeapStats* heapStats)
376 getHeapStats(heapStats);
377 size_t used = heapStats->totalObjectSpace();
378 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
379 getHeapStats(heapStats);
380 if (heapStats->totalObjectSpace() >= used)
385 class OffHeapInt : public RefCounted<OffHeapInt> {
387 static RefPtr<OffHeapInt> create(int x)
389 return adoptRef(new OffHeapInt(x));
392 virtual ~OffHeapInt()
397 static int s_destructorCalls;
399 int value() const { return m_x; }
401 bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
403 unsigned hash() { return IntHash<int>::hash(m_x); }
404 void voidFunction() { }
407 OffHeapInt(int x) : m_x(x) { }
414 int IntWrapper::s_destructorCalls = 0;
415 int OffHeapInt::s_destructorCalls = 0;
417 class ThreadedTesterBase {
419 static void test(ThreadedTesterBase* tester)
421 for (int i = 0; i < numberOfThreads; i++)
422 createThread(&threadFunc, tester, "testing thread");
423 while (tester->m_threadsToFinish) {
424 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
430 virtual void runThread() = 0;
433 static const int numberOfThreads = 10;
434 static const int gcPerThread = 5;
435 static const int numberOfAllocations = 50;
437 ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
441 virtual ~ThreadedTesterBase()
445 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
447 volatile int m_gcCount;
448 volatile int m_threadsToFinish;
451 static void threadFunc(void* data)
453 reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
457 class ThreadedHeapTester : public ThreadedTesterBase {
461 ThreadedTesterBase::test(new ThreadedHeapTester);
465 virtual void runThread() OVERRIDE
467 ThreadState::attach();
471 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
473 Persistent<IntWrapper> wrapper;
475 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
476 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
478 for (int i = 0; i < numberOfAllocations; i++) {
479 wrapper = IntWrapper::create(0x0bbac0de);
481 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
483 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
487 if (gcCount < gcPerThread) {
488 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
490 atomicIncrement(&m_gcCount);
493 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
494 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
495 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
497 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
500 ThreadState::detach();
501 atomicDecrement(&m_threadsToFinish);
505 class ThreadedWeaknessTester : public ThreadedTesterBase {
509 ThreadedTesterBase::test(new ThreadedWeaknessTester);
513 virtual void runThread() OVERRIDE
515 ThreadState::attach();
519 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
521 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
522 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
524 for (int i = 0; i < numberOfAllocations; i++) {
525 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
526 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
527 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
531 if (gcCount < gcPerThread) {
532 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
534 atomicIncrement(&m_gcCount);
537 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
538 EXPECT_TRUE(weakMap->isEmpty());
539 EXPECT_TRUE(weakMap2.isEmpty());
541 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
544 ThreadState::detach();
545 atomicDecrement(&m_threadsToFinish);
549 // The accounting for memory includes the memory used by rounding up object
550 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
551 // have some slack in the tests.
553 void CheckWithSlack(T expected, T actual, int slack)
555 EXPECT_LE(expected, actual);
556 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
559 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
561 static TraceCounter* create()
563 return new TraceCounter();
566 void trace(Visitor*) { m_traceCount++; }
568 int traceCount() { return m_traceCount; }
579 class ClassWithMember : public GarbageCollected<ClassWithMember> {
581 static ClassWithMember* create()
583 return new ClassWithMember();
586 void trace(Visitor* visitor)
588 EXPECT_TRUE(visitor->isMarked(this));
590 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
592 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
594 visitor->trace(m_traceCounter);
597 int traceCount() { return m_traceCounter->traceCount(); }
601 : m_traceCounter(TraceCounter::create())
604 Member<TraceCounter> m_traceCounter;
607 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
609 static SimpleFinalizedObject* create()
611 return new SimpleFinalizedObject();
614 ~SimpleFinalizedObject()
619 static int s_destructorCalls;
621 void trace(Visitor*) { }
624 SimpleFinalizedObject() { }
627 int SimpleFinalizedObject::s_destructorCalls = 0;
629 class Node : public GarbageCollected<Node> {
631 static Node* create()
636 void trace(Visitor*) { }
642 class Bar : public GarbageCollectedFinalized<Bar> {
649 void finalizeGarbageCollectedObject()
651 EXPECT_TRUE(m_magic == magic);
655 bool hasBeenFinalized() const { return !m_magic; }
657 virtual void trace(Visitor* visitor) { }
658 static unsigned s_live;
661 static const int magic = 1337;
671 unsigned Bar::s_live = 0;
673 class Baz : public GarbageCollected<Baz> {
675 static Baz* create(Bar* bar)
680 void trace(Visitor* visitor)
682 visitor->trace(m_bar);
685 void clear() { m_bar.release(); }
687 // willFinalize is called by FinalizationObserver.
690 EXPECT_TRUE(!m_bar->hasBeenFinalized());
694 explicit Baz(Bar* bar)
702 class Foo : public Bar {
704 static Foo* create(Bar* bar)
709 static Foo* create(Foo* foo)
714 virtual void trace(Visitor* visitor) OVERRIDE
717 visitor->mark(static_cast<Foo*>(m_bar));
719 visitor->mark(m_bar);
726 , m_pointsToFoo(false)
733 , m_pointsToFoo(true)
741 class Bars : public Bar {
743 static Bars* create()
748 virtual void trace(Visitor* visitor) OVERRIDE
750 for (unsigned i = 0; i < m_width; i++)
751 visitor->trace(m_bars[i]);
754 unsigned getWidth() const
759 static const unsigned width = 7500;
763 for (unsigned i = 0; i < width; i++) {
764 m_bars[i] = Bar::create();
770 Member<Bar> m_bars[width];
773 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
775 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
777 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
780 ConstructorAllocation()
782 m_intWrapper = IntWrapper::create(42);
785 Member<IntWrapper> m_intWrapper;
788 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
794 static LargeObject* create() { return new LargeObject(); }
795 char get(size_t i) { return m_data[i]; }
796 void set(size_t i, char c) { m_data[i] = c; }
797 size_t length() { return s_length; }
798 void trace(Visitor* visitor)
800 visitor->trace(m_intWrapper);
802 static int s_destructorCalls;
805 static const size_t s_length = 1024*1024;
808 m_intWrapper = IntWrapper::create(23);
810 Member<IntWrapper> m_intWrapper;
811 char m_data[s_length];
814 int LargeObject::s_destructorCalls = 0;
816 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
818 static PassRefPtr<RefCountedAndGarbageCollected> create()
820 return adoptRef(new RefCountedAndGarbageCollected());
823 ~RefCountedAndGarbageCollected()
828 // These are here with their default implementations so you can break in
829 // them in the debugger.
830 void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref(); }
831 void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::deref(); }
833 void trace(Visitor*) { }
835 static int s_destructorCalls;
838 RefCountedAndGarbageCollected()
843 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
845 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
847 static RefCountedAndGarbageCollected2* create()
849 return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
852 ~RefCountedAndGarbageCollected2()
857 void trace(Visitor*) { }
859 static int s_destructorCalls;
862 RefCountedAndGarbageCollected2()
867 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
869 #define DEFINE_VISITOR_METHODS(Type) \
870 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
875 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
877 RefCountedGarbageCollectedVisitor(int expected, void** objects)
879 , m_expectedCount(expected)
880 , m_expectedObjects(objects)
884 void mark(const void* ptr) { markNoTrace(ptr); }
886 virtual void markNoTrace(const void* ptr)
890 if (m_count < m_expectedCount)
891 EXPECT_TRUE(expectedObject(ptr));
893 EXPECT_FALSE(expectedObject(ptr));
897 virtual void mark(const void* ptr, TraceCallback) OVERRIDE
902 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
904 mark(header->payload());
907 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
909 mark(header->payload());
912 bool validate() { return m_count >= m_expectedCount; }
913 void reset() { m_count = 0; }
915 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
918 bool expectedObject(const void* ptr)
920 for (int i = 0; i < m_expectedCount; i++) {
921 if (m_expectedObjects[i] == ptr)
929 void** m_expectedObjects;
932 #undef DEFINE_VISITOR_METHODS
934 class Weak : public Bar {
936 static Weak* create(Bar* strong, Bar* weak)
938 return new Weak(strong, weak);
941 virtual void trace(Visitor* visitor) OVERRIDE
943 visitor->trace(m_strongBar);
944 visitor->registerWeakMembers(this, zapWeakMembers);
947 static void zapWeakMembers(Visitor* visitor, void* self)
949 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
952 bool strongIsThere() { return !!m_strongBar; }
953 bool weakIsThere() { return !!m_weakBar; }
956 Weak(Bar* strongBar, Bar* weakBar)
958 , m_strongBar(strongBar)
963 void zapWeakMembers(Visitor* visitor)
965 if (!visitor->isAlive(m_weakBar))
969 Member<Bar> m_strongBar;
973 class WithWeakMember : public Bar {
975 static WithWeakMember* create(Bar* strong, Bar* weak)
977 return new WithWeakMember(strong, weak);
980 virtual void trace(Visitor* visitor) OVERRIDE
982 visitor->trace(m_strongBar);
983 visitor->trace(m_weakBar);
986 bool strongIsThere() { return !!m_strongBar; }
987 bool weakIsThere() { return !!m_weakBar; }
990 WithWeakMember(Bar* strongBar, Bar* weakBar)
992 , m_strongBar(strongBar)
997 Member<Bar> m_strongBar;
998 WeakMember<Bar> m_weakBar;
1001 class Observable : public GarbageCollectedFinalized<Observable> {
1003 static Observable* create(Bar* bar) { return new Observable(bar); }
1004 ~Observable() { m_wasDestructed = true; }
1005 void trace(Visitor* visitor) { visitor->trace(m_bar); }
1007 // willFinalize is called by FinalizationObserver. willFinalize can touch
1008 // other on-heap objects.
1011 EXPECT_FALSE(m_wasDestructed);
1012 EXPECT_FALSE(m_bar->hasBeenFinalized());
1016 explicit Observable(Bar* bar)
1018 , m_wasDestructed(false)
1023 bool m_wasDestructed;
1026 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
1028 static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
1029 bool didCallWillFinalize() const { return m_didCallWillFinalize; }
1031 void trace(Visitor* visitor)
1033 visitor->registerWeakMembers(this, zapWeakMembers);
1037 FinalizationObserver(T* data)
1039 , m_didCallWillFinalize(false)
1043 static void zapWeakMembers(Visitor* visitor, void* self)
1045 FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
1046 if (o->m_data && !visitor->isAlive(o->m_data)) {
1047 o->m_data->willFinalize();
1048 o->m_data = nullptr;
1049 o->m_didCallWillFinalize = true;
1053 WeakMember<T> m_data;
1054 bool m_didCallWillFinalize;
1057 class FinalizationObserverWithHashMap {
1059 typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
1061 explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
1062 ~FinalizationObserverWithHashMap()
1064 m_target.willFinalize();
1065 s_didCallWillFinalize = true;
1068 static ObserverMap& observe(Observable& target)
1070 ObserverMap& map = observers();
1071 ObserverMap::AddResult result = map.add(&target, nullptr);
1072 if (result.isNewEntry)
1073 result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
1075 ASSERT(result.storedValue->value);
1079 static bool s_didCallWillFinalize;
1082 static ObserverMap& observers()
1084 DEFINE_STATIC_LOCAL(Persistent<ObserverMap>, observerMap, ());
1086 observerMap = new ObserverMap();
1087 return *observerMap;
1090 Observable& m_target;
1093 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
1097 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
1099 static PassRefPtrWillBeRawPtr<PointsBack> create()
1101 return adoptRefWillBeNoop(new PointsBack());
1109 void setBackPointer(SuperClass* backPointer)
1111 m_backPointer = backPointer;
1114 SuperClass* backPointer() const { return m_backPointer; }
1116 void trace(Visitor* visitor)
1119 visitor->trace(m_backPointer);
1123 static int s_aliveCount;
1125 PointsBack() : m_backPointer(nullptr)
1130 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1133 int PointsBack::s_aliveCount = 0;
1135 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1137 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1139 return adoptRefWillBeNoop(new SuperClass(pointsBack));
1142 virtual ~SuperClass()
1145 m_pointsBack->setBackPointer(0);
1150 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1152 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1153 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1154 EXPECT_EQ(pointsBack, target->pointsBack());
1155 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1158 virtual void trace(Visitor* visitor)
1161 visitor->trace(m_pointsBack);
1165 PointsBack* pointsBack() const { return m_pointsBack.get(); }
1167 static int s_aliveCount;
1169 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1170 : m_pointsBack(pointsBack)
1172 m_pointsBack->setBackPointer(this);
1177 RefPtrWillBeMember<PointsBack> m_pointsBack;
1180 int SuperClass::s_aliveCount = 0;
1181 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1183 SubData() { ++s_aliveCount; }
1184 ~SubData() { --s_aliveCount; }
1186 void trace(Visitor*) { }
1188 static int s_aliveCount;
1191 int SubData::s_aliveCount = 0;
1193 class SubClass : public SuperClass {
1195 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1197 return adoptRefWillBeNoop(new SubClass(pointsBack));
1205 virtual void trace(Visitor* visitor)
1208 SuperClass::trace(visitor);
1209 visitor->trace(m_data);
1213 static int s_aliveCount;
1215 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1216 : SuperClass(pointsBack)
1217 , m_data(adoptPtrWillBeNoop(new SubData()))
1223 OwnPtrWillBeMember<SubData> m_data;
1226 int SubClass::s_aliveCount = 0;
1228 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1230 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1232 return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
1235 ~TransitionRefCounted()
1240 void trace(Visitor* visitor) { }
1242 static int s_aliveCount;
1245 TransitionRefCounted()
1251 int TransitionRefCounted::s_aliveCount = 0;
1253 class Mixin : public GarbageCollectedMixin {
1255 virtual void trace(Visitor* visitor) { }
1257 virtual char getPayload(int i) { return m_padding[i]; }
1263 class UseMixin : public SimpleObject, public Mixin {
1264 USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1266 static UseMixin* create()
1268 return new UseMixin();
1271 static int s_traceCount;
1272 virtual void trace(Visitor* visitor)
1274 SimpleObject::trace(visitor);
1275 Mixin::trace(visitor);
1286 int UseMixin::s_traceCount = 0;
1288 class VectorObject {
1289 ALLOW_ONLY_INLINE_ALLOCATION();
1293 m_value = SimpleFinalizedObject::create();
1296 void trace(Visitor* visitor)
1298 visitor->trace(m_value);
1302 Member<SimpleFinalizedObject> m_value;
1305 class VectorObjectInheritedTrace : public VectorObject { };
1307 class VectorObjectNoTrace {
1308 ALLOW_ONLY_INLINE_ALLOCATION();
1310 VectorObjectNoTrace()
1312 m_value = SimpleFinalizedObject::create();
1316 Member<SimpleFinalizedObject> m_value;
1319 class TerminatedArrayItem {
1320 ALLOW_ONLY_INLINE_ALLOCATION();
1322 TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1324 void trace(Visitor* visitor) { visitor->trace(m_payload); }
1326 bool isLastInArray() const { return m_isLast; }
1327 void setLastInArray(bool value) { m_isLast = value; }
1329 IntWrapper* payload() const { return m_payload; }
1332 Member<IntWrapper> m_payload;
1336 } // namespace blink
1338 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObject);
1339 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectInheritedTrace);
1340 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectNoTrace);
1344 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1346 ~OneKiloByteObject() { s_destructorCalls++; }
1347 char* data() { return m_data; }
1348 void trace(Visitor* visitor) { }
1349 static int s_destructorCalls;
1352 static const size_t s_length = 1024;
1353 char m_data[s_length];
1356 int OneKiloByteObject::s_destructorCalls = 0;
1358 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1360 static DynamicallySizedObject* create(size_t size)
1362 void* slot = Heap::allocate<DynamicallySizedObject>(size);
1363 return new (slot) DynamicallySizedObject();
1366 void* operator new(std::size_t, void* location)
1373 return *(reinterpret_cast<uint8_t*>(this) + i);
1376 void trace(Visitor*) { }
1379 DynamicallySizedObject() { }
1382 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1384 FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1385 : m_wrapper(wrapper)
1389 ~FinalizationAllocator()
1391 for (int i = 0; i < 10; ++i)
1392 *m_wrapper = IntWrapper::create(42);
1393 for (int i = 0; i < 512; ++i)
1394 new OneKiloByteObject();
1397 void trace(Visitor*) { }
1400 Persistent<IntWrapper>* m_wrapper;
1403 TEST(HeapTest, Transition)
1406 RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1407 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1408 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1409 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1411 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1412 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1414 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1415 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1416 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1417 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1418 EXPECT_EQ(2, PointsBack::s_aliveCount);
1419 EXPECT_EQ(2, SuperClass::s_aliveCount);
1420 EXPECT_EQ(1, SubClass::s_aliveCount);
1421 EXPECT_EQ(1, SubData::s_aliveCount);
1423 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1424 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
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 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1431 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1432 EXPECT_EQ(2, PointsBack::s_aliveCount);
1433 EXPECT_EQ(1, SuperClass::s_aliveCount);
1434 EXPECT_EQ(1, SubClass::s_aliveCount);
1435 EXPECT_EQ(1, SubData::s_aliveCount);
1436 EXPECT_EQ(0, pointsBack1->backPointer());
1438 pointsBack1.release();
1439 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1440 EXPECT_EQ(1, PointsBack::s_aliveCount);
1441 EXPECT_EQ(1, SuperClass::s_aliveCount);
1442 EXPECT_EQ(1, SubClass::s_aliveCount);
1443 EXPECT_EQ(1, SubData::s_aliveCount);
1445 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1446 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1447 EXPECT_EQ(1, PointsBack::s_aliveCount);
1448 EXPECT_EQ(0, SuperClass::s_aliveCount);
1449 EXPECT_EQ(0, SubClass::s_aliveCount);
1450 EXPECT_EQ(0, SubData::s_aliveCount);
1451 EXPECT_EQ(0, pointsBack2->backPointer());
1453 pointsBack2.release();
1454 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1455 EXPECT_EQ(0, PointsBack::s_aliveCount);
1456 EXPECT_EQ(0, SuperClass::s_aliveCount);
1457 EXPECT_EQ(0, SubClass::s_aliveCount);
1458 EXPECT_EQ(0, SubData::s_aliveCount);
1460 EXPECT_TRUE(superClass == subClass);
1463 TEST(HeapTest, Threading)
1465 ThreadedHeapTester::test();
1468 TEST(HeapTest, ThreadedWeakness)
1470 ThreadedWeaknessTester::test();
1473 TEST(HeapTest, BasicFunctionality)
1475 HeapStats heapStats;
1476 clearOutOldGarbage(&heapStats);
1480 // When the test starts there may already have been leaked some memory
1481 // on the heap, so we establish a base line.
1482 size_t baseLevel = heapStats.totalObjectSpace();
1483 bool testPagesAllocated = !baseLevel;
1484 if (testPagesAllocated)
1485 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1487 // This allocates objects on the general heap which should add a page of memory.
1488 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1490 memset(alloc32, 40, 32);
1491 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1493 memset(alloc64, 27, 64);
1497 getHeapStats(&heapStats);
1498 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1499 if (testPagesAllocated)
1500 EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1502 CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
1504 EXPECT_EQ(alloc32->get(0), 40);
1505 EXPECT_EQ(alloc32->get(31), 40);
1506 EXPECT_EQ(alloc64->get(0), 27);
1507 EXPECT_EQ(alloc64->get(63), 27);
1509 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
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);
1517 clearOutOldGarbage(&heapStats);
1520 size_t baseLevel = heapStats.totalObjectSpace();
1521 bool testPagesAllocated = !baseLevel;
1522 if (testPagesAllocated)
1523 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1526 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1530 size_t persistentCount = 0;
1531 const size_t numPersistents = 100000;
1532 Persistent<DynamicallySizedObject>* persistents[numPersistents];
1534 for (int i = 0; i < 1000; i++) {
1535 size_t size = 128 + i * 8;
1537 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1539 getHeapStats(&heapStats);
1540 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1541 if (testPagesAllocated)
1542 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1546 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1548 memset(alloc32b, 40, 32);
1549 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1551 memset(alloc64b, 27, 64);
1552 EXPECT_TRUE(alloc32b != alloc64b);
1555 getHeapStats(&heapStats);
1556 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1557 if (testPagesAllocated)
1558 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1561 clearOutOldGarbage(&heapStats);
1564 if (testPagesAllocated)
1565 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1567 DynamicallySizedObject* bigAreaRaw = bigArea;
1568 // Clear the persistent, so that the big area will be garbage collected.
1570 clearOutOldGarbage(&heapStats);
1574 getHeapStats(&heapStats);
1575 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1576 if (testPagesAllocated)
1577 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1579 // Endless loop unless we eventually get the memory back that we just freed.
1581 Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
1583 persistents[persistentCount++] = alloc;
1584 EXPECT_LT(persistentCount, numPersistents);
1586 if (bigAreaRaw == alloc->get())
1590 getHeapStats(&heapStats);
1591 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1592 if (testPagesAllocated)
1593 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1595 for (size_t i = 0; i < persistentCount; i++) {
1596 delete persistents[i];
1600 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1601 for (int i = 0; i < 100; i++)
1603 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1604 for (int i = 0; i < 100; i++)
1605 EXPECT_EQ(address[i], i);
1606 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1607 for (int i = 0; i < 50; i++)
1608 EXPECT_EQ(address[i], i);
1609 // This should be equivalent to free(address).
1610 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1611 // This should be equivalent to malloc(0).
1612 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1615 TEST(HeapTest, SimpleAllocation)
1617 HeapStats initialHeapStats;
1618 clearOutOldGarbage(&initialHeapStats);
1619 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1621 // Allocate an object in the heap.
1622 HeapAllocatedArray* array = new HeapAllocatedArray();
1623 HeapStats statsAfterAllocation;
1624 getHeapStats(&statsAfterAllocation);
1625 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1627 // Sanity check of the contents in the heap.
1628 EXPECT_EQ(0, array->at(0));
1629 EXPECT_EQ(42, array->at(42));
1630 EXPECT_EQ(0, array->at(128));
1631 EXPECT_EQ(999 % 128, array->at(999));
1634 TEST(HeapTest, SimplePersistent)
1636 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1637 EXPECT_EQ(0, traceCounter->traceCount());
1639 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1640 EXPECT_EQ(1, traceCounter->traceCount());
1642 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1643 EXPECT_EQ(0, classWithMember->traceCount());
1645 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1646 EXPECT_EQ(1, classWithMember->traceCount());
1647 EXPECT_EQ(2, traceCounter->traceCount());
1650 TEST(HeapTest, SimpleFinalization)
1653 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1654 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1655 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1656 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1659 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1660 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1663 TEST(HeapTest, Finalization)
1666 HeapTestSubClass* t1 = HeapTestSubClass::create();
1667 HeapTestSubClass* t2 = HeapTestSubClass::create();
1668 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1669 // FIXME(oilpan): Ignore unused variables.
1674 // Nothing is marked so the GC should free everything and call
1675 // the finalizer on all three objects.
1676 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1677 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1678 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1679 // Destructors not called again when GCing again.
1680 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1681 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1682 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1685 TEST(HeapTest, TypedHeapSanity)
1687 // We use TraceCounter for allocating an object on the general heap.
1688 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1689 Persistent<Node> typedHeapObject = Node::create();
1690 EXPECT_NE(pageHeaderFromObject(generalHeapObject.get()),
1691 pageHeaderFromObject(typedHeapObject.get()));
1694 TEST(HeapTest, NoAllocation)
1696 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1698 // Disallow allocation
1699 NoAllocationScope<AnyThread> noAllocationScope;
1700 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1702 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1705 TEST(HeapTest, Members)
1712 h1 = Baz::create(Bar::create());
1713 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1714 EXPECT_EQ(1u, Bar::s_live);
1715 h2 = Baz::create(Bar::create());
1716 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1717 EXPECT_EQ(2u, Bar::s_live);
1719 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1720 EXPECT_EQ(2u, Bar::s_live);
1722 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1723 EXPECT_EQ(1u, Bar::s_live);
1725 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1726 EXPECT_EQ(0u, Bar::s_live);
1729 TEST(HeapTest, MarkTest)
1733 Persistent<Bar> bar = Bar::create();
1734 EXPECT_TRUE(ThreadState::current()->contains(bar));
1735 EXPECT_EQ(1u, Bar::s_live);
1737 Foo* foo = Foo::create(bar);
1738 EXPECT_TRUE(ThreadState::current()->contains(foo));
1739 EXPECT_EQ(2u, Bar::s_live);
1740 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1741 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1742 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1743 EXPECT_EQ(2u, Bar::s_live);
1745 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1746 EXPECT_EQ(1u, Bar::s_live);
1748 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1749 EXPECT_EQ(0u, Bar::s_live);
1752 TEST(HeapTest, DeepTest)
1754 const unsigned depth = 100000;
1757 Bar* bar = Bar::create();
1758 EXPECT_TRUE(ThreadState::current()->contains(bar));
1759 Foo* foo = Foo::create(bar);
1760 EXPECT_TRUE(ThreadState::current()->contains(foo));
1761 EXPECT_EQ(2u, Bar::s_live);
1762 for (unsigned i = 0; i < depth; i++) {
1763 Foo* foo2 = Foo::create(foo);
1765 EXPECT_TRUE(ThreadState::current()->contains(foo));
1767 EXPECT_EQ(depth + 2, Bar::s_live);
1768 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1769 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1770 EXPECT_EQ(depth + 2, Bar::s_live);
1772 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1773 EXPECT_EQ(0u, Bar::s_live);
1776 TEST(HeapTest, WideTest)
1780 Bars* bars = Bars::create();
1781 unsigned width = Bars::width;
1782 EXPECT_EQ(width + 1, Bar::s_live);
1783 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1784 EXPECT_EQ(width + 1, Bar::s_live);
1785 // Use bars here to make sure that it will be on the stack
1786 // for the conservative stack scan to find.
1787 EXPECT_EQ(width, bars->getWidth());
1789 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1790 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1791 EXPECT_EQ(0u, Bar::s_live);
1794 TEST(HeapTest, HashMapOfMembers)
1796 HeapStats initialHeapSize;
1797 IntWrapper::s_destructorCalls = 0;
1799 clearOutOldGarbage(&initialHeapSize);
1801 typedef HeapHashMap<
1804 DefaultHash<Member<IntWrapper> >::Hash,
1805 HashTraits<Member<IntWrapper> >,
1806 HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1808 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1811 HeapStats afterSetWasCreated;
1812 getHeapStats(&afterSetWasCreated);
1813 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1815 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1817 getHeapStats(&afterGC);
1818 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1820 // If the additions below cause garbage collections, these
1821 // pointers should be found by conservative stack scanning.
1822 IntWrapper* one(IntWrapper::create(1));
1823 IntWrapper* anotherOne(IntWrapper::create(1));
1827 HeapStats afterOneAdd;
1828 getHeapStats(&afterOneAdd);
1829 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1831 HeapObjectIdentityMap::iterator it(map->begin());
1832 HeapObjectIdentityMap::iterator it2(map->begin());
1836 map->add(anotherOne, one);
1838 // The addition above can cause an allocation of a new
1839 // backing store. We therefore garbage collect before
1840 // taking the heap stats in order to get rid of the old
1841 // backing store. We make sure to not use conservative
1842 // stack scanning as that could find a pointer to the
1844 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1845 HeapStats afterAddAndGC;
1846 getHeapStats(&afterAddAndGC);
1847 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1849 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1851 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1852 EXPECT_TRUE(map->contains(one));
1853 EXPECT_TRUE(map->contains(anotherOne));
1855 IntWrapper* gotten(map->get(one));
1856 EXPECT_EQ(gotten->value(), one->value());
1857 EXPECT_EQ(gotten, one);
1860 getHeapStats(&afterGC2);
1861 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1863 IntWrapper* dozen = 0;
1865 for (int i = 1; i < 1000; i++) { // 999 iterations.
1866 IntWrapper* iWrapper(IntWrapper::create(i));
1867 IntWrapper* iSquared(IntWrapper::create(i * i));
1868 map->add(iWrapper, iSquared);
1872 HeapStats afterAdding1000;
1873 getHeapStats(&afterAdding1000);
1874 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1876 IntWrapper* gross(map->get(dozen));
1877 EXPECT_EQ(gross->value(), 144);
1879 // This should clear out junk created by all the adds.
1880 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1882 getHeapStats(&afterGC3);
1883 EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1886 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1887 // The objects 'one', anotherOne, and the 999 other pairs.
1888 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1890 getHeapStats(&afterGC4);
1891 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1894 TEST(HeapTest, NestedAllocation)
1896 HeapStats initialHeapSize;
1897 clearOutOldGarbage(&initialHeapSize);
1899 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1901 HeapStats afterFree;
1902 clearOutOldGarbage(&afterFree);
1903 EXPECT_TRUE(initialHeapSize == afterFree);
1906 TEST(HeapTest, LargeObjects)
1908 HeapStats initialHeapSize;
1909 clearOutOldGarbage(&initialHeapSize);
1910 IntWrapper::s_destructorCalls = 0;
1911 LargeObject::s_destructorCalls = 0;
1913 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1914 Persistent<LargeObject> object = LargeObject::create();
1915 EXPECT_TRUE(ThreadState::current()->contains(object));
1916 EXPECT_TRUE(ThreadState::current()->contains(reinterpret_cast<char*>(object.get()) + sizeof(LargeObject) - 1));
1917 #if ENABLE(GC_PROFILE_MARKING)
1918 const GCInfo* info = ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()));
1919 EXPECT_NE(reinterpret_cast<const GCInfo*>(0), info);
1920 EXPECT_EQ(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject) - 1));
1921 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject)));
1922 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) - 1));
1924 HeapStats afterAllocation;
1925 clearOutOldGarbage(&afterAllocation);
1927 object->set(0, 'a');
1928 EXPECT_EQ('a', object->get(0));
1929 object->set(object->length() - 1, 'b');
1930 EXPECT_EQ('b', object->get(object->length() - 1));
1931 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1932 size_t actualObjectSpace =
1933 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1934 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1935 // There is probably space for the IntWrapper in a heap page without
1936 // allocating extra pages. However, the IntWrapper allocation might cause
1937 // the addition of a heap page.
1938 size_t largeObjectAllocationSize =
1939 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1940 size_t allocatedSpaceLowerBound =
1941 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1942 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1943 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1944 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1945 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1946 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1947 for (int i = 0; i < 10; i++)
1948 object = LargeObject::create();
1950 HeapStats oneLargeObject;
1951 clearOutOldGarbage(&oneLargeObject);
1952 EXPECT_TRUE(oneLargeObject == afterAllocation);
1953 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1954 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1956 HeapStats backToInitial;
1957 clearOutOldGarbage(&backToInitial);
1958 EXPECT_TRUE(initialHeapSize == backToInitial);
1959 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1960 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1961 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1964 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1965 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1966 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1967 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1968 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1969 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1971 class Container : public GarbageCollected<Container> {
1973 static Container* create() { return new Container(); }
1974 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1975 HeapHashSet<Member<IntWrapper> > set;
1976 HeapHashSet<Member<IntWrapper> > set2;
1977 HeapHashCountedSet<Member<IntWrapper> > set3;
1978 HeapVector<Member<IntWrapper>, 2> vector;
1979 HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1980 HeapVector<PairUnwrappedWrapped, 2> vectorUW;
1981 HeapDeque<Member<IntWrapper>, 0> deque;
1982 HeapDeque<PairWrappedUnwrapped, 0> dequeWU;
1983 HeapDeque<PairUnwrappedWrapped, 0> dequeUW;
1984 void trace(Visitor* visitor)
1986 visitor->trace(map);
1987 visitor->trace(set);
1988 visitor->trace(set2);
1989 visitor->trace(set3);
1990 visitor->trace(vector);
1991 visitor->trace(vectorWU);
1992 visitor->trace(vectorUW);
1993 visitor->trace(deque);
1994 visitor->trace(dequeWU);
1995 visitor->trace(dequeUW);
1999 struct ShouldBeTraced {
2000 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
2001 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
2002 Member<IntWrapper> m_wrapper;
2005 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
2007 static OffHeapContainer* create() { return new OffHeapContainer(); }
2009 static const int iterations = 300;
2010 static const int deadWrappers = 1200;
2014 for (int i = 0; i < iterations; i++) {
2015 m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
2016 m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
2017 m_deque2.append(IntWrapper::create(i));
2018 m_vector2.append(IntWrapper::create(i));
2021 Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
2022 Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
2023 Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
2024 Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
2026 for (int i = 0; i < iterations; i++) {
2027 EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
2028 EXPECT_EQ(i, m_vector2[i]->value());
2029 EXPECT_EQ(i, d1Iterator->m_wrapper->value());
2030 EXPECT_EQ(i, v1Iterator->m_wrapper->value());
2031 EXPECT_EQ(i, d2Iterator->get()->value());
2032 EXPECT_EQ(i, v2Iterator->get()->value());
2038 EXPECT_EQ(d1Iterator, m_deque1.end());
2039 EXPECT_EQ(v1Iterator, m_vector1.end());
2040 EXPECT_EQ(d2Iterator, m_deque2.end());
2041 EXPECT_EQ(v2Iterator, m_vector2.end());
2044 void trace(Visitor* visitor)
2046 visitor->trace(m_deque1);
2047 visitor->trace(m_vector1);
2048 visitor->trace(m_deque2);
2049 visitor->trace(m_vector2);
2052 Deque<ShouldBeTraced> m_deque1;
2053 Vector<ShouldBeTraced> m_vector1;
2054 Deque<Member<IntWrapper> > m_deque2;
2055 Vector<Member<IntWrapper> > m_vector2;
2058 const int OffHeapContainer::iterations;
2059 const int OffHeapContainer::deadWrappers;
2061 // These class definitions test compile-time asserts with transition
2062 // types. They are therefore unused in test code and just need to
2063 // compile. This is intentional; do not delete the A and B classes below.
2064 class A : public WillBeGarbageCollectedMixin {
2067 class B : public NoBaseWillBeGarbageCollected<B>, public A {
2068 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
2070 void trace(Visitor*) { }
2073 TEST(HeapTest, HeapVectorFilledWithValue)
2075 IntWrapper* val = IntWrapper::create(1);
2076 HeapVector<Member<IntWrapper> > vector(10, val);
2077 EXPECT_EQ(10u, vector.size());
2078 for (size_t i = 0; i < vector.size(); i++)
2079 EXPECT_EQ(val, vector[i]);
2082 TEST(HeapTest, HeapVectorWithInlineCapacity)
2084 IntWrapper* one = IntWrapper::create(1);
2085 IntWrapper* two = IntWrapper::create(2);
2086 IntWrapper* three = IntWrapper::create(3);
2087 IntWrapper* four = IntWrapper::create(4);
2088 IntWrapper* five = IntWrapper::create(5);
2089 IntWrapper* six = IntWrapper::create(6);
2091 HeapVector<Member<IntWrapper>, 2> vector;
2094 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2095 EXPECT_TRUE(vector.contains(one));
2096 EXPECT_TRUE(vector.contains(two));
2098 vector.append(three);
2099 vector.append(four);
2100 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2101 EXPECT_TRUE(vector.contains(one));
2102 EXPECT_TRUE(vector.contains(two));
2103 EXPECT_TRUE(vector.contains(three));
2104 EXPECT_TRUE(vector.contains(four));
2107 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2108 EXPECT_TRUE(vector.contains(one));
2109 EXPECT_FALSE(vector.contains(two));
2110 EXPECT_FALSE(vector.contains(three));
2111 EXPECT_FALSE(vector.contains(four));
2114 HeapVector<Member<IntWrapper>, 2> vector1;
2115 HeapVector<Member<IntWrapper>, 2> vector2;
2117 vector1.append(one);
2118 vector2.append(two);
2119 vector1.swap(vector2);
2120 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2121 EXPECT_TRUE(vector1.contains(two));
2122 EXPECT_TRUE(vector2.contains(one));
2125 HeapVector<Member<IntWrapper>, 2> vector1;
2126 HeapVector<Member<IntWrapper>, 2> vector2;
2128 vector1.append(one);
2129 vector1.append(two);
2130 vector2.append(three);
2131 vector2.append(four);
2132 vector2.append(five);
2133 vector2.append(six);
2134 vector1.swap(vector2);
2135 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2136 EXPECT_TRUE(vector1.contains(three));
2137 EXPECT_TRUE(vector1.contains(four));
2138 EXPECT_TRUE(vector1.contains(five));
2139 EXPECT_TRUE(vector1.contains(six));
2140 EXPECT_TRUE(vector2.contains(one));
2141 EXPECT_TRUE(vector2.contains(two));
2145 template<typename T, size_t inlineCapacity, typename U>
2146 bool dequeContains(HeapDeque<T, inlineCapacity>& deque, U u)
2148 typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
2149 for (iterator it = deque.begin(); it != deque.end(); ++it) {
2156 TEST(HeapTest, HeapCollectionTypes)
2158 HeapStats initialHeapSize;
2159 IntWrapper::s_destructorCalls = 0;
2161 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
2162 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2163 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
2165 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2166 typedef HeapHashCountedSet<Member<IntWrapper> > MemberCountedSet;
2168 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2169 typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
2171 typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2172 typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2173 typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
2174 typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
2176 Persistent<MemberMember> memberMember = new MemberMember();
2177 Persistent<MemberMember> memberMember2 = new MemberMember();
2178 Persistent<MemberMember> memberMember3 = new MemberMember();
2179 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2180 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2181 Persistent<MemberSet> set = new MemberSet();
2182 Persistent<MemberSet> set2 = new MemberSet();
2183 Persistent<MemberCountedSet> set3 = new MemberCountedSet();
2184 Persistent<MemberVector> vector = new MemberVector();
2185 Persistent<MemberVector> vector2 = new MemberVector();
2186 Persistent<VectorWU> vectorWU = new VectorWU();
2187 Persistent<VectorWU> vectorWU2 = new VectorWU();
2188 Persistent<VectorUW> vectorUW = new VectorUW();
2189 Persistent<VectorUW> vectorUW2 = new VectorUW();
2190 Persistent<MemberDeque> deque = new MemberDeque();
2191 Persistent<MemberDeque> deque2 = new MemberDeque();
2192 Persistent<DequeWU> dequeWU = new DequeWU();
2193 Persistent<DequeWU> dequeWU2 = new DequeWU();
2194 Persistent<DequeUW> dequeUW = new DequeUW();
2195 Persistent<DequeUW> dequeUW2 = new DequeUW();
2196 Persistent<Container> container = Container::create();
2198 clearOutOldGarbage(&initialHeapSize);
2200 Persistent<IntWrapper> one(IntWrapper::create(1));
2201 Persistent<IntWrapper> two(IntWrapper::create(2));
2202 Persistent<IntWrapper> oneB(IntWrapper::create(1));
2203 Persistent<IntWrapper> twoB(IntWrapper::create(2));
2204 Persistent<IntWrapper> oneC(IntWrapper::create(1));
2205 Persistent<IntWrapper> oneD(IntWrapper::create(1));
2206 Persistent<IntWrapper> oneE(IntWrapper::create(1));
2207 Persistent<IntWrapper> oneF(IntWrapper::create(1));
2209 IntWrapper* threeB(IntWrapper::create(3));
2210 IntWrapper* threeC(IntWrapper::create(3));
2211 IntWrapper* threeD(IntWrapper::create(3));
2212 IntWrapper* threeE(IntWrapper::create(3));
2213 IntWrapper* threeF(IntWrapper::create(3));
2214 IntWrapper* three(IntWrapper::create(3));
2215 IntWrapper* fourB(IntWrapper::create(4));
2216 IntWrapper* fourC(IntWrapper::create(4));
2217 IntWrapper* fourD(IntWrapper::create(4));
2218 IntWrapper* fourE(IntWrapper::create(4));
2219 IntWrapper* fourF(IntWrapper::create(4));
2220 IntWrapper* four(IntWrapper::create(4));
2221 IntWrapper* fiveC(IntWrapper::create(5));
2222 IntWrapper* fiveD(IntWrapper::create(5));
2223 IntWrapper* fiveE(IntWrapper::create(5));
2224 IntWrapper* fiveF(IntWrapper::create(5));
2226 // Member Collections.
2227 memberMember2->add(one, two);
2228 memberMember2->add(two, three);
2229 memberMember2->add(three, four);
2230 memberMember2->add(four, one);
2231 primitiveMember->add(1, two);
2232 primitiveMember->add(2, three);
2233 primitiveMember->add(3, four);
2234 primitiveMember->add(4, one);
2235 memberPrimitive->add(one, 2);
2236 memberPrimitive->add(two, 3);
2237 memberPrimitive->add(three, 4);
2238 memberPrimitive->add(four, 1);
2246 vector->append(oneB);
2247 deque->append(oneB);
2248 vector2->append(threeB);
2249 vector2->append(fourB);
2250 deque2->append(threeE);
2251 deque2->append(fourE);
2252 vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2253 dequeWU->append(PairWrappedUnwrapped(&*oneE, 42));
2254 vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2255 vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2256 vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2257 dequeWU2->append(PairWrappedUnwrapped(&*threeE, 43));
2258 dequeWU2->append(PairWrappedUnwrapped(&*fourE, 44));
2259 dequeWU2->append(PairWrappedUnwrapped(&*fiveE, 45));
2260 vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2261 vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2262 vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2263 vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2264 dequeUW->append(PairUnwrappedWrapped(1, &*oneF));
2265 dequeUW2->append(PairUnwrappedWrapped(103, &*threeF));
2266 dequeUW2->append(PairUnwrappedWrapped(104, &*fourF));
2267 dequeUW2->append(PairUnwrappedWrapped(105, &*fiveF));
2269 EXPECT_TRUE(dequeContains(*deque, oneB));
2271 // Collect garbage. This should change nothing since we are keeping
2272 // alive the IntWrapper objects with on-stack pointers.
2273 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2275 EXPECT_TRUE(dequeContains(*deque, oneB));
2277 EXPECT_EQ(0u, memberMember->size());
2278 EXPECT_EQ(4u, memberMember2->size());
2279 EXPECT_EQ(4u, primitiveMember->size());
2280 EXPECT_EQ(4u, memberPrimitive->size());
2281 EXPECT_EQ(1u, set->size());
2282 EXPECT_EQ(4u, set2->size());
2283 EXPECT_EQ(1u, set3->size());
2284 EXPECT_EQ(1u, vector->size());
2285 EXPECT_EQ(2u, vector2->size());
2286 EXPECT_EQ(1u, vectorWU->size());
2287 EXPECT_EQ(3u, vectorWU2->size());
2288 EXPECT_EQ(1u, vectorUW->size());
2289 EXPECT_EQ(3u, vectorUW2->size());
2290 EXPECT_EQ(1u, deque->size());
2291 EXPECT_EQ(2u, deque2->size());
2292 EXPECT_EQ(1u, dequeWU->size());
2293 EXPECT_EQ(3u, dequeWU2->size());
2294 EXPECT_EQ(1u, dequeUW->size());
2295 EXPECT_EQ(3u, dequeUW2->size());
2297 MemberVector& cvec = container->vector;
2298 cvec.swap(*vector.get());
2299 vector2->swap(cvec);
2302 VectorWU& cvecWU = container->vectorWU;
2303 cvecWU.swap(*vectorWU.get());
2304 vectorWU2->swap(cvecWU);
2305 vectorWU->swap(cvecWU);
2307 VectorUW& cvecUW = container->vectorUW;
2308 cvecUW.swap(*vectorUW.get());
2309 vectorUW2->swap(cvecUW);
2310 vectorUW->swap(cvecUW);
2312 MemberDeque& cDeque = container->deque;
2313 cDeque.swap(*deque.get());
2314 deque2->swap(cDeque);
2315 deque->swap(cDeque);
2317 DequeWU& cDequeWU = container->dequeWU;
2318 cDequeWU.swap(*dequeWU.get());
2319 dequeWU2->swap(cDequeWU);
2320 dequeWU->swap(cDequeWU);
2322 DequeUW& cDequeUW = container->dequeUW;
2323 cDequeUW.swap(*dequeUW.get());
2324 dequeUW2->swap(cDequeUW);
2325 dequeUW->swap(cDequeUW);
2327 // Swap set and set2 in a roundabout way.
2328 MemberSet& cset1 = container->set;
2329 MemberSet& cset2 = container->set2;
2336 MemberCountedSet& cCountedSet = container->set3;
2337 set3->swap(cCountedSet);
2338 EXPECT_EQ(0u, set3->size());
2339 set3->swap(cCountedSet);
2342 container->map.swap(memberMember2);
2343 MemberMember& containedMap = container->map;
2344 memberMember3->swap(containedMap);
2345 memberMember3->swap(memberMember);
2347 EXPECT_TRUE(memberMember->get(one) == two);
2348 EXPECT_TRUE(memberMember->get(two) == three);
2349 EXPECT_TRUE(memberMember->get(three) == four);
2350 EXPECT_TRUE(memberMember->get(four) == one);
2351 EXPECT_TRUE(primitiveMember->get(1) == two);
2352 EXPECT_TRUE(primitiveMember->get(2) == three);
2353 EXPECT_TRUE(primitiveMember->get(3) == four);
2354 EXPECT_TRUE(primitiveMember->get(4) == one);
2355 EXPECT_EQ(1, memberPrimitive->get(four));
2356 EXPECT_EQ(2, memberPrimitive->get(one));
2357 EXPECT_EQ(3, memberPrimitive->get(two));
2358 EXPECT_EQ(4, memberPrimitive->get(three));
2359 EXPECT_TRUE(set->contains(one));
2360 EXPECT_TRUE(set->contains(two));
2361 EXPECT_TRUE(set->contains(three));
2362 EXPECT_TRUE(set->contains(four));
2363 EXPECT_TRUE(set2->contains(oneB));
2364 EXPECT_TRUE(set3->contains(oneB));
2365 EXPECT_TRUE(vector->contains(threeB));
2366 EXPECT_TRUE(vector->contains(fourB));
2367 EXPECT_TRUE(dequeContains(*deque, threeE));
2368 EXPECT_TRUE(dequeContains(*deque, fourE));
2369 EXPECT_TRUE(vector2->contains(oneB));
2370 EXPECT_FALSE(vector2->contains(threeB));
2371 EXPECT_TRUE(dequeContains(*deque2, oneB));
2372 EXPECT_FALSE(dequeContains(*deque2, threeE));
2373 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2374 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2375 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2376 EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2377 EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2378 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2379 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2380 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2381 EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2382 EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2383 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*threeE, 43)));
2384 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fourE, 44)));
2385 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fiveE, 45)));
2386 EXPECT_TRUE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*oneE, 42)));
2387 EXPECT_FALSE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*threeE, 43)));
2388 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(103, &*threeF)));
2389 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(104, &*fourF)));
2390 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(105, &*fiveF)));
2391 EXPECT_TRUE(dequeContains(*dequeUW2, PairUnwrappedWrapped(1, &*oneF)));
2392 EXPECT_FALSE(dequeContains(*dequeUW2, PairUnwrappedWrapped(103, &*threeF)));
2395 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2397 EXPECT_EQ(4u, memberMember->size());
2398 EXPECT_EQ(0u, memberMember2->size());
2399 EXPECT_EQ(4u, primitiveMember->size());
2400 EXPECT_EQ(4u, memberPrimitive->size());
2401 EXPECT_EQ(4u, set->size());
2402 EXPECT_EQ(1u, set2->size());
2403 EXPECT_EQ(1u, set3->size());
2404 EXPECT_EQ(2u, vector->size());
2405 EXPECT_EQ(1u, vector2->size());
2406 EXPECT_EQ(3u, vectorUW->size());
2407 EXPECT_EQ(1u, vector2->size());
2408 EXPECT_EQ(2u, deque->size());
2409 EXPECT_EQ(1u, deque2->size());
2410 EXPECT_EQ(3u, dequeUW->size());
2411 EXPECT_EQ(1u, deque2->size());
2413 EXPECT_TRUE(memberMember->get(one) == two);
2414 EXPECT_TRUE(primitiveMember->get(1) == two);
2415 EXPECT_TRUE(primitiveMember->get(4) == one);
2416 EXPECT_EQ(2, memberPrimitive->get(one));
2417 EXPECT_EQ(3, memberPrimitive->get(two));
2418 EXPECT_TRUE(set->contains(one));
2419 EXPECT_TRUE(set->contains(two));
2420 EXPECT_FALSE(set->contains(oneB));
2421 EXPECT_TRUE(set2->contains(oneB));
2422 EXPECT_TRUE(set3->contains(oneB));
2423 EXPECT_EQ(2u, set3->find(oneB)->value);
2424 EXPECT_EQ(3, vector->at(0)->value());
2425 EXPECT_EQ(4, vector->at(1)->value());
2426 EXPECT_EQ(3, deque->begin()->get()->value());
2429 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2430 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2432 EXPECT_EQ(4u, memberMember->size());
2433 EXPECT_EQ(4u, primitiveMember->size());
2434 EXPECT_EQ(4u, memberPrimitive->size());
2435 EXPECT_EQ(4u, set->size());
2436 EXPECT_EQ(1u, set2->size());
2437 EXPECT_EQ(2u, vector->size());
2438 EXPECT_EQ(1u, vector2->size());
2439 EXPECT_EQ(3u, vectorWU->size());
2440 EXPECT_EQ(1u, vectorWU2->size());
2441 EXPECT_EQ(3u, vectorUW->size());
2442 EXPECT_EQ(1u, vectorUW2->size());
2443 EXPECT_EQ(2u, deque->size());
2444 EXPECT_EQ(1u, deque2->size());
2445 EXPECT_EQ(3u, dequeWU->size());
2446 EXPECT_EQ(1u, dequeWU2->size());
2447 EXPECT_EQ(3u, dequeUW->size());
2448 EXPECT_EQ(1u, dequeUW2->size());
2451 template<typename T>
2452 void MapIteratorCheck(T& it, const T& end, int expected)
2457 int key = it->key->value();
2458 int value = it->value->value();
2459 EXPECT_TRUE(key >= 0 && key < 1100);
2460 EXPECT_TRUE(value >= 0 && value < 1100);
2463 EXPECT_EQ(expected, found);
2466 template<typename T>
2467 void SetIteratorCheck(T& it, const T& end, int expected)
2472 int value = (*it)->value();
2473 EXPECT_TRUE(value >= 0 && value < 1100);
2476 EXPECT_EQ(expected, found);
2479 TEST(HeapTest, HeapWeakCollectionSimple)
2481 HeapStats initialHeapStats;
2482 clearOutOldGarbage(&initialHeapStats);
2483 IntWrapper::s_destructorCalls = 0;
2485 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2487 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2488 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2489 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2490 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2491 typedef HeapHashCountedSet<WeakMember<IntWrapper> > WeakCountedSet;
2493 Persistent<WeakStrong> weakStrong = new WeakStrong();
2494 Persistent<StrongWeak> strongWeak = new StrongWeak();
2495 Persistent<WeakWeak> weakWeak = new WeakWeak();
2496 Persistent<WeakSet> weakSet = new WeakSet();
2497 Persistent<WeakCountedSet> weakCountedSet = new WeakCountedSet();
2499 Persistent<IntWrapper> two = IntWrapper::create(2);
2501 keepNumbersAlive.append(IntWrapper::create(103));
2502 keepNumbersAlive.append(IntWrapper::create(10));
2505 weakStrong->add(IntWrapper::create(1), two);
2506 strongWeak->add(two, IntWrapper::create(1));
2507 weakWeak->add(two, IntWrapper::create(42));
2508 weakWeak->add(IntWrapper::create(42), two);
2509 weakSet->add(IntWrapper::create(0));
2511 weakSet->add(keepNumbersAlive[0]);
2512 weakSet->add(keepNumbersAlive[1]);
2513 weakCountedSet->add(IntWrapper::create(0));
2514 weakCountedSet->add(two);
2515 weakCountedSet->add(two);
2516 weakCountedSet->add(two);
2517 weakCountedSet->add(keepNumbersAlive[0]);
2518 weakCountedSet->add(keepNumbersAlive[1]);
2519 EXPECT_EQ(1u, weakStrong->size());
2520 EXPECT_EQ(1u, strongWeak->size());
2521 EXPECT_EQ(2u, weakWeak->size());
2522 EXPECT_EQ(4u, weakSet->size());
2523 EXPECT_EQ(4u, weakCountedSet->size());
2524 EXPECT_EQ(3u, weakCountedSet->find(two)->value);
2525 weakCountedSet->remove(two);
2526 EXPECT_EQ(2u, weakCountedSet->find(two)->value);
2529 keepNumbersAlive[0] = nullptr;
2531 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2533 EXPECT_EQ(0u, weakStrong->size());
2534 EXPECT_EQ(0u, strongWeak->size());
2535 EXPECT_EQ(0u, weakWeak->size());
2536 EXPECT_EQ(2u, weakSet->size());
2537 EXPECT_EQ(2u, weakCountedSet->size());
2540 template<typename Set>
2541 void orderedSetHelper(bool strong)
2543 HeapStats initialHeapStats;
2544 clearOutOldGarbage(&initialHeapStats);
2545 IntWrapper::s_destructorCalls = 0;
2547 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2549 Persistent<Set> set1 = new Set();
2550 Persistent<Set> set2 = new Set();
2552 const Set& constSet = *set1.get();
2554 keepNumbersAlive.append(IntWrapper::create(2));
2555 keepNumbersAlive.append(IntWrapper::create(103));
2556 keepNumbersAlive.append(IntWrapper::create(10));
2558 set1->add(IntWrapper::create(0));
2559 set1->add(keepNumbersAlive[0]);
2560 set1->add(keepNumbersAlive[1]);
2561 set1->add(keepNumbersAlive[2]);
2564 set2->add(IntWrapper::create(42));
2567 EXPECT_EQ(4u, set1->size());
2568 typename Set::iterator it(set1->begin());
2569 typename Set::reverse_iterator reverse(set1->rbegin());
2570 typename Set::const_iterator cit(constSet.begin());
2571 typename Set::const_reverse_iterator creverse(constSet.rbegin());
2573 EXPECT_EQ(0, (*it)->value());
2574 EXPECT_EQ(0, (*cit)->value());
2577 EXPECT_EQ(2, (*it)->value());
2578 EXPECT_EQ(2, (*cit)->value());
2581 EXPECT_EQ(0, (*it)->value());
2582 EXPECT_EQ(0, (*cit)->value());
2587 EXPECT_EQ(103, (*it)->value());
2588 EXPECT_EQ(103, (*cit)->value());
2591 EXPECT_EQ(10, (*it)->value());
2592 EXPECT_EQ(10, (*cit)->value());
2596 EXPECT_EQ(10, (*reverse)->value());
2597 EXPECT_EQ(10, (*creverse)->value());
2600 EXPECT_EQ(103, (*reverse)->value());
2601 EXPECT_EQ(103, (*creverse)->value());
2604 EXPECT_EQ(10, (*reverse)->value());
2605 EXPECT_EQ(10, (*creverse)->value());
2610 EXPECT_EQ(2, (*reverse)->value());
2611 EXPECT_EQ(2, (*creverse)->value());
2614 EXPECT_EQ(0, (*reverse)->value());
2615 EXPECT_EQ(0, (*creverse)->value());
2619 EXPECT_EQ(set1->end(), it);
2620 EXPECT_EQ(constSet.end(), cit);
2621 EXPECT_EQ(set1->rend(), reverse);
2622 EXPECT_EQ(constSet.rend(), creverse);
2624 typename Set::iterator iX(set2->begin());
2625 EXPECT_EQ(set2->end(), iX);
2628 set1->remove(keepNumbersAlive[0]);
2630 keepNumbersAlive[0] = nullptr;
2632 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2634 EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
2636 EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
2638 typename Set::iterator i2(set1->begin());
2640 EXPECT_EQ(0, (*i2)->value());
2642 EXPECT_NE(set1->end(), i2);
2644 EXPECT_EQ(103, (*i2)->value());
2646 EXPECT_NE(set1->end(), i2);
2647 EXPECT_EQ(10, (*i2)->value());
2649 EXPECT_EQ(set1->end(), i2);
2652 TEST(HeapTest, HeapWeakLinkedHashSet)
2654 orderedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
2655 orderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
2656 orderedSetHelper<HeapListHashSet<Member<IntWrapper> > >(true);
2659 class ThingWithDestructor {
2661 ThingWithDestructor()
2664 s_liveThingsWithDestructor++;
2667 ThingWithDestructor(int x)
2670 s_liveThingsWithDestructor++;
2673 ThingWithDestructor(const ThingWithDestructor&other)
2676 s_liveThingsWithDestructor++;
2679 ~ThingWithDestructor()
2681 s_liveThingsWithDestructor--;
2684 int value() { return m_x; }
2686 static int s_liveThingsWithDestructor;
2688 unsigned hash() { return IntHash<int>::hash(m_x); }
2691 static const int emptyValue = 0;
2695 int ThingWithDestructor::s_liveThingsWithDestructor;
2697 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2698 static const bool needsDestruction = true;
2701 static void heapMapDestructorHelper(bool clearMaps)
2703 HeapStats initialHeapStats;
2704 clearOutOldGarbage(&initialHeapStats);
2705 ThingWithDestructor::s_liveThingsWithDestructor = 0;
2707 typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageCollected> > RefMap;
2709 typedef HeapHashMap<
2710 WeakMember<IntWrapper>,
2711 ThingWithDestructor,
2712 DefaultHash<WeakMember<IntWrapper> >::Hash,
2713 HashTraits<WeakMember<IntWrapper> >,
2714 ThingWithDestructorTraits> Map;
2716 Persistent<Map> map(new Map());
2717 Persistent<RefMap> refMap(new RefMap());
2719 Persistent<IntWrapper> luck(IntWrapper::create(103));
2721 int baseLine, refBaseLine;
2727 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2728 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2730 stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2731 stackMap.add(luck, ThingWithDestructor(8128));
2732 stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2733 stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2735 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2736 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2738 // Although the heap maps are on-stack, we can't expect prompt
2739 // finalization of the elements, so when they go out of scope here we
2740 // will not necessarily have called the relevant destructors.
2743 // The RefCountedAndGarbageCollected things need an extra GC to discover
2744 // that they are no longer ref counted.
2745 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2746 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2747 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2748 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2750 // Now use maps kept alive with persistents. Here we don't expect any
2751 // destructors to be called before there have been GCs.
2753 map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2754 map->add(luck, ThingWithDestructor(8128));
2755 refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2756 refMap->add(luck, RefCountedAndGarbageCollected::create());
2758 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2759 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2763 map->clear(); // Clear map.
2764 refMap->clear(); // Clear map.
2766 map.clear(); // Clear Persistent handle, not map.
2767 refMap.clear(); // Clear Persistent handle, not map.
2768 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2769 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2772 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2774 // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2775 // noticies it's been decremented to zero.
2776 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2777 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2780 TEST(HeapTest, HeapMapDestructor)
2782 heapMapDestructorHelper(true);
2783 heapMapDestructorHelper(false);
2786 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2787 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2788 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2789 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2790 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
2791 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
2792 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
2793 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
2794 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
2795 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
2796 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
2797 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
2799 template<typename T>
2800 T& iteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair)
2805 template<typename T>
2806 T& iteratorExtractor(T& notAPair)
2811 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2813 Persistent<WSSet>& weakStrong,
2814 Persistent<SWSet>& strongWeak,
2815 Persistent<WUSet>& weakUnwrapped,
2816 Persistent<UWSet>& unwrappedWeak,
2818 Persistent<IntWrapper>& two)
2820 typename WSSet::iterator itWS = weakStrong->begin();
2821 typename SWSet::iterator itSW = strongWeak->begin();
2822 typename WUSet::iterator itWU = weakUnwrapped->begin();
2823 typename UWSet::iterator itUW = unwrappedWeak->begin();
2825 EXPECT_EQ(2u, weakStrong->size());
2826 EXPECT_EQ(2u, strongWeak->size());
2827 EXPECT_EQ(2u, weakUnwrapped->size());
2828 EXPECT_EQ(2u, unwrappedWeak->size());
2830 PairWeakStrong p = iteratorExtractor(*itWS);
2831 PairStrongWeak p2 = iteratorExtractor(*itSW);
2832 PairWeakUnwrapped p3 = iteratorExtractor(*itWU);
2833 PairUnwrappedWeak p4 = iteratorExtractor(*itUW);
2834 if (p.first == two && p.second == two)
2836 if (p2.first == two && p2.second == two)
2838 if (p3.first == two && p3.second == 2)
2840 if (p4.first == 2 && p4.second == two)
2842 p = iteratorExtractor(*itWS);
2843 p2 = iteratorExtractor(*itSW);
2844 p3 = iteratorExtractor(*itWU);
2845 p4 = iteratorExtractor(*itUW);
2846 IntWrapper* nullWrapper = 0;
2848 EXPECT_EQ(p.first->value(), 1);
2849 EXPECT_EQ(p2.second->value(), 1);
2850 EXPECT_EQ(p3.first->value(), 1);
2851 EXPECT_EQ(p4.second->value(), 1);
2853 EXPECT_EQ(p.first, nullWrapper);
2854 EXPECT_EQ(p2.second, nullWrapper);
2855 EXPECT_EQ(p3.first, nullWrapper);
2856 EXPECT_EQ(p4.second, nullWrapper);
2859 EXPECT_EQ(p.second->value(), 2);
2860 EXPECT_EQ(p2.first->value(), 2);
2861 EXPECT_EQ(p3.second, 2);
2862 EXPECT_EQ(p4.first, 2);
2864 EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2865 EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2866 EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2867 EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2870 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2871 void weakPairsHelper()
2873 IntWrapper::s_destructorCalls = 0;
2875 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2877 Persistent<WSSet> weakStrong = new WSSet();
2878 Persistent<SWSet> strongWeak = new SWSet();
2879 Persistent<WUSet> weakUnwrapped = new WUSet();
2880 Persistent<UWSet> unwrappedWeak = new UWSet();
2882 Persistent<IntWrapper> two = IntWrapper::create(2);
2884 weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2885 weakStrong->add(PairWeakStrong(&*two, &*two));
2886 strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2887 strongWeak->add(PairStrongWeak(&*two, &*two));
2888 weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2889 weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2890 unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2891 unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2893 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2895 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2896 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2899 TEST(HeapTest, HeapWeakPairs)
2902 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2903 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2904 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2905 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2906 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2910 typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
2911 typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2912 typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
2913 typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2914 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2918 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
2919 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2920 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
2921 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2922 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2926 TEST(HeapTest, HeapWeakCollectionTypes)
2928 HeapStats initialHeapSize;
2929 IntWrapper::s_destructorCalls = 0;
2931 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2932 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2933 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2934 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2935 typedef HeapLinkedHashSet<WeakMember<IntWrapper> > WeakOrderedSet;
2937 clearOutOldGarbage(&initialHeapSize);
2939 const int weakStrongIndex = 0;
2940 const int strongWeakIndex = 1;
2941 const int weakWeakIndex = 2;
2942 const int numberOfMapIndices = 3;
2943 const int weakSetIndex = 3;
2944 const int weakOrderedSetIndex = 4;
2945 const int numberOfCollections = 5;
2947 for (int testRun = 0; testRun < 4; testRun++) {
2948 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2949 bool deleteAfterwards = (testRun == 1);
2950 bool addAfterwards = (testRun == 2);
2951 bool testThatIteratorsMakeStrong = (testRun == 3);
2953 // The test doesn't work for strongWeak with deleting because we lost
2954 // the key from the keepNumbersAlive array, so we can't do the lookup.
2955 if (deleteAfterwards && collectionNumber == strongWeakIndex)
2958 unsigned added = addAfterwards ? 100 : 0;
2960 Persistent<WeakStrong> weakStrong = new WeakStrong();
2961 Persistent<StrongWeak> strongWeak = new StrongWeak();
2962 Persistent<WeakWeak> weakWeak = new WeakWeak();
2964 Persistent<WeakSet> weakSet = new WeakSet();
2965 Persistent<WeakOrderedSet> weakOrderedSet = new WeakOrderedSet();
2967 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2968 for (int i = 0; i < 128; i += 2) {
2969 IntWrapper* wrapped = IntWrapper::create(i);
2970 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
2971 keepNumbersAlive.append(wrapped);
2972 keepNumbersAlive.append(wrapped2);
2973 weakStrong->add(wrapped, wrapped2);
2974 strongWeak->add(wrapped2, wrapped);
2975 weakWeak->add(wrapped, wrapped2);
2976 weakSet->add(wrapped);
2977 weakOrderedSet->add(wrapped);
2980 EXPECT_EQ(64u, weakStrong->size());
2981 EXPECT_EQ(64u, strongWeak->size());
2982 EXPECT_EQ(64u, weakWeak->size());
2983 EXPECT_EQ(64u, weakSet->size());
2984 EXPECT_EQ(64u, weakOrderedSet->size());
2986 // Collect garbage. This should change nothing since we are keeping
2987 // alive the IntWrapper objects.
2988 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2990 EXPECT_EQ(64u, weakStrong->size());
2991 EXPECT_EQ(64u, strongWeak->size());
2992 EXPECT_EQ(64u, weakWeak->size());
2993 EXPECT_EQ(64u, weakSet->size());
2994 EXPECT_EQ(64u, weakOrderedSet->size());
2996 for (int i = 0; i < 128; i += 2) {
2997 IntWrapper* wrapped = keepNumbersAlive[i];
2998 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
2999 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
3000 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
3001 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
3002 EXPECT_TRUE(weakSet->contains(wrapped));
3003 EXPECT_TRUE(weakOrderedSet->contains(wrapped));
3006 for (int i = 0; i < 128; i += 3)
3007 keepNumbersAlive[i] = nullptr;
3009 if (collectionNumber != weakStrongIndex)
3010 weakStrong->clear();
3011 if (collectionNumber != strongWeakIndex)
3012 strongWeak->clear();
3013 if (collectionNumber != weakWeakIndex)
3015 if (collectionNumber != weakSetIndex)
3017 if (collectionNumber != weakOrderedSetIndex)
3018 weakOrderedSet->clear();
3020 if (testThatIteratorsMakeStrong) {
3021 WeakStrong::iterator it1 = weakStrong->begin();
3022 StrongWeak::iterator it2 = strongWeak->begin();
3023 WeakWeak::iterator it3 = weakWeak->begin();
3024 WeakSet::iterator it4 = weakSet->begin();
3025 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3026 // Collect garbage. This should change nothing since the
3027 // iterators make the collections strong.
3028 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3029 if (collectionNumber == weakStrongIndex) {
3030 EXPECT_EQ(64u, weakStrong->size());
3031 MapIteratorCheck(it1, weakStrong->end(), 64);
3032 } else if (collectionNumber == strongWeakIndex) {
3033 EXPECT_EQ(64u, strongWeak->size());
3034 MapIteratorCheck(it2, strongWeak->end(), 64);
3035 } else if (collectionNumber == weakWeakIndex) {
3036 EXPECT_EQ(64u, weakWeak->size());
3037 MapIteratorCheck(it3, weakWeak->end(), 64);
3038 } else if (collectionNumber == weakSetIndex) {
3039 EXPECT_EQ(64u, weakSet->size());
3040 SetIteratorCheck(it4, weakSet->end(), 64);
3041 } else if (collectionNumber == weakOrderedSetIndex) {
3042 EXPECT_EQ(64u, weakOrderedSet->size());
3043 SetIteratorCheck(it5, weakOrderedSet->end(), 64);
3046 // Collect garbage. This causes weak processing to remove
3047 // things from the collections.
3048 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3050 for (int i = 0; i < 128; i += 2) {
3051 bool firstAlive = keepNumbersAlive[i];
3052 bool secondAlive = keepNumbersAlive[i + 1];
3053 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
3055 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
3056 if (collectionNumber == weakStrongIndex) {
3057 if (deleteAfterwards)
3058 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
3059 } else if (collectionNumber == strongWeakIndex) {
3060 if (deleteAfterwards)
3061 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
3062 } else if (collectionNumber == weakWeakIndex) {
3063 if (deleteAfterwards)
3064 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
3066 if (!deleteAfterwards)
3068 } else if (collectionNumber == weakSetIndex && firstAlive) {
3069 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
3070 if (deleteAfterwards)
3071 weakSet->remove(keepNumbersAlive[i]);
3074 } else if (collectionNumber == weakOrderedSetIndex && firstAlive) {
3075 ASSERT_TRUE(weakOrderedSet->contains(keepNumbersAlive[i]));
3076 if (deleteAfterwards)
3077 weakOrderedSet->remove(keepNumbersAlive[i]);
3082 if (addAfterwards) {
3083 for (int i = 1000; i < 1100; i++) {
3084 IntWrapper* wrapped = IntWrapper::create(i);
3085 keepNumbersAlive.append(wrapped);
3086 weakStrong->add(wrapped, wrapped);
3087 strongWeak->add(wrapped, wrapped);
3088 weakWeak->add(wrapped, wrapped);
3089 weakSet->add(wrapped);
3090 weakOrderedSet->add(wrapped);
3093 if (collectionNumber == weakStrongIndex)
3094 EXPECT_EQ(count + added, weakStrong->size());
3095 else if (collectionNumber == strongWeakIndex)
3096 EXPECT_EQ(count + added, strongWeak->size());
3097 else if (collectionNumber == weakWeakIndex)
3098 EXPECT_EQ(count + added, weakWeak->size());
3099 else if (collectionNumber == weakSetIndex)
3100 EXPECT_EQ(count + added, weakSet->size());
3101 else if (collectionNumber == weakOrderedSetIndex)
3102 EXPECT_EQ(count + added, weakOrderedSet->size());
3103 WeakStrong::iterator it1 = weakStrong->begin();
3104 StrongWeak::iterator it2 = strongWeak->begin();
3105 WeakWeak::iterator it3 = weakWeak->begin();
3106 WeakSet::iterator it4 = weakSet->begin();
3107 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3108 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
3109 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
3110 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
3111 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
3112 SetIteratorCheck(it5, weakOrderedSet->end(), (collectionNumber == weakOrderedSetIndex ? count : 0) + added);
3114 for (unsigned i = 0; i < 128 + added; i++)
3115 keepNumbersAlive[i] = nullptr;
3116 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3117 EXPECT_EQ(0u, weakStrong->size());
3118 EXPECT_EQ(0u, strongWeak->size());
3119 EXPECT_EQ(0u, weakWeak->size());
3120 EXPECT_EQ(0u, weakSet->size());
3121 EXPECT_EQ(0u, weakOrderedSet->size());
3126 TEST(HeapTest, RefCountedGarbageCollected)
3128 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3130 RefPtr<RefCountedAndGarbageCollected> refPtr3;
3132 Persistent<RefCountedAndGarbageCollected> persistent;
3134 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
3135 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
3136 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3137 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3138 persistent = refPtr1.get();
3140 // Reference count is zero for both objects but one of
3141 // them is kept alive by a persistent handle.
3142 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3143 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3144 refPtr3 = persistent.get();
3146 // The persistent handle is gone but the ref count has been
3148 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3149 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3151 // Both persistent handle is gone and ref count is zero so the
3152 // object can be collected.
3153 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3154 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
3157 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
3159 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3160 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
3162 RefCountedAndGarbageCollected* pointer1 = 0;
3163 RefCountedAndGarbageCollected2* pointer2 = 0;
3165 RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
3166 RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
3167 pointer1 = object1.get();
3168 pointer2 = object2.get();
3169 void* objects[2] = { object1.get(), object2.get() };
3170 RefCountedGarbageCollectedVisitor visitor(2, objects);
3171 ThreadState::current()->visitPersistents(&visitor);
3172 EXPECT_TRUE(visitor.validate());
3174 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3175 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3176 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3178 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3179 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3180 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3182 // At this point, the reference counts of object1 and object2 are 0.
3183 // Only pointer1 and pointer2 keep references to object1 and object2.
3184 void* objects[] = { 0 };
3185 RefCountedGarbageCollectedVisitor visitor(0, objects);
3186 ThreadState::current()->visitPersistents(&visitor);
3187 EXPECT_TRUE(visitor.validate());
3190 RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
3191 RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
3192 void* objects[2] = { object1.get(), object2.get() };
3193 RefCountedGarbageCollectedVisitor visitor(2, objects);
3194 ThreadState::current()->visitPersistents(&visitor);
3195 EXPECT_TRUE(visitor.validate());
3197 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3198 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3199 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3202 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3203 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3204 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3207 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3208 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3209 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
3212 TEST(HeapTest, WeakMembers)
3216 Persistent<Bar> h1 = Bar::create();
3217 Persistent<Weak> h4;
3218 Persistent<WithWeakMember> h5;
3219 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3220 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
3222 Bar* h2 = Bar::create();
3223 Bar* h3 = Bar::create();
3224 h4 = Weak::create(h2, h3);
3225 h5 = WithWeakMember::create(h2, h3);
3226 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3227 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
3228 EXPECT_TRUE(h4->strongIsThere());
3229 EXPECT_TRUE(h4->weakIsThere());
3230 EXPECT_TRUE(h5->strongIsThere());
3231 EXPECT_TRUE(h5->weakIsThere());
3233 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3234 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3235 EXPECT_EQ(4u, Bar::s_live);
3236 EXPECT_TRUE(h4->strongIsThere());
3237 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
3238 EXPECT_TRUE(h5->strongIsThere());
3239 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
3240 h1.release(); // Zero out h1.
3241 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3242 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
3243 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
3244 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
3246 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3247 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3248 EXPECT_EQ(0u, Bar::s_live); // All gone.
3251 TEST(HeapTest, FinalizationObserver)
3253 Persistent<FinalizationObserver<Observable> > o;
3255 Observable* foo = Observable::create(Bar::create());
3256 // |o| observes |foo|.
3257 o = FinalizationObserver<Observable>::create(foo);
3259 // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3260 // and its member will be collected.
3261 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3262 EXPECT_EQ(0u, Bar::s_live);
3263 EXPECT_TRUE(o->didCallWillFinalize());
3265 FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
3266 Observable* foo = Observable::create(Bar::create());
3267 FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
3268 EXPECT_EQ(1u, map.size());
3270 // FinalizationObserverWithHashMap doesn't have a strong reference to
3271 // |foo|. So |foo| and its member will be collected.
3272 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3273 EXPECT_EQ(0u, Bar::s_live);
3274 EXPECT_EQ(0u, map.size());
3275 EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
3278 TEST(HeapTest, Comparisons)
3280 Persistent<Bar> barPersistent = Bar::create();
3281 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
3282 EXPECT_TRUE(barPersistent != fooPersistent);
3283 barPersistent = fooPersistent;
3284 EXPECT_TRUE(barPersistent == fooPersistent);
3287 TEST(HeapTest, CheckAndMarkPointer)
3289 HeapStats initialHeapStats;
3290 clearOutOldGarbage(&initialHeapStats);
3292 Vector<Address> objectAddresses;
3293 Vector<Address> endAddresses;
3294 Address largeObjectAddress;
3295 Address largeObjectEndAddress;
3296 CountingVisitor visitor;
3297 for (int i = 0; i < 10; i++) {
3298 SimpleObject* object = SimpleObject::create();
3299 Address objectAddress = reinterpret_cast<Address>(object);
3300 objectAddresses.append(objectAddress);
3301 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
3303 LargeObject* largeObject = LargeObject::create();
3304 largeObjectAddress = reinterpret_cast<Address>(largeObject);
3305 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
3307 // This is a low-level test where we call checkAndMarkPointer. This method
3308 // causes the object start bitmap to be computed which requires the heap
3309 // to be in a consistent state (e.g. the free allocation area must be put
3310 // into a free list header). However when we call makeConsistentForGC it
3311 // also clears out the freelists so we have to rebuild those before trying
3312 // to allocate anything again. We do this by forcing a GC after doing the
3313 // checkAndMarkPointer tests.
3315 TestGCScope scope(ThreadState::HeapPointersOnStack);
3316 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3317 Heap::makeConsistentForGC();
3318 for (size_t i = 0; i < objectAddresses.size(); i++) {
3319 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3320 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3322 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3324 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3325 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3326 EXPECT_EQ(2ul, visitor.count());
3329 // This forces a GC without stack scanning which results in the objects
3330 // being collected. This will also rebuild the above mentioned freelists,
3331 // however we don't rely on that below since we don't have any allocations.
3332 clearOutOldGarbage(&initialHeapStats);
3334 TestGCScope scope(ThreadState::HeapPointersOnStack);
3335 EXPECT_TRUE(scope.allThreadsParked());
3336 Heap::makeConsistentForGC();
3337 for (size_t i = 0; i < objectAddresses.size(); i++) {
3338 // We would like to assert that checkAndMarkPointer returned false
3339 // here because the pointers no longer point into a valid object
3340 // (it's been freed by the GCs. But checkAndMarkPointer will return
3341 // true for any pointer that points into a heap page, regardless of
3342 // whether it points at a valid object (this ensures the
3343 // correctness of the page-based on-heap address caches), so we
3344 // can't make that assert.
3345 Heap::checkAndMarkPointer(&visitor, objectAddresses[i]);
3346 Heap::checkAndMarkPointer(&visitor, endAddresses[i]);
3348 EXPECT_EQ(0ul, visitor.count());
3349 Heap::checkAndMarkPointer(&visitor, largeObjectAddress);
3350 Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress);
3351 EXPECT_EQ(0ul, visitor.count());
3353 // This round of GC is important to make sure that the object start
3354 // bitmap are cleared out and that the free lists are rebuild.
3355 clearOutOldGarbage(&initialHeapStats);
3358 TEST(HeapTest, VisitOffHeapCollections)
3360 HeapStats initialHeapStats;
3361 clearOutOldGarbage(&initialHeapStats);
3362 IntWrapper::s_destructorCalls = 0;
3363 Persistent<OffHeapContainer> container = OffHeapContainer::create();
3364 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3365 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3366 container = nullptr;
3367 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3368 EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
3371 TEST(HeapTest, PersistentHeapCollectionTypes)
3373 HeapStats initialHeapSize;
3374 IntWrapper::s_destructorCalls = 0;
3376 typedef HeapVector<Member<IntWrapper> > Vec;
3377 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
3378 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
3379 typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet;
3380 typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet;
3381 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
3382 typedef PersistentHeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakPMap;
3383 typedef PersistentHeapDeque<Member<IntWrapper> > PDeque;
3385 clearOutOldGarbage(&initialHeapSize);
3391 PLinkedSet pLinkedSet;
3395 IntWrapper* one(IntWrapper::create(1));
3396 IntWrapper* two(IntWrapper::create(2));
3397 IntWrapper* three(IntWrapper::create(3));
3398 IntWrapper* four(IntWrapper::create(4));
3399 IntWrapper* five(IntWrapper::create(5));
3400 IntWrapper* six(IntWrapper::create(6));
3401 IntWrapper* seven(IntWrapper::create(7));
3402 IntWrapper* eight(IntWrapper::create(8));
3403 IntWrapper* nine(IntWrapper::create(9));
3404 Persistent<IntWrapper> ten(IntWrapper::create(10));
3405 IntWrapper* eleven(IntWrapper::create(11));
3410 pDeque.append(seven);
3413 Vec* vec = new Vec();
3420 pListSet.add(eight);
3421 pLinkedSet.add(nine);
3422 pMap.add(five, six);
3423 wpMap.add(ten, eleven);
3425 // Collect |vec| and |one|.
3427 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3428 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3430 EXPECT_EQ(2u, pVec.size());
3431 EXPECT_EQ(two, pVec.at(0));
3432 EXPECT_EQ(three, pVec.at(1));
3434 EXPECT_EQ(2u, pDeque.size());
3435 EXPECT_EQ(seven, pDeque.first());
3436 EXPECT_EQ(seven, pDeque.takeFirst());
3437 EXPECT_EQ(two, pDeque.first());
3439 EXPECT_EQ(1u, pDeque.size());
3441 EXPECT_EQ(1u, pSet.size());
3442 EXPECT_TRUE(pSet.contains(four));
3444 EXPECT_EQ(1u, pListSet.size());
3445 EXPECT_TRUE(pListSet.contains(eight));
3447 EXPECT_EQ(1u, pLinkedSet.size());
3448 EXPECT_TRUE(pLinkedSet.contains(nine));
3450 EXPECT_EQ(1u, pMap.size());
3451 EXPECT_EQ(six, pMap.get(five));
3453 EXPECT_EQ(1u, wpMap.size());
3454 EXPECT_EQ(eleven, wpMap.get(ten));
3456 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3457 EXPECT_EQ(0u, wpMap.size());
3460 // Collect previous roots.
3461 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3462 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
3465 TEST(HeapTest, CollectionNesting)
3467 HeapStats initialStats;
3468 clearOutOldGarbage(&initialStats);
3469 int* key = &IntWrapper::s_destructorCalls;
3470 IntWrapper::s_destructorCalls = 0;
3471 typedef HeapVector<Member<IntWrapper> > IntVector;
3472 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3473 HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
3474 HeapHashMap<void*, IntDeque>* map2 = new HeapHashMap<void*, IntDeque>();
3476 map->add(key, IntVector());
3477 map2->add(key, IntDeque());
3479 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3480 EXPECT_EQ(0u, map->get(key).size());
3482 HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3483 EXPECT_EQ(0u, map2->get(key).size());
3485 it->value.append(IntWrapper::create(42));
3486 EXPECT_EQ(1u, map->get(key).size());
3488 it2->value.append(IntWrapper::create(42));
3489 EXPECT_EQ(1u, map2->get(key).size());
3491 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
3492 Persistent<HeapHashMap<void*, IntDeque> > keepAlive2(map2);
3494 for (int i = 0; i < 100; i++) {
3495 map->add(key + 1 + i, IntVector());
3496 map2->add(key + 1 + i, IntDeque());
3499 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3501 EXPECT_EQ(1u, map->get(key).size());
3502 EXPECT_EQ(1u, map2->get(key).size());
3503 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3505 keepAlive = nullptr;
3506 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3507 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3510 TEST(HeapTest, GarbageCollectedMixin)
3512 HeapStats initialHeapStats;
3513 clearOutOldGarbage(&initialHeapStats);
3515 Persistent<UseMixin> usemixin = UseMixin::create();
3516 EXPECT_EQ(0, UseMixin::s_traceCount);
3517 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3518 EXPECT_EQ(1, UseMixin::s_traceCount);
3520 Persistent<Mixin> mixin = usemixin;
3522 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3523 EXPECT_EQ(2, UseMixin::s_traceCount);
3525 PersistentHeapHashSet<WeakMember<Mixin> > weakMap;
3526 weakMap.add(UseMixin::create());
3527 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3528 EXPECT_EQ(0u, weakMap.size());
3531 TEST(HeapTest, CollectionNesting2)
3533 HeapStats initialStats;
3534 clearOutOldGarbage(&initialStats);
3535 void* key = &IntWrapper::s_destructorCalls;
3536 IntWrapper::s_destructorCalls = 0;
3537 typedef HeapHashSet<Member<IntWrapper> > IntSet;
3538 HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
3540 map->add(key, IntSet());
3542 HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3543 EXPECT_EQ(0u, map->get(key).size());
3545 it->value.add(IntWrapper::create(42));
3546 EXPECT_EQ(1u, map->get(key).size());
3548 Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
3549 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3550 EXPECT_EQ(1u, map->get(key).size());
3551 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3554 TEST(HeapTest, CollectionNesting3)
3556 HeapStats initialStats;
3557 clearOutOldGarbage(&initialStats);
3558 IntWrapper::s_destructorCalls = 0;
3559 typedef HeapVector<Member<IntWrapper> > IntVector;
3560 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3561 HeapVector<IntVector>* vector = new HeapVector<IntVector>();
3562 HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
3564 vector->append(IntVector());
3565 deque->append(IntDeque());
3567 HeapVector<IntVector>::iterator it = vector->begin();
3568 HeapDeque<IntDeque>::iterator it2 = deque->begin();
3569 EXPECT_EQ(0u, it->size());
3570 EXPECT_EQ(0u, it2->size());
3572 it->append(IntWrapper::create(42));
3573 it2->append(IntWrapper::create(42));
3574 EXPECT_EQ(1u, it->size());
3575 EXPECT_EQ(1u, it2->size());
3577 Persistent<HeapVector<IntVector> > keepAlive(vector);
3578 Persistent<HeapDeque<IntDeque> > keepAlive2(deque);
3579 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3580 EXPECT_EQ(1u, it->size());
3581 EXPECT_EQ(1u, it2->size());
3582 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3585 TEST(HeapTest, EmbeddedInVector)
3587 HeapStats initialStats;
3588 clearOutOldGarbage(&initialStats);
3589 SimpleFinalizedObject::s_destructorCalls = 0;
3591 PersistentHeapVector<VectorObject, 2> inlineVector;
3592 PersistentHeapVector<VectorObject> outlineVector;
3593 VectorObject i1, i2;
3594 inlineVector.append(i1);
3595 inlineVector.append(i2);
3597 VectorObject o1, o2;
3598 outlineVector.append(o1);
3599 outlineVector.append(o2);
3601 PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
3602 VectorObjectInheritedTrace it1, it2;
3603 vectorInheritedTrace.append(it1);
3604 vectorInheritedTrace.append(it2);
3606 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3607 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3609 // Since VectorObjectNoTrace has no trace method it will
3610 // not be traced and hence be collected when doing GC.
3611 // We trace items in a collection braced on the item's
3612 // having a trace method. This is determined via the
3613 // NeedsTracing trait in wtf/TypeTraits.h.
3614 PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
3615 VectorObjectNoTrace n1, n2;
3616 vectorNoTrace.append(n1);
3617 vectorNoTrace.append(n2);
3618 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3619 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3621 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3622 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3625 TEST(HeapTest, EmbeddedInDeque)
3627 HeapStats initialStats;
3628 clearOutOldGarbage(&initialStats);
3629 SimpleFinalizedObject::s_destructorCalls = 0;
3631 PersistentHeapDeque<VectorObject, 2> inlineDeque;
3632 PersistentHeapDeque<VectorObject> outlineDeque;
3633 VectorObject i1, i2;
3634 inlineDeque.append(i1);
3635 inlineDeque.append(i2);
3637 VectorObject o1, o2;
3638 outlineDeque.append(o1);
3639 outlineDeque.append(o2);
3641 PersistentHeapDeque<VectorObjectInheritedTrace> dequeInheritedTrace;
3642 VectorObjectInheritedTrace it1, it2;
3643 dequeInheritedTrace.append(it1);
3644 dequeInheritedTrace.append(it2);
3646 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3647 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3649 // Since VectorObjectNoTrace has no trace method it will
3650 // not be traced and hence be collected when doing GC.
3651 // We trace items in a collection braced on the item's
3652 // having a trace method. This is determined via the
3653 // NeedsTracing trait in wtf/TypeTraits.h.
3654 PersistentHeapDeque<VectorObjectNoTrace> dequeNoTrace;
3655 VectorObjectNoTrace n1, n2;
3656 dequeNoTrace.append(n1);
3657 dequeNoTrace.append(n2);
3658 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3659 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3661 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3662 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3665 template<typename Set>
3666 void rawPtrInHashHelper()
3669 set.add(new int(42));
3670 set.add(new int(42));
3671 EXPECT_EQ(2u, set.size());
3672 for (typename Set::iterator it = set.begin(); it != set.end(); ++it) {
3673 EXPECT_EQ(42, **it);
3678 TEST(HeapTest, RawPtrInHash)
3680 rawPtrInHashHelper<HashSet<RawPtr<int> > >();
3681 rawPtrInHashHelper<ListHashSet<RawPtr<int> > >();
3682 rawPtrInHashHelper<LinkedHashSet<RawPtr<int> > >();
3685 TEST(HeapTest, HeapTerminatedArray)
3687 HeapStats initialHeapSize;
3688 clearOutOldGarbage(&initialHeapSize);
3689 IntWrapper::s_destructorCalls = 0;
3691 HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
3693 const size_t prefixSize = 4;
3694 const size_t suffixSize = 4;
3697 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3698 builder.grow(prefixSize);
3699 for (size_t i = 0; i < prefixSize; i++)
3700 builder.append(TerminatedArrayItem(IntWrapper::create(i)));
3701 arr = builder.release();
3704 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3705 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3706 EXPECT_EQ(prefixSize, arr->size());
3707 for (size_t i = 0; i < prefixSize; i++)
3708 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3711 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3712 builder.grow(suffixSize);
3713 for (size_t i = 0; i < suffixSize; i++)
3714 builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
3715 arr = builder.release();
3718 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3719 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3720 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3721 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3722 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3725 Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3727 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3728 arr = persistentArr.get();
3729 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3730 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3731 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3732 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3736 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3737 EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3740 TEST(HeapTest, HeapLinkedStack)
3742 HeapStats initialHeapSize;
3743 clearOutOldGarbage(&initialHeapSize);
3744 IntWrapper::s_destructorCalls = 0;
3746 HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3748 const size_t stackSize = 10;
3750 for (size_t i = 0; i < stackSize; i++)
3751 stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3753 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3754 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3755 EXPECT_EQ(stackSize, stack->size());
3756 while (!stack->isEmpty()) {
3757 EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3761 Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3763 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3764 EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3765 EXPECT_EQ(0u, pStack->size());
3768 TEST(HeapTest, AllocationDuringFinalization)
3770 HeapStats initialHeapSize;
3771 clearOutOldGarbage(&initialHeapSize);
3772 IntWrapper::s_destructorCalls = 0;
3773 OneKiloByteObject::s_destructorCalls = 0;
3775 Persistent<IntWrapper> wrapper;
3776 new FinalizationAllocator(&wrapper);
3778 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3779 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3780 // Check that the wrapper allocated during finalization is not
3781 // swept away and zapped later in the same sweeping phase.
3782 EXPECT_EQ(42, wrapper->value());
3785 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3786 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3787 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3790 class SimpleClassWithDestructor {
3792 SimpleClassWithDestructor() { }
3793 ~SimpleClassWithDestructor()
3795 s_wasDestructed = true;
3797 static bool s_wasDestructed;
3800 bool SimpleClassWithDestructor::s_wasDestructed;
3802 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
3804 RefCountedWithDestructor() { }
3805 ~RefCountedWithDestructor()
3807 s_wasDestructed = true;
3809 static bool s_wasDestructed;
3812 bool RefCountedWithDestructor::s_wasDestructed;
3814 template<typename Set>
3815 void destructorsCalledOnGC(bool addLots)
3817 RefCountedWithDestructor::s_wasDestructed = false;
3820 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3821 set.add(adoptRef(hasDestructor));
3822 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3825 for (int i = 0; i < 1000; i++) {
3826 set.add(adoptRef(new RefCountedWithDestructor()));
3830 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3831 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3832 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3834 // The destructors of the sets don't call the destructors of the elements
3835 // in the heap sets. You have to actually remove the elments, call clear()
3836 // or have a GC to get the destructors called.
3837 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3838 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3839 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3842 template<typename Set>
3843 void destructorsCalledOnClear(bool addLots)
3845 RefCountedWithDestructor::s_wasDestructed = false;
3847 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3848 set.add(adoptRef(hasDestructor));
3849 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3852 for (int i = 0; i < 1000; i++) {
3853 set.add(adoptRef(new RefCountedWithDestructor()));
3857 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3859 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3862 TEST(HeapTest, DestructorsCalled)
3864 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3865 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3866 map.add(hasDestructor, adoptPtr(hasDestructor));
3867 SimpleClassWithDestructor::s_wasDestructed = false;
3869 EXPECT_TRUE(SimpleClassWithDestructor::s_wasDestructed);
3871 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3872 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3873 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3874 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3875 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3876 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3878 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3879 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3880 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3881 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3882 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3883 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3886 class MixinA : public GarbageCollectedMixin {
3888 MixinA() : m_obj(IntWrapper::create(100)) { }
3889 virtual void trace(Visitor* visitor)
3891 visitor->trace(m_obj);
3893 Member<IntWrapper> m_obj;
3896 class MixinB : public GarbageCollectedMixin {
3898 MixinB() : m_obj(IntWrapper::create(101)) { }
3899 virtual void trace(Visitor* visitor)
3901 visitor->trace(m_obj);
3903 Member<IntWrapper> m_obj;
3906 class MultipleMixins : public GarbageCollected<MultipleMixins>, public MixinA, public MixinB {
3907 USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
3909 MultipleMixins() : m_obj(IntWrapper::create(102)) { }
3910 virtual void trace(Visitor* visitor)
3912 visitor->trace(m_obj);
3913 MixinA::trace(visitor);
3914 MixinB::trace(visitor);
3916 Member<IntWrapper> m_obj;
3919 static const bool s_isMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
3920 static const bool s_isMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
3922 TEST(HeapTest, MultipleMixins)
3924 EXPECT_TRUE(s_isMixinTrue);
3925 EXPECT_FALSE(s_isMixinFalse);
3927 HeapStats initialHeapSize;
3928 clearOutOldGarbage(&initialHeapSize);
3929 IntWrapper::s_destructorCalls = 0;
3930 MultipleMixins* obj = new MultipleMixins();
3932 Persistent<MixinA> a = obj;
3933 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3934 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3937 Persistent<MixinB> b = obj;
3938 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3939 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3941 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3942 EXPECT_EQ(3, IntWrapper::s_destructorCalls);
3945 class GCParkingThreadTester {
3949 createThread(&sleeperMainFunc, 0, "SleepingThread");
3951 // Wait for the sleeper to run.
3952 while (!s_sleeperRunning) {
3957 // Expect the first attempt to park the sleeping thread to fail
3958 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3959 EXPECT_FALSE(scope.allThreadsParked());
3962 s_sleeperDone = true;
3964 // Wait for the sleeper to finish.
3965 while (s_sleeperRunning) {
3966 // We enter the safepoint here since the sleeper thread will detach
3967 // causing it to GC.
3968 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
3972 // Since the sleeper thread has detached this is the only thread.
3973 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3974 EXPECT_TRUE(scope.allThreadsParked());
3979 static void sleeperMainFunc(void* data)
3981 ThreadState::attach();
3982 s_sleeperRunning = true;
3984 // Simulate a long running op that is not entering a safepoint.
3985 while (!s_sleeperDone) {
3989 ThreadState::detach();
3990 s_sleeperRunning = false;
3993 static volatile bool s_sleeperRunning;
3994 static volatile bool s_sleeperDone;
3997 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
3998 volatile bool GCParkingThreadTester::s_sleeperDone = false;
4000 TEST(HeapTest, GCParkingTimeout)
4002 GCParkingThreadTester::test();
4005 TEST(HeapTest, NeedsAdjustAndMark)
4007 // class Mixin : public GarbageCollectedMixin {};
4008 EXPECT_TRUE(NeedsAdjustAndMark<Mixin>::value);
4009 EXPECT_TRUE(NeedsAdjustAndMark<const Mixin>::value);
4011 // class SimpleObject : public GarbageCollected<SimpleObject> {};
4012 EXPECT_FALSE(NeedsAdjustAndMark<SimpleObject>::value);
4013 EXPECT_FALSE(NeedsAdjustAndMark<const SimpleObject>::value);
4015 // class UseMixin : public SimpleObject, public Mixin {};
4016 EXPECT_FALSE(NeedsAdjustAndMark<UseMixin>::value);
4017 EXPECT_FALSE(NeedsAdjustAndMark<const UseMixin>::value);
4020 template<typename Set>
4021 void setWithCustomWeaknessHandling()
4023 typedef typename Set::iterator Iterator;
4024 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4025 Persistent<Set> set1(new Set());
4028 Set* set3 = new Set();
4029 set2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4030 set3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4031 set1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4032 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4033 // The first set is pointed to from a persistent, so it's referenced, but
4034 // the weak processing may have taken place.
4036 Iterator i1 = set1->begin();
4037 EXPECT_EQ(4, i1->first->value());
4038 EXPECT_EQ(5, i1->second->value());
4040 // The second set is on-stack, so its backing store must be referenced from
4041 // the stack. That makes the weak references strong.
4042 Iterator i2 = set2.begin();
4043 EXPECT_EQ(0, i2->first->value());
4044 EXPECT_EQ(1, i2->second->value());
4045 // The third set is pointed to from the stack, so it's referenced, but the
4046 // weak processing may have taken place.
4048 Iterator i3 = set3->begin();
4049 EXPECT_EQ(2, i3->first->value());
4050 EXPECT_EQ(3, i3->second->value());
4053 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4054 EXPECT_EQ(0u, set1->size());
4055 set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt));
4056 set1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4057 set1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4058 set1->add(PairWithWeakHandling(livingInt, livingInt));
4059 set1->add(PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4060 EXPECT_EQ(4u, set1->size());
4061 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4062 EXPECT_EQ(2u, set1->size());
4063 Iterator i1 = set1->begin();
4064 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4065 EXPECT_EQ(livingInt, i1->second);
4067 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4068 EXPECT_EQ(livingInt, i1->second);
4071 TEST(HeapTest, SetWithCustomWeaknessHandling)
4073 setWithCustomWeaknessHandling<HeapHashSet<PairWithWeakHandling> >();
4074 setWithCustomWeaknessHandling<HeapLinkedHashSet<PairWithWeakHandling> >();
4077 TEST(HeapTest, MapWithCustomWeaknessHandling)
4079 typedef HeapHashMap<PairWithWeakHandling, RefPtr<OffHeapInt> > Map;
4080 typedef Map::iterator Iterator;
4081 HeapStats initialHeapSize;
4082 clearOutOldGarbage(&initialHeapSize);
4083 OffHeapInt::s_destructorCalls = 0;
4085 Persistent<Map> map1(new Map());
4086 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4089 Map* map3 = new Map();
4090 map2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)), OffHeapInt::create(1001));
4091 map3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)), OffHeapInt::create(1002));
4092 map1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)), OffHeapInt::create(1003));
4093 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4095 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4096 // The first map2 is pointed to from a persistent, so it's referenced, but
4097 // the weak processing may have taken place.
4099 Iterator i1 = map1->begin();
4100 EXPECT_EQ(4, i1->key.first->value());
4101 EXPECT_EQ(5, i1->key.second->value());
4102 EXPECT_EQ(1003, i1->value->value());
4104 // The second map2 is on-stack, so its backing store must be referenced from
4105 // the stack. That makes the weak references strong.
4106 Iterator i2 = map2.begin();
4107 EXPECT_EQ(0, i2->key.first->value());
4108 EXPECT_EQ(1, i2->key.second->value());
4109 EXPECT_EQ(1001, i2->value->value());
4110 // The third map2 is pointed to from the stack, so it's referenced, but the
4111 // weak processing may have taken place.
4113 Iterator i3 = map3->begin();
4114 EXPECT_EQ(2, i3->key.first->value());
4115 EXPECT_EQ(3, i3->key.second->value());
4116 EXPECT_EQ(1002, i3->value->value());
4119 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4121 EXPECT_EQ(0u, map1->size());
4122 EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4124 OffHeapInt::s_destructorCalls = 0;
4126 map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), OffHeapInt::create(2000));
4127 map1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103)), OffHeapInt::create(2001)); // This one gets zapped at GC time because nothing holds the 103 alive.
4128 map1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), OffHeapInt::create(2002)); // This one gets zapped too.
4129 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4130 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt);
4131 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); // This one is identical to the previous and doesn't add anything.
4134 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4135 EXPECT_EQ(4u, map1->size());
4136 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4137 EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4138 EXPECT_EQ(2u, map1->size());
4139 Iterator i1 = map1->begin();
4140 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4141 EXPECT_EQ(livingInt, i1->key.second);
4143 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4144 EXPECT_EQ(livingInt, i1->key.second);
4147 TEST(HeapTest, MapWithCustomWeaknessHandling2)
4149 typedef HeapHashMap<RefPtr<OffHeapInt>, PairWithWeakHandling> Map;
4150 typedef Map::iterator Iterator;
4151 HeapStats initialHeapSize;
4152 clearOutOldGarbage(&initialHeapSize);
4153 OffHeapInt::s_destructorCalls = 0;
4155 Persistent<Map> map1(new Map());
4156 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4160 Map* map3 = new Map();
4161 map2.add(OffHeapInt::create(1001), PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4162 map3->add(OffHeapInt::create(1002), PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4163 map1->add(OffHeapInt::create(1003), PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4164 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4166 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4167 // The first map2 is pointed to from a persistent, so it's referenced, but
4168 // the weak processing may have taken place.
4170 Iterator i1 = map1->begin();
4171 EXPECT_EQ(4, i1->value.first->value());
4172 EXPECT_EQ(5, i1->value.second->value());
4173 EXPECT_EQ(1003, i1->key->value());
4175 // The second map2 is on-stack, so its backing store must be referenced from
4176 // the stack. That makes the weak references strong.
4177 Iterator i2 = map2.begin();
4178 EXPECT_EQ(0, i2->value.first->value());
4179 EXPECT_EQ(1, i2->value.second->value());
4180 EXPECT_EQ(1001, i2->key->value());
4181 // The third map2 is pointed to from the stack, so it's referenced, but the
4182 // weak processing may have taken place.
4184 Iterator i3 = map3->begin();
4185 EXPECT_EQ(2, i3->value.first->value());
4186 EXPECT_EQ(3, i3->value.second->value());
4187 EXPECT_EQ(1002, i3->key->value());
4190 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4192 EXPECT_EQ(0u, map1->size());
4193 EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4195 OffHeapInt::s_destructorCalls = 0;
4197 map1->add(OffHeapInt::create(2000), PairWithWeakHandling(IntWrapper::create(103), livingInt));
4198 map1->add(OffHeapInt::create(2001), PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4199 map1->add(OffHeapInt::create(2002), PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4200 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4201 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt));
4202 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4205 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4206 EXPECT_EQ(4u, map1->size());
4207 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4208 EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4209 EXPECT_EQ(2u, map1->size());
4210 Iterator i1 = map1->begin();
4211 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4212 EXPECT_EQ(livingInt, i1->value.second);
4214 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4215 EXPECT_EQ(livingInt, i1->value.second);
4218 static void addElementsToWeakMap(HeapHashMap<int, WeakMember<IntWrapper> >* map)
4220 // Key cannot be zero in hashmap.
4221 for (int i = 1; i < 11; i++)
4222 map->add(i, IntWrapper::create(i));
4226 // If it doesn't assert a concurrent modification to the map, then it's passing.
4227 TEST(HeapTest, RegressNullIsStrongified)
4229 Persistent<HeapHashMap<int, WeakMember<IntWrapper> > > map = new HeapHashMap<int, WeakMember<IntWrapper> >();
4230 addElementsToWeakMap(map);
4231 HeapHashMap<int, WeakMember<IntWrapper> >::AddResult result = map->add(800, nullptr);
4232 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4233 result.storedValue->value = IntWrapper::create(42);
4236 TEST(HeapTest, Bind)
4238 Closure closure = bind(&Bar::trace, Bar::create(), static_cast<Visitor*>(0));
4239 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4240 // The closure should have a persistent handle to the Bar.
4241 EXPECT_EQ(1u, Bar::s_live);
4243 Closure closure2 = bind(&Bar::trace, RawPtr<Bar>(Bar::create()), static_cast<Visitor*>(0));
4244 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4245 // The closure should have a persistent handle to the Bar.
4246 EXPECT_EQ(2u, Bar::s_live);
4247 // RawPtr<OffHeapInt> should not make Persistent.
4248 Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHeapInt::create(1).get()));
4250 UseMixin::s_traceCount = 0;
4251 Mixin* mixin = UseMixin::create();
4252 Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0));
4253 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4254 // The closure should have a persistent handle to the mixin.
4255 EXPECT_EQ(1, UseMixin::s_traceCount);
4258 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
4260 // These special traits will remove a set from a map when the set is empty.
4261 struct EmptyClearingHashSetTraits : HashTraits<WeakSet> {
4262 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
4263 static bool traceInCollection(Visitor* visitor, WeakSet& set, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
4265 bool liveEntriesFound = false;
4266 WeakSet::iterator end = set.end();
4267 for (WeakSet::iterator it = set.begin(); it != end; ++it) {
4268 if (visitor->isAlive(*it)) {
4269 liveEntriesFound = true;
4273 // If there are live entries in the set then the set cannot be removed
4274 // from the map it is contained in, and we need to mark it (and its
4275 // backing) live. We just trace normally, which will invoke the normal
4276 // weak handling for any entries that are not live.
4277 if (liveEntriesFound)
4279 return !liveEntriesFound;
4283 // This is an example to show how you can remove entries from a T->WeakSet map
4284 // when the weak sets become empty. For this example we are using a type that
4285 // is given to use (HeapHashSet) rather than a type of our own. This means:
4286 // 1) We can't just override the HashTrait for the type since this would affect
4287 // all collections that use this kind of weak set. Instead we have our own
4288 // traits and use a map with custom traits for the value type. These traits
4289 // are the 5th template parameter, so we have to supply default values for
4290 // the 3rd and 4th template parameters
4291 // 2) We can't just inherit from WeakHandlingHashTraits, since that trait
4292 // assumes we can add methods to the type, but we can't add methods to
4294 TEST(HeapTest, RemoveEmptySets)
4296 HeapStats initialHeapSize;
4297 clearOutOldGarbage(&initialHeapSize);
4298 OffHeapInt::s_destructorCalls = 0;
4300 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4302 typedef RefPtr<OffHeapInt> Key;
4303 typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash, HashTraits<Key>, EmptyClearingHashSetTraits> Map;
4304 Persistent<Map> map(new Map());
4305 map->add(OffHeapInt::create(1), WeakSet());
4307 WeakSet& set = map->begin()->value;
4308 set.add(IntWrapper::create(103)); // Weak set can't hold this long.
4309 set.add(livingInt); // This prevents the set from being emptied.
4310 EXPECT_EQ(2u, set.size());
4313 // The set we add here is empty, so the entry will be removed from the map
4315 map->add(OffHeapInt::create(2), WeakSet());
4316 EXPECT_EQ(2u, map->size());
4318 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4319 EXPECT_EQ(1u, map->size()); // The one with key 2 was removed.
4320 EXPECT_EQ(1, OffHeapInt::s_destructorCalls);
4322 WeakSet& set = map->begin()->value;
4323 EXPECT_EQ(1u, set.size());
4326 livingInt.clear(); // The weak set can no longer keep the '42' alive now.
4327 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4328 EXPECT_EQ(0u, map->size());
4331 TEST(HeapTest, EphemeronsInEphemerons)
4333 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > InnerMap;
4334 typedef HeapHashMap<WeakMember<IntWrapper>, InnerMap> OuterMap;
4336 for (int keepOuterAlive = 0; keepOuterAlive <= 1; keepOuterAlive++) {
4337 for (int keepInnerAlive = 0; keepInnerAlive <=1; keepInnerAlive++) {
4338 Persistent<OuterMap> outer = new OuterMap();
4339 Persistent<IntWrapper> one = IntWrapper::create(1);
4340 Persistent<IntWrapper> two = IntWrapper::create(2);
4341 outer->add(one, InnerMap());
4342 outer->begin()->value.add(two, IntWrapper::create(3));
4343 EXPECT_EQ(1u, outer->get(one).size());
4344 if (!keepOuterAlive)
4346 if (!keepInnerAlive)
4348 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4349 if (keepOuterAlive) {
4350 const InnerMap& inner = outer->get(one);
4351 if (keepInnerAlive) {
4352 EXPECT_EQ(1u, inner.size());
4353 IntWrapper* three = inner.get(two);
4354 EXPECT_EQ(3, three->value());
4356 EXPECT_EQ(0u, inner.size());
4359 EXPECT_EQ(0u, outer->size());
4362 Persistent<IntWrapper> deep = IntWrapper::create(42);
4363 Persistent<IntWrapper> home = IntWrapper::create(103);
4364 Persistent<IntWrapper> composite = IntWrapper::create(91);
4365 Persistent<HeapVector<Member<IntWrapper> > > keepAlive = new HeapVector<Member<IntWrapper> >();
4366 for (int i = 0; i < 10000; i++) {
4367 IntWrapper* value = IntWrapper::create(i);
4368 keepAlive->append(value);
4369 OuterMap::AddResult newEntry = outer->add(value, InnerMap());
4370 newEntry.storedValue->value.add(deep, home);
4371 newEntry.storedValue->value.add(composite, home);
4374 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4375 EXPECT_EQ(10000u, outer->size());
4376 for (int i = 0; i < 10000; i++) {
4377 IntWrapper* value = keepAlive->at(i);
4378 EXPECT_EQ(1u, outer->get(value).size()); // Other one was deleted by weak handling.
4380 keepAlive->at(i) = nullptr;
4382 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4383 EXPECT_EQ(5000u, outer->size());
4388 class EphemeronWrapper : public GarbageCollected<EphemeronWrapper> {
4390 void trace(Visitor* visitor)
4392 visitor->trace(m_map);
4395 typedef HeapHashMap<WeakMember<IntWrapper>, Member<EphemeronWrapper> > Map;
4396 Map& map() { return m_map; }
4402 TEST(HeapTest, EphemeronsPointToEphemerons)
4404 Persistent<IntWrapper> key = IntWrapper::create(42);
4405 Persistent<IntWrapper> key2 = IntWrapper::create(103);
4407 Persistent<EphemeronWrapper> chain;
4408 for (int i = 0; i < 100; i++) {
4409 EphemeronWrapper* oldHead = chain;
4410 chain = new EphemeronWrapper();
4412 chain->map().add(key2, oldHead);
4414 chain->map().add(key, oldHead);
4415 chain->map().add(IntWrapper::create(103), new EphemeronWrapper());
4418 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4420 EphemeronWrapper* wrapper = chain;
4421 for (int i = 0; i< 100; i++) {
4422 EXPECT_EQ(1u, wrapper->map().size());
4424 wrapper = wrapper->map().get(key2);
4426 wrapper = wrapper->map().get(key);
4428 EXPECT_EQ(nullptr, wrapper);
4431 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4434 for (int i = 0; i < 50; i++) {
4435 EXPECT_EQ(i == 49 ? 0u : 1u, wrapper->map().size());
4436 wrapper = wrapper->map().get(key);
4438 EXPECT_EQ(nullptr, wrapper);
4441 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4442 EXPECT_EQ(0u, chain->map().size());
4445 TEST(HeapTest, Ephemeron)
4447 typedef HeapHashMap<WeakMember<IntWrapper>, PairWithWeakHandling> WeakPairMap;
4448 typedef HeapHashMap<PairWithWeakHandling, WeakMember<IntWrapper> > PairWeakMap;
4449 typedef HeapHashSet<WeakMember<IntWrapper> > Set;
4451 Persistent<WeakPairMap> weakPairMap = new WeakPairMap();
4452 Persistent<WeakPairMap> weakPairMap2 = new WeakPairMap();
4453 Persistent<WeakPairMap> weakPairMap3 = new WeakPairMap();
4454 Persistent<WeakPairMap> weakPairMap4 = new WeakPairMap();
4456 Persistent<PairWeakMap> pairWeakMap = new PairWeakMap();
4457 Persistent<PairWeakMap> pairWeakMap2 = new PairWeakMap();
4459 Persistent<Set> set = new Set();
4461 Persistent<IntWrapper> wp1 = IntWrapper::create(1);
4462 Persistent<IntWrapper> wp2 = IntWrapper::create(2);
4463 Persistent<IntWrapper> pw1 = IntWrapper::create(3);
4464 Persistent<IntWrapper> pw2 = IntWrapper::create(4);
4466 weakPairMap->add(wp1, PairWithWeakHandling(wp1, wp1));
4467 weakPairMap->add(wp2, PairWithWeakHandling(wp1, wp1));
4468 weakPairMap2->add(wp1, PairWithWeakHandling(wp1, wp2));
4469 weakPairMap2->add(wp2, PairWithWeakHandling(wp1, wp2));
4470 // The map from wp1 to (wp2, wp1) would mark wp2 live, so we skip that.
4471 weakPairMap3->add(wp2, PairWithWeakHandling(wp2, wp1));
4472 weakPairMap4->add(wp1, PairWithWeakHandling(wp2, wp2));
4473 weakPairMap4->add(wp2, PairWithWeakHandling(wp2, wp2));
4475 pairWeakMap->add(PairWithWeakHandling(pw1, pw1), pw1);
4476 pairWeakMap->add(PairWithWeakHandling(pw1, pw2), pw1);
4477 // The map from (pw2, pw1) to pw1 would make pw2 live, so we skip that.
4478 pairWeakMap->add(PairWithWeakHandling(pw2, pw2), pw1);
4479 pairWeakMap2->add(PairWithWeakHandling(pw1, pw1), pw2);
4480 pairWeakMap2->add(PairWithWeakHandling(pw1, pw2), pw2);
4481 pairWeakMap2->add(PairWithWeakHandling(pw2, pw1), pw2);
4482 pairWeakMap2->add(PairWithWeakHandling(pw2, pw2), pw2);
4490 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4492 EXPECT_EQ(2u, weakPairMap->size());
4493 EXPECT_EQ(2u, weakPairMap2->size());
4494 EXPECT_EQ(1u, weakPairMap3->size());
4495 EXPECT_EQ(2u, weakPairMap4->size());
4497 EXPECT_EQ(3u, pairWeakMap->size());
4498 EXPECT_EQ(4u, pairWeakMap2->size());
4500 EXPECT_EQ(4u, set->size());
4502 wp2.clear(); // Kills all entries in the weakPairMaps except the first.
4503 pw2.clear(); // Kills all entries in the pairWeakMaps except the first.
4505 for (int i = 0; i < 2; i++) {
4506 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4508 EXPECT_EQ(1u, weakPairMap->size());
4509 EXPECT_EQ(0u, weakPairMap2->size());
4510 EXPECT_EQ(0u, weakPairMap3->size());
4511 EXPECT_EQ(0u, weakPairMap4->size());
4513 EXPECT_EQ(1u, pairWeakMap->size());
4514 EXPECT_EQ(0u, pairWeakMap2->size());
4516 EXPECT_EQ(2u, set->size()); // wp1 and pw1.
4522 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4524 EXPECT_EQ(0u, weakPairMap->size());
4525 EXPECT_EQ(0u, pairWeakMap->size());
4526 EXPECT_EQ(0u, set->size());
4529 class Link1 : public GarbageCollected<Link1> {
4531 Link1(IntWrapper* link) : m_link(link) { }
4533 void trace(Visitor* visitor)
4535 visitor->trace(m_link);
4538 IntWrapper* link() { return m_link; }
4541 Member<IntWrapper> m_link;
4544 TEST(HeapTest, IndirectStrongToWeak)
4546 typedef HeapHashMap<WeakMember<IntWrapper>, Member<Link1> > Map;
4547 Persistent<Map> map = new Map();
4548 Persistent<IntWrapper> deadObject = IntWrapper::create(100); // Named for "Drowning by Numbers" (1988).
4549 Persistent<IntWrapper> lifeObject = IntWrapper::create(42);
4550 map->add(deadObject, new Link1(deadObject));
4551 map->add(lifeObject, new Link1(lifeObject));
4552 EXPECT_EQ(2u, map->size());
4553 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4554 EXPECT_EQ(2u, map->size());
4555 EXPECT_EQ(deadObject, map->get(deadObject)->link());
4556 EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4557 deadObject.clear(); // Now it can live up to its name.
4558 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4559 EXPECT_EQ(1u, map->size());
4560 EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4561 lifeObject.clear(); // Despite its name.
4562 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4563 EXPECT_EQ(0u, map->size());
4566 static Mutex& mainThreadMutex()
4568 AtomicallyInitializedStatic(Mutex&, mainMutex = *new Mutex);
4572 static ThreadCondition& mainThreadCondition()
4574 AtomicallyInitializedStatic(ThreadCondition&, mainCondition = *new ThreadCondition);
4575 return mainCondition;
4578 static void parkMainThread()
4580 mainThreadCondition().wait(mainThreadMutex());
4583 static void wakeMainThread()
4585 MutexLocker locker(mainThreadMutex());
4586 mainThreadCondition().signal();
4589 static Mutex& workerThreadMutex()
4591 AtomicallyInitializedStatic(Mutex&, workerMutex = *new Mutex);
4595 static ThreadCondition& workerThreadCondition()
4597 AtomicallyInitializedStatic(ThreadCondition&, workerCondition = *new ThreadCondition);
4598 return workerCondition;
4601 static void parkWorkerThread()
4603 workerThreadCondition().wait(workerThreadMutex());
4606 static void wakeWorkerThread()
4608 MutexLocker locker(workerThreadMutex());
4609 workerThreadCondition().signal();
4612 class CrossThreadObject : public GarbageCollectedFinalized<CrossThreadObject> {
4614 static CrossThreadObject* create(IntWrapper* workerObjectPointer)
4616 return new CrossThreadObject(workerObjectPointer);
4619 virtual ~CrossThreadObject()
4621 ++s_destructorCalls;
4624 static int s_destructorCalls;
4625 void trace(Visitor* visitor) { visitor->trace(m_workerObject); }
4628 CrossThreadObject(IntWrapper* workerObjectPointer) : m_workerObject(workerObjectPointer) { }
4631 Member<IntWrapper> m_workerObject;
4634 int CrossThreadObject::s_destructorCalls = 0;
4636 class CrossThreadPointerTester {
4640 CrossThreadObject::s_destructorCalls = 0;
4641 IntWrapper::s_destructorCalls = 0;
4643 MutexLocker locker(mainThreadMutex());
4644 createThread(&workerThreadMain, 0, "Worker Thread");
4648 uintptr_t stackPtrValue = 0;
4650 // Create an object with a pointer to the other heap's IntWrapper.
4651 Persistent<CrossThreadObject> cto = CrossThreadObject::create(const_cast<IntWrapper*>(s_workerObjectPointer));
4652 s_workerObjectPointer = 0;
4654 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4656 // Nothing should have been collected/destructed.
4657 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4658 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4660 // Put cto into a stack value. This is used to check that a conservative
4661 // GC succeeds even though we are tracing the other thread heap after
4662 // shutting it down.
4663 stackPtrValue = reinterpret_cast<uintptr_t>(cto.get());
4665 // At this point it is "programatically" okay to shut down the worker thread
4666 // since the cto object should be dead. However out stackPtrValue will cause a
4667 // trace of the object when doing a conservative GC.
4668 // The worker thread's thread local GC's should just add the worker thread's
4669 // pages to the heap after finalizing IntWrapper.
4672 // Wait for the worker to shutdown.
4675 // After the worker thread has detached it should have finalized the
4676 // IntWrapper object on its heaps. Since there has been no global GC
4677 // the cto object should not have been finalized.
4678 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4679 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4681 // Now do a conservative GC. The stackPtrValue should keep cto alive
4682 // and will also cause the orphaned page of the other thread to be
4683 // traced. At this point cto should still not be finalized.
4684 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4685 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4686 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4688 // This release assert is here to ensure the stackValuePtr is not
4689 // optimized away before doing the above conservative GC. If the
4690 // EXPECT_EQ(0, CrossThreadObject::s_destructorCalls) call above
4691 // starts failing it means we have to find a better way to ensure
4692 // the stackPtrValue is not optimized away.
4693 RELEASE_ASSERT(stackPtrValue);
4695 // Do a GC with no pointers on the stack to see the cto being collected.
4696 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4697 EXPECT_EQ(1, CrossThreadObject::s_destructorCalls);
4698 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4702 static void workerThreadMain(void* data)
4704 MutexLocker locker(workerThreadMutex());
4705 ThreadState::attach();
4708 // Create a worker object that is only kept alive by a cross thread
4709 // pointer (from CrossThreadObject).
4710 IntWrapper* workerObject = IntWrapper::create(42);
4711 s_workerObjectPointer = workerObject;
4714 // Wake up the main thread which is waiting for the worker to do its
4715 // allocation and passing the pointer.
4718 // Wait for main thread to signal the worker to shutdown.
4720 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4724 ThreadState::detach();
4726 // Tell the main thread the worker has done its shutdown.
4730 static volatile IntWrapper* s_workerObjectPointer;
4733 volatile IntWrapper* CrossThreadPointerTester::s_workerObjectPointer = 0;
4735 TEST(HeapTest, CrossThreadPointerToOrphanedPage)
4737 CrossThreadPointerTester::test();
4740 class DeadBitTester {
4744 IntWrapper::s_destructorCalls = 0;
4746 MutexLocker locker(mainThreadMutex());
4747 createThread(&workerThreadMain, 0, "Worker Thread");
4749 // Wait for the worker thread to have done its initialization,
4750 // IE. the worker allocates an object and then throw aways any
4754 // Now do a GC. This will not find the worker threads object since it
4755 // is not referred from any of the threads. Even a conservative
4756 // GC will not find it.
4757 // Also at this point the worker is waiting for the main thread
4758 // to be parked and will not do any sweep of its heap.
4759 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4761 // Since the worker thread is not sweeping the worker object should
4762 // not have been finalized.
4763 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4765 // Put the worker thread's object address on the stack and do a
4766 // conservative GC. This should find the worker object, but since
4767 // it was dead in the previous GC it should not be traced in this
4769 uintptr_t stackPtrValue = s_workerObjectPointer;
4770 s_workerObjectPointer = 0;
4771 ASSERT_UNUSED(stackPtrValue, stackPtrValue);
4772 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4774 // Since the worker thread is not sweeping the worker object should
4775 // not have been finalized.
4776 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4778 // Wake up the worker thread so it can continue with its sweeping.
4779 // This should finalized the worker object which we test below.
4780 // The worker thread will go back to sleep once sweeping to ensure
4781 // we don't have thread local GCs until after validating the destructor
4785 // Wait for the worker thread to sweep its heaps before checking.
4787 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4789 // Wake up the worker to allow it thread to continue with thread
4796 static void workerThreadMain(void* data)
4798 MutexLocker locker(workerThreadMutex());
4800 ThreadState::attach();
4803 // Create a worker object that is not kept alive except the
4804 // main thread will keep it as an integer value on its stack.
4805 IntWrapper* workerObject = IntWrapper::create(42);
4806 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject);
4809 // Signal the main thread that the worker is done with its allocation.
4813 // Wait for the main thread to do two GCs without sweeping this thread
4814 // heap. The worker waits within a safepoint, but there is no sweeping
4815 // until leaving the safepoint scope.
4816 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4820 // Wake up the main thread when done sweeping.
4823 // Wait with detach until the main thread says so. This is not strictly
4824 // necessary, but it means the worker thread will not do its thread local
4825 // GCs just yet, making it easier to reason about that no new GC has occurred
4826 // and the above sweep was the one finalizing the worker object.
4829 ThreadState::detach();
4832 static volatile uintptr_t s_workerObjectPointer;
4835 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0;
4837 TEST(HeapTest, ObjectDeadBit)
4839 DeadBitTester::test();
4842 static bool allocateAndReturnBool()
4844 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4848 class MixinWithGarbageCollectionInConstructor : public GarbageCollectedMixin {
4850 MixinWithGarbageCollectionInConstructor() : m_dummy(allocateAndReturnBool())
4857 class ClassWithGarbageCollectingMixinConstructor
4858 : public GarbageCollected<ClassWithGarbageCollectingMixinConstructor>
4859 , public MixinWithGarbageCollectionInConstructor {
4860 USING_GARBAGE_COLLECTED_MIXIN(ClassWithGarbageCollectingMixinConstructor);
4862 ClassWithGarbageCollectingMixinConstructor() : m_wrapper(IntWrapper::create(32))
4866 virtual void trace(Visitor* visitor)
4868 visitor->trace(m_wrapper);
4873 EXPECT_EQ(32, m_wrapper->value());
4877 Member<IntWrapper> m_wrapper;
4880 // Regression test for out of bounds call through vtable.
4881 // Passes if it doesn't crash.
4882 TEST(HeapTest, GarbageCollectionDuringMixinConstruction)
4884 ClassWithGarbageCollectingMixinConstructor* a =
4885 new ClassWithGarbageCollectingMixinConstructor();
4889 static RecursiveMutex& recursiveMutex()
4891 AtomicallyInitializedStatic(RecursiveMutex&, recursiveMutex = *new RecursiveMutex);
4892 return recursiveMutex;
4895 class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLockingObject> {
4897 static DestructorLockingObject* create()
4899 return new DestructorLockingObject();
4902 virtual ~DestructorLockingObject()
4904 SafePointAwareMutexLocker lock(recursiveMutex());
4905 ++s_destructorCalls;
4908 static int s_destructorCalls;
4909 void trace(Visitor* visitor) { }
4912 DestructorLockingObject() { }
4915 int DestructorLockingObject::s_destructorCalls = 0;
4917 class RecursiveLockingTester {
4921 DestructorLockingObject::s_destructorCalls = 0;
4923 MutexLocker locker(mainThreadMutex());
4924 createThread(&workerThreadMain, 0, "Worker Thread");
4926 // Park the main thread until the worker thread has initialized.
4930 SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
4932 // Let the worker try to acquire the above mutex. It won't get it
4933 // until the main thread has done its GC.
4936 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4938 // The worker thread should not have swept yet since it is waiting
4939 // to get the global mutex.
4940 EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
4942 // At this point the main thread releases the global lock and the worker
4943 // can acquire it and do its sweep of its heaps. Just wait for the worker
4944 // to complete its sweep and check the result.
4946 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
4950 static void workerThreadMain(void* data)
4952 MutexLocker locker(workerThreadMutex());
4953 ThreadState::attach();
4955 DestructorLockingObject* dlo = DestructorLockingObject::create();
4956 ASSERT_UNUSED(dlo, dlo);
4958 // Wake up the main thread which is waiting for the worker to do its
4962 // Wait for the main thread to get the global lock to ensure it has
4963 // it before the worker tries to acquire it. We want the worker to
4964 // block in the SafePointAwareMutexLocker until the main thread
4965 // has done a GC. The GC will not mark the "dlo" object since the worker
4966 // is entering the safepoint with NoHeapPointersOnStack. When the worker
4967 // subsequently gets the global lock and leaves the safepoint it will
4968 // sweep its heap and finalize "dlo". The destructor of "dlo" will try
4969 // to acquire the same global lock that the thread just got and deadlock
4970 // unless the global lock is recursive.
4972 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState::NoHeapPointersOnStack);
4974 // We won't get here unless the lock is recursive since the sweep done
4975 // in the constructor of SafePointAwareMutexLocker after
4976 // getting the lock will not complete given the "dlo" destructor is
4977 // waiting to get the same lock.
4978 // Tell the main thread the worker has done its sweep.
4981 ThreadState::detach();
4984 static volatile IntWrapper* s_workerObjectPointer;
4987 TEST(HeapTest, RecursiveMutex)
4989 RecursiveLockingTester::test();
4992 template<typename T>
4993 class TraceIfNeededTester : public GarbageCollectedFinalized<TraceIfNeededTester<T> > {
4995 static TraceIfNeededTester<T>* create() { return new TraceIfNeededTester<T>(); }
4996 static TraceIfNeededTester<T>* create(const T& obj) { return new TraceIfNeededTester<T>(obj); }
4997 void trace(Visitor* visitor) { TraceIfNeeded<T>::trace(visitor, &m_obj); }
4998 T& obj() { return m_obj; }
4999 ~TraceIfNeededTester() { }
5001 TraceIfNeededTester() { }
5002 explicit TraceIfNeededTester(const T& obj) : m_obj(obj) { }
5007 DISALLOW_ALLOCATION();
5009 PartObject() : m_obj(SimpleObject::create()) { }
5010 void trace(Visitor* visitor) { visitor->trace(m_obj); }
5012 Member<SimpleObject> m_obj;
5015 TEST(HeapTest, TraceIfNeeded)
5017 CountingVisitor visitor;
5020 TraceIfNeededTester<RefPtr<OffHeapInt> >* m_offHeap = TraceIfNeededTester<RefPtr<OffHeapInt> >::create(OffHeapInt::create(42));
5022 m_offHeap->trace(&visitor);
5023 EXPECT_EQ(0u, visitor.count());
5027 TraceIfNeededTester<PartObject>* m_part = TraceIfNeededTester<PartObject>::create();
5029 m_part->trace(&visitor);
5030 EXPECT_EQ(1u, visitor.count());
5034 TraceIfNeededTester<Member<SimpleObject> >* m_obj = TraceIfNeededTester<Member<SimpleObject> >::create(Member<SimpleObject>(SimpleObject::create()));
5036 m_obj->trace(&visitor);
5037 EXPECT_EQ(1u, visitor.count());
5041 TraceIfNeededTester<HeapVector<Member<SimpleObject> > >* m_vec = TraceIfNeededTester<HeapVector<Member<SimpleObject> > >::create();
5042 m_vec->obj().append(SimpleObject::create());
5044 m_vec->trace(&visitor);
5045 EXPECT_EQ(2u, visitor.count());
5049 class PartObjectWithVirtualMethod {
5051 virtual void trace(Visitor*) { }
5054 class ObjectWithVirtualPartObject : public GarbageCollected<ObjectWithVirtualPartObject> {
5056 ObjectWithVirtualPartObject() : m_dummy(allocateAndReturnBool()) { }
5057 void trace(Visitor* visitor) { visitor->trace(m_part); }
5060 PartObjectWithVirtualMethod m_part;
5063 TEST(HeapTest, PartObjectWithVirtualMethod)
5065 ObjectWithVirtualPartObject* object = new ObjectWithVirtualPartObject();
5066 EXPECT_TRUE(object);
5069 class AllocInSuperConstructorArgumentSuper : public GarbageCollectedFinalized<AllocInSuperConstructorArgumentSuper> {
5071 AllocInSuperConstructorArgumentSuper(bool value) : m_value(value) { }
5072 virtual void trace(Visitor*) { }
5073 bool value() { return m_value; }
5078 class AllocInSuperConstructorArgument : public AllocInSuperConstructorArgumentSuper {
5080 AllocInSuperConstructorArgument()
5081 : AllocInSuperConstructorArgumentSuper(allocateAndReturnBool())
5086 // Regression test for crbug.com/404511. Tests conservative marking of
5087 // an object with an uninitialized vtable.
5088 TEST(HeapTest, AllocationInSuperConstructorArgument)
5090 AllocInSuperConstructorArgument* object = new AllocInSuperConstructorArgument();
5091 EXPECT_TRUE(object);
5092 Heap::collectAllGarbage();
5095 } // namespace blink