2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "platform/Task.h"
34 #include "platform/heap/Handle.h"
35 #include "platform/heap/Heap.h"
36 #include "platform/heap/HeapLinkedStack.h"
37 #include "platform/heap/HeapTerminatedArrayBuilder.h"
38 #include "platform/heap/ThreadState.h"
39 #include "platform/heap/Visitor.h"
40 #include "public/platform/Platform.h"
41 #include "wtf/HashTraits.h"
42 #include "wtf/LinkedHashSet.h"
44 #include <gtest/gtest.h>
48 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
50 static IntWrapper* create(int x)
52 return new IntWrapper(x);
60 static int s_destructorCalls;
61 static void trace(Visitor*) { }
63 int value() const { return m_x; }
65 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
67 unsigned hash() { return IntHash<int>::hash(m_x); }
69 IntWrapper(int x) : m_x(x) { }
78 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(0) { }
79 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i) { }
80 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(reinterpret_cast<ThreadState*>(-1)), m_num(0) { }
83 EXPECT_TRUE((m_creatingThread == ThreadState::current())
84 || (m_creatingThread == reinterpret_cast<ThreadState*>(0))
85 || (m_creatingThread == reinterpret_cast<ThreadState*>(-1)));
87 bool isHashTableDeletedValue() const { return m_creatingThread == reinterpret_cast<ThreadState*>(-1); }
88 bool operator==(const ThreadMarker& other) const { return other.m_creatingThread == m_creatingThread && other.m_num == m_num; }
89 ThreadState* m_creatingThread;
93 struct ThreadMarkerHash {
94 static unsigned hash(const ThreadMarker& key)
96 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(key.m_creatingThread) + key.m_num);
99 static bool equal(const ThreadMarker& a, const ThreadMarker& b)
104 static const bool safeToCompareToEmptyOrDeleted = false;
107 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeakPair;
109 struct PairWithWeakHandling : public StrongWeakPair {
110 ALLOW_ONLY_INLINE_ALLOCATION();
113 // Regular constructor.
114 PairWithWeakHandling(IntWrapper* one, IntWrapper* two)
115 : StrongWeakPair(one, two)
117 ASSERT(one); // We use null first field to indicate empty slots in the hash table.
120 // The HashTable (via the HashTrait) calls this constructor with a
121 // placement new to mark slots in the hash table as being deleted. We will
122 // never call trace or the destructor on these slots. We mark ourselves deleted
123 // with a pointer to -1 in the first field.
124 PairWithWeakHandling(WTF::HashTableDeletedValueType)
125 : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr)
129 // Used by the HashTable (via the HashTrait) to skip deleted slots in the
130 // table. Recognizes objects that were 'constructed' using the above
132 bool isHashTableDeletedValue() const { return first == reinterpret_cast<IntWrapper*>(-1); }
134 // Since we don't allocate independent objects of this type, we don't need
135 // a regular trace method. Instead, we use a traceInCollection method. If
136 // the entry should be deleted from the collection we return true and don't
137 // trace the strong pointer.
138 bool traceInCollection(Visitor* visitor, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
140 visitor->traceInCollection(second, strongify);
141 if (!visitor->isAlive(second))
143 visitor->trace(first);
152 template<typename T> struct DefaultHash;
153 template<> struct DefaultHash<blink::ThreadMarker> {
154 typedef blink::ThreadMarkerHash Hash;
157 // ThreadMarkerHash is the default hash for ThreadMarker
158 template<> struct HashTraits<blink::ThreadMarker> : GenericHashTraits<blink::ThreadMarker> {
159 static const bool emptyValueIsZero = true;
160 static void constructDeletedValue(blink::ThreadMarker& slot, bool) { new (NotNull, &slot) blink::ThreadMarker(HashTableDeletedValue); }
161 static bool isDeletedValue(const blink::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
164 // The hash algorithm for our custom pair class is just the standard double
165 // hash for pairs. Note that this means you can't mutate either of the parts of
166 // the pair while they are in the hash table, as that would change their hash
167 // code and thus their preferred placement in the table.
168 template<> struct DefaultHash<blink::PairWithWeakHandling> {
169 typedef PairHash<blink::Member<blink::IntWrapper>, blink::WeakMember<blink::IntWrapper> > Hash;
172 // Custom traits for the pair. These are weakness handling traits, which means
173 // PairWithWeakHandling must implement the traceInCollection method.
174 // In addition, these traits are concerned with the two magic values for the
175 // object, that represent empty and deleted slots in the hash table. The
176 // SimpleClassHashTraits allow empty slots in the table to be initialzed with
177 // memset to zero, and we use -1 in the first part of the pair to represent
179 template<> struct HashTraits<blink::PairWithWeakHandling> : blink::WeakHandlingHashTraits<blink::PairWithWeakHandling> {
180 static const bool needsDestruction = false;
181 static const bool hasIsEmptyValueFunction = true;
182 static bool isEmptyValue(const blink::PairWithWeakHandling& value) { return !value.first; }
183 static void constructDeletedValue(blink::PairWithWeakHandling& slot, bool) { new (NotNull, &slot) blink::PairWithWeakHandling(HashTableDeletedValue); }
184 static bool isDeletedValue(const blink::PairWithWeakHandling& value) { return value.isHashTableDeletedValue(); }
193 explicit TestGCScope(ThreadState::StackState state)
194 : m_state(ThreadState::current())
195 , m_safePointScope(state)
196 , m_parkedAllThreads(false)
198 m_state->checkThread();
199 EXPECT_FALSE(m_state->isInGC());
200 if (LIKELY(ThreadState::stopThreads())) {
202 m_parkedAllThreads = true;
206 bool allThreadsParked() { return m_parkedAllThreads; }
210 // Only cleanup if we parked all threads in which case the GC happened
211 // and we need to resume the other threads.
212 if (LIKELY(m_parkedAllThreads)) {
214 EXPECT_FALSE(m_state->isInGC());
215 ThreadState::resumeThreads();
220 ThreadState* m_state;
221 ThreadState::SafePointScope m_safePointScope;
222 bool m_parkedAllThreads; // False if we fail to park all threads
225 static void getHeapStats(HeapStats* stats)
227 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
228 EXPECT_TRUE(scope.allThreadsParked());
229 Heap::getStatsForTesting(stats);
232 #define DEFINE_VISITOR_METHODS(Type) \
233 virtual void mark(const Type* object, TraceCallback callback) override \
238 virtual bool isMarked(const Type*) override { return false; }
240 class CountingVisitor : public Visitor {
247 virtual void mark(const void* object, TraceCallback) override
253 virtual void mark(HeapObjectHeader* header, TraceCallback callback) override
255 ASSERT(header->payload());
259 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) override
261 ASSERT(header->payload());
265 virtual void registerDelayedMarkNoTracing(const void*) override { }
266 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) override { }
267 virtual void registerWeakTable(const void*, EphemeronCallback, EphemeronCallback) override { }
269 virtual bool weakTableRegistered(const void*) override { return false; }
271 virtual void registerWeakCell(void**, WeakPointerCallback) override { }
272 virtual bool isMarked(const void*) override { return false; }
274 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
276 size_t count() { return m_count; }
277 void reset() { m_count = 0; }
283 class SimpleObject : public GarbageCollected<SimpleObject> {
285 static SimpleObject* create() { return new SimpleObject(); }
286 void trace(Visitor*) { }
287 char getPayload(int i) { return payload[i]; }
288 // This virtual method is unused but it is here to make sure
289 // that this object has a vtable. This object is used
290 // as the super class for objects that also have garbage
291 // collected mixins and having a virtual here makes sure
292 // that adjustment is needed both for marking and for isAlive
294 virtual void virtualMethod() { }
300 #undef DEFINE_VISITOR_METHODS
302 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
304 static HeapTestSuperClass* create()
306 return new HeapTestSuperClass();
309 virtual ~HeapTestSuperClass()
314 static int s_destructorCalls;
315 void trace(Visitor*) { }
318 HeapTestSuperClass() { }
321 int HeapTestSuperClass::s_destructorCalls = 0;
323 class HeapTestOtherSuperClass {
328 static const size_t classMagic = 0xABCDDBCA;
330 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
332 static HeapTestSubClass* create()
334 return new HeapTestSubClass();
337 virtual ~HeapTestSubClass()
339 EXPECT_EQ(classMagic, m_magic);
343 static int s_destructorCalls;
347 HeapTestSubClass() : m_magic(classMagic) { }
349 const size_t m_magic;
352 int HeapTestSubClass::s_destructorCalls = 0;
354 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
358 for (int i = 0; i < s_arraySize; ++i) {
359 m_array[i] = i % 128;
363 int8_t at(size_t i) { return m_array[i]; }
364 void trace(Visitor*) { }
366 static const int s_arraySize = 1000;
367 int8_t m_array[s_arraySize];
370 // Do several GCs to make sure that later GCs don't free up old memory from
371 // previously run tests in this process.
372 static void clearOutOldGarbage(HeapStats* heapStats)
375 getHeapStats(heapStats);
376 size_t used = heapStats->totalObjectSpace();
377 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
378 getHeapStats(heapStats);
379 if (heapStats->totalObjectSpace() >= used)
384 class OffHeapInt : public RefCounted<OffHeapInt> {
386 static RefPtr<OffHeapInt> create(int x)
388 return adoptRef(new OffHeapInt(x));
391 virtual ~OffHeapInt()
396 static int s_destructorCalls;
398 int value() const { return m_x; }
400 bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
402 unsigned hash() { return IntHash<int>::hash(m_x); }
403 void voidFunction() { }
406 OffHeapInt(int x) : m_x(x) { }
413 int IntWrapper::s_destructorCalls = 0;
414 int OffHeapInt::s_destructorCalls = 0;
416 class ThreadedTesterBase {
418 static void test(ThreadedTesterBase* tester)
420 Vector<OwnPtr<WebThread>, numberOfThreads> m_threads;
421 for (int i = 0; i < numberOfThreads; i++) {
422 m_threads.append(adoptPtr(Platform::current()->createThread("blink gc testing thread")));
423 m_threads.last()->postTask(new Task(WTF::bind(threadFunc, tester)));
425 while (tester->m_threadsToFinish) {
426 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
427 Platform::current()->yieldCurrentThread();
432 virtual void runThread() = 0;
435 static const int numberOfThreads = 10;
436 static const int gcPerThread = 5;
437 static const int numberOfAllocations = 50;
439 ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
443 virtual ~ThreadedTesterBase()
447 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
449 volatile int m_gcCount;
450 volatile int m_threadsToFinish;
453 static void threadFunc(void* data)
455 reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
459 class ThreadedHeapTester : public ThreadedTesterBase {
463 ThreadedTesterBase::test(new ThreadedHeapTester);
467 virtual void runThread() override
469 ThreadState::attach();
473 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
475 Persistent<IntWrapper> wrapper;
477 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
478 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
480 for (int i = 0; i < numberOfAllocations; i++) {
481 wrapper = IntWrapper::create(0x0bbac0de);
483 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
485 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
486 Platform::current()->yieldCurrentThread();
489 if (gcCount < gcPerThread) {
490 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
492 atomicIncrement(&m_gcCount);
495 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
496 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
497 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
499 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
500 Platform::current()->yieldCurrentThread();
502 ThreadState::detach();
503 atomicDecrement(&m_threadsToFinish);
507 class ThreadedWeaknessTester : public ThreadedTesterBase {
511 ThreadedTesterBase::test(new ThreadedWeaknessTester);
515 virtual void runThread() override
517 ThreadState::attach();
521 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
523 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
524 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
526 for (int i = 0; i < numberOfAllocations; i++) {
527 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
528 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
529 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
530 Platform::current()->yieldCurrentThread();
533 if (gcCount < gcPerThread) {
534 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
536 atomicIncrement(&m_gcCount);
539 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
540 EXPECT_TRUE(weakMap->isEmpty());
541 EXPECT_TRUE(weakMap2.isEmpty());
543 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
544 Platform::current()->yieldCurrentThread();
546 ThreadState::detach();
547 atomicDecrement(&m_threadsToFinish);
551 // The accounting for memory includes the memory used by rounding up object
552 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
553 // have some slack in the tests.
555 void CheckWithSlack(T expected, T actual, int slack)
557 EXPECT_LE(expected, actual);
558 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
561 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
563 static TraceCounter* create()
565 return new TraceCounter();
568 void trace(Visitor*) { m_traceCount++; }
570 int traceCount() { return m_traceCount; }
581 class ClassWithMember : public GarbageCollected<ClassWithMember> {
583 static ClassWithMember* create()
585 return new ClassWithMember();
588 void trace(Visitor* visitor)
590 EXPECT_TRUE(visitor->isMarked(this));
592 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
594 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
596 visitor->trace(m_traceCounter);
599 int traceCount() { return m_traceCounter->traceCount(); }
603 : m_traceCounter(TraceCounter::create())
606 Member<TraceCounter> m_traceCounter;
609 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
611 static SimpleFinalizedObject* create()
613 return new SimpleFinalizedObject();
616 ~SimpleFinalizedObject()
621 static int s_destructorCalls;
623 void trace(Visitor*) { }
626 SimpleFinalizedObject() { }
629 int SimpleFinalizedObject::s_destructorCalls = 0;
631 class Node : public GarbageCollected<Node> {
633 static Node* create(int i)
638 void trace(Visitor*) { }
640 int value() { return m_value; }
643 Node(int i) : m_value(i) { }
647 class Bar : public GarbageCollectedFinalized<Bar> {
654 void finalizeGarbageCollectedObject()
656 EXPECT_TRUE(m_magic == magic);
660 bool hasBeenFinalized() const { return !m_magic; }
662 virtual void trace(Visitor* visitor) { }
663 static unsigned s_live;
666 static const int magic = 1337;
676 unsigned Bar::s_live = 0;
678 class Baz : public GarbageCollected<Baz> {
680 static Baz* create(Bar* bar)
685 void trace(Visitor* visitor)
687 visitor->trace(m_bar);
690 void clear() { m_bar.release(); }
692 // willFinalize is called by FinalizationObserver.
695 EXPECT_TRUE(!m_bar->hasBeenFinalized());
699 explicit Baz(Bar* bar)
707 class Foo : public Bar {
709 static Foo* create(Bar* bar)
714 static Foo* create(Foo* foo)
719 virtual void trace(Visitor* visitor) override
722 visitor->mark(static_cast<Foo*>(m_bar));
724 visitor->mark(m_bar);
731 , m_pointsToFoo(false)
738 , m_pointsToFoo(true)
746 class Bars : public Bar {
748 static Bars* create()
753 virtual void trace(Visitor* visitor) override
755 for (unsigned i = 0; i < m_width; i++)
756 visitor->trace(m_bars[i]);
759 unsigned getWidth() const
764 static const unsigned width = 7500;
768 for (unsigned i = 0; i < width; i++) {
769 m_bars[i] = Bar::create();
775 Member<Bar> m_bars[width];
778 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
780 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
782 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
785 ConstructorAllocation()
787 m_intWrapper = IntWrapper::create(42);
790 Member<IntWrapper> m_intWrapper;
793 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
799 static LargeObject* create() { return new LargeObject(); }
800 char get(size_t i) { return m_data[i]; }
801 void set(size_t i, char c) { m_data[i] = c; }
802 size_t length() { return s_length; }
803 void trace(Visitor* visitor)
805 visitor->trace(m_intWrapper);
807 static int s_destructorCalls;
810 static const size_t s_length = 1024*1024;
813 m_intWrapper = IntWrapper::create(23);
815 Member<IntWrapper> m_intWrapper;
816 char m_data[s_length];
819 int LargeObject::s_destructorCalls = 0;
821 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
823 static RefCountedAndGarbageCollected* create()
825 return new RefCountedAndGarbageCollected();
828 ~RefCountedAndGarbageCollected()
833 // These are here with their default implementations so you can break in
834 // them in the debugger.
835 void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref(); }
836 void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::deref(); }
838 void trace(Visitor*) { }
840 static int s_destructorCalls;
843 RefCountedAndGarbageCollected()
848 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
850 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
852 static RefCountedAndGarbageCollected2* create()
854 return new RefCountedAndGarbageCollected2();
857 ~RefCountedAndGarbageCollected2()
862 void trace(Visitor*) { }
864 static int s_destructorCalls;
867 RefCountedAndGarbageCollected2()
872 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
874 #define DEFINE_VISITOR_METHODS(Type) \
875 virtual void mark(const Type* object, TraceCallback callback) override \
880 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
882 RefCountedGarbageCollectedVisitor(int expected, void** objects)
884 , m_expectedCount(expected)
885 , m_expectedObjects(objects)
889 void mark(const void* ptr) { markNoTrace(ptr); }
891 virtual void markNoTrace(const void* ptr)
895 if (m_count < m_expectedCount)
896 EXPECT_TRUE(expectedObject(ptr));
898 EXPECT_FALSE(expectedObject(ptr));
902 virtual void mark(const void* ptr, TraceCallback) override
907 virtual void mark(HeapObjectHeader* header, TraceCallback callback) override
909 mark(header->payload());
912 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) override
914 mark(header->payload());
917 bool validate() { return m_count >= m_expectedCount; }
918 void reset() { m_count = 0; }
920 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
923 bool expectedObject(const void* ptr)
925 for (int i = 0; i < m_expectedCount; i++) {
926 if (m_expectedObjects[i] == ptr)
934 void** m_expectedObjects;
937 #undef DEFINE_VISITOR_METHODS
939 class Weak : public Bar {
941 static Weak* create(Bar* strong, Bar* weak)
943 return new Weak(strong, weak);
946 virtual void trace(Visitor* visitor) override
948 visitor->trace(m_strongBar);
949 visitor->registerWeakMembers(this, zapWeakMembers);
952 static void zapWeakMembers(Visitor* visitor, void* self)
954 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
957 bool strongIsThere() { return !!m_strongBar; }
958 bool weakIsThere() { return !!m_weakBar; }
961 Weak(Bar* strongBar, Bar* weakBar)
963 , m_strongBar(strongBar)
968 void zapWeakMembers(Visitor* visitor)
970 if (!visitor->isAlive(m_weakBar))
974 Member<Bar> m_strongBar;
978 class WithWeakMember : public Bar {
980 static WithWeakMember* create(Bar* strong, Bar* weak)
982 return new WithWeakMember(strong, weak);
985 virtual void trace(Visitor* visitor) override
987 visitor->trace(m_strongBar);
988 visitor->trace(m_weakBar);
991 bool strongIsThere() { return !!m_strongBar; }
992 bool weakIsThere() { return !!m_weakBar; }
995 WithWeakMember(Bar* strongBar, Bar* weakBar)
997 , m_strongBar(strongBar)
1002 Member<Bar> m_strongBar;
1003 WeakMember<Bar> m_weakBar;
1006 class Observable : public GarbageCollectedFinalized<Observable> {
1007 USING_PRE_FINALIZER(Observable, willFinalize);
1009 static Observable* create(Bar* bar) { return new Observable(bar); }
1010 ~Observable() { m_wasDestructed = true; }
1011 void trace(Visitor* visitor) { visitor->trace(m_bar); }
1013 // willFinalize is called by FinalizationObserver. willFinalize can touch
1014 // other on-heap objects.
1017 EXPECT_FALSE(m_wasDestructed);
1018 EXPECT_FALSE(m_bar->hasBeenFinalized());
1019 s_willFinalizeWasCalled = true;
1021 static bool s_willFinalizeWasCalled;
1024 explicit Observable(Bar* bar)
1026 , m_wasDestructed(false)
1031 bool m_wasDestructed;
1034 bool Observable::s_willFinalizeWasCalled = false;
1036 class ObservableWithPreFinalizer : public GarbageCollected<ObservableWithPreFinalizer> {
1037 USING_PRE_FINALIZER(ObservableWithPreFinalizer, dispose);
1039 static ObservableWithPreFinalizer* create() { return new ObservableWithPreFinalizer(); }
1040 ~ObservableWithPreFinalizer() { m_wasDestructed = true; }
1041 void trace(Visitor*) { }
1044 ThreadState::current()->unregisterPreFinalizer(*this);
1045 EXPECT_FALSE(m_wasDestructed);
1046 s_disposeWasCalled = true;
1048 static bool s_disposeWasCalled;
1051 explicit ObservableWithPreFinalizer()
1052 : m_wasDestructed(false)
1054 ThreadState::current()->registerPreFinalizer(*this);
1057 bool m_wasDestructed;
1060 bool ObservableWithPreFinalizer::s_disposeWasCalled = false;
1062 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
1064 static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
1065 bool didCallWillFinalize() const { return m_didCallWillFinalize; }
1067 void trace(Visitor* visitor)
1069 visitor->registerWeakMembers(this, zapWeakMembers);
1073 FinalizationObserver(T* data)
1075 , m_didCallWillFinalize(false)
1079 static void zapWeakMembers(Visitor* visitor, void* self)
1081 FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
1082 if (o->m_data && !visitor->isAlive(o->m_data)) {
1083 o->m_data->willFinalize();
1084 o->m_data = nullptr;
1085 o->m_didCallWillFinalize = true;
1089 WeakMember<T> m_data;
1090 bool m_didCallWillFinalize;
1093 class FinalizationObserverWithHashMap {
1095 typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
1097 explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
1098 ~FinalizationObserverWithHashMap()
1100 m_target.willFinalize();
1101 s_didCallWillFinalize = true;
1104 static ObserverMap& observe(Observable& target)
1106 ObserverMap& map = observers();
1107 ObserverMap::AddResult result = map.add(&target, nullptr);
1108 if (result.isNewEntry)
1109 result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
1111 ASSERT(result.storedValue->value);
1115 static void clearObservers()
1117 delete s_observerMap;
1118 s_observerMap = nullptr;
1121 static bool s_didCallWillFinalize;
1124 static ObserverMap& observers()
1127 s_observerMap = new Persistent<ObserverMap>(new ObserverMap());
1128 return **s_observerMap;
1131 Observable& m_target;
1132 static Persistent<ObserverMap>* s_observerMap;
1135 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
1136 Persistent<FinalizationObserverWithHashMap::ObserverMap>* FinalizationObserverWithHashMap::s_observerMap;
1140 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
1142 static PassRefPtrWillBeRawPtr<PointsBack> create()
1144 return adoptRefWillBeNoop(new PointsBack());
1152 void setBackPointer(SuperClass* backPointer)
1154 m_backPointer = backPointer;
1157 SuperClass* backPointer() const { return m_backPointer; }
1159 void trace(Visitor* visitor)
1162 visitor->trace(m_backPointer);
1166 static int s_aliveCount;
1168 PointsBack() : m_backPointer(nullptr)
1173 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1176 int PointsBack::s_aliveCount = 0;
1178 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1180 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1182 return adoptRefWillBeNoop(new SuperClass(pointsBack));
1185 virtual ~SuperClass()
1188 m_pointsBack->setBackPointer(0);
1193 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1195 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1196 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1197 EXPECT_EQ(pointsBack, target->pointsBack());
1198 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1201 virtual void trace(Visitor* visitor)
1204 visitor->trace(m_pointsBack);
1208 PointsBack* pointsBack() const { return m_pointsBack.get(); }
1210 static int s_aliveCount;
1212 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1213 : m_pointsBack(pointsBack)
1215 m_pointsBack->setBackPointer(this);
1220 RefPtrWillBeMember<PointsBack> m_pointsBack;
1223 int SuperClass::s_aliveCount = 0;
1224 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1226 SubData() { ++s_aliveCount; }
1227 ~SubData() { --s_aliveCount; }
1229 void trace(Visitor*) { }
1231 static int s_aliveCount;
1234 int SubData::s_aliveCount = 0;
1236 class SubClass : public SuperClass {
1238 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1240 return adoptRefWillBeNoop(new SubClass(pointsBack));
1248 virtual void trace(Visitor* visitor)
1251 SuperClass::trace(visitor);
1252 visitor->trace(m_data);
1256 static int s_aliveCount;
1258 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1259 : SuperClass(pointsBack)
1260 , m_data(adoptPtrWillBeNoop(new SubData()))
1266 OwnPtrWillBeMember<SubData> m_data;
1269 int SubClass::s_aliveCount = 0;
1271 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1273 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1275 return adoptRefWillBeNoop(new TransitionRefCounted());
1278 ~TransitionRefCounted()
1283 void trace(Visitor* visitor) { }
1285 static int s_aliveCount;
1288 TransitionRefCounted()
1294 int TransitionRefCounted::s_aliveCount = 0;
1296 class Mixin : public GarbageCollectedMixin {
1298 virtual void trace(Visitor* visitor) { }
1300 virtual char getPayload(int i) { return m_padding[i]; }
1306 class UseMixin : public SimpleObject, public Mixin {
1307 USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1309 static UseMixin* create()
1311 return new UseMixin();
1314 static int s_traceCount;
1315 virtual void trace(Visitor* visitor)
1317 SimpleObject::trace(visitor);
1318 Mixin::trace(visitor);
1329 int UseMixin::s_traceCount = 0;
1331 class VectorObject {
1332 ALLOW_ONLY_INLINE_ALLOCATION();
1336 m_value = SimpleFinalizedObject::create();
1339 void trace(Visitor* visitor)
1341 visitor->trace(m_value);
1345 Member<SimpleFinalizedObject> m_value;
1348 class VectorObjectInheritedTrace : public VectorObject { };
1350 class VectorObjectNoTrace {
1351 ALLOW_ONLY_INLINE_ALLOCATION();
1353 VectorObjectNoTrace()
1355 m_value = SimpleFinalizedObject::create();
1359 Member<SimpleFinalizedObject> m_value;
1362 class TerminatedArrayItem {
1363 ALLOW_ONLY_INLINE_ALLOCATION();
1365 TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1367 void trace(Visitor* visitor) { visitor->trace(m_payload); }
1369 bool isLastInArray() const { return m_isLast; }
1370 void setLastInArray(bool value) { m_isLast = value; }
1372 IntWrapper* payload() const { return m_payload; }
1375 Member<IntWrapper> m_payload;
1379 } // namespace blink
1381 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObject);
1382 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectInheritedTrace);
1383 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectNoTrace);
1387 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1389 ~OneKiloByteObject() { s_destructorCalls++; }
1390 char* data() { return m_data; }
1391 void trace(Visitor* visitor) { }
1392 static int s_destructorCalls;
1395 static const size_t s_length = 1024;
1396 char m_data[s_length];
1399 int OneKiloByteObject::s_destructorCalls = 0;
1401 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1403 static DynamicallySizedObject* create(size_t size)
1405 void* slot = Heap::allocate<DynamicallySizedObject>(size);
1406 return new (slot) DynamicallySizedObject();
1409 void* operator new(std::size_t, void* location)
1416 return *(reinterpret_cast<uint8_t*>(this) + i);
1419 void trace(Visitor*) { }
1422 DynamicallySizedObject() { }
1425 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1427 FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1428 : m_wrapper(wrapper)
1432 ~FinalizationAllocator()
1434 for (int i = 0; i < 10; ++i)
1435 *m_wrapper = IntWrapper::create(42);
1436 for (int i = 0; i < 512; ++i)
1437 new OneKiloByteObject();
1440 void trace(Visitor*) { }
1443 Persistent<IntWrapper>* m_wrapper;
1446 TEST(HeapTest, Transition)
1449 RefPtrWillBePersistent<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1450 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1451 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1452 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1454 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1455 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1457 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1458 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1459 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1460 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1461 EXPECT_EQ(2, PointsBack::s_aliveCount);
1462 EXPECT_EQ(2, SuperClass::s_aliveCount);
1463 EXPECT_EQ(1, SubClass::s_aliveCount);
1464 EXPECT_EQ(1, SubData::s_aliveCount);
1466 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1467 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1468 EXPECT_EQ(2, PointsBack::s_aliveCount);
1469 EXPECT_EQ(2, SuperClass::s_aliveCount);
1470 EXPECT_EQ(1, SubClass::s_aliveCount);
1471 EXPECT_EQ(1, SubData::s_aliveCount);
1473 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1474 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1475 EXPECT_EQ(2, PointsBack::s_aliveCount);
1476 EXPECT_EQ(1, SuperClass::s_aliveCount);
1477 EXPECT_EQ(1, SubClass::s_aliveCount);
1478 EXPECT_EQ(1, SubData::s_aliveCount);
1479 EXPECT_EQ(0, pointsBack1->backPointer());
1481 pointsBack1.release();
1482 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1483 EXPECT_EQ(1, PointsBack::s_aliveCount);
1484 EXPECT_EQ(1, SuperClass::s_aliveCount);
1485 EXPECT_EQ(1, SubClass::s_aliveCount);
1486 EXPECT_EQ(1, SubData::s_aliveCount);
1488 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1489 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1490 EXPECT_EQ(1, PointsBack::s_aliveCount);
1491 EXPECT_EQ(0, SuperClass::s_aliveCount);
1492 EXPECT_EQ(0, SubClass::s_aliveCount);
1493 EXPECT_EQ(0, SubData::s_aliveCount);
1494 EXPECT_EQ(0, pointsBack2->backPointer());
1496 pointsBack2.release();
1497 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1498 EXPECT_EQ(0, PointsBack::s_aliveCount);
1499 EXPECT_EQ(0, SuperClass::s_aliveCount);
1500 EXPECT_EQ(0, SubClass::s_aliveCount);
1501 EXPECT_EQ(0, SubData::s_aliveCount);
1503 EXPECT_TRUE(superClass == subClass);
1506 TEST(HeapTest, Threading)
1508 ThreadedHeapTester::test();
1511 TEST(HeapTest, ThreadedWeakness)
1513 ThreadedWeaknessTester::test();
1516 TEST(HeapTest, BasicFunctionality)
1518 HeapStats heapStats;
1519 clearOutOldGarbage(&heapStats);
1523 // When the test starts there may already have been leaked some memory
1524 // on the heap, so we establish a base line.
1525 size_t baseLevel = heapStats.totalObjectSpace();
1526 bool testPagesAllocated = !baseLevel;
1527 if (testPagesAllocated)
1528 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1530 // This allocates objects on the general heap which should add a page of memory.
1531 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1533 memset(alloc32, 40, 32);
1534 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1536 memset(alloc64, 27, 64);
1540 getHeapStats(&heapStats);
1541 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1542 if (testPagesAllocated)
1543 EXPECT_EQ(heapStats.totalAllocatedSpace(), 2 * blinkPageSize);
1545 EXPECT_EQ(alloc32->get(0), 40);
1546 EXPECT_EQ(alloc32->get(31), 40);
1547 EXPECT_EQ(alloc64->get(0), 27);
1548 EXPECT_EQ(alloc64->get(63), 27);
1550 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1552 EXPECT_EQ(alloc32->get(0), 40);
1553 EXPECT_EQ(alloc32->get(31), 40);
1554 EXPECT_EQ(alloc64->get(0), 27);
1555 EXPECT_EQ(alloc64->get(63), 27);
1558 clearOutOldGarbage(&heapStats);
1561 size_t baseLevel = heapStats.totalObjectSpace();
1562 bool testPagesAllocated = !baseLevel;
1563 if (testPagesAllocated)
1564 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1567 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1571 size_t persistentCount = 0;
1572 const size_t numPersistents = 100000;
1573 Persistent<DynamicallySizedObject>* persistents[numPersistents];
1575 for (int i = 0; i < 1000; i++) {
1576 size_t size = 128 + i * 8;
1578 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1580 getHeapStats(&heapStats);
1581 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1582 if (testPagesAllocated)
1583 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1587 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1589 memset(alloc32b, 40, 32);
1590 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1592 memset(alloc64b, 27, 64);
1593 EXPECT_TRUE(alloc32b != alloc64b);
1596 getHeapStats(&heapStats);
1597 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1598 if (testPagesAllocated)
1599 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1602 clearOutOldGarbage(&heapStats);
1605 if (testPagesAllocated)
1606 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1608 // Clear the persistent, so that the big area will be garbage collected.
1610 clearOutOldGarbage(&heapStats);
1614 getHeapStats(&heapStats);
1615 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1616 if (testPagesAllocated)
1617 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1619 getHeapStats(&heapStats);
1620 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1621 if (testPagesAllocated)
1622 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1624 for (size_t i = 0; i < persistentCount; i++) {
1625 delete persistents[i];
1629 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1630 for (int i = 0; i < 100; i++)
1632 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1633 for (int i = 0; i < 100; i++)
1634 EXPECT_EQ(address[i], i);
1635 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1636 for (int i = 0; i < 50; i++)
1637 EXPECT_EQ(address[i], i);
1638 // This should be equivalent to free(address).
1639 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1640 // This should be equivalent to malloc(0).
1641 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1644 TEST(HeapTest, SimpleAllocation)
1646 HeapStats initialHeapStats;
1647 clearOutOldGarbage(&initialHeapStats);
1648 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1650 // Allocate an object in the heap.
1651 HeapAllocatedArray* array = new HeapAllocatedArray();
1652 HeapStats statsAfterAllocation;
1653 getHeapStats(&statsAfterAllocation);
1654 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1656 // Sanity check of the contents in the heap.
1657 EXPECT_EQ(0, array->at(0));
1658 EXPECT_EQ(42, array->at(42));
1659 EXPECT_EQ(0, array->at(128));
1660 EXPECT_EQ(999 % 128, array->at(999));
1663 TEST(HeapTest, SimplePersistent)
1665 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1666 EXPECT_EQ(0, traceCounter->traceCount());
1668 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1669 EXPECT_EQ(1, traceCounter->traceCount());
1671 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1672 EXPECT_EQ(0, classWithMember->traceCount());
1674 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1675 EXPECT_EQ(1, classWithMember->traceCount());
1676 EXPECT_EQ(2, traceCounter->traceCount());
1679 TEST(HeapTest, SimpleFinalization)
1682 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1683 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1684 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1685 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1688 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1689 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1692 TEST(HeapTest, Finalization)
1695 HeapTestSubClass* t1 = HeapTestSubClass::create();
1696 HeapTestSubClass* t2 = HeapTestSubClass::create();
1697 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1698 // FIXME(oilpan): Ignore unused variables.
1703 // Nothing is marked so the GC should free everything and call
1704 // the finalizer on all three objects.
1705 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1706 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1707 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1708 // Destructors not called again when GCing again.
1709 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1710 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1711 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1714 TEST(HeapTest, TypedHeapSanity)
1716 // We use TraceCounter for allocating an object on the general heap.
1717 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1718 Persistent<Node> typedHeapObject = Node::create(0);
1719 EXPECT_NE(pageHeaderFromObject(generalHeapObject.get()),
1720 pageHeaderFromObject(typedHeapObject.get()));
1723 TEST(HeapTest, NoAllocation)
1725 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1727 // Disallow allocation
1728 NoAllocationScope<AnyThread> noAllocationScope;
1729 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1731 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1734 TEST(HeapTest, Members)
1741 h1 = Baz::create(Bar::create());
1742 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1743 EXPECT_EQ(1u, Bar::s_live);
1744 h2 = Baz::create(Bar::create());
1745 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1746 EXPECT_EQ(2u, Bar::s_live);
1748 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1749 EXPECT_EQ(2u, Bar::s_live);
1751 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1752 EXPECT_EQ(1u, Bar::s_live);
1754 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1755 EXPECT_EQ(0u, Bar::s_live);
1758 TEST(HeapTest, MarkTest)
1762 Persistent<Bar> bar = Bar::create();
1763 EXPECT_TRUE(ThreadState::current()->contains(bar));
1764 EXPECT_EQ(1u, Bar::s_live);
1766 Foo* foo = Foo::create(bar);
1767 EXPECT_TRUE(ThreadState::current()->contains(foo));
1768 EXPECT_EQ(2u, Bar::s_live);
1769 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1770 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1771 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1772 EXPECT_EQ(2u, Bar::s_live);
1774 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1775 EXPECT_EQ(1u, Bar::s_live);
1777 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1778 EXPECT_EQ(0u, Bar::s_live);
1781 TEST(HeapTest, DeepTest)
1783 const unsigned depth = 100000;
1786 Bar* bar = Bar::create();
1787 EXPECT_TRUE(ThreadState::current()->contains(bar));
1788 Foo* foo = Foo::create(bar);
1789 EXPECT_TRUE(ThreadState::current()->contains(foo));
1790 EXPECT_EQ(2u, Bar::s_live);
1791 for (unsigned i = 0; i < depth; i++) {
1792 Foo* foo2 = Foo::create(foo);
1794 EXPECT_TRUE(ThreadState::current()->contains(foo));
1796 EXPECT_EQ(depth + 2, Bar::s_live);
1797 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1798 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1799 EXPECT_EQ(depth + 2, Bar::s_live);
1801 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1802 EXPECT_EQ(0u, Bar::s_live);
1805 TEST(HeapTest, WideTest)
1809 Bars* bars = Bars::create();
1810 unsigned width = Bars::width;
1811 EXPECT_EQ(width + 1, Bar::s_live);
1812 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1813 EXPECT_EQ(width + 1, Bar::s_live);
1814 // Use bars here to make sure that it will be on the stack
1815 // for the conservative stack scan to find.
1816 EXPECT_EQ(width, bars->getWidth());
1818 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1819 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1820 EXPECT_EQ(0u, Bar::s_live);
1823 TEST(HeapTest, HashMapOfMembers)
1825 HeapStats initialHeapSize;
1826 IntWrapper::s_destructorCalls = 0;
1828 clearOutOldGarbage(&initialHeapSize);
1830 typedef HeapHashMap<
1833 DefaultHash<Member<IntWrapper> >::Hash,
1834 HashTraits<Member<IntWrapper> >,
1835 HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1837 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1840 HeapStats afterSetWasCreated;
1841 getHeapStats(&afterSetWasCreated);
1842 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1844 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1846 getHeapStats(&afterGC);
1847 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1849 // If the additions below cause garbage collections, these
1850 // pointers should be found by conservative stack scanning.
1851 IntWrapper* one(IntWrapper::create(1));
1852 IntWrapper* anotherOne(IntWrapper::create(1));
1856 HeapStats afterOneAdd;
1857 getHeapStats(&afterOneAdd);
1858 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1860 HeapObjectIdentityMap::iterator it(map->begin());
1861 HeapObjectIdentityMap::iterator it2(map->begin());
1865 map->add(anotherOne, one);
1867 // The addition above can cause an allocation of a new
1868 // backing store. We therefore garbage collect before
1869 // taking the heap stats in order to get rid of the old
1870 // backing store. We make sure to not use conservative
1871 // stack scanning as that could find a pointer to the
1873 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1874 HeapStats afterAddAndGC;
1875 getHeapStats(&afterAddAndGC);
1876 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1878 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1880 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1881 EXPECT_TRUE(map->contains(one));
1882 EXPECT_TRUE(map->contains(anotherOne));
1884 IntWrapper* gotten(map->get(one));
1885 EXPECT_EQ(gotten->value(), one->value());
1886 EXPECT_EQ(gotten, one);
1889 getHeapStats(&afterGC2);
1890 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1892 IntWrapper* dozen = 0;
1894 for (int i = 1; i < 1000; i++) { // 999 iterations.
1895 IntWrapper* iWrapper(IntWrapper::create(i));
1896 IntWrapper* iSquared(IntWrapper::create(i * i));
1897 map->add(iWrapper, iSquared);
1901 HeapStats afterAdding1000;
1902 getHeapStats(&afterAdding1000);
1903 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1905 IntWrapper* gross(map->get(dozen));
1906 EXPECT_EQ(gross->value(), 144);
1908 // This should clear out any junk backings created by all the adds.
1909 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1911 getHeapStats(&afterGC3);
1912 EXPECT_TRUE(afterGC3.totalObjectSpace() <= afterAdding1000.totalObjectSpace());
1915 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1916 // The objects 'one', anotherOne, and the 999 other pairs.
1917 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1919 getHeapStats(&afterGC4);
1920 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1923 TEST(HeapTest, NestedAllocation)
1925 HeapStats initialHeapSize;
1926 clearOutOldGarbage(&initialHeapSize);
1928 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1930 HeapStats afterFree;
1931 clearOutOldGarbage(&afterFree);
1932 EXPECT_TRUE(initialHeapSize == afterFree);
1935 TEST(HeapTest, LargeObjects)
1937 HeapStats initialHeapSize;
1938 clearOutOldGarbage(&initialHeapSize);
1939 IntWrapper::s_destructorCalls = 0;
1940 LargeObject::s_destructorCalls = 0;
1942 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1943 Persistent<LargeObject> object = LargeObject::create();
1944 EXPECT_TRUE(ThreadState::current()->contains(object));
1945 EXPECT_TRUE(ThreadState::current()->contains(reinterpret_cast<char*>(object.get()) + sizeof(LargeObject) - 1));
1946 #if ENABLE(GC_PROFILE_MARKING)
1947 const GCInfo* info = ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()));
1948 EXPECT_NE(reinterpret_cast<const GCInfo*>(0), info);
1949 EXPECT_EQ(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject) - 1));
1950 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject)));
1951 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) - 1));
1953 HeapStats afterAllocation;
1954 clearOutOldGarbage(&afterAllocation);
1956 object->set(0, 'a');
1957 EXPECT_EQ('a', object->get(0));
1958 object->set(object->length() - 1, 'b');
1959 EXPECT_EQ('b', object->get(object->length() - 1));
1960 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1961 size_t actualObjectSpace =
1962 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1963 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1964 // There is probably space for the IntWrapper in a heap page without
1965 // allocating extra pages. However, the IntWrapper allocation might cause
1966 // the addition of a heap page.
1967 size_t largeObjectAllocationSize =
1968 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1969 size_t allocatedSpaceLowerBound =
1970 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1971 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1972 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1973 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1974 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1975 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1976 for (int i = 0; i < 10; i++)
1977 object = LargeObject::create();
1979 HeapStats oneLargeObject;
1980 clearOutOldGarbage(&oneLargeObject);
1981 EXPECT_TRUE(oneLargeObject == afterAllocation);
1982 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1983 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1985 HeapStats backToInitial;
1986 clearOutOldGarbage(&backToInitial);
1987 EXPECT_TRUE(initialHeapSize == backToInitial);
1988 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1989 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1990 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1993 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1994 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1995 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1996 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1997 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1998 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
2000 class Container : public GarbageCollected<Container> {
2002 static Container* create() { return new Container(); }
2003 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
2004 HeapHashSet<Member<IntWrapper> > set;
2005 HeapHashSet<Member<IntWrapper> > set2;
2006 HeapHashCountedSet<Member<IntWrapper> > set3;
2007 HeapVector<Member<IntWrapper>, 2> vector;
2008 HeapVector<PairWrappedUnwrapped, 2> vectorWU;
2009 HeapVector<PairUnwrappedWrapped, 2> vectorUW;
2010 HeapDeque<Member<IntWrapper>, 0> deque;
2011 HeapDeque<PairWrappedUnwrapped, 0> dequeWU;
2012 HeapDeque<PairUnwrappedWrapped, 0> dequeUW;
2013 void trace(Visitor* visitor)
2015 visitor->trace(map);
2016 visitor->trace(set);
2017 visitor->trace(set2);
2018 visitor->trace(set3);
2019 visitor->trace(vector);
2020 visitor->trace(vectorWU);
2021 visitor->trace(vectorUW);
2022 visitor->trace(deque);
2023 visitor->trace(dequeWU);
2024 visitor->trace(dequeUW);
2028 struct ShouldBeTraced {
2029 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
2030 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
2031 Member<IntWrapper> m_wrapper;
2034 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
2036 static OffHeapContainer* create() { return new OffHeapContainer(); }
2038 static const int iterations = 300;
2039 static const int deadWrappers = 1200;
2043 for (int i = 0; i < iterations; i++) {
2044 m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
2045 m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
2046 m_deque2.append(IntWrapper::create(i));
2047 m_vector2.append(IntWrapper::create(i));
2050 Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
2051 Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
2052 Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
2053 Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
2055 for (int i = 0; i < iterations; i++) {
2056 EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
2057 EXPECT_EQ(i, m_vector2[i]->value());
2058 EXPECT_EQ(i, d1Iterator->m_wrapper->value());
2059 EXPECT_EQ(i, v1Iterator->m_wrapper->value());
2060 EXPECT_EQ(i, d2Iterator->get()->value());
2061 EXPECT_EQ(i, v2Iterator->get()->value());
2067 EXPECT_EQ(d1Iterator, m_deque1.end());
2068 EXPECT_EQ(v1Iterator, m_vector1.end());
2069 EXPECT_EQ(d2Iterator, m_deque2.end());
2070 EXPECT_EQ(v2Iterator, m_vector2.end());
2073 void trace(Visitor* visitor)
2075 visitor->trace(m_deque1);
2076 visitor->trace(m_vector1);
2077 visitor->trace(m_deque2);
2078 visitor->trace(m_vector2);
2081 Deque<ShouldBeTraced> m_deque1;
2082 Vector<ShouldBeTraced> m_vector1;
2083 Deque<Member<IntWrapper> > m_deque2;
2084 Vector<Member<IntWrapper> > m_vector2;
2087 const int OffHeapContainer::iterations;
2088 const int OffHeapContainer::deadWrappers;
2090 // These class definitions test compile-time asserts with transition
2091 // types. They are therefore unused in test code and just need to
2092 // compile. This is intentional; do not delete the A and B classes below.
2093 class A : public WillBeGarbageCollectedMixin {
2096 class B : public NoBaseWillBeGarbageCollected<B>, public A {
2097 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
2099 void trace(Visitor*) { }
2102 TEST(HeapTest, HeapVectorFilledWithValue)
2104 IntWrapper* val = IntWrapper::create(1);
2105 HeapVector<Member<IntWrapper> > vector(10, val);
2106 EXPECT_EQ(10u, vector.size());
2107 for (size_t i = 0; i < vector.size(); i++)
2108 EXPECT_EQ(val, vector[i]);
2111 TEST(HeapTest, HeapVectorWithInlineCapacity)
2113 IntWrapper* one = IntWrapper::create(1);
2114 IntWrapper* two = IntWrapper::create(2);
2115 IntWrapper* three = IntWrapper::create(3);
2116 IntWrapper* four = IntWrapper::create(4);
2117 IntWrapper* five = IntWrapper::create(5);
2118 IntWrapper* six = IntWrapper::create(6);
2120 HeapVector<Member<IntWrapper>, 2> vector;
2123 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2124 EXPECT_TRUE(vector.contains(one));
2125 EXPECT_TRUE(vector.contains(two));
2127 vector.append(three);
2128 vector.append(four);
2129 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2130 EXPECT_TRUE(vector.contains(one));
2131 EXPECT_TRUE(vector.contains(two));
2132 EXPECT_TRUE(vector.contains(three));
2133 EXPECT_TRUE(vector.contains(four));
2136 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2137 EXPECT_TRUE(vector.contains(one));
2138 EXPECT_FALSE(vector.contains(two));
2139 EXPECT_FALSE(vector.contains(three));
2140 EXPECT_FALSE(vector.contains(four));
2143 HeapVector<Member<IntWrapper>, 2> vector1;
2144 HeapVector<Member<IntWrapper>, 2> vector2;
2146 vector1.append(one);
2147 vector2.append(two);
2148 vector1.swap(vector2);
2149 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2150 EXPECT_TRUE(vector1.contains(two));
2151 EXPECT_TRUE(vector2.contains(one));
2154 HeapVector<Member<IntWrapper>, 2> vector1;
2155 HeapVector<Member<IntWrapper>, 2> vector2;
2157 vector1.append(one);
2158 vector1.append(two);
2159 vector2.append(three);
2160 vector2.append(four);
2161 vector2.append(five);
2162 vector2.append(six);
2163 vector1.swap(vector2);
2164 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2165 EXPECT_TRUE(vector1.contains(three));
2166 EXPECT_TRUE(vector1.contains(four));
2167 EXPECT_TRUE(vector1.contains(five));
2168 EXPECT_TRUE(vector1.contains(six));
2169 EXPECT_TRUE(vector2.contains(one));
2170 EXPECT_TRUE(vector2.contains(two));
2174 template<typename T, size_t inlineCapacity, typename U>
2175 bool dequeContains(HeapDeque<T, inlineCapacity>& deque, U u)
2177 typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
2178 for (iterator it = deque.begin(); it != deque.end(); ++it) {
2185 TEST(HeapTest, HeapCollectionTypes)
2187 HeapStats initialHeapSize;
2188 IntWrapper::s_destructorCalls = 0;
2190 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
2191 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2192 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
2194 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2195 typedef HeapHashCountedSet<Member<IntWrapper> > MemberCountedSet;
2197 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2198 typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
2200 typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2201 typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2202 typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
2203 typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
2205 Persistent<MemberMember> memberMember = new MemberMember();
2206 Persistent<MemberMember> memberMember2 = new MemberMember();
2207 Persistent<MemberMember> memberMember3 = new MemberMember();
2208 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2209 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2210 Persistent<MemberSet> set = new MemberSet();
2211 Persistent<MemberSet> set2 = new MemberSet();
2212 Persistent<MemberCountedSet> set3 = new MemberCountedSet();
2213 Persistent<MemberVector> vector = new MemberVector();
2214 Persistent<MemberVector> vector2 = new MemberVector();
2215 Persistent<VectorWU> vectorWU = new VectorWU();
2216 Persistent<VectorWU> vectorWU2 = new VectorWU();
2217 Persistent<VectorUW> vectorUW = new VectorUW();
2218 Persistent<VectorUW> vectorUW2 = new VectorUW();
2219 Persistent<MemberDeque> deque = new MemberDeque();
2220 Persistent<MemberDeque> deque2 = new MemberDeque();
2221 Persistent<DequeWU> dequeWU = new DequeWU();
2222 Persistent<DequeWU> dequeWU2 = new DequeWU();
2223 Persistent<DequeUW> dequeUW = new DequeUW();
2224 Persistent<DequeUW> dequeUW2 = new DequeUW();
2225 Persistent<Container> container = Container::create();
2227 clearOutOldGarbage(&initialHeapSize);
2229 Persistent<IntWrapper> one(IntWrapper::create(1));
2230 Persistent<IntWrapper> two(IntWrapper::create(2));
2231 Persistent<IntWrapper> oneB(IntWrapper::create(1));
2232 Persistent<IntWrapper> twoB(IntWrapper::create(2));
2233 Persistent<IntWrapper> oneC(IntWrapper::create(1));
2234 Persistent<IntWrapper> oneD(IntWrapper::create(1));
2235 Persistent<IntWrapper> oneE(IntWrapper::create(1));
2236 Persistent<IntWrapper> oneF(IntWrapper::create(1));
2238 IntWrapper* threeB(IntWrapper::create(3));
2239 IntWrapper* threeC(IntWrapper::create(3));
2240 IntWrapper* threeD(IntWrapper::create(3));
2241 IntWrapper* threeE(IntWrapper::create(3));
2242 IntWrapper* threeF(IntWrapper::create(3));
2243 IntWrapper* three(IntWrapper::create(3));
2244 IntWrapper* fourB(IntWrapper::create(4));
2245 IntWrapper* fourC(IntWrapper::create(4));
2246 IntWrapper* fourD(IntWrapper::create(4));
2247 IntWrapper* fourE(IntWrapper::create(4));
2248 IntWrapper* fourF(IntWrapper::create(4));
2249 IntWrapper* four(IntWrapper::create(4));
2250 IntWrapper* fiveC(IntWrapper::create(5));
2251 IntWrapper* fiveD(IntWrapper::create(5));
2252 IntWrapper* fiveE(IntWrapper::create(5));
2253 IntWrapper* fiveF(IntWrapper::create(5));
2255 // Member Collections.
2256 memberMember2->add(one, two);
2257 memberMember2->add(two, three);
2258 memberMember2->add(three, four);
2259 memberMember2->add(four, one);
2260 primitiveMember->add(1, two);
2261 primitiveMember->add(2, three);
2262 primitiveMember->add(3, four);
2263 primitiveMember->add(4, one);
2264 memberPrimitive->add(one, 2);
2265 memberPrimitive->add(two, 3);
2266 memberPrimitive->add(three, 4);
2267 memberPrimitive->add(four, 1);
2275 vector->append(oneB);
2276 deque->append(oneB);
2277 vector2->append(threeB);
2278 vector2->append(fourB);
2279 deque2->append(threeE);
2280 deque2->append(fourE);
2281 vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2282 dequeWU->append(PairWrappedUnwrapped(&*oneE, 42));
2283 vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2284 vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2285 vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2286 dequeWU2->append(PairWrappedUnwrapped(&*threeE, 43));
2287 dequeWU2->append(PairWrappedUnwrapped(&*fourE, 44));
2288 dequeWU2->append(PairWrappedUnwrapped(&*fiveE, 45));
2289 vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2290 vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2291 vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2292 vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2293 dequeUW->append(PairUnwrappedWrapped(1, &*oneF));
2294 dequeUW2->append(PairUnwrappedWrapped(103, &*threeF));
2295 dequeUW2->append(PairUnwrappedWrapped(104, &*fourF));
2296 dequeUW2->append(PairUnwrappedWrapped(105, &*fiveF));
2298 EXPECT_TRUE(dequeContains(*deque, oneB));
2300 // Collect garbage. This should change nothing since we are keeping
2301 // alive the IntWrapper objects with on-stack pointers.
2302 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2304 EXPECT_TRUE(dequeContains(*deque, oneB));
2306 EXPECT_EQ(0u, memberMember->size());
2307 EXPECT_EQ(4u, memberMember2->size());
2308 EXPECT_EQ(4u, primitiveMember->size());
2309 EXPECT_EQ(4u, memberPrimitive->size());
2310 EXPECT_EQ(1u, set->size());
2311 EXPECT_EQ(4u, set2->size());
2312 EXPECT_EQ(1u, set3->size());
2313 EXPECT_EQ(1u, vector->size());
2314 EXPECT_EQ(2u, vector2->size());
2315 EXPECT_EQ(1u, vectorWU->size());
2316 EXPECT_EQ(3u, vectorWU2->size());
2317 EXPECT_EQ(1u, vectorUW->size());
2318 EXPECT_EQ(3u, vectorUW2->size());
2319 EXPECT_EQ(1u, deque->size());
2320 EXPECT_EQ(2u, deque2->size());
2321 EXPECT_EQ(1u, dequeWU->size());
2322 EXPECT_EQ(3u, dequeWU2->size());
2323 EXPECT_EQ(1u, dequeUW->size());
2324 EXPECT_EQ(3u, dequeUW2->size());
2326 MemberVector& cvec = container->vector;
2327 cvec.swap(*vector.get());
2328 vector2->swap(cvec);
2331 VectorWU& cvecWU = container->vectorWU;
2332 cvecWU.swap(*vectorWU.get());
2333 vectorWU2->swap(cvecWU);
2334 vectorWU->swap(cvecWU);
2336 VectorUW& cvecUW = container->vectorUW;
2337 cvecUW.swap(*vectorUW.get());
2338 vectorUW2->swap(cvecUW);
2339 vectorUW->swap(cvecUW);
2341 MemberDeque& cDeque = container->deque;
2342 cDeque.swap(*deque.get());
2343 deque2->swap(cDeque);
2344 deque->swap(cDeque);
2346 DequeWU& cDequeWU = container->dequeWU;
2347 cDequeWU.swap(*dequeWU.get());
2348 dequeWU2->swap(cDequeWU);
2349 dequeWU->swap(cDequeWU);
2351 DequeUW& cDequeUW = container->dequeUW;
2352 cDequeUW.swap(*dequeUW.get());
2353 dequeUW2->swap(cDequeUW);
2354 dequeUW->swap(cDequeUW);
2356 // Swap set and set2 in a roundabout way.
2357 MemberSet& cset1 = container->set;
2358 MemberSet& cset2 = container->set2;
2365 MemberCountedSet& cCountedSet = container->set3;
2366 set3->swap(cCountedSet);
2367 EXPECT_EQ(0u, set3->size());
2368 set3->swap(cCountedSet);
2371 container->map.swap(memberMember2);
2372 MemberMember& containedMap = container->map;
2373 memberMember3->swap(containedMap);
2374 memberMember3->swap(memberMember);
2376 EXPECT_TRUE(memberMember->get(one) == two);
2377 EXPECT_TRUE(memberMember->get(two) == three);
2378 EXPECT_TRUE(memberMember->get(three) == four);
2379 EXPECT_TRUE(memberMember->get(four) == one);
2380 EXPECT_TRUE(primitiveMember->get(1) == two);
2381 EXPECT_TRUE(primitiveMember->get(2) == three);
2382 EXPECT_TRUE(primitiveMember->get(3) == four);
2383 EXPECT_TRUE(primitiveMember->get(4) == one);
2384 EXPECT_EQ(1, memberPrimitive->get(four));
2385 EXPECT_EQ(2, memberPrimitive->get(one));
2386 EXPECT_EQ(3, memberPrimitive->get(two));
2387 EXPECT_EQ(4, memberPrimitive->get(three));
2388 EXPECT_TRUE(set->contains(one));
2389 EXPECT_TRUE(set->contains(two));
2390 EXPECT_TRUE(set->contains(three));
2391 EXPECT_TRUE(set->contains(four));
2392 EXPECT_TRUE(set2->contains(oneB));
2393 EXPECT_TRUE(set3->contains(oneB));
2394 EXPECT_TRUE(vector->contains(threeB));
2395 EXPECT_TRUE(vector->contains(fourB));
2396 EXPECT_TRUE(dequeContains(*deque, threeE));
2397 EXPECT_TRUE(dequeContains(*deque, fourE));
2398 EXPECT_TRUE(vector2->contains(oneB));
2399 EXPECT_FALSE(vector2->contains(threeB));
2400 EXPECT_TRUE(dequeContains(*deque2, oneB));
2401 EXPECT_FALSE(dequeContains(*deque2, threeE));
2402 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2403 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2404 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2405 EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2406 EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2407 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2408 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2409 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2410 EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2411 EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2412 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*threeE, 43)));
2413 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fourE, 44)));
2414 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fiveE, 45)));
2415 EXPECT_TRUE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*oneE, 42)));
2416 EXPECT_FALSE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*threeE, 43)));
2417 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(103, &*threeF)));
2418 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(104, &*fourF)));
2419 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(105, &*fiveF)));
2420 EXPECT_TRUE(dequeContains(*dequeUW2, PairUnwrappedWrapped(1, &*oneF)));
2421 EXPECT_FALSE(dequeContains(*dequeUW2, PairUnwrappedWrapped(103, &*threeF)));
2424 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2426 EXPECT_EQ(4u, memberMember->size());
2427 EXPECT_EQ(0u, memberMember2->size());
2428 EXPECT_EQ(4u, primitiveMember->size());
2429 EXPECT_EQ(4u, memberPrimitive->size());
2430 EXPECT_EQ(4u, set->size());
2431 EXPECT_EQ(1u, set2->size());
2432 EXPECT_EQ(1u, set3->size());
2433 EXPECT_EQ(2u, vector->size());
2434 EXPECT_EQ(1u, vector2->size());
2435 EXPECT_EQ(3u, vectorUW->size());
2436 EXPECT_EQ(1u, vector2->size());
2437 EXPECT_EQ(2u, deque->size());
2438 EXPECT_EQ(1u, deque2->size());
2439 EXPECT_EQ(3u, dequeUW->size());
2440 EXPECT_EQ(1u, deque2->size());
2442 EXPECT_TRUE(memberMember->get(one) == two);
2443 EXPECT_TRUE(primitiveMember->get(1) == two);
2444 EXPECT_TRUE(primitiveMember->get(4) == one);
2445 EXPECT_EQ(2, memberPrimitive->get(one));
2446 EXPECT_EQ(3, memberPrimitive->get(two));
2447 EXPECT_TRUE(set->contains(one));
2448 EXPECT_TRUE(set->contains(two));
2449 EXPECT_FALSE(set->contains(oneB));
2450 EXPECT_TRUE(set2->contains(oneB));
2451 EXPECT_TRUE(set3->contains(oneB));
2452 EXPECT_EQ(2u, set3->find(oneB)->value);
2453 EXPECT_EQ(3, vector->at(0)->value());
2454 EXPECT_EQ(4, vector->at(1)->value());
2455 EXPECT_EQ(3, deque->begin()->get()->value());
2458 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2459 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2461 EXPECT_EQ(4u, memberMember->size());
2462 EXPECT_EQ(4u, primitiveMember->size());
2463 EXPECT_EQ(4u, memberPrimitive->size());
2464 EXPECT_EQ(4u, set->size());
2465 EXPECT_EQ(1u, set2->size());
2466 EXPECT_EQ(2u, vector->size());
2467 EXPECT_EQ(1u, vector2->size());
2468 EXPECT_EQ(3u, vectorWU->size());
2469 EXPECT_EQ(1u, vectorWU2->size());
2470 EXPECT_EQ(3u, vectorUW->size());
2471 EXPECT_EQ(1u, vectorUW2->size());
2472 EXPECT_EQ(2u, deque->size());
2473 EXPECT_EQ(1u, deque2->size());
2474 EXPECT_EQ(3u, dequeWU->size());
2475 EXPECT_EQ(1u, dequeWU2->size());
2476 EXPECT_EQ(3u, dequeUW->size());
2477 EXPECT_EQ(1u, dequeUW2->size());
2480 template<typename T>
2481 void MapIteratorCheck(T& it, const T& end, int expected)
2486 int key = it->key->value();
2487 int value = it->value->value();
2488 EXPECT_TRUE(key >= 0 && key < 1100);
2489 EXPECT_TRUE(value >= 0 && value < 1100);
2492 EXPECT_EQ(expected, found);
2495 template<typename T>
2496 void SetIteratorCheck(T& it, const T& end, int expected)
2501 int value = (*it)->value();
2502 EXPECT_TRUE(value >= 0 && value < 1100);
2505 EXPECT_EQ(expected, found);
2508 TEST(HeapTest, HeapWeakCollectionSimple)
2510 HeapStats initialHeapStats;
2511 clearOutOldGarbage(&initialHeapStats);
2512 IntWrapper::s_destructorCalls = 0;
2514 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2516 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2517 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2518 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2519 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2520 typedef HeapHashCountedSet<WeakMember<IntWrapper> > WeakCountedSet;
2522 Persistent<WeakStrong> weakStrong = new WeakStrong();
2523 Persistent<StrongWeak> strongWeak = new StrongWeak();
2524 Persistent<WeakWeak> weakWeak = new WeakWeak();
2525 Persistent<WeakSet> weakSet = new WeakSet();
2526 Persistent<WeakCountedSet> weakCountedSet = new WeakCountedSet();
2528 Persistent<IntWrapper> two = IntWrapper::create(2);
2530 keepNumbersAlive.append(IntWrapper::create(103));
2531 keepNumbersAlive.append(IntWrapper::create(10));
2534 weakStrong->add(IntWrapper::create(1), two);
2535 strongWeak->add(two, IntWrapper::create(1));
2536 weakWeak->add(two, IntWrapper::create(42));
2537 weakWeak->add(IntWrapper::create(42), two);
2538 weakSet->add(IntWrapper::create(0));
2540 weakSet->add(keepNumbersAlive[0]);
2541 weakSet->add(keepNumbersAlive[1]);
2542 weakCountedSet->add(IntWrapper::create(0));
2543 weakCountedSet->add(two);
2544 weakCountedSet->add(two);
2545 weakCountedSet->add(two);
2546 weakCountedSet->add(keepNumbersAlive[0]);
2547 weakCountedSet->add(keepNumbersAlive[1]);
2548 EXPECT_EQ(1u, weakStrong->size());
2549 EXPECT_EQ(1u, strongWeak->size());
2550 EXPECT_EQ(2u, weakWeak->size());
2551 EXPECT_EQ(4u, weakSet->size());
2552 EXPECT_EQ(4u, weakCountedSet->size());
2553 EXPECT_EQ(3u, weakCountedSet->find(two)->value);
2554 weakCountedSet->remove(two);
2555 EXPECT_EQ(2u, weakCountedSet->find(two)->value);
2558 keepNumbersAlive[0] = nullptr;
2560 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2562 EXPECT_EQ(0u, weakStrong->size());
2563 EXPECT_EQ(0u, strongWeak->size());
2564 EXPECT_EQ(0u, weakWeak->size());
2565 EXPECT_EQ(2u, weakSet->size());
2566 EXPECT_EQ(2u, weakCountedSet->size());
2569 template<typename Set>
2570 void orderedSetHelper(bool strong)
2572 HeapStats initialHeapStats;
2573 clearOutOldGarbage(&initialHeapStats);
2574 IntWrapper::s_destructorCalls = 0;
2576 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2578 Persistent<Set> set1 = new Set();
2579 Persistent<Set> set2 = new Set();
2581 const Set& constSet = *set1.get();
2583 keepNumbersAlive.append(IntWrapper::create(2));
2584 keepNumbersAlive.append(IntWrapper::create(103));
2585 keepNumbersAlive.append(IntWrapper::create(10));
2587 set1->add(IntWrapper::create(0));
2588 set1->add(keepNumbersAlive[0]);
2589 set1->add(keepNumbersAlive[1]);
2590 set1->add(keepNumbersAlive[2]);
2593 set2->add(IntWrapper::create(42));
2596 EXPECT_EQ(4u, set1->size());
2597 typename Set::iterator it(set1->begin());
2598 typename Set::reverse_iterator reverse(set1->rbegin());
2599 typename Set::const_iterator cit(constSet.begin());
2600 typename Set::const_reverse_iterator creverse(constSet.rbegin());
2602 EXPECT_EQ(0, (*it)->value());
2603 EXPECT_EQ(0, (*cit)->value());
2606 EXPECT_EQ(2, (*it)->value());
2607 EXPECT_EQ(2, (*cit)->value());
2610 EXPECT_EQ(0, (*it)->value());
2611 EXPECT_EQ(0, (*cit)->value());
2616 EXPECT_EQ(103, (*it)->value());
2617 EXPECT_EQ(103, (*cit)->value());
2620 EXPECT_EQ(10, (*it)->value());
2621 EXPECT_EQ(10, (*cit)->value());
2625 EXPECT_EQ(10, (*reverse)->value());
2626 EXPECT_EQ(10, (*creverse)->value());
2629 EXPECT_EQ(103, (*reverse)->value());
2630 EXPECT_EQ(103, (*creverse)->value());
2633 EXPECT_EQ(10, (*reverse)->value());
2634 EXPECT_EQ(10, (*creverse)->value());
2639 EXPECT_EQ(2, (*reverse)->value());
2640 EXPECT_EQ(2, (*creverse)->value());
2643 EXPECT_EQ(0, (*reverse)->value());
2644 EXPECT_EQ(0, (*creverse)->value());
2648 EXPECT_EQ(set1->end(), it);
2649 EXPECT_EQ(constSet.end(), cit);
2650 EXPECT_EQ(set1->rend(), reverse);
2651 EXPECT_EQ(constSet.rend(), creverse);
2653 typename Set::iterator iX(set2->begin());
2654 EXPECT_EQ(set2->end(), iX);
2657 set1->remove(keepNumbersAlive[0]);
2659 keepNumbersAlive[0] = nullptr;
2661 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2663 EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
2665 EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
2667 typename Set::iterator i2(set1->begin());
2669 EXPECT_EQ(0, (*i2)->value());
2671 EXPECT_NE(set1->end(), i2);
2673 EXPECT_EQ(103, (*i2)->value());
2675 EXPECT_NE(set1->end(), i2);
2676 EXPECT_EQ(10, (*i2)->value());
2678 EXPECT_EQ(set1->end(), i2);
2681 TEST(HeapTest, HeapWeakLinkedHashSet)
2683 orderedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
2684 orderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
2685 orderedSetHelper<HeapListHashSet<Member<IntWrapper> > >(true);
2688 class ThingWithDestructor {
2690 ThingWithDestructor()
2693 s_liveThingsWithDestructor++;
2696 ThingWithDestructor(int x)
2699 s_liveThingsWithDestructor++;
2702 ThingWithDestructor(const ThingWithDestructor&other)
2705 s_liveThingsWithDestructor++;
2708 ~ThingWithDestructor()
2710 s_liveThingsWithDestructor--;
2713 int value() { return m_x; }
2715 static int s_liveThingsWithDestructor;
2717 unsigned hash() { return IntHash<int>::hash(m_x); }
2720 static const int emptyValue = 0;
2724 int ThingWithDestructor::s_liveThingsWithDestructor;
2726 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2727 static const bool needsDestruction = true;
2730 static void heapMapDestructorHelper(bool clearMaps)
2732 HeapStats initialHeapStats;
2733 clearOutOldGarbage(&initialHeapStats);
2734 ThingWithDestructor::s_liveThingsWithDestructor = 0;
2736 typedef HeapHashMap<WeakMember<IntWrapper>, Member<RefCountedAndGarbageCollected> > RefMap;
2738 typedef HeapHashMap<
2739 WeakMember<IntWrapper>,
2740 ThingWithDestructor,
2741 DefaultHash<WeakMember<IntWrapper> >::Hash,
2742 HashTraits<WeakMember<IntWrapper> >,
2743 ThingWithDestructorTraits> Map;
2745 Persistent<Map> map(new Map());
2746 Persistent<RefMap> refMap(new RefMap());
2748 Persistent<IntWrapper> luck(IntWrapper::create(103));
2750 int baseLine, refBaseLine;
2756 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2757 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2759 stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2760 stackMap.add(luck, ThingWithDestructor(8128));
2761 stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2762 stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2764 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2765 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2767 // Although the heap maps are on-stack, we can't expect prompt
2768 // finalization of the elements, so when they go out of scope here we
2769 // will not necessarily have called the relevant destructors.
2772 // The RefCountedAndGarbageCollected things need an extra GC to discover
2773 // that they are no longer ref counted.
2774 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2775 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2776 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2777 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2779 // Now use maps kept alive with persistents. Here we don't expect any
2780 // destructors to be called before there have been GCs.
2782 map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2783 map->add(luck, ThingWithDestructor(8128));
2784 refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2785 refMap->add(luck, RefCountedAndGarbageCollected::create());
2787 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2788 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2792 map->clear(); // Clear map.
2793 refMap->clear(); // Clear map.
2795 map.clear(); // Clear Persistent handle, not map.
2796 refMap.clear(); // Clear Persistent handle, not map.
2797 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2798 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2801 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2803 // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2804 // noticies it's been decremented to zero.
2805 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2806 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2809 TEST(HeapTest, HeapMapDestructor)
2811 heapMapDestructorHelper(true);
2812 heapMapDestructorHelper(false);
2815 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2816 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2817 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2818 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2819 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
2820 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
2821 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
2822 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
2823 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
2824 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
2825 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
2826 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
2828 template<typename T>
2829 T& iteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair)
2834 template<typename T>
2835 T& iteratorExtractor(T& notAPair)
2840 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2842 Persistent<WSSet>& weakStrong,
2843 Persistent<SWSet>& strongWeak,
2844 Persistent<WUSet>& weakUnwrapped,
2845 Persistent<UWSet>& unwrappedWeak,
2847 Persistent<IntWrapper>& two)
2849 typename WSSet::iterator itWS = weakStrong->begin();
2850 typename SWSet::iterator itSW = strongWeak->begin();
2851 typename WUSet::iterator itWU = weakUnwrapped->begin();
2852 typename UWSet::iterator itUW = unwrappedWeak->begin();
2854 EXPECT_EQ(2u, weakStrong->size());
2855 EXPECT_EQ(2u, strongWeak->size());
2856 EXPECT_EQ(2u, weakUnwrapped->size());
2857 EXPECT_EQ(2u, unwrappedWeak->size());
2859 PairWeakStrong p = iteratorExtractor(*itWS);
2860 PairStrongWeak p2 = iteratorExtractor(*itSW);
2861 PairWeakUnwrapped p3 = iteratorExtractor(*itWU);
2862 PairUnwrappedWeak p4 = iteratorExtractor(*itUW);
2863 if (p.first == two && p.second == two)
2865 if (p2.first == two && p2.second == two)
2867 if (p3.first == two && p3.second == 2)
2869 if (p4.first == 2 && p4.second == two)
2871 p = iteratorExtractor(*itWS);
2872 p2 = iteratorExtractor(*itSW);
2873 p3 = iteratorExtractor(*itWU);
2874 p4 = iteratorExtractor(*itUW);
2875 IntWrapper* nullWrapper = 0;
2877 EXPECT_EQ(p.first->value(), 1);
2878 EXPECT_EQ(p2.second->value(), 1);
2879 EXPECT_EQ(p3.first->value(), 1);
2880 EXPECT_EQ(p4.second->value(), 1);
2882 EXPECT_EQ(p.first, nullWrapper);
2883 EXPECT_EQ(p2.second, nullWrapper);
2884 EXPECT_EQ(p3.first, nullWrapper);
2885 EXPECT_EQ(p4.second, nullWrapper);
2888 EXPECT_EQ(p.second->value(), 2);
2889 EXPECT_EQ(p2.first->value(), 2);
2890 EXPECT_EQ(p3.second, 2);
2891 EXPECT_EQ(p4.first, 2);
2893 EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2894 EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2895 EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2896 EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2899 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2900 void weakPairsHelper()
2902 IntWrapper::s_destructorCalls = 0;
2904 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2906 Persistent<WSSet> weakStrong = new WSSet();
2907 Persistent<SWSet> strongWeak = new SWSet();
2908 Persistent<WUSet> weakUnwrapped = new WUSet();
2909 Persistent<UWSet> unwrappedWeak = new UWSet();
2911 Persistent<IntWrapper> two = IntWrapper::create(2);
2913 weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2914 weakStrong->add(PairWeakStrong(&*two, &*two));
2915 strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2916 strongWeak->add(PairStrongWeak(&*two, &*two));
2917 weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2918 weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2919 unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2920 unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2922 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2924 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2925 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2928 TEST(HeapTest, HeapWeakPairs)
2931 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2932 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2933 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2934 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2935 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2939 typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
2940 typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2941 typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
2942 typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2943 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2947 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
2948 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2949 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
2950 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2951 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2955 TEST(HeapTest, HeapWeakCollectionTypes)
2957 HeapStats initialHeapSize;
2958 IntWrapper::s_destructorCalls = 0;
2960 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2961 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2962 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2963 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2964 typedef HeapLinkedHashSet<WeakMember<IntWrapper> > WeakOrderedSet;
2966 clearOutOldGarbage(&initialHeapSize);
2968 const int weakStrongIndex = 0;
2969 const int strongWeakIndex = 1;
2970 const int weakWeakIndex = 2;
2971 const int numberOfMapIndices = 3;
2972 const int weakSetIndex = 3;
2973 const int weakOrderedSetIndex = 4;
2974 const int numberOfCollections = 5;
2976 for (int testRun = 0; testRun < 4; testRun++) {
2977 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2978 bool deleteAfterwards = (testRun == 1);
2979 bool addAfterwards = (testRun == 2);
2980 bool testThatIteratorsMakeStrong = (testRun == 3);
2982 // The test doesn't work for strongWeak with deleting because we lost
2983 // the key from the keepNumbersAlive array, so we can't do the lookup.
2984 if (deleteAfterwards && collectionNumber == strongWeakIndex)
2987 unsigned added = addAfterwards ? 100 : 0;
2989 Persistent<WeakStrong> weakStrong = new WeakStrong();
2990 Persistent<StrongWeak> strongWeak = new StrongWeak();
2991 Persistent<WeakWeak> weakWeak = new WeakWeak();
2993 Persistent<WeakSet> weakSet = new WeakSet();
2994 Persistent<WeakOrderedSet> weakOrderedSet = new WeakOrderedSet();
2996 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2997 for (int i = 0; i < 128; i += 2) {
2998 IntWrapper* wrapped = IntWrapper::create(i);
2999 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
3000 keepNumbersAlive.append(wrapped);
3001 keepNumbersAlive.append(wrapped2);
3002 weakStrong->add(wrapped, wrapped2);
3003 strongWeak->add(wrapped2, wrapped);
3004 weakWeak->add(wrapped, wrapped2);
3005 weakSet->add(wrapped);
3006 weakOrderedSet->add(wrapped);
3009 EXPECT_EQ(64u, weakStrong->size());
3010 EXPECT_EQ(64u, strongWeak->size());
3011 EXPECT_EQ(64u, weakWeak->size());
3012 EXPECT_EQ(64u, weakSet->size());
3013 EXPECT_EQ(64u, weakOrderedSet->size());
3015 // Collect garbage. This should change nothing since we are keeping
3016 // alive the IntWrapper objects.
3017 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3019 EXPECT_EQ(64u, weakStrong->size());
3020 EXPECT_EQ(64u, strongWeak->size());
3021 EXPECT_EQ(64u, weakWeak->size());
3022 EXPECT_EQ(64u, weakSet->size());
3023 EXPECT_EQ(64u, weakOrderedSet->size());
3025 for (int i = 0; i < 128; i += 2) {
3026 IntWrapper* wrapped = keepNumbersAlive[i];
3027 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
3028 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
3029 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
3030 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
3031 EXPECT_TRUE(weakSet->contains(wrapped));
3032 EXPECT_TRUE(weakOrderedSet->contains(wrapped));
3035 for (int i = 0; i < 128; i += 3)
3036 keepNumbersAlive[i] = nullptr;
3038 if (collectionNumber != weakStrongIndex)
3039 weakStrong->clear();
3040 if (collectionNumber != strongWeakIndex)
3041 strongWeak->clear();
3042 if (collectionNumber != weakWeakIndex)
3044 if (collectionNumber != weakSetIndex)
3046 if (collectionNumber != weakOrderedSetIndex)
3047 weakOrderedSet->clear();
3049 if (testThatIteratorsMakeStrong) {
3050 WeakStrong::iterator it1 = weakStrong->begin();
3051 StrongWeak::iterator it2 = strongWeak->begin();
3052 WeakWeak::iterator it3 = weakWeak->begin();
3053 WeakSet::iterator it4 = weakSet->begin();
3054 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3055 // Collect garbage. This should change nothing since the
3056 // iterators make the collections strong.
3057 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3058 if (collectionNumber == weakStrongIndex) {
3059 EXPECT_EQ(64u, weakStrong->size());
3060 MapIteratorCheck(it1, weakStrong->end(), 64);
3061 } else if (collectionNumber == strongWeakIndex) {
3062 EXPECT_EQ(64u, strongWeak->size());
3063 MapIteratorCheck(it2, strongWeak->end(), 64);
3064 } else if (collectionNumber == weakWeakIndex) {
3065 EXPECT_EQ(64u, weakWeak->size());
3066 MapIteratorCheck(it3, weakWeak->end(), 64);
3067 } else if (collectionNumber == weakSetIndex) {
3068 EXPECT_EQ(64u, weakSet->size());
3069 SetIteratorCheck(it4, weakSet->end(), 64);
3070 } else if (collectionNumber == weakOrderedSetIndex) {
3071 EXPECT_EQ(64u, weakOrderedSet->size());
3072 SetIteratorCheck(it5, weakOrderedSet->end(), 64);
3075 // Collect garbage. This causes weak processing to remove
3076 // things from the collections.
3077 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3079 for (int i = 0; i < 128; i += 2) {
3080 bool firstAlive = keepNumbersAlive[i];
3081 bool secondAlive = keepNumbersAlive[i + 1];
3082 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
3084 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
3085 if (collectionNumber == weakStrongIndex) {
3086 if (deleteAfterwards)
3087 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
3088 } else if (collectionNumber == strongWeakIndex) {
3089 if (deleteAfterwards)
3090 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
3091 } else if (collectionNumber == weakWeakIndex) {
3092 if (deleteAfterwards)
3093 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
3095 if (!deleteAfterwards)
3097 } else if (collectionNumber == weakSetIndex && firstAlive) {
3098 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
3099 if (deleteAfterwards)
3100 weakSet->remove(keepNumbersAlive[i]);
3103 } else if (collectionNumber == weakOrderedSetIndex && firstAlive) {
3104 ASSERT_TRUE(weakOrderedSet->contains(keepNumbersAlive[i]));
3105 if (deleteAfterwards)
3106 weakOrderedSet->remove(keepNumbersAlive[i]);
3111 if (addAfterwards) {
3112 for (int i = 1000; i < 1100; i++) {
3113 IntWrapper* wrapped = IntWrapper::create(i);
3114 keepNumbersAlive.append(wrapped);
3115 weakStrong->add(wrapped, wrapped);
3116 strongWeak->add(wrapped, wrapped);
3117 weakWeak->add(wrapped, wrapped);
3118 weakSet->add(wrapped);
3119 weakOrderedSet->add(wrapped);
3122 if (collectionNumber == weakStrongIndex)
3123 EXPECT_EQ(count + added, weakStrong->size());
3124 else if (collectionNumber == strongWeakIndex)
3125 EXPECT_EQ(count + added, strongWeak->size());
3126 else if (collectionNumber == weakWeakIndex)
3127 EXPECT_EQ(count + added, weakWeak->size());
3128 else if (collectionNumber == weakSetIndex)
3129 EXPECT_EQ(count + added, weakSet->size());
3130 else if (collectionNumber == weakOrderedSetIndex)
3131 EXPECT_EQ(count + added, weakOrderedSet->size());
3132 WeakStrong::iterator it1 = weakStrong->begin();
3133 StrongWeak::iterator it2 = strongWeak->begin();
3134 WeakWeak::iterator it3 = weakWeak->begin();
3135 WeakSet::iterator it4 = weakSet->begin();
3136 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3137 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
3138 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
3139 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
3140 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
3141 SetIteratorCheck(it5, weakOrderedSet->end(), (collectionNumber == weakOrderedSetIndex ? count : 0) + added);
3143 for (unsigned i = 0; i < 128 + added; i++)
3144 keepNumbersAlive[i] = nullptr;
3145 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3146 EXPECT_EQ(0u, weakStrong->size());
3147 EXPECT_EQ(0u, strongWeak->size());
3148 EXPECT_EQ(0u, weakWeak->size());
3149 EXPECT_EQ(0u, weakSet->size());
3150 EXPECT_EQ(0u, weakOrderedSet->size());
3155 TEST(HeapTest, RefCountedGarbageCollected)
3157 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3159 RefPtr<RefCountedAndGarbageCollected> refPtr3;
3161 Persistent<RefCountedAndGarbageCollected> persistent;
3163 Persistent<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
3164 Persistent<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
3165 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3166 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3167 persistent = refPtr1.get();
3169 // Reference count is zero for both objects but one of
3170 // them is kept alive by a persistent handle.
3171 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3172 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3173 refPtr3 = persistent.get();
3175 // The persistent handle is gone but the ref count has been
3177 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3178 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3180 // Both persistent handle is gone and ref count is zero so the
3181 // object can be collected.
3182 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3183 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
3186 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
3188 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3189 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
3191 RefCountedAndGarbageCollected* pointer1 = 0;
3192 RefCountedAndGarbageCollected2* pointer2 = 0;
3194 Persistent<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
3195 Persistent<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
3196 pointer1 = object1.get();
3197 pointer2 = object2.get();
3198 void* objects[2] = { object1.get(), object2.get() };
3199 RefCountedGarbageCollectedVisitor visitor(2, objects);
3200 ThreadState::current()->visitPersistents(&visitor);
3201 EXPECT_TRUE(visitor.validate());
3203 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3204 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3205 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3207 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3208 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3209 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3211 // At this point, the reference counts of object1 and object2 are 0.
3212 // Only pointer1 and pointer2 keep references to object1 and object2.
3213 void* objects[] = { 0 };
3214 RefCountedGarbageCollectedVisitor visitor(0, objects);
3215 ThreadState::current()->visitPersistents(&visitor);
3216 EXPECT_TRUE(visitor.validate());
3219 Persistent<RefCountedAndGarbageCollected> object1(pointer1);
3220 Persistent<RefCountedAndGarbageCollected2> object2(pointer2);
3221 void* objects[2] = { object1.get(), object2.get() };
3222 RefCountedGarbageCollectedVisitor visitor(2, objects);
3223 ThreadState::current()->visitPersistents(&visitor);
3224 EXPECT_TRUE(visitor.validate());
3226 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3227 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3228 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3231 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3232 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3233 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3236 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3237 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3238 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
3241 TEST(HeapTest, WeakMembers)
3245 Persistent<Bar> h1 = Bar::create();
3246 Persistent<Weak> h4;
3247 Persistent<WithWeakMember> h5;
3248 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3249 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
3251 Bar* h2 = Bar::create();
3252 Bar* h3 = Bar::create();
3253 h4 = Weak::create(h2, h3);
3254 h5 = WithWeakMember::create(h2, h3);
3255 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3256 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
3257 EXPECT_TRUE(h4->strongIsThere());
3258 EXPECT_TRUE(h4->weakIsThere());
3259 EXPECT_TRUE(h5->strongIsThere());
3260 EXPECT_TRUE(h5->weakIsThere());
3262 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3263 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3264 EXPECT_EQ(4u, Bar::s_live);
3265 EXPECT_TRUE(h4->strongIsThere());
3266 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
3267 EXPECT_TRUE(h5->strongIsThere());
3268 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
3269 h1.release(); // Zero out h1.
3270 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3271 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
3272 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
3273 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
3275 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3276 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3277 EXPECT_EQ(0u, Bar::s_live); // All gone.
3280 TEST(HeapTest, FinalizationObserver)
3282 Persistent<FinalizationObserver<Observable> > o;
3284 Observable* foo = Observable::create(Bar::create());
3285 // |o| observes |foo|.
3286 o = FinalizationObserver<Observable>::create(foo);
3288 // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3289 // and its member will be collected.
3290 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3291 EXPECT_EQ(0u, Bar::s_live);
3292 EXPECT_TRUE(o->didCallWillFinalize());
3294 FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
3295 Observable* foo = Observable::create(Bar::create());
3296 FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
3297 EXPECT_EQ(1u, map.size());
3299 // FinalizationObserverWithHashMap doesn't have a strong reference to
3300 // |foo|. So |foo| and its member will be collected.
3301 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3302 EXPECT_EQ(0u, Bar::s_live);
3303 EXPECT_EQ(0u, map.size());
3304 EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
3306 FinalizationObserverWithHashMap::clearObservers();
3309 TEST(HeapTest, PreFinalizer)
3311 Observable::s_willFinalizeWasCalled = false;
3313 Observable* foo = Observable::create(Bar::create());
3314 ThreadState::current()->registerPreFinalizer(*foo);
3316 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3317 EXPECT_TRUE(Observable::s_willFinalizeWasCalled);
3320 TEST(HeapTest, PreFinalizerIsNotCalledIfUnregistered)
3322 Observable::s_willFinalizeWasCalled = false;
3324 Observable* foo = Observable::create(Bar::create());
3325 ThreadState::current()->registerPreFinalizer(*foo);
3326 ThreadState::current()->unregisterPreFinalizer(*foo);
3328 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3329 EXPECT_FALSE(Observable::s_willFinalizeWasCalled);
3332 TEST(HeapTest, PreFinalizerUnregistersItself)
3334 ObservableWithPreFinalizer::s_disposeWasCalled = false;
3335 ObservableWithPreFinalizer::create();
3336 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3337 EXPECT_TRUE(ObservableWithPreFinalizer::s_disposeWasCalled);
3338 // Don't crash, and assertions don't fail.
3341 TEST(HeapTest, Comparisons)
3343 Persistent<Bar> barPersistent = Bar::create();
3344 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
3345 EXPECT_TRUE(barPersistent != fooPersistent);
3346 barPersistent = fooPersistent;
3347 EXPECT_TRUE(barPersistent == fooPersistent);
3350 TEST(HeapTest, CheckAndMarkPointer)
3352 HeapStats initialHeapStats;
3353 clearOutOldGarbage(&initialHeapStats);
3355 Vector<Address> objectAddresses;
3356 Vector<Address> endAddresses;
3357 Address largeObjectAddress;
3358 Address largeObjectEndAddress;
3359 CountingVisitor visitor;
3360 for (int i = 0; i < 10; i++) {
3361 SimpleObject* object = SimpleObject::create();
3362 Address objectAddress = reinterpret_cast<Address>(object);
3363 objectAddresses.append(objectAddress);
3364 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
3366 LargeObject* largeObject = LargeObject::create();
3367 largeObjectAddress = reinterpret_cast<Address>(largeObject);
3368 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
3370 // This is a low-level test where we call checkAndMarkPointer. This method
3371 // causes the object start bitmap to be computed which requires the heap
3372 // to be in a consistent state (e.g. the free allocation area must be put
3373 // into a free list header). However when we call makeConsistentForSweeping it
3374 // also clears out the freelists so we have to rebuild those before trying
3375 // to allocate anything again. We do this by forcing a GC after doing the
3376 // checkAndMarkPointer tests.
3378 TestGCScope scope(ThreadState::HeapPointersOnStack);
3379 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3380 Heap::prepareForGC();
3381 Heap::flushHeapDoesNotContainCache();
3382 for (size_t i = 0; i < objectAddresses.size(); i++) {
3383 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3384 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3386 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3388 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3389 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3390 EXPECT_EQ(2ul, visitor.count());
3393 // This forces a GC without stack scanning which results in the objects
3394 // being collected. This will also rebuild the above mentioned freelists,
3395 // however we don't rely on that below since we don't have any allocations.
3396 clearOutOldGarbage(&initialHeapStats);
3398 TestGCScope scope(ThreadState::HeapPointersOnStack);
3399 EXPECT_TRUE(scope.allThreadsParked());
3400 Heap::prepareForGC();
3401 Heap::flushHeapDoesNotContainCache();
3402 for (size_t i = 0; i < objectAddresses.size(); i++) {
3403 // We would like to assert that checkAndMarkPointer returned false
3404 // here because the pointers no longer point into a valid object
3405 // (it's been freed by the GCs. But checkAndMarkPointer will return
3406 // true for any pointer that points into a heap page, regardless of
3407 // whether it points at a valid object (this ensures the
3408 // correctness of the page-based on-heap address caches), so we
3409 // can't make that assert.
3410 Heap::checkAndMarkPointer(&visitor, objectAddresses[i]);
3411 Heap::checkAndMarkPointer(&visitor, endAddresses[i]);
3413 EXPECT_EQ(0ul, visitor.count());
3414 Heap::checkAndMarkPointer(&visitor, largeObjectAddress);
3415 Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress);
3416 EXPECT_EQ(0ul, visitor.count());
3418 // This round of GC is important to make sure that the object start
3419 // bitmap are cleared out and that the free lists are rebuild.
3420 clearOutOldGarbage(&initialHeapStats);
3423 TEST(HeapTest, VisitOffHeapCollections)
3425 HeapStats initialHeapStats;
3426 clearOutOldGarbage(&initialHeapStats);
3427 IntWrapper::s_destructorCalls = 0;
3428 Persistent<OffHeapContainer> container = OffHeapContainer::create();
3429 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3430 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3431 container = nullptr;
3432 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3433 EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
3436 TEST(HeapTest, PersistentHeapCollectionTypes)
3438 HeapStats initialHeapSize;
3439 IntWrapper::s_destructorCalls = 0;
3441 typedef HeapVector<Member<IntWrapper> > Vec;
3442 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
3443 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
3444 typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet;
3445 typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet;
3446 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
3447 typedef PersistentHeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakPMap;
3448 typedef PersistentHeapDeque<Member<IntWrapper> > PDeque;
3450 clearOutOldGarbage(&initialHeapSize);
3456 PLinkedSet pLinkedSet;
3460 IntWrapper* one(IntWrapper::create(1));
3461 IntWrapper* two(IntWrapper::create(2));
3462 IntWrapper* three(IntWrapper::create(3));
3463 IntWrapper* four(IntWrapper::create(4));
3464 IntWrapper* five(IntWrapper::create(5));
3465 IntWrapper* six(IntWrapper::create(6));
3466 IntWrapper* seven(IntWrapper::create(7));
3467 IntWrapper* eight(IntWrapper::create(8));
3468 IntWrapper* nine(IntWrapper::create(9));
3469 Persistent<IntWrapper> ten(IntWrapper::create(10));
3470 IntWrapper* eleven(IntWrapper::create(11));
3475 pDeque.append(seven);
3478 Vec* vec = new Vec();
3485 pListSet.add(eight);
3486 pLinkedSet.add(nine);
3487 pMap.add(five, six);
3488 wpMap.add(ten, eleven);
3490 // Collect |vec| and |one|.
3492 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3493 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3495 EXPECT_EQ(2u, pVec.size());
3496 EXPECT_EQ(two, pVec.at(0));
3497 EXPECT_EQ(three, pVec.at(1));
3499 EXPECT_EQ(2u, pDeque.size());
3500 EXPECT_EQ(seven, pDeque.first());
3501 EXPECT_EQ(seven, pDeque.takeFirst());
3502 EXPECT_EQ(two, pDeque.first());
3504 EXPECT_EQ(1u, pDeque.size());
3506 EXPECT_EQ(1u, pSet.size());
3507 EXPECT_TRUE(pSet.contains(four));
3509 EXPECT_EQ(1u, pListSet.size());
3510 EXPECT_TRUE(pListSet.contains(eight));
3512 EXPECT_EQ(1u, pLinkedSet.size());
3513 EXPECT_TRUE(pLinkedSet.contains(nine));
3515 EXPECT_EQ(1u, pMap.size());
3516 EXPECT_EQ(six, pMap.get(five));
3518 EXPECT_EQ(1u, wpMap.size());
3519 EXPECT_EQ(eleven, wpMap.get(ten));
3521 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3522 EXPECT_EQ(0u, wpMap.size());
3525 // Collect previous roots.
3526 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3527 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
3530 TEST(HeapTest, CollectionNesting)
3532 HeapStats initialStats;
3533 clearOutOldGarbage(&initialStats);
3534 int* key = &IntWrapper::s_destructorCalls;
3535 IntWrapper::s_destructorCalls = 0;
3536 typedef HeapVector<Member<IntWrapper> > IntVector;
3537 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3538 HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
3539 HeapHashMap<void*, IntDeque>* map2 = new HeapHashMap<void*, IntDeque>();
3541 map->add(key, IntVector());
3542 map2->add(key, IntDeque());
3544 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3545 EXPECT_EQ(0u, map->get(key).size());
3547 HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3548 EXPECT_EQ(0u, map2->get(key).size());
3550 it->value.append(IntWrapper::create(42));
3551 EXPECT_EQ(1u, map->get(key).size());
3553 it2->value.append(IntWrapper::create(42));
3554 EXPECT_EQ(1u, map2->get(key).size());
3556 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
3557 Persistent<HeapHashMap<void*, IntDeque> > keepAlive2(map2);
3559 for (int i = 0; i < 100; i++) {
3560 map->add(key + 1 + i, IntVector());
3561 map2->add(key + 1 + i, IntDeque());
3564 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3566 EXPECT_EQ(1u, map->get(key).size());
3567 EXPECT_EQ(1u, map2->get(key).size());
3568 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3570 keepAlive = nullptr;
3571 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3572 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3575 TEST(HeapTest, GarbageCollectedMixin)
3577 HeapStats initialHeapStats;
3578 clearOutOldGarbage(&initialHeapStats);
3580 Persistent<UseMixin> usemixin = UseMixin::create();
3581 EXPECT_EQ(0, UseMixin::s_traceCount);
3582 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3583 EXPECT_EQ(1, UseMixin::s_traceCount);
3585 Persistent<Mixin> mixin = usemixin;
3587 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3588 EXPECT_EQ(2, UseMixin::s_traceCount);
3590 PersistentHeapHashSet<WeakMember<Mixin> > weakMap;
3591 weakMap.add(UseMixin::create());
3592 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3593 EXPECT_EQ(0u, weakMap.size());
3596 TEST(HeapTest, CollectionNesting2)
3598 HeapStats initialStats;
3599 clearOutOldGarbage(&initialStats);
3600 void* key = &IntWrapper::s_destructorCalls;
3601 IntWrapper::s_destructorCalls = 0;
3602 typedef HeapHashSet<Member<IntWrapper> > IntSet;
3603 HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
3605 map->add(key, IntSet());
3607 HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3608 EXPECT_EQ(0u, map->get(key).size());
3610 it->value.add(IntWrapper::create(42));
3611 EXPECT_EQ(1u, map->get(key).size());
3613 Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
3614 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3615 EXPECT_EQ(1u, map->get(key).size());
3616 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3619 TEST(HeapTest, CollectionNesting3)
3621 HeapStats initialStats;
3622 clearOutOldGarbage(&initialStats);
3623 IntWrapper::s_destructorCalls = 0;
3624 typedef HeapVector<Member<IntWrapper> > IntVector;
3625 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3626 HeapVector<IntVector>* vector = new HeapVector<IntVector>();
3627 HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
3629 vector->append(IntVector());
3630 deque->append(IntDeque());
3632 HeapVector<IntVector>::iterator it = vector->begin();
3633 HeapDeque<IntDeque>::iterator it2 = deque->begin();
3634 EXPECT_EQ(0u, it->size());
3635 EXPECT_EQ(0u, it2->size());
3637 it->append(IntWrapper::create(42));
3638 it2->append(IntWrapper::create(42));
3639 EXPECT_EQ(1u, it->size());
3640 EXPECT_EQ(1u, it2->size());
3642 Persistent<HeapVector<IntVector> > keepAlive(vector);
3643 Persistent<HeapDeque<IntDeque> > keepAlive2(deque);
3644 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3645 EXPECT_EQ(1u, it->size());
3646 EXPECT_EQ(1u, it2->size());
3647 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3650 TEST(HeapTest, EmbeddedInVector)
3652 HeapStats initialStats;
3653 clearOutOldGarbage(&initialStats);
3654 SimpleFinalizedObject::s_destructorCalls = 0;
3656 PersistentHeapVector<VectorObject, 2> inlineVector;
3657 PersistentHeapVector<VectorObject> outlineVector;
3658 VectorObject i1, i2;
3659 inlineVector.append(i1);
3660 inlineVector.append(i2);
3662 VectorObject o1, o2;
3663 outlineVector.append(o1);
3664 outlineVector.append(o2);
3666 PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
3667 VectorObjectInheritedTrace it1, it2;
3668 vectorInheritedTrace.append(it1);
3669 vectorInheritedTrace.append(it2);
3671 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3672 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3674 // Since VectorObjectNoTrace has no trace method it will
3675 // not be traced and hence be collected when doing GC.
3676 // We trace items in a collection braced on the item's
3677 // having a trace method. This is determined via the
3678 // NeedsTracing trait in wtf/TypeTraits.h.
3679 PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
3680 VectorObjectNoTrace n1, n2;
3681 vectorNoTrace.append(n1);
3682 vectorNoTrace.append(n2);
3683 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3684 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3686 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3687 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3690 TEST(HeapTest, EmbeddedInDeque)
3692 HeapStats initialStats;
3693 clearOutOldGarbage(&initialStats);
3694 SimpleFinalizedObject::s_destructorCalls = 0;
3696 PersistentHeapDeque<VectorObject, 2> inlineDeque;
3697 PersistentHeapDeque<VectorObject> outlineDeque;
3698 VectorObject i1, i2;
3699 inlineDeque.append(i1);
3700 inlineDeque.append(i2);
3702 VectorObject o1, o2;
3703 outlineDeque.append(o1);
3704 outlineDeque.append(o2);
3706 PersistentHeapDeque<VectorObjectInheritedTrace> dequeInheritedTrace;
3707 VectorObjectInheritedTrace it1, it2;
3708 dequeInheritedTrace.append(it1);
3709 dequeInheritedTrace.append(it2);
3711 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3712 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3714 // Since VectorObjectNoTrace has no trace method it will
3715 // not be traced and hence be collected when doing GC.
3716 // We trace items in a collection braced on the item's
3717 // having a trace method. This is determined via the
3718 // NeedsTracing trait in wtf/TypeTraits.h.
3719 PersistentHeapDeque<VectorObjectNoTrace> dequeNoTrace;
3720 VectorObjectNoTrace n1, n2;
3721 dequeNoTrace.append(n1);
3722 dequeNoTrace.append(n2);
3723 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3724 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3726 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3727 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3730 template<typename Set>
3731 void rawPtrInHashHelper()
3734 set.add(new int(42));
3735 set.add(new int(42));
3736 EXPECT_EQ(2u, set.size());
3737 for (typename Set::iterator it = set.begin(); it != set.end(); ++it) {
3738 EXPECT_EQ(42, **it);
3743 TEST(HeapTest, RawPtrInHash)
3745 rawPtrInHashHelper<HashSet<RawPtr<int> > >();
3746 rawPtrInHashHelper<ListHashSet<RawPtr<int> > >();
3747 rawPtrInHashHelper<LinkedHashSet<RawPtr<int> > >();
3750 TEST(HeapTest, HeapTerminatedArray)
3752 HeapStats initialHeapSize;
3753 clearOutOldGarbage(&initialHeapSize);
3754 IntWrapper::s_destructorCalls = 0;
3756 HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
3758 const size_t prefixSize = 4;
3759 const size_t suffixSize = 4;
3762 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3763 builder.grow(prefixSize);
3764 for (size_t i = 0; i < prefixSize; i++)
3765 builder.append(TerminatedArrayItem(IntWrapper::create(i)));
3766 arr = builder.release();
3769 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3770 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3771 EXPECT_EQ(prefixSize, arr->size());
3772 for (size_t i = 0; i < prefixSize; i++)
3773 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3776 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3777 builder.grow(suffixSize);
3778 for (size_t i = 0; i < suffixSize; i++)
3779 builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
3780 arr = builder.release();
3783 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3784 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3785 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3786 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3787 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3790 Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3792 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3793 arr = persistentArr.get();
3794 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3795 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3796 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3797 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3801 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3802 EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3805 TEST(HeapTest, HeapLinkedStack)
3807 HeapStats initialHeapSize;
3808 clearOutOldGarbage(&initialHeapSize);
3809 IntWrapper::s_destructorCalls = 0;
3811 HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3813 const size_t stackSize = 10;
3815 for (size_t i = 0; i < stackSize; i++)
3816 stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3818 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3819 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3820 EXPECT_EQ(stackSize, stack->size());
3821 while (!stack->isEmpty()) {
3822 EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3826 Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3828 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3829 EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3830 EXPECT_EQ(0u, pStack->size());
3833 TEST(HeapTest, AllocationDuringFinalization)
3835 HeapStats initialHeapSize;
3836 clearOutOldGarbage(&initialHeapSize);
3837 IntWrapper::s_destructorCalls = 0;
3838 OneKiloByteObject::s_destructorCalls = 0;
3840 Persistent<IntWrapper> wrapper;
3841 new FinalizationAllocator(&wrapper);
3843 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3844 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3845 // Check that the wrapper allocated during finalization is not
3846 // swept away and zapped later in the same sweeping phase.
3847 EXPECT_EQ(42, wrapper->value());
3850 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3851 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3852 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3855 class SimpleClassWithDestructor {
3857 SimpleClassWithDestructor() { }
3858 ~SimpleClassWithDestructor()
3860 s_wasDestructed = true;
3862 static bool s_wasDestructed;
3865 bool SimpleClassWithDestructor::s_wasDestructed;
3867 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
3869 RefCountedWithDestructor() { }
3870 ~RefCountedWithDestructor()
3872 s_wasDestructed = true;
3874 static bool s_wasDestructed;
3877 bool RefCountedWithDestructor::s_wasDestructed;
3879 template<typename Set>
3880 void destructorsCalledOnGC(bool addLots)
3882 RefCountedWithDestructor::s_wasDestructed = false;
3885 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3886 set.add(adoptRef(hasDestructor));
3887 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3890 for (int i = 0; i < 1000; i++) {
3891 set.add(adoptRef(new RefCountedWithDestructor()));
3895 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3896 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3897 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3899 // The destructors of the sets don't call the destructors of the elements
3900 // in the heap sets. You have to actually remove the elments, call clear()
3901 // or have a GC to get the destructors called.
3902 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3903 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3904 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3907 template<typename Set>
3908 void destructorsCalledOnClear(bool addLots)
3910 RefCountedWithDestructor::s_wasDestructed = false;
3912 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3913 set.add(adoptRef(hasDestructor));
3914 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3917 for (int i = 0; i < 1000; i++) {
3918 set.add(adoptRef(new RefCountedWithDestructor()));
3922 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3924 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3927 TEST(HeapTest, DestructorsCalled)
3929 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3930 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3931 map.add(hasDestructor, adoptPtr(hasDestructor));
3932 SimpleClassWithDestructor::s_wasDestructed = false;
3934 EXPECT_TRUE(SimpleClassWithDestructor::s_wasDestructed);
3936 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3937 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3938 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3939 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3940 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3941 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3943 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3944 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3945 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3946 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3947 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3948 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3951 class MixinA : public GarbageCollectedMixin {
3953 MixinA() : m_obj(IntWrapper::create(100)) { }
3954 virtual void trace(Visitor* visitor)
3956 visitor->trace(m_obj);
3958 Member<IntWrapper> m_obj;
3961 class MixinB : public GarbageCollectedMixin {
3963 MixinB() : m_obj(IntWrapper::create(101)) { }
3964 virtual void trace(Visitor* visitor)
3966 visitor->trace(m_obj);
3968 Member<IntWrapper> m_obj;
3971 class MultipleMixins : public GarbageCollected<MultipleMixins>, public MixinA, public MixinB {
3972 USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
3974 MultipleMixins() : m_obj(IntWrapper::create(102)) { }
3975 virtual void trace(Visitor* visitor)
3977 visitor->trace(m_obj);
3978 MixinA::trace(visitor);
3979 MixinB::trace(visitor);
3981 Member<IntWrapper> m_obj;
3984 static const bool s_isMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
3985 static const bool s_isMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
3987 TEST(HeapTest, MultipleMixins)
3989 EXPECT_TRUE(s_isMixinTrue);
3990 EXPECT_FALSE(s_isMixinFalse);
3992 HeapStats initialHeapSize;
3993 clearOutOldGarbage(&initialHeapSize);
3994 IntWrapper::s_destructorCalls = 0;
3995 MultipleMixins* obj = new MultipleMixins();
3997 Persistent<MixinA> a = obj;
3998 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3999 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4002 Persistent<MixinB> b = obj;
4003 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4004 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4006 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4007 EXPECT_EQ(3, IntWrapper::s_destructorCalls);
4010 class GCParkingThreadTester {
4014 OwnPtr<WebThread> sleepingThread = adoptPtr(Platform::current()->createThread("SleepingThread"));
4015 sleepingThread->postTask(new Task(WTF::bind(sleeperMainFunc)));
4017 // Wait for the sleeper to run.
4018 while (!s_sleeperRunning) {
4019 Platform::current()->yieldCurrentThread();
4023 // Expect the first attempt to park the sleeping thread to fail
4024 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
4025 EXPECT_FALSE(scope.allThreadsParked());
4028 s_sleeperDone = true;
4030 // Wait for the sleeper to finish.
4031 while (s_sleeperRunning) {
4032 // We enter the safepoint here since the sleeper thread will detach
4033 // causing it to GC.
4034 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
4035 Platform::current()->yieldCurrentThread();
4039 // Since the sleeper thread has detached this is the only thread.
4040 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
4041 EXPECT_TRUE(scope.allThreadsParked());
4046 static void sleeperMainFunc()
4048 ThreadState::attach();
4049 s_sleeperRunning = true;
4051 // Simulate a long running op that is not entering a safepoint.
4052 while (!s_sleeperDone) {
4053 Platform::current()->yieldCurrentThread();
4056 ThreadState::detach();
4057 s_sleeperRunning = false;
4060 static volatile bool s_sleeperRunning;
4061 static volatile bool s_sleeperDone;
4064 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
4065 volatile bool GCParkingThreadTester::s_sleeperDone = false;
4067 TEST(HeapTest, GCParkingTimeout)
4069 GCParkingThreadTester::test();
4072 TEST(HeapTest, NeedsAdjustAndMark)
4074 // class Mixin : public GarbageCollectedMixin {};
4075 EXPECT_TRUE(NeedsAdjustAndMark<Mixin>::value);
4076 EXPECT_TRUE(NeedsAdjustAndMark<const Mixin>::value);
4078 // class SimpleObject : public GarbageCollected<SimpleObject> {};
4079 EXPECT_FALSE(NeedsAdjustAndMark<SimpleObject>::value);
4080 EXPECT_FALSE(NeedsAdjustAndMark<const SimpleObject>::value);
4082 // class UseMixin : public SimpleObject, public Mixin {};
4083 EXPECT_FALSE(NeedsAdjustAndMark<UseMixin>::value);
4084 EXPECT_FALSE(NeedsAdjustAndMark<const UseMixin>::value);
4087 template<typename Set>
4088 void setWithCustomWeaknessHandling()
4090 typedef typename Set::iterator Iterator;
4091 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4092 Persistent<Set> set1(new Set());
4095 Set* set3 = new Set();
4096 set2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4097 set3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4098 set1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4099 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4100 // The first set is pointed to from a persistent, so it's referenced, but
4101 // the weak processing may have taken place.
4103 Iterator i1 = set1->begin();
4104 EXPECT_EQ(4, i1->first->value());
4105 EXPECT_EQ(5, i1->second->value());
4107 // The second set is on-stack, so its backing store must be referenced from
4108 // the stack. That makes the weak references strong.
4109 Iterator i2 = set2.begin();
4110 EXPECT_EQ(0, i2->first->value());
4111 EXPECT_EQ(1, i2->second->value());
4112 // The third set is pointed to from the stack, so it's referenced, but the
4113 // weak processing may have taken place.
4115 Iterator i3 = set3->begin();
4116 EXPECT_EQ(2, i3->first->value());
4117 EXPECT_EQ(3, i3->second->value());
4120 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4121 EXPECT_EQ(0u, set1->size());
4122 set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt));
4123 set1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4124 set1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4125 set1->add(PairWithWeakHandling(livingInt, livingInt));
4126 set1->add(PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4127 EXPECT_EQ(4u, set1->size());
4128 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4129 EXPECT_EQ(2u, set1->size());
4130 Iterator i1 = set1->begin();
4131 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4132 EXPECT_EQ(livingInt, i1->second);
4134 EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4135 EXPECT_EQ(livingInt, i1->second);
4138 TEST(HeapTest, SetWithCustomWeaknessHandling)
4140 setWithCustomWeaknessHandling<HeapHashSet<PairWithWeakHandling> >();
4141 setWithCustomWeaknessHandling<HeapLinkedHashSet<PairWithWeakHandling> >();
4144 TEST(HeapTest, MapWithCustomWeaknessHandling)
4146 typedef HeapHashMap<PairWithWeakHandling, RefPtr<OffHeapInt> > Map;
4147 typedef Map::iterator Iterator;
4148 HeapStats initialHeapSize;
4149 clearOutOldGarbage(&initialHeapSize);
4150 OffHeapInt::s_destructorCalls = 0;
4152 Persistent<Map> map1(new Map());
4153 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4156 Map* map3 = new Map();
4157 map2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)), OffHeapInt::create(1001));
4158 map3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)), OffHeapInt::create(1002));
4159 map1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)), OffHeapInt::create(1003));
4160 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4162 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4163 // The first map2 is pointed to from a persistent, so it's referenced, but
4164 // the weak processing may have taken place.
4166 Iterator i1 = map1->begin();
4167 EXPECT_EQ(4, i1->key.first->value());
4168 EXPECT_EQ(5, i1->key.second->value());
4169 EXPECT_EQ(1003, i1->value->value());
4171 // The second map2 is on-stack, so its backing store must be referenced from
4172 // the stack. That makes the weak references strong.
4173 Iterator i2 = map2.begin();
4174 EXPECT_EQ(0, i2->key.first->value());
4175 EXPECT_EQ(1, i2->key.second->value());
4176 EXPECT_EQ(1001, i2->value->value());
4177 // The third map2 is pointed to from the stack, so it's referenced, but the
4178 // weak processing may have taken place.
4180 Iterator i3 = map3->begin();
4181 EXPECT_EQ(2, i3->key.first->value());
4182 EXPECT_EQ(3, i3->key.second->value());
4183 EXPECT_EQ(1002, i3->value->value());
4186 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4188 EXPECT_EQ(0u, map1->size());
4189 EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4191 OffHeapInt::s_destructorCalls = 0;
4193 map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), OffHeapInt::create(2000));
4194 map1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103)), OffHeapInt::create(2001)); // This one gets zapped at GC time because nothing holds the 103 alive.
4195 map1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), OffHeapInt::create(2002)); // This one gets zapped too.
4196 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4197 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt);
4198 map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); // This one is identical to the previous and doesn't add anything.
4201 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4202 EXPECT_EQ(4u, map1->size());
4203 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4204 EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4205 EXPECT_EQ(2u, map1->size());
4206 Iterator i1 = map1->begin();
4207 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4208 EXPECT_EQ(livingInt, i1->key.second);
4210 EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4211 EXPECT_EQ(livingInt, i1->key.second);
4214 TEST(HeapTest, MapWithCustomWeaknessHandling2)
4216 typedef HeapHashMap<RefPtr<OffHeapInt>, PairWithWeakHandling> Map;
4217 typedef Map::iterator Iterator;
4218 HeapStats initialHeapSize;
4219 clearOutOldGarbage(&initialHeapSize);
4220 OffHeapInt::s_destructorCalls = 0;
4222 Persistent<Map> map1(new Map());
4223 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4227 Map* map3 = new Map();
4228 map2.add(OffHeapInt::create(1001), PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4229 map3->add(OffHeapInt::create(1002), PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4230 map1->add(OffHeapInt::create(1003), PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4231 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4233 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4234 // The first map2 is pointed to from a persistent, so it's referenced, but
4235 // the weak processing may have taken place.
4237 Iterator i1 = map1->begin();
4238 EXPECT_EQ(4, i1->value.first->value());
4239 EXPECT_EQ(5, i1->value.second->value());
4240 EXPECT_EQ(1003, i1->key->value());
4242 // The second map2 is on-stack, so its backing store must be referenced from
4243 // the stack. That makes the weak references strong.
4244 Iterator i2 = map2.begin();
4245 EXPECT_EQ(0, i2->value.first->value());
4246 EXPECT_EQ(1, i2->value.second->value());
4247 EXPECT_EQ(1001, i2->key->value());
4248 // The third map2 is pointed to from the stack, so it's referenced, but the
4249 // weak processing may have taken place.
4251 Iterator i3 = map3->begin();
4252 EXPECT_EQ(2, i3->value.first->value());
4253 EXPECT_EQ(3, i3->value.second->value());
4254 EXPECT_EQ(1002, i3->key->value());
4257 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4259 EXPECT_EQ(0u, map1->size());
4260 EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4262 OffHeapInt::s_destructorCalls = 0;
4264 map1->add(OffHeapInt::create(2000), PairWithWeakHandling(IntWrapper::create(103), livingInt));
4265 map1->add(OffHeapInt::create(2001), PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4266 map1->add(OffHeapInt::create(2002), PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4267 RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4268 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt));
4269 map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4272 EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4273 EXPECT_EQ(4u, map1->size());
4274 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4275 EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4276 EXPECT_EQ(2u, map1->size());
4277 Iterator i1 = map1->begin();
4278 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4279 EXPECT_EQ(livingInt, i1->value.second);
4281 EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4282 EXPECT_EQ(livingInt, i1->value.second);
4285 static void addElementsToWeakMap(HeapHashMap<int, WeakMember<IntWrapper> >* map)
4287 // Key cannot be zero in hashmap.
4288 for (int i = 1; i < 11; i++)
4289 map->add(i, IntWrapper::create(i));
4293 // If it doesn't assert a concurrent modification to the map, then it's passing.
4294 TEST(HeapTest, RegressNullIsStrongified)
4296 Persistent<HeapHashMap<int, WeakMember<IntWrapper> > > map = new HeapHashMap<int, WeakMember<IntWrapper> >();
4297 addElementsToWeakMap(map);
4298 HeapHashMap<int, WeakMember<IntWrapper> >::AddResult result = map->add(800, nullptr);
4299 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4300 result.storedValue->value = IntWrapper::create(42);
4303 TEST(HeapTest, Bind)
4305 Closure closure = bind(&Bar::trace, Bar::create(), static_cast<Visitor*>(0));
4306 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4307 // The closure should have a persistent handle to the Bar.
4308 EXPECT_EQ(1u, Bar::s_live);
4310 Closure closure2 = bind(&Bar::trace, RawPtr<Bar>(Bar::create()), static_cast<Visitor*>(0));
4311 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4312 // The closure should have a persistent handle to the Bar.
4313 EXPECT_EQ(2u, Bar::s_live);
4314 // RawPtr<OffHeapInt> should not make Persistent.
4315 Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHeapInt::create(1).get()));
4317 UseMixin::s_traceCount = 0;
4318 Mixin* mixin = UseMixin::create();
4319 Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0));
4320 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4321 // The closure should have a persistent handle to the mixin.
4322 EXPECT_EQ(1, UseMixin::s_traceCount);
4325 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
4327 // These special traits will remove a set from a map when the set is empty.
4328 struct EmptyClearingHashSetTraits : HashTraits<WeakSet> {
4329 static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
4330 static bool traceInCollection(Visitor* visitor, WeakSet& set, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
4332 bool liveEntriesFound = false;
4333 WeakSet::iterator end = set.end();
4334 for (WeakSet::iterator it = set.begin(); it != end; ++it) {
4335 if (visitor->isAlive(*it)) {
4336 liveEntriesFound = true;
4340 // If there are live entries in the set then the set cannot be removed
4341 // from the map it is contained in, and we need to mark it (and its
4342 // backing) live. We just trace normally, which will invoke the normal
4343 // weak handling for any entries that are not live.
4344 if (liveEntriesFound)
4346 return !liveEntriesFound;
4350 // This is an example to show how you can remove entries from a T->WeakSet map
4351 // when the weak sets become empty. For this example we are using a type that
4352 // is given to use (HeapHashSet) rather than a type of our own. This means:
4353 // 1) We can't just override the HashTrait for the type since this would affect
4354 // all collections that use this kind of weak set. Instead we have our own
4355 // traits and use a map with custom traits for the value type. These traits
4356 // are the 5th template parameter, so we have to supply default values for
4357 // the 3rd and 4th template parameters
4358 // 2) We can't just inherit from WeakHandlingHashTraits, since that trait
4359 // assumes we can add methods to the type, but we can't add methods to
4361 TEST(HeapTest, RemoveEmptySets)
4363 HeapStats initialHeapSize;
4364 clearOutOldGarbage(&initialHeapSize);
4365 OffHeapInt::s_destructorCalls = 0;
4367 Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4369 typedef RefPtr<OffHeapInt> Key;
4370 typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash, HashTraits<Key>, EmptyClearingHashSetTraits> Map;
4371 Persistent<Map> map(new Map());
4372 map->add(OffHeapInt::create(1), WeakSet());
4374 WeakSet& set = map->begin()->value;
4375 set.add(IntWrapper::create(103)); // Weak set can't hold this long.
4376 set.add(livingInt); // This prevents the set from being emptied.
4377 EXPECT_EQ(2u, set.size());
4380 // The set we add here is empty, so the entry will be removed from the map
4382 map->add(OffHeapInt::create(2), WeakSet());
4383 EXPECT_EQ(2u, map->size());
4385 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4386 EXPECT_EQ(1u, map->size()); // The one with key 2 was removed.
4387 EXPECT_EQ(1, OffHeapInt::s_destructorCalls);
4389 WeakSet& set = map->begin()->value;
4390 EXPECT_EQ(1u, set.size());
4393 livingInt.clear(); // The weak set can no longer keep the '42' alive now.
4394 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4395 EXPECT_EQ(0u, map->size());
4398 TEST(HeapTest, EphemeronsInEphemerons)
4400 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > InnerMap;
4401 typedef HeapHashMap<WeakMember<IntWrapper>, InnerMap> OuterMap;
4403 for (int keepOuterAlive = 0; keepOuterAlive <= 1; keepOuterAlive++) {
4404 for (int keepInnerAlive = 0; keepInnerAlive <=1; keepInnerAlive++) {
4405 Persistent<OuterMap> outer = new OuterMap();
4406 Persistent<IntWrapper> one = IntWrapper::create(1);
4407 Persistent<IntWrapper> two = IntWrapper::create(2);
4408 outer->add(one, InnerMap());
4409 outer->begin()->value.add(two, IntWrapper::create(3));
4410 EXPECT_EQ(1u, outer->get(one).size());
4411 if (!keepOuterAlive)
4413 if (!keepInnerAlive)
4415 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4416 if (keepOuterAlive) {
4417 const InnerMap& inner = outer->get(one);
4418 if (keepInnerAlive) {
4419 EXPECT_EQ(1u, inner.size());
4420 IntWrapper* three = inner.get(two);
4421 EXPECT_EQ(3, three->value());
4423 EXPECT_EQ(0u, inner.size());
4426 EXPECT_EQ(0u, outer->size());
4429 Persistent<IntWrapper> deep = IntWrapper::create(42);
4430 Persistent<IntWrapper> home = IntWrapper::create(103);
4431 Persistent<IntWrapper> composite = IntWrapper::create(91);
4432 Persistent<HeapVector<Member<IntWrapper> > > keepAlive = new HeapVector<Member<IntWrapper> >();
4433 for (int i = 0; i < 10000; i++) {
4434 IntWrapper* value = IntWrapper::create(i);
4435 keepAlive->append(value);
4436 OuterMap::AddResult newEntry = outer->add(value, InnerMap());
4437 newEntry.storedValue->value.add(deep, home);
4438 newEntry.storedValue->value.add(composite, home);
4441 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4442 EXPECT_EQ(10000u, outer->size());
4443 for (int i = 0; i < 10000; i++) {
4444 IntWrapper* value = keepAlive->at(i);
4445 EXPECT_EQ(1u, outer->get(value).size()); // Other one was deleted by weak handling.
4447 keepAlive->at(i) = nullptr;
4449 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4450 EXPECT_EQ(5000u, outer->size());
4455 class EphemeronWrapper : public GarbageCollected<EphemeronWrapper> {
4457 void trace(Visitor* visitor)
4459 visitor->trace(m_map);
4462 typedef HeapHashMap<WeakMember<IntWrapper>, Member<EphemeronWrapper> > Map;
4463 Map& map() { return m_map; }
4469 TEST(HeapTest, EphemeronsPointToEphemerons)
4471 Persistent<IntWrapper> key = IntWrapper::create(42);
4472 Persistent<IntWrapper> key2 = IntWrapper::create(103);
4474 Persistent<EphemeronWrapper> chain;
4475 for (int i = 0; i < 100; i++) {
4476 EphemeronWrapper* oldHead = chain;
4477 chain = new EphemeronWrapper();
4479 chain->map().add(key2, oldHead);
4481 chain->map().add(key, oldHead);
4482 chain->map().add(IntWrapper::create(103), new EphemeronWrapper());
4485 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4487 EphemeronWrapper* wrapper = chain;
4488 for (int i = 0; i< 100; i++) {
4489 EXPECT_EQ(1u, wrapper->map().size());
4491 wrapper = wrapper->map().get(key2);
4493 wrapper = wrapper->map().get(key);
4495 EXPECT_EQ(nullptr, wrapper);
4498 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4501 for (int i = 0; i < 50; i++) {
4502 EXPECT_EQ(i == 49 ? 0u : 1u, wrapper->map().size());
4503 wrapper = wrapper->map().get(key);
4505 EXPECT_EQ(nullptr, wrapper);
4508 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4509 EXPECT_EQ(0u, chain->map().size());
4512 TEST(HeapTest, Ephemeron)
4514 typedef HeapHashMap<WeakMember<IntWrapper>, PairWithWeakHandling> WeakPairMap;
4515 typedef HeapHashMap<PairWithWeakHandling, WeakMember<IntWrapper> > PairWeakMap;
4516 typedef HeapHashSet<WeakMember<IntWrapper> > Set;
4518 Persistent<WeakPairMap> weakPairMap = new WeakPairMap();
4519 Persistent<WeakPairMap> weakPairMap2 = new WeakPairMap();
4520 Persistent<WeakPairMap> weakPairMap3 = new WeakPairMap();
4521 Persistent<WeakPairMap> weakPairMap4 = new WeakPairMap();
4523 Persistent<PairWeakMap> pairWeakMap = new PairWeakMap();
4524 Persistent<PairWeakMap> pairWeakMap2 = new PairWeakMap();
4526 Persistent<Set> set = new Set();
4528 Persistent<IntWrapper> wp1 = IntWrapper::create(1);
4529 Persistent<IntWrapper> wp2 = IntWrapper::create(2);
4530 Persistent<IntWrapper> pw1 = IntWrapper::create(3);
4531 Persistent<IntWrapper> pw2 = IntWrapper::create(4);
4533 weakPairMap->add(wp1, PairWithWeakHandling(wp1, wp1));
4534 weakPairMap->add(wp2, PairWithWeakHandling(wp1, wp1));
4535 weakPairMap2->add(wp1, PairWithWeakHandling(wp1, wp2));
4536 weakPairMap2->add(wp2, PairWithWeakHandling(wp1, wp2));
4537 // The map from wp1 to (wp2, wp1) would mark wp2 live, so we skip that.
4538 weakPairMap3->add(wp2, PairWithWeakHandling(wp2, wp1));
4539 weakPairMap4->add(wp1, PairWithWeakHandling(wp2, wp2));
4540 weakPairMap4->add(wp2, PairWithWeakHandling(wp2, wp2));
4542 pairWeakMap->add(PairWithWeakHandling(pw1, pw1), pw1);
4543 pairWeakMap->add(PairWithWeakHandling(pw1, pw2), pw1);
4544 // The map from (pw2, pw1) to pw1 would make pw2 live, so we skip that.
4545 pairWeakMap->add(PairWithWeakHandling(pw2, pw2), pw1);
4546 pairWeakMap2->add(PairWithWeakHandling(pw1, pw1), pw2);
4547 pairWeakMap2->add(PairWithWeakHandling(pw1, pw2), pw2);
4548 pairWeakMap2->add(PairWithWeakHandling(pw2, pw1), pw2);
4549 pairWeakMap2->add(PairWithWeakHandling(pw2, pw2), pw2);
4557 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4559 EXPECT_EQ(2u, weakPairMap->size());
4560 EXPECT_EQ(2u, weakPairMap2->size());
4561 EXPECT_EQ(1u, weakPairMap3->size());
4562 EXPECT_EQ(2u, weakPairMap4->size());
4564 EXPECT_EQ(3u, pairWeakMap->size());
4565 EXPECT_EQ(4u, pairWeakMap2->size());
4567 EXPECT_EQ(4u, set->size());
4569 wp2.clear(); // Kills all entries in the weakPairMaps except the first.
4570 pw2.clear(); // Kills all entries in the pairWeakMaps except the first.
4572 for (int i = 0; i < 2; i++) {
4573 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4575 EXPECT_EQ(1u, weakPairMap->size());
4576 EXPECT_EQ(0u, weakPairMap2->size());
4577 EXPECT_EQ(0u, weakPairMap3->size());
4578 EXPECT_EQ(0u, weakPairMap4->size());
4580 EXPECT_EQ(1u, pairWeakMap->size());
4581 EXPECT_EQ(0u, pairWeakMap2->size());
4583 EXPECT_EQ(2u, set->size()); // wp1 and pw1.
4589 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4591 EXPECT_EQ(0u, weakPairMap->size());
4592 EXPECT_EQ(0u, pairWeakMap->size());
4593 EXPECT_EQ(0u, set->size());
4596 class Link1 : public GarbageCollected<Link1> {
4598 Link1(IntWrapper* link) : m_link(link) { }
4600 void trace(Visitor* visitor)
4602 visitor->trace(m_link);
4605 IntWrapper* link() { return m_link; }
4608 Member<IntWrapper> m_link;
4611 TEST(HeapTest, IndirectStrongToWeak)
4613 typedef HeapHashMap<WeakMember<IntWrapper>, Member<Link1> > Map;
4614 Persistent<Map> map = new Map();
4615 Persistent<IntWrapper> deadObject = IntWrapper::create(100); // Named for "Drowning by Numbers" (1988).
4616 Persistent<IntWrapper> lifeObject = IntWrapper::create(42);
4617 map->add(deadObject, new Link1(deadObject));
4618 map->add(lifeObject, new Link1(lifeObject));
4619 EXPECT_EQ(2u, map->size());
4620 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4621 EXPECT_EQ(2u, map->size());
4622 EXPECT_EQ(deadObject, map->get(deadObject)->link());
4623 EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4624 deadObject.clear(); // Now it can live up to its name.
4625 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4626 EXPECT_EQ(1u, map->size());
4627 EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4628 lifeObject.clear(); // Despite its name.
4629 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4630 EXPECT_EQ(0u, map->size());
4633 static Mutex& mainThreadMutex()
4635 AtomicallyInitializedStatic(Mutex&, mainMutex = *new Mutex);
4639 static ThreadCondition& mainThreadCondition()
4641 AtomicallyInitializedStatic(ThreadCondition&, mainCondition = *new ThreadCondition);
4642 return mainCondition;
4645 static void parkMainThread()
4647 mainThreadCondition().wait(mainThreadMutex());
4650 static void wakeMainThread()
4652 MutexLocker locker(mainThreadMutex());
4653 mainThreadCondition().signal();
4656 static Mutex& workerThreadMutex()
4658 AtomicallyInitializedStatic(Mutex&, workerMutex = *new Mutex);
4662 static ThreadCondition& workerThreadCondition()
4664 AtomicallyInitializedStatic(ThreadCondition&, workerCondition = *new ThreadCondition);
4665 return workerCondition;
4668 static void parkWorkerThread()
4670 workerThreadCondition().wait(workerThreadMutex());
4673 static void wakeWorkerThread()
4675 MutexLocker locker(workerThreadMutex());
4676 workerThreadCondition().signal();
4679 class CrossThreadObject : public GarbageCollectedFinalized<CrossThreadObject> {
4681 static CrossThreadObject* create(IntWrapper* workerObjectPointer)
4683 return new CrossThreadObject(workerObjectPointer);
4686 virtual ~CrossThreadObject()
4688 ++s_destructorCalls;
4691 static int s_destructorCalls;
4692 void trace(Visitor* visitor) { visitor->trace(m_workerObject); }
4695 CrossThreadObject(IntWrapper* workerObjectPointer) : m_workerObject(workerObjectPointer) { }
4698 Member<IntWrapper> m_workerObject;
4701 int CrossThreadObject::s_destructorCalls = 0;
4703 class CrossThreadPointerTester {
4707 CrossThreadObject::s_destructorCalls = 0;
4708 IntWrapper::s_destructorCalls = 0;
4710 MutexLocker locker(mainThreadMutex());
4711 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4712 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4716 uintptr_t stackPtrValue = 0;
4718 // Create an object with a pointer to the other heap's IntWrapper.
4719 Persistent<CrossThreadObject> cto = CrossThreadObject::create(const_cast<IntWrapper*>(s_workerObjectPointer));
4720 s_workerObjectPointer = 0;
4722 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4724 // Nothing should have been collected/destructed.
4725 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4726 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4728 // Put cto into a stack value. This is used to check that a conservative
4729 // GC succeeds even though we are tracing the other thread heap after
4730 // shutting it down.
4731 stackPtrValue = reinterpret_cast<uintptr_t>(cto.get());
4733 // At this point it is "programatically" okay to shut down the worker thread
4734 // since the cto object should be dead. However out stackPtrValue will cause a
4735 // trace of the object when doing a conservative GC.
4736 // The worker thread's thread local GC's should just add the worker thread's
4737 // pages to the heap after finalizing IntWrapper.
4740 // Wait for the worker to shutdown.
4743 // After the worker thread has detached it should have finalized the
4744 // IntWrapper object on its heaps. Since there has been no global GC
4745 // the cto object should not have been finalized.
4746 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4747 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4749 // Now do a conservative GC. The stackPtrValue should keep cto alive
4750 // and will also cause the orphaned page of the other thread to be
4751 // traced. At this point cto should still not be finalized.
4752 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4753 EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4754 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4756 // This release assert is here to ensure the stackValuePtr is not
4757 // optimized away before doing the above conservative GC. If the
4758 // EXPECT_EQ(0, CrossThreadObject::s_destructorCalls) call above
4759 // starts failing it means we have to find a better way to ensure
4760 // the stackPtrValue is not optimized away.
4761 RELEASE_ASSERT(stackPtrValue);
4763 // Do a GC with no pointers on the stack to see the cto being collected.
4764 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4765 EXPECT_EQ(1, CrossThreadObject::s_destructorCalls);
4766 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4770 static void workerThreadMain()
4772 MutexLocker locker(workerThreadMutex());
4773 ThreadState::attach();
4776 // Create a worker object that is only kept alive by a cross thread
4777 // pointer (from CrossThreadObject).
4778 IntWrapper* workerObject = IntWrapper::create(42);
4779 s_workerObjectPointer = workerObject;
4782 // Wake up the main thread which is waiting for the worker to do its
4783 // allocation and passing the pointer.
4786 // Wait for main thread to signal the worker to shutdown.
4788 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4792 ThreadState::detach();
4794 // Tell the main thread the worker has done its shutdown.
4798 static volatile IntWrapper* s_workerObjectPointer;
4801 volatile IntWrapper* CrossThreadPointerTester::s_workerObjectPointer = 0;
4803 TEST(HeapTest, CrossThreadPointerToOrphanedPage)
4805 CrossThreadPointerTester::test();
4808 class DeadBitTester {
4812 IntWrapper::s_destructorCalls = 0;
4814 MutexLocker locker(mainThreadMutex());
4815 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4816 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4818 // Wait for the worker thread to have done its initialization,
4819 // IE. the worker allocates an object and then throw aways any
4823 // Now do a GC. This will not find the worker threads object since it
4824 // is not referred from any of the threads. Even a conservative
4825 // GC will not find it.
4826 // Also at this point the worker is waiting for the main thread
4827 // to be parked and will not do any sweep of its heap.
4828 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4830 // Since the worker thread is not sweeping the worker object should
4831 // not have been finalized.
4832 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4834 // Put the worker thread's object address on the stack and do a
4835 // conservative GC. This should find the worker object, but since
4836 // it was dead in the previous GC it should not be traced in this
4838 uintptr_t stackPtrValue = s_workerObjectPointer;
4839 s_workerObjectPointer = 0;
4840 ASSERT_UNUSED(stackPtrValue, stackPtrValue);
4841 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4843 // Since the worker thread is not sweeping the worker object should
4844 // not have been finalized.
4845 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4847 // Wake up the worker thread so it can continue with its sweeping.
4848 // This should finalized the worker object which we test below.
4849 // The worker thread will go back to sleep once sweeping to ensure
4850 // we don't have thread local GCs until after validating the destructor
4854 // Wait for the worker thread to sweep its heaps before checking.
4856 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4858 // Wake up the worker to allow it thread to continue with thread
4865 static void workerThreadMain()
4867 MutexLocker locker(workerThreadMutex());
4869 ThreadState::attach();
4872 // Create a worker object that is not kept alive except the
4873 // main thread will keep it as an integer value on its stack.
4874 IntWrapper* workerObject = IntWrapper::create(42);
4875 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject);
4878 // Signal the main thread that the worker is done with its allocation.
4882 // Wait for the main thread to do two GCs without sweeping this thread
4883 // heap. The worker waits within a safepoint, but there is no sweeping
4884 // until leaving the safepoint scope.
4885 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4889 // Wake up the main thread when done sweeping.
4892 // Wait with detach until the main thread says so. This is not strictly
4893 // necessary, but it means the worker thread will not do its thread local
4894 // GCs just yet, making it easier to reason about that no new GC has occurred
4895 // and the above sweep was the one finalizing the worker object.
4898 ThreadState::detach();
4901 static volatile uintptr_t s_workerObjectPointer;
4904 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0;
4906 TEST(HeapTest, ObjectDeadBit)
4908 DeadBitTester::test();
4911 class ThreadedStrongificationTester {
4915 IntWrapper::s_destructorCalls = 0;
4917 MutexLocker locker(mainThreadMutex());
4918 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4919 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4921 // Wait for the worker thread initialization. The worker
4922 // allocates a weak collection where both collection and
4923 // contents are kept alive via persistent pointers.
4926 // Perform two garbage collections where the worker thread does
4927 // not wake up in between. This will cause us to remove marks
4928 // and mark unmarked objects dead. The collection on the worker
4929 // heap is found through the persistent and the backing should
4931 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4932 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4934 // Wake up the worker thread so it can continue. It will sweep
4935 // and perform another GC where the backing store of its
4936 // collection should be strongified.
4939 // Wait for the worker thread to sweep its heaps before checking.
4941 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4948 static HeapHashSet<WeakMember<IntWrapper> >* allocateCollection()
4950 // Create a weak collection that is kept alive by a persistent
4951 // and keep the contents alive with a persistents as
4953 Persistent<IntWrapper> wrapper1 = IntWrapper::create(32);
4954 Persistent<IntWrapper> wrapper2 = IntWrapper::create(32);
4955 Persistent<IntWrapper> wrapper3 = IntWrapper::create(32);
4956 Persistent<IntWrapper> wrapper4 = IntWrapper::create(32);
4957 Persistent<IntWrapper> wrapper5 = IntWrapper::create(32);
4958 Persistent<IntWrapper> wrapper6 = IntWrapper::create(32);
4959 Persistent<HeapHashSet<WeakMember<IntWrapper> > > weakCollection = new HeapHashSet<WeakMember<IntWrapper> >;
4960 weakCollection->add(wrapper1);
4961 weakCollection->add(wrapper2);
4962 weakCollection->add(wrapper3);
4963 weakCollection->add(wrapper4);
4964 weakCollection->add(wrapper5);
4965 weakCollection->add(wrapper6);
4967 // Signal the main thread that the worker is done with its allocation.
4971 // Wait for the main thread to do two GCs without sweeping
4972 // this thread heap. The worker waits within a safepoint,
4973 // but there is no sweeping until leaving the safepoint
4974 // scope. If the weak collection backing is marked dead
4975 // because of this we will not get strongification in the
4976 // GC we force when we continue.
4977 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4981 return weakCollection;
4984 static void workerThreadMain()
4986 MutexLocker locker(workerThreadMutex());
4988 ThreadState::attach();
4991 Persistent<HeapHashSet<WeakMember<IntWrapper> > > collection = allocateCollection();
4993 // Prevent weak processing with an iterator and GC.
4994 HeapHashSet<WeakMember<IntWrapper> >::iterator it = collection->begin();
4995 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4997 // The backing should be strongified because of the iterator.
4998 EXPECT_EQ(6u, collection->size());
4999 EXPECT_EQ(32, (*it)->value());
5002 // Disregarding the iterator but keeping the collection alive
5003 // with a persistent should lead to weak processing.
5004 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5005 EXPECT_EQ(0u, collection->size());
5009 ThreadState::detach();
5012 static volatile uintptr_t s_workerObjectPointer;
5015 TEST(HeapTest, ThreadedStrongification)
5017 ThreadedStrongificationTester::test();
5020 static bool allocateAndReturnBool()
5022 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
5026 class MixinWithGarbageCollectionInConstructor : public GarbageCollectedMixin {
5028 MixinWithGarbageCollectionInConstructor() : m_dummy(allocateAndReturnBool())
5035 class ClassWithGarbageCollectingMixinConstructor
5036 : public GarbageCollected<ClassWithGarbageCollectingMixinConstructor>
5037 , public MixinWithGarbageCollectionInConstructor {
5038 USING_GARBAGE_COLLECTED_MIXIN(ClassWithGarbageCollectingMixinConstructor);
5040 ClassWithGarbageCollectingMixinConstructor() : m_wrapper(IntWrapper::create(32))
5044 virtual void trace(Visitor* visitor)
5046 visitor->trace(m_wrapper);
5051 EXPECT_EQ(32, m_wrapper->value());
5055 Member<IntWrapper> m_wrapper;
5058 // Regression test for out of bounds call through vtable.
5059 // Passes if it doesn't crash.
5060 TEST(HeapTest, GarbageCollectionDuringMixinConstruction)
5062 ClassWithGarbageCollectingMixinConstructor* a =
5063 new ClassWithGarbageCollectingMixinConstructor();
5067 static RecursiveMutex& recursiveMutex()
5069 AtomicallyInitializedStatic(RecursiveMutex&, recursiveMutex = *new RecursiveMutex);
5070 return recursiveMutex;
5073 class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLockingObject> {
5075 static DestructorLockingObject* create()
5077 return new DestructorLockingObject();
5080 virtual ~DestructorLockingObject()
5082 SafePointAwareMutexLocker lock(recursiveMutex());
5083 ++s_destructorCalls;
5086 static int s_destructorCalls;
5087 void trace(Visitor* visitor) { }
5090 DestructorLockingObject() { }
5093 int DestructorLockingObject::s_destructorCalls = 0;
5095 class RecursiveLockingTester {
5099 DestructorLockingObject::s_destructorCalls = 0;
5101 MutexLocker locker(mainThreadMutex());
5102 OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
5103 workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
5105 // Park the main thread until the worker thread has initialized.
5109 SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
5111 // Let the worker try to acquire the above mutex. It won't get it
5112 // until the main thread has done its GC.
5115 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5117 // The worker thread should not have swept yet since it is waiting
5118 // to get the global mutex.
5119 EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
5121 // At this point the main thread releases the global lock and the worker
5122 // can acquire it and do its sweep of its heaps. Just wait for the worker
5123 // to complete its sweep and check the result.
5125 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
5129 static void workerThreadMain()
5131 MutexLocker locker(workerThreadMutex());
5132 ThreadState::attach();
5134 DestructorLockingObject* dlo = DestructorLockingObject::create();
5135 ASSERT_UNUSED(dlo, dlo);
5137 // Wake up the main thread which is waiting for the worker to do its
5141 // Wait for the main thread to get the global lock to ensure it has
5142 // it before the worker tries to acquire it. We want the worker to
5143 // block in the SafePointAwareMutexLocker until the main thread
5144 // has done a GC. The GC will not mark the "dlo" object since the worker
5145 // is entering the safepoint with NoHeapPointersOnStack. When the worker
5146 // subsequently gets the global lock and leaves the safepoint it will
5147 // sweep its heap and finalize "dlo". The destructor of "dlo" will try
5148 // to acquire the same global lock that the thread just got and deadlock
5149 // unless the global lock is recursive.
5151 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState::NoHeapPointersOnStack);
5153 // We won't get here unless the lock is recursive since the sweep done
5154 // in the constructor of SafePointAwareMutexLocker after
5155 // getting the lock will not complete given the "dlo" destructor is
5156 // waiting to get the same lock.
5157 // Tell the main thread the worker has done its sweep.
5160 ThreadState::detach();
5163 static volatile IntWrapper* s_workerObjectPointer;
5166 TEST(HeapTest, RecursiveMutex)
5168 RecursiveLockingTester::test();
5171 template<typename T>
5172 class TraceIfNeededTester : public GarbageCollectedFinalized<TraceIfNeededTester<T> > {
5174 static TraceIfNeededTester<T>* create() { return new TraceIfNeededTester<T>(); }
5175 static TraceIfNeededTester<T>* create(const T& obj) { return new TraceIfNeededTester<T>(obj); }
5176 void trace(Visitor* visitor) { TraceIfNeeded<T>::trace(visitor, &m_obj); }
5177 T& obj() { return m_obj; }
5178 ~TraceIfNeededTester() { }
5180 TraceIfNeededTester() { }
5181 explicit TraceIfNeededTester(const T& obj) : m_obj(obj) { }
5186 DISALLOW_ALLOCATION();
5188 PartObject() : m_obj(SimpleObject::create()) { }
5189 void trace(Visitor* visitor) { visitor->trace(m_obj); }
5191 Member<SimpleObject> m_obj;
5194 TEST(HeapTest, TraceIfNeeded)
5196 CountingVisitor visitor;
5199 TraceIfNeededTester<RefPtr<OffHeapInt> >* m_offHeap = TraceIfNeededTester<RefPtr<OffHeapInt> >::create(OffHeapInt::create(42));
5201 m_offHeap->trace(&visitor);
5202 EXPECT_EQ(0u, visitor.count());
5206 TraceIfNeededTester<PartObject>* m_part = TraceIfNeededTester<PartObject>::create();
5208 m_part->trace(&visitor);
5209 EXPECT_EQ(1u, visitor.count());
5213 TraceIfNeededTester<Member<SimpleObject> >* m_obj = TraceIfNeededTester<Member<SimpleObject> >::create(Member<SimpleObject>(SimpleObject::create()));
5215 m_obj->trace(&visitor);
5216 EXPECT_EQ(1u, visitor.count());
5220 TraceIfNeededTester<HeapVector<Member<SimpleObject> > >* m_vec = TraceIfNeededTester<HeapVector<Member<SimpleObject> > >::create();
5221 m_vec->obj().append(SimpleObject::create());
5223 m_vec->trace(&visitor);
5224 EXPECT_EQ(2u, visitor.count());
5228 class AllocatesOnAssignment {
5230 AllocatesOnAssignment(std::nullptr_t)
5233 AllocatesOnAssignment(int x)
5234 : m_value(new IntWrapper(x))
5236 AllocatesOnAssignment(IntWrapper* x)
5240 AllocatesOnAssignment& operator=(const AllocatesOnAssignment x)
5242 m_value = x.m_value;
5246 enum DeletedMarker {
5250 AllocatesOnAssignment(const AllocatesOnAssignment& other)
5252 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
5253 m_value = new IntWrapper(other.m_value->value());
5256 AllocatesOnAssignment(DeletedMarker)
5257 : m_value(reinterpret_cast<IntWrapper*>(-1)) { }
5259 inline bool isDeleted() const { return m_value == reinterpret_cast<IntWrapper*>(-1); }
5261 virtual void trace(Visitor* visitor)
5263 visitor->trace(m_value);
5266 int value() { return m_value->value(); }
5269 Member<IntWrapper> m_value;
5271 friend bool operator==(const AllocatesOnAssignment&, const AllocatesOnAssignment&);
5272 friend void swap(AllocatesOnAssignment&, AllocatesOnAssignment&);
5275 bool operator==(const AllocatesOnAssignment& a, const AllocatesOnAssignment& b)
5278 return b.m_value && a.m_value->value() == b.m_value->value();
5282 void swap(AllocatesOnAssignment& a, AllocatesOnAssignment& b)
5284 std::swap(a.m_value, b.m_value);
5287 struct DegenerateHash {
5288 static unsigned hash(const AllocatesOnAssignment&) { return 0; }
5289 static bool equal(const AllocatesOnAssignment& a, const AllocatesOnAssignment& b) { return !a.isDeleted() && a == b; }
5290 static const bool safeToCompareToEmptyOrDeleted = true;
5293 struct AllocatesOnAssignmentHashTraits : WTF::GenericHashTraits<AllocatesOnAssignment> {
5294 typedef AllocatesOnAssignment T;
5295 typedef std::nullptr_t EmptyValueType;
5296 static EmptyValueType emptyValue() { return nullptr; }
5297 static const bool emptyValueIsZero = false; // Can't be zero if it has a vtable.
5298 static const bool needsDestruction = false;
5299 static void constructDeletedValue(T& slot, bool) { slot = T(AllocatesOnAssignment::DeletedValue); }
5300 static bool isDeletedValue(const T& value) { return value.isDeleted(); }
5303 } // namespace blink
5307 template<> struct DefaultHash<blink::AllocatesOnAssignment> {
5308 typedef blink::DegenerateHash Hash;
5311 template <> struct HashTraits<blink::AllocatesOnAssignment> : blink::AllocatesOnAssignmentHashTraits { };
5317 TEST(HeapTest, GCInHashMapOperations)
5319 typedef HeapHashMap<AllocatesOnAssignment, AllocatesOnAssignment> Map;
5320 Map* map = new Map();
5321 IntWrapper* key = new IntWrapper(42);
5322 map->add(key, AllocatesOnAssignment(103));
5324 for (int i = 0; i < 10; i++)
5325 map->add(AllocatesOnAssignment(i), AllocatesOnAssignment(i));
5326 for (Map::iterator it = map->begin(); it != map->end(); ++it)
5327 EXPECT_EQ(it->key.value(), it->value.value());
5330 class PartObjectWithVirtualMethod {
5332 virtual void trace(Visitor*) { }
5335 class ObjectWithVirtualPartObject : public GarbageCollected<ObjectWithVirtualPartObject> {
5337 ObjectWithVirtualPartObject() : m_dummy(allocateAndReturnBool()) { }
5338 void trace(Visitor* visitor) { visitor->trace(m_part); }
5341 PartObjectWithVirtualMethod m_part;
5344 TEST(HeapTest, PartObjectWithVirtualMethod)
5346 ObjectWithVirtualPartObject* object = new ObjectWithVirtualPartObject();
5347 EXPECT_TRUE(object);
5350 class AllocInSuperConstructorArgumentSuper : public GarbageCollectedFinalized<AllocInSuperConstructorArgumentSuper> {
5352 AllocInSuperConstructorArgumentSuper(bool value) : m_value(value) { }
5353 virtual void trace(Visitor*) { }
5354 bool value() { return m_value; }
5359 class AllocInSuperConstructorArgument : public AllocInSuperConstructorArgumentSuper {
5361 AllocInSuperConstructorArgument()
5362 : AllocInSuperConstructorArgumentSuper(allocateAndReturnBool())
5367 // Regression test for crbug.com/404511. Tests conservative marking of
5368 // an object with an uninitialized vtable.
5369 TEST(HeapTest, AllocationInSuperConstructorArgument)
5371 AllocInSuperConstructorArgument* object = new AllocInSuperConstructorArgument();
5372 EXPECT_TRUE(object);
5373 Heap::collectAllGarbage();
5376 class NonNodeAllocatingNodeInDestructor : public GarbageCollectedFinalized<NonNodeAllocatingNodeInDestructor> {
5378 ~NonNodeAllocatingNodeInDestructor()
5380 s_node = new Persistent<Node>(Node::create(10));
5383 void trace(Visitor*) { }
5385 static Persistent<Node>* s_node;
5388 Persistent<Node>* NonNodeAllocatingNodeInDestructor::s_node = 0;
5390 TEST(HeapTest, NonNodeAllocatingNodeInDestructor)
5392 new NonNodeAllocatingNodeInDestructor();
5393 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5394 EXPECT_EQ(10, (*NonNodeAllocatingNodeInDestructor::s_node)->value());
5395 delete NonNodeAllocatingNodeInDestructor::s_node;
5396 NonNodeAllocatingNodeInDestructor::s_node = 0;
5399 } // namespace blink