2 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "platform/heap/Handle.h"
34 #include "platform/heap/Heap.h"
35 #include "platform/heap/HeapLinkedStack.h"
36 #include "platform/heap/HeapTerminatedArrayBuilder.h"
37 #include "platform/heap/ThreadState.h"
38 #include "platform/heap/Visitor.h"
39 #include "public/platform/Platform.h"
40 #include "wtf/HashTraits.h"
41 #include "wtf/LinkedHashSet.h"
43 #include <gtest/gtest.h>
49 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(0) { }
50 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i) { }
51 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(reinterpret_cast<ThreadState*>(-1)), m_num(0) { }
54 EXPECT_TRUE((m_creatingThread == ThreadState::current())
55 || (m_creatingThread == reinterpret_cast<ThreadState*>(0))
56 || (m_creatingThread == reinterpret_cast<ThreadState*>(-1)));
58 bool isHashTableDeletedValue() const { return m_creatingThread == reinterpret_cast<ThreadState*>(-1); }
59 bool operator==(const ThreadMarker& other) const { return other.m_creatingThread == m_creatingThread && other.m_num == m_num; }
60 ThreadState* m_creatingThread;
64 struct ThreadMarkerHash {
65 static unsigned hash(const ThreadMarker& key)
67 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(key.m_creatingThread) + key.m_num);
70 static bool equal(const ThreadMarker& a, const ThreadMarker& b)
75 static const bool safeToCompareToEmptyOrDeleted = false;
82 template<typename T> struct DefaultHash;
83 template<> struct DefaultHash<WebCore::ThreadMarker> {
84 typedef WebCore::ThreadMarkerHash Hash;
87 // ThreadMarkerHash is the default hash for ThreadMarker
88 template<> struct HashTraits<WebCore::ThreadMarker> : GenericHashTraits<WebCore::ThreadMarker> {
89 static const bool emptyValueIsZero = true;
90 static void constructDeletedValue(WebCore::ThreadMarker& slot) { new (NotNull, &slot) WebCore::ThreadMarker(HashTableDeletedValue); }
91 static bool isDeletedValue(const WebCore::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
100 explicit TestGCScope(ThreadState::StackState state)
101 : m_state(ThreadState::current())
102 , m_safePointScope(state)
103 , m_parkedAllThreads(false)
105 m_state->checkThread();
106 EXPECT_FALSE(m_state->isInGC());
107 if (LIKELY(ThreadState::stopThreads())) {
109 m_parkedAllThreads = true;
113 bool allThreadsParked() { return m_parkedAllThreads; }
117 // Only cleanup if we parked all threads in which case the GC happened
118 // and we need to resume the other threads.
119 if (LIKELY(m_parkedAllThreads)) {
121 EXPECT_FALSE(m_state->isInGC());
122 ThreadState::resumeThreads();
127 ThreadState* m_state;
128 ThreadState::SafePointScope m_safePointScope;
129 bool m_parkedAllThreads; // False if we fail to park all threads
132 static void getHeapStats(HeapStats* stats)
134 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
135 EXPECT_TRUE(scope.allThreadsParked());
136 Heap::getStats(stats);
139 #define DEFINE_VISITOR_METHODS(Type) \
140 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
145 virtual bool isMarked(const Type*) OVERRIDE { return false; }
147 class CountingVisitor : public Visitor {
154 virtual void mark(const void* object, TraceCallback) OVERRIDE
160 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
162 ASSERT(header->payload());
166 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
168 ASSERT(header->payload());
172 virtual void markConservatively(HeapObjectHeader* header) OVERRIDE
174 ASSERT_NOT_REACHED();
177 virtual void markConservatively(FinalizedHeapObjectHeader* header) OVERRIDE
179 ASSERT_NOT_REACHED();
182 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
183 virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
184 virtual bool isMarked(const void*) OVERRIDE { return false; }
186 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
188 size_t count() { return m_count; }
189 void reset() { m_count = 0; }
195 class SimpleObject : public GarbageCollected<SimpleObject> {
197 static SimpleObject* create() { return new SimpleObject(); }
198 void trace(Visitor*) { }
199 char getPayload(int i) { return payload[i]; }
200 // This virtual method is unused but it is here to make sure
201 // that this object has a vtable. This object is used
202 // as the super class for objects that also have garbage
203 // collected mixins and having a virtual here makes sure
204 // that adjustment is needed both for marking and for isAlive
206 virtual void virtualMethod() { }
212 #undef DEFINE_VISITOR_METHODS
214 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
216 static HeapTestSuperClass* create()
218 return new HeapTestSuperClass();
221 virtual ~HeapTestSuperClass()
226 static int s_destructorCalls;
227 void trace(Visitor*) { }
230 HeapTestSuperClass() { }
233 int HeapTestSuperClass::s_destructorCalls = 0;
235 class HeapTestOtherSuperClass {
240 static const size_t classMagic = 0xABCDDBCA;
242 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
244 static HeapTestSubClass* create()
246 return new HeapTestSubClass();
249 virtual ~HeapTestSubClass()
251 EXPECT_EQ(classMagic, m_magic);
255 static int s_destructorCalls;
259 HeapTestSubClass() : m_magic(classMagic) { }
261 const size_t m_magic;
264 int HeapTestSubClass::s_destructorCalls = 0;
266 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
270 for (int i = 0; i < s_arraySize; ++i) {
271 m_array[i] = i % 128;
275 int8_t at(size_t i) { return m_array[i]; }
276 void trace(Visitor*) { }
278 static const int s_arraySize = 1000;
279 int8_t m_array[s_arraySize];
282 // Do several GCs to make sure that later GCs don't free up old memory from
283 // previously run tests in this process.
284 static void clearOutOldGarbage(HeapStats* heapStats)
287 getHeapStats(heapStats);
288 size_t used = heapStats->totalObjectSpace();
289 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
290 getHeapStats(heapStats);
291 if (heapStats->totalObjectSpace() >= used)
296 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
298 static IntWrapper* create(int x)
300 return new IntWrapper(x);
303 virtual ~IntWrapper()
308 static int s_destructorCalls;
309 static void trace(Visitor*) { }
311 int value() const { return m_x; }
313 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
315 unsigned hash() { return IntHash<int>::hash(m_x); }
318 IntWrapper(int x) : m_x(x) { }
325 class OffHeapInt : public RefCounted<OffHeapInt> {
327 static RefPtr<OffHeapInt> create(int x)
329 return adoptRef(new OffHeapInt(x));
332 virtual ~OffHeapInt()
337 static int s_destructorCalls;
339 int value() const { return m_x; }
341 bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
343 unsigned hash() { return IntHash<int>::hash(m_x); }
346 OffHeapInt(int x) : m_x(x) { }
353 USED_FROM_MULTIPLE_THREADS(IntWrapper);
355 int IntWrapper::s_destructorCalls = 0;
356 int OffHeapInt::s_destructorCalls = 0;
358 class ThreadedTesterBase {
360 static void test(ThreadedTesterBase* tester)
362 for (int i = 0; i < numberOfThreads; i++)
363 createThread(&threadFunc, tester, "testing thread");
364 while (tester->m_threadsToFinish) {
365 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
371 virtual void runThread() = 0;
374 static const int numberOfThreads = 10;
375 static const int gcPerThread = 5;
376 static const int numberOfAllocations = 50;
378 ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
382 virtual ~ThreadedTesterBase()
386 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
388 volatile int m_gcCount;
389 volatile int m_threadsToFinish;
392 static void threadFunc(void* data)
394 reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
398 class ThreadedHeapTester : public ThreadedTesterBase {
402 ThreadedTesterBase::test(new ThreadedHeapTester);
406 virtual void runThread() OVERRIDE
408 ThreadState::attach();
412 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
414 Persistent<IntWrapper> wrapper;
416 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
417 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
419 for (int i = 0; i < numberOfAllocations; i++) {
420 wrapper = IntWrapper::create(0x0bbac0de);
422 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
424 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
428 if (gcCount < gcPerThread) {
429 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
431 atomicIncrement(&m_gcCount);
434 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
435 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
436 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
438 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
441 ThreadState::detach();
442 atomicDecrement(&m_threadsToFinish);
446 class ThreadedWeaknessTester : public ThreadedTesterBase {
450 ThreadedTesterBase::test(new ThreadedWeaknessTester);
454 virtual void runThread() OVERRIDE
456 ThreadState::attach();
460 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
462 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
463 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
465 for (int i = 0; i < numberOfAllocations; i++) {
466 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
467 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
468 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
472 if (gcCount < gcPerThread) {
473 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
475 atomicIncrement(&m_gcCount);
478 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
479 EXPECT_TRUE(weakMap->isEmpty());
480 EXPECT_TRUE(weakMap2.isEmpty());
482 ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
485 ThreadState::detach();
486 atomicDecrement(&m_threadsToFinish);
490 // The accounting for memory includes the memory used by rounding up object
491 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
492 // have some slack in the tests.
494 void CheckWithSlack(T expected, T actual, int slack)
496 EXPECT_LE(expected, actual);
497 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
500 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
502 static TraceCounter* create()
504 return new TraceCounter();
507 void trace(Visitor*) { m_traceCount++; }
509 int traceCount() { return m_traceCount; }
520 class ClassWithMember : public GarbageCollected<ClassWithMember> {
522 static ClassWithMember* create()
524 return new ClassWithMember();
527 void trace(Visitor* visitor)
529 EXPECT_TRUE(visitor->isMarked(this));
531 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
533 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
535 visitor->trace(m_traceCounter);
538 int traceCount() { return m_traceCounter->traceCount(); }
542 : m_traceCounter(TraceCounter::create())
545 Member<TraceCounter> m_traceCounter;
548 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
550 static SimpleFinalizedObject* create()
552 return new SimpleFinalizedObject();
555 ~SimpleFinalizedObject()
560 static int s_destructorCalls;
562 void trace(Visitor*) { }
565 SimpleFinalizedObject() { }
568 int SimpleFinalizedObject::s_destructorCalls = 0;
570 class TestTypedHeapClass : public GarbageCollected<TestTypedHeapClass> {
572 static TestTypedHeapClass* create()
574 return new TestTypedHeapClass();
577 void trace(Visitor*) { }
580 TestTypedHeapClass() { }
583 class Bar : public GarbageCollectedFinalized<Bar> {
590 void finalizeGarbageCollectedObject()
592 EXPECT_TRUE(m_magic == magic);
596 bool hasBeenFinalized() const { return !m_magic; }
598 virtual void trace(Visitor* visitor) { }
599 static unsigned s_live;
602 static const int magic = 1337;
612 unsigned Bar::s_live = 0;
614 class Baz : public GarbageCollected<Baz> {
616 static Baz* create(Bar* bar)
621 void trace(Visitor* visitor)
623 visitor->trace(m_bar);
626 void clear() { m_bar.release(); }
628 // willFinalize is called by FinalizationObserver.
631 EXPECT_TRUE(!m_bar->hasBeenFinalized());
635 explicit Baz(Bar* bar)
643 class Foo : public Bar {
645 static Foo* create(Bar* bar)
650 static Foo* create(Foo* foo)
655 virtual void trace(Visitor* visitor) OVERRIDE
658 visitor->mark(static_cast<Foo*>(m_bar));
660 visitor->mark(m_bar);
667 , m_pointsToFoo(false)
674 , m_pointsToFoo(true)
682 class Bars : public Bar {
684 static Bars* create()
689 virtual void trace(Visitor* visitor) OVERRIDE
691 for (unsigned i = 0; i < m_width; i++)
692 visitor->trace(m_bars[i]);
695 unsigned getWidth() const
700 static const unsigned width = 7500;
704 for (unsigned i = 0; i < width; i++) {
705 m_bars[i] = Bar::create();
711 Member<Bar> m_bars[width];
714 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
716 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
718 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
721 ConstructorAllocation()
723 m_intWrapper = IntWrapper::create(42);
726 Member<IntWrapper> m_intWrapper;
729 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
735 static LargeObject* create() { return new LargeObject(); }
736 char get(size_t i) { return m_data[i]; }
737 void set(size_t i, char c) { m_data[i] = c; }
738 size_t length() { return s_length; }
739 void trace(Visitor* visitor)
741 visitor->trace(m_intWrapper);
743 static int s_destructorCalls;
746 static const size_t s_length = 1024*1024;
749 m_intWrapper = IntWrapper::create(23);
751 Member<IntWrapper> m_intWrapper;
752 char m_data[s_length];
755 int LargeObject::s_destructorCalls = 0;
757 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
759 static PassRefPtr<RefCountedAndGarbageCollected> create()
761 return adoptRef(new RefCountedAndGarbageCollected());
764 ~RefCountedAndGarbageCollected()
769 // These are here with their default implementations so you can break in
770 // them in the debugger.
771 void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref(); }
772 void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::deref(); }
774 void trace(Visitor*) { }
776 static int s_destructorCalls;
779 RefCountedAndGarbageCollected()
784 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
786 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
788 static RefCountedAndGarbageCollected2* create()
790 return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
793 ~RefCountedAndGarbageCollected2()
798 void trace(Visitor*) { }
800 static int s_destructorCalls;
803 RefCountedAndGarbageCollected2()
808 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
810 #define DEFINE_VISITOR_METHODS(Type) \
811 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
816 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
818 RefCountedGarbageCollectedVisitor(int expected, void** objects)
820 , m_expectedCount(expected)
821 , m_expectedObjects(objects)
825 void mark(const void* ptr) { markNoTrace(ptr); }
827 virtual void markNoTrace(const void* ptr)
831 if (m_count < m_expectedCount)
832 EXPECT_TRUE(expectedObject(ptr));
834 EXPECT_FALSE(expectedObject(ptr));
838 virtual void mark(const void* ptr, TraceCallback) OVERRIDE
843 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
845 mark(header->payload());
848 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
850 mark(header->payload());
853 bool validate() { return m_count >= m_expectedCount; }
854 void reset() { m_count = 0; }
856 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
859 bool expectedObject(const void* ptr)
861 for (int i = 0; i < m_expectedCount; i++) {
862 if (m_expectedObjects[i] == ptr)
870 void** m_expectedObjects;
873 #undef DEFINE_VISITOR_METHODS
875 class Weak : public Bar {
877 static Weak* create(Bar* strong, Bar* weak)
879 return new Weak(strong, weak);
882 virtual void trace(Visitor* visitor) OVERRIDE
884 visitor->trace(m_strongBar);
885 visitor->registerWeakMembers(this, zapWeakMembers);
888 static void zapWeakMembers(Visitor* visitor, void* self)
890 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
893 bool strongIsThere() { return !!m_strongBar; }
894 bool weakIsThere() { return !!m_weakBar; }
897 Weak(Bar* strongBar, Bar* weakBar)
899 , m_strongBar(strongBar)
904 void zapWeakMembers(Visitor* visitor)
906 if (!visitor->isAlive(m_weakBar))
910 Member<Bar> m_strongBar;
914 class WithWeakMember : public Bar {
916 static WithWeakMember* create(Bar* strong, Bar* weak)
918 return new WithWeakMember(strong, weak);
921 virtual void trace(Visitor* visitor) OVERRIDE
923 visitor->trace(m_strongBar);
924 visitor->trace(m_weakBar);
927 bool strongIsThere() { return !!m_strongBar; }
928 bool weakIsThere() { return !!m_weakBar; }
931 WithWeakMember(Bar* strongBar, Bar* weakBar)
933 , m_strongBar(strongBar)
938 Member<Bar> m_strongBar;
939 WeakMember<Bar> m_weakBar;
942 class Observable : public GarbageCollectedFinalized<Observable> {
944 static Observable* create(Bar* bar) { return new Observable(bar); }
945 ~Observable() { m_wasDestructed = true; }
946 void trace(Visitor* visitor) { visitor->trace(m_bar); }
948 // willFinalize is called by FinalizationObserver. willFinalize can touch
949 // other on-heap objects.
952 EXPECT_FALSE(m_wasDestructed);
953 EXPECT_FALSE(m_bar->hasBeenFinalized());
957 explicit Observable(Bar* bar)
959 , m_wasDestructed(false)
964 bool m_wasDestructed;
967 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
969 static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
970 bool didCallWillFinalize() const { return m_didCallWillFinalize; }
972 void trace(Visitor* visitor)
974 visitor->registerWeakMembers(this, zapWeakMembers);
978 FinalizationObserver(T* data)
980 , m_didCallWillFinalize(false)
984 static void zapWeakMembers(Visitor* visitor, void* self)
986 FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
987 if (o->m_data && !visitor->isAlive(o->m_data)) {
988 o->m_data->willFinalize();
990 o->m_didCallWillFinalize = true;
994 WeakMember<T> m_data;
995 bool m_didCallWillFinalize;
998 class FinalizationObserverWithHashMap {
1000 typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
1002 explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
1003 ~FinalizationObserverWithHashMap()
1005 m_target.willFinalize();
1006 s_didCallWillFinalize = true;
1009 static ObserverMap& observe(Observable& target)
1011 ObserverMap& map = observers();
1012 ObserverMap::AddResult result = map.add(&target, nullptr);
1013 if (result.isNewEntry)
1014 result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
1016 ASSERT(result.storedValue->value);
1020 static bool s_didCallWillFinalize;
1023 static ObserverMap& observers()
1025 DEFINE_STATIC_LOCAL(Persistent<ObserverMap>, observerMap, ());
1027 observerMap = new ObserverMap();
1028 return *observerMap;
1031 Observable& m_target;
1034 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
1038 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
1040 static PassRefPtrWillBeRawPtr<PointsBack> create()
1042 return adoptRefWillBeNoop(new PointsBack());
1050 void setBackPointer(SuperClass* backPointer)
1052 m_backPointer = backPointer;
1055 SuperClass* backPointer() const { return m_backPointer; }
1057 void trace(Visitor* visitor)
1060 visitor->trace(m_backPointer);
1064 static int s_aliveCount;
1066 PointsBack() : m_backPointer(nullptr)
1071 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1074 int PointsBack::s_aliveCount = 0;
1076 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1078 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1080 return adoptRefWillBeNoop(new SuperClass(pointsBack));
1083 virtual ~SuperClass()
1086 m_pointsBack->setBackPointer(0);
1091 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1093 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1094 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1095 EXPECT_EQ(pointsBack, target->pointsBack());
1096 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1099 virtual void trace(Visitor* visitor)
1102 visitor->trace(m_pointsBack);
1106 PointsBack* pointsBack() const { return m_pointsBack.get(); }
1108 static int s_aliveCount;
1110 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1111 : m_pointsBack(pointsBack)
1113 m_pointsBack->setBackPointer(this);
1118 RefPtrWillBeMember<PointsBack> m_pointsBack;
1121 int SuperClass::s_aliveCount = 0;
1122 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1124 SubData() { ++s_aliveCount; }
1125 ~SubData() { --s_aliveCount; }
1127 void trace(Visitor*) { }
1129 static int s_aliveCount;
1132 int SubData::s_aliveCount = 0;
1134 class SubClass : public SuperClass {
1136 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1138 return adoptRefWillBeNoop(new SubClass(pointsBack));
1146 virtual void trace(Visitor* visitor)
1149 SuperClass::trace(visitor);
1150 visitor->trace(m_data);
1154 static int s_aliveCount;
1156 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1157 : SuperClass(pointsBack)
1158 , m_data(adoptPtrWillBeNoop(new SubData()))
1164 OwnPtrWillBeMember<SubData> m_data;
1167 int SubClass::s_aliveCount = 0;
1169 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1171 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1173 return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
1176 ~TransitionRefCounted()
1181 void trace(Visitor* visitor) { }
1183 static int s_aliveCount;
1186 TransitionRefCounted()
1192 int TransitionRefCounted::s_aliveCount = 0;
1194 class Mixin : public GarbageCollectedMixin {
1196 virtual void trace(Visitor* visitor) { }
1198 virtual char getPayload(int i) { return m_padding[i]; }
1204 class UseMixin : public SimpleObject, public Mixin {
1205 USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1207 static UseMixin* create()
1209 return new UseMixin();
1212 static int s_traceCount;
1213 virtual void trace(Visitor* visitor)
1215 SimpleObject::trace(visitor);
1216 Mixin::trace(visitor);
1227 int UseMixin::s_traceCount = 0;
1229 class VectorObject {
1230 ALLOW_ONLY_INLINE_ALLOCATION();
1234 m_value = SimpleFinalizedObject::create();
1237 void trace(Visitor* visitor)
1239 visitor->trace(m_value);
1243 Member<SimpleFinalizedObject> m_value;
1246 class VectorObjectInheritedTrace : public VectorObject { };
1248 class VectorObjectNoTrace {
1249 ALLOW_ONLY_INLINE_ALLOCATION();
1251 VectorObjectNoTrace()
1253 m_value = SimpleFinalizedObject::create();
1257 Member<SimpleFinalizedObject> m_value;
1260 class TerminatedArrayItem {
1261 ALLOW_ONLY_INLINE_ALLOCATION();
1263 TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1265 void trace(Visitor* visitor) { visitor->trace(m_payload); }
1267 bool isLastInArray() const { return m_isLast; }
1268 void setLastInArray(bool value) { m_isLast = value; }
1270 IntWrapper* payload() const { return m_payload; }
1273 Member<IntWrapper> m_payload;
1277 } // WebCore namespace
1279 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::VectorObject);
1280 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::VectorObjectInheritedTrace);
1281 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::VectorObjectNoTrace);
1285 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1287 ~OneKiloByteObject() { s_destructorCalls++; }
1288 char* data() { return m_data; }
1289 void trace(Visitor* visitor) { }
1290 static int s_destructorCalls;
1293 static const size_t s_length = 1024;
1294 char m_data[s_length];
1297 int OneKiloByteObject::s_destructorCalls = 0;
1299 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1301 static DynamicallySizedObject* create(size_t size)
1303 void* slot = Heap::allocate<DynamicallySizedObject>(size);
1304 return new (slot) DynamicallySizedObject();
1307 void* operator new(std::size_t, void* location)
1314 return *(reinterpret_cast<uint8_t*>(this) + i);
1317 void trace(Visitor*) { }
1320 DynamicallySizedObject() { }
1323 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1325 FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1326 : m_wrapper(wrapper)
1330 ~FinalizationAllocator()
1332 for (int i = 0; i < 10; ++i)
1333 *m_wrapper = IntWrapper::create(42);
1334 for (int i = 0; i < 512; ++i)
1335 new OneKiloByteObject();
1338 void trace(Visitor*) { }
1341 Persistent<IntWrapper>* m_wrapper;
1344 TEST(HeapTest, Transition)
1347 RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1348 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1349 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1350 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1352 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1353 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1355 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1356 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1357 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1358 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1359 EXPECT_EQ(2, PointsBack::s_aliveCount);
1360 EXPECT_EQ(2, SuperClass::s_aliveCount);
1361 EXPECT_EQ(1, SubClass::s_aliveCount);
1362 EXPECT_EQ(1, SubData::s_aliveCount);
1364 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1365 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1366 EXPECT_EQ(2, PointsBack::s_aliveCount);
1367 EXPECT_EQ(2, SuperClass::s_aliveCount);
1368 EXPECT_EQ(1, SubClass::s_aliveCount);
1369 EXPECT_EQ(1, SubData::s_aliveCount);
1371 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1372 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1373 EXPECT_EQ(2, PointsBack::s_aliveCount);
1374 EXPECT_EQ(1, SuperClass::s_aliveCount);
1375 EXPECT_EQ(1, SubClass::s_aliveCount);
1376 EXPECT_EQ(1, SubData::s_aliveCount);
1377 EXPECT_EQ(0, pointsBack1->backPointer());
1379 pointsBack1.release();
1380 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1381 EXPECT_EQ(1, PointsBack::s_aliveCount);
1382 EXPECT_EQ(1, SuperClass::s_aliveCount);
1383 EXPECT_EQ(1, SubClass::s_aliveCount);
1384 EXPECT_EQ(1, SubData::s_aliveCount);
1386 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1387 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1388 EXPECT_EQ(1, PointsBack::s_aliveCount);
1389 EXPECT_EQ(0, SuperClass::s_aliveCount);
1390 EXPECT_EQ(0, SubClass::s_aliveCount);
1391 EXPECT_EQ(0, SubData::s_aliveCount);
1392 EXPECT_EQ(0, pointsBack2->backPointer());
1394 pointsBack2.release();
1395 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1396 EXPECT_EQ(0, PointsBack::s_aliveCount);
1397 EXPECT_EQ(0, SuperClass::s_aliveCount);
1398 EXPECT_EQ(0, SubClass::s_aliveCount);
1399 EXPECT_EQ(0, SubData::s_aliveCount);
1401 EXPECT_TRUE(superClass == subClass);
1404 TEST(HeapTest, Threading)
1406 ThreadedHeapTester::test();
1409 TEST(HeapTest, ThreadedWeakness)
1411 ThreadedWeaknessTester::test();
1414 TEST(HeapTest, BasicFunctionality)
1416 HeapStats heapStats;
1417 clearOutOldGarbage(&heapStats);
1421 // When the test starts there may already have been leaked some memory
1422 // on the heap, so we establish a base line.
1423 size_t baseLevel = heapStats.totalObjectSpace();
1424 bool testPagesAllocated = !baseLevel;
1425 if (testPagesAllocated)
1426 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1428 // This allocates objects on the general heap which should add a page of memory.
1429 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1431 memset(alloc32, 40, 32);
1432 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1434 memset(alloc64, 27, 64);
1438 getHeapStats(&heapStats);
1439 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1440 if (testPagesAllocated)
1441 EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1443 CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
1445 EXPECT_EQ(alloc32->get(0), 40);
1446 EXPECT_EQ(alloc32->get(31), 40);
1447 EXPECT_EQ(alloc64->get(0), 27);
1448 EXPECT_EQ(alloc64->get(63), 27);
1450 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1452 EXPECT_EQ(alloc32->get(0), 40);
1453 EXPECT_EQ(alloc32->get(31), 40);
1454 EXPECT_EQ(alloc64->get(0), 27);
1455 EXPECT_EQ(alloc64->get(63), 27);
1458 clearOutOldGarbage(&heapStats);
1461 size_t baseLevel = heapStats.totalObjectSpace();
1462 bool testPagesAllocated = !baseLevel;
1463 if (testPagesAllocated)
1464 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1467 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1471 size_t persistentCount = 0;
1472 const size_t numPersistents = 100000;
1473 Persistent<DynamicallySizedObject>* persistents[numPersistents];
1475 for (int i = 0; i < 1000; i++) {
1476 size_t size = 128 + i * 8;
1478 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1480 getHeapStats(&heapStats);
1481 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1482 if (testPagesAllocated)
1483 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1487 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1489 memset(alloc32b, 40, 32);
1490 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1492 memset(alloc64b, 27, 64);
1493 EXPECT_TRUE(alloc32b != alloc64b);
1496 getHeapStats(&heapStats);
1497 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1498 if (testPagesAllocated)
1499 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1502 clearOutOldGarbage(&heapStats);
1505 if (testPagesAllocated)
1506 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1508 DynamicallySizedObject* bigAreaRaw = bigArea;
1509 // Clear the persistent, so that the big area will be garbage collected.
1511 clearOutOldGarbage(&heapStats);
1515 getHeapStats(&heapStats);
1516 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1517 if (testPagesAllocated)
1518 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1520 // Endless loop unless we eventually get the memory back that we just freed.
1522 Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
1524 persistents[persistentCount++] = alloc;
1525 EXPECT_LT(persistentCount, numPersistents);
1527 if (bigAreaRaw == alloc->get())
1531 getHeapStats(&heapStats);
1532 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1533 if (testPagesAllocated)
1534 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1536 for (size_t i = 0; i < persistentCount; i++) {
1537 delete persistents[i];
1541 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1542 for (int i = 0; i < 100; i++)
1544 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1545 for (int i = 0; i < 100; i++)
1546 EXPECT_EQ(address[i], i);
1547 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1548 for (int i = 0; i < 50; i++)
1549 EXPECT_EQ(address[i], i);
1550 // This should be equivalent to free(address).
1551 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1552 // This should be equivalent to malloc(0).
1553 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1556 TEST(HeapTest, SimpleAllocation)
1558 HeapStats initialHeapStats;
1559 clearOutOldGarbage(&initialHeapStats);
1560 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1562 // Allocate an object in the heap.
1563 HeapAllocatedArray* array = new HeapAllocatedArray();
1564 HeapStats statsAfterAllocation;
1565 getHeapStats(&statsAfterAllocation);
1566 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1568 // Sanity check of the contents in the heap.
1569 EXPECT_EQ(0, array->at(0));
1570 EXPECT_EQ(42, array->at(42));
1571 EXPECT_EQ(0, array->at(128));
1572 EXPECT_EQ(999 % 128, array->at(999));
1575 TEST(HeapTest, SimplePersistent)
1577 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1578 EXPECT_EQ(0, traceCounter->traceCount());
1580 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1581 EXPECT_EQ(1, traceCounter->traceCount());
1583 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1584 EXPECT_EQ(0, classWithMember->traceCount());
1586 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1587 EXPECT_EQ(1, classWithMember->traceCount());
1588 EXPECT_EQ(2, traceCounter->traceCount());
1591 TEST(HeapTest, SimpleFinalization)
1594 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1595 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1596 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1597 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1600 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1601 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1604 TEST(HeapTest, Finalization)
1607 HeapTestSubClass* t1 = HeapTestSubClass::create();
1608 HeapTestSubClass* t2 = HeapTestSubClass::create();
1609 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1610 // FIXME(oilpan): Ignore unused variables.
1615 // Nothing is marked so the GC should free everything and call
1616 // the finalizer on all three objects.
1617 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1618 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1619 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1620 // Destructors not called again when GCing again.
1621 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1622 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1623 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1626 TEST(HeapTest, TypedHeapSanity)
1628 // We use TraceCounter for allocating an object on the general heap.
1629 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1630 Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create();
1631 EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get())),
1632 pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get())));
1635 TEST(HeapTest, NoAllocation)
1637 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1639 // Disallow allocation
1640 NoAllocationScope<AnyThread> noAllocationScope;
1641 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1643 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1646 TEST(HeapTest, Members)
1653 h1 = Baz::create(Bar::create());
1654 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1655 EXPECT_EQ(1u, Bar::s_live);
1656 h2 = Baz::create(Bar::create());
1657 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1658 EXPECT_EQ(2u, Bar::s_live);
1660 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1661 EXPECT_EQ(2u, Bar::s_live);
1663 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1664 EXPECT_EQ(1u, Bar::s_live);
1666 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1667 EXPECT_EQ(0u, Bar::s_live);
1670 TEST(HeapTest, MarkTest)
1674 Persistent<Bar> bar = Bar::create();
1675 EXPECT_TRUE(ThreadState::current()->contains(bar));
1676 EXPECT_EQ(1u, Bar::s_live);
1678 Foo* foo = Foo::create(bar);
1679 EXPECT_TRUE(ThreadState::current()->contains(foo));
1680 EXPECT_EQ(2u, Bar::s_live);
1681 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1682 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1683 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1684 EXPECT_EQ(2u, Bar::s_live);
1686 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1687 EXPECT_EQ(1u, Bar::s_live);
1689 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1690 EXPECT_EQ(0u, Bar::s_live);
1693 TEST(HeapTest, DeepTest)
1695 const unsigned depth = 100000;
1698 Bar* bar = Bar::create();
1699 EXPECT_TRUE(ThreadState::current()->contains(bar));
1700 Foo* foo = Foo::create(bar);
1701 EXPECT_TRUE(ThreadState::current()->contains(foo));
1702 EXPECT_EQ(2u, Bar::s_live);
1703 for (unsigned i = 0; i < depth; i++) {
1704 Foo* foo2 = Foo::create(foo);
1706 EXPECT_TRUE(ThreadState::current()->contains(foo));
1708 EXPECT_EQ(depth + 2, Bar::s_live);
1709 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1710 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1711 EXPECT_EQ(depth + 2, Bar::s_live);
1713 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1714 EXPECT_EQ(0u, Bar::s_live);
1717 TEST(HeapTest, WideTest)
1721 Bars* bars = Bars::create();
1722 unsigned width = Bars::width;
1723 EXPECT_EQ(width + 1, Bar::s_live);
1724 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1725 EXPECT_EQ(width + 1, Bar::s_live);
1726 // Use bars here to make sure that it will be on the stack
1727 // for the conservative stack scan to find.
1728 EXPECT_EQ(width, bars->getWidth());
1730 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1731 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1732 EXPECT_EQ(0u, Bar::s_live);
1735 TEST(HeapTest, HashMapOfMembers)
1737 HeapStats initialHeapSize;
1738 IntWrapper::s_destructorCalls = 0;
1740 clearOutOldGarbage(&initialHeapSize);
1742 typedef HeapHashMap<
1745 DefaultHash<Member<IntWrapper> >::Hash,
1746 HashTraits<Member<IntWrapper> >,
1747 HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1749 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1752 HeapStats afterSetWasCreated;
1753 getHeapStats(&afterSetWasCreated);
1754 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1756 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1758 getHeapStats(&afterGC);
1759 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1761 // If the additions below cause garbage collections, these
1762 // pointers should be found by conservative stack scanning.
1763 IntWrapper* one(IntWrapper::create(1));
1764 IntWrapper* anotherOne(IntWrapper::create(1));
1768 HeapStats afterOneAdd;
1769 getHeapStats(&afterOneAdd);
1770 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1772 HeapObjectIdentityMap::iterator it(map->begin());
1773 HeapObjectIdentityMap::iterator it2(map->begin());
1777 map->add(anotherOne, one);
1779 // The addition above can cause an allocation of a new
1780 // backing store. We therefore garbage collect before
1781 // taking the heap stats in order to get rid of the old
1782 // backing store. We make sure to not use conservative
1783 // stack scanning as that could find a pointer to the
1785 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1786 HeapStats afterAddAndGC;
1787 getHeapStats(&afterAddAndGC);
1788 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1790 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1792 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1793 EXPECT_TRUE(map->contains(one));
1794 EXPECT_TRUE(map->contains(anotherOne));
1796 IntWrapper* gotten(map->get(one));
1797 EXPECT_EQ(gotten->value(), one->value());
1798 EXPECT_EQ(gotten, one);
1801 getHeapStats(&afterGC2);
1802 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1804 IntWrapper* dozen = 0;
1806 for (int i = 1; i < 1000; i++) { // 999 iterations.
1807 IntWrapper* iWrapper(IntWrapper::create(i));
1808 IntWrapper* iSquared(IntWrapper::create(i * i));
1809 map->add(iWrapper, iSquared);
1813 HeapStats afterAdding1000;
1814 getHeapStats(&afterAdding1000);
1815 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1817 IntWrapper* gross(map->get(dozen));
1818 EXPECT_EQ(gross->value(), 144);
1820 // This should clear out junk created by all the adds.
1821 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1823 getHeapStats(&afterGC3);
1824 EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1827 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1828 // The objects 'one', anotherOne, and the 999 other pairs.
1829 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1831 getHeapStats(&afterGC4);
1832 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1835 TEST(HeapTest, NestedAllocation)
1837 HeapStats initialHeapSize;
1838 clearOutOldGarbage(&initialHeapSize);
1840 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1842 HeapStats afterFree;
1843 clearOutOldGarbage(&afterFree);
1844 EXPECT_TRUE(initialHeapSize == afterFree);
1847 TEST(HeapTest, LargeObjects)
1849 HeapStats initialHeapSize;
1850 clearOutOldGarbage(&initialHeapSize);
1851 IntWrapper::s_destructorCalls = 0;
1852 LargeObject::s_destructorCalls = 0;
1854 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1855 Persistent<LargeObject> object = LargeObject::create();
1856 EXPECT_TRUE(ThreadState::current()->contains(object));
1857 EXPECT_TRUE(ThreadState::current()->contains(reinterpret_cast<char*>(object.get()) + sizeof(LargeObject) - 1));
1858 #if ENABLE(GC_TRACING)
1859 const GCInfo* info = ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()));
1860 EXPECT_NE(reinterpret_cast<const GCInfo*>(0), info);
1861 EXPECT_EQ(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject) - 1));
1862 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject)));
1863 EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) - 1));
1865 HeapStats afterAllocation;
1866 clearOutOldGarbage(&afterAllocation);
1868 object->set(0, 'a');
1869 EXPECT_EQ('a', object->get(0));
1870 object->set(object->length() - 1, 'b');
1871 EXPECT_EQ('b', object->get(object->length() - 1));
1872 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1873 size_t actualObjectSpace =
1874 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1875 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1876 // There is probably space for the IntWrapper in a heap page without
1877 // allocating extra pages. However, the IntWrapper allocation might cause
1878 // the addition of a heap page.
1879 size_t largeObjectAllocationSize =
1880 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1881 size_t allocatedSpaceLowerBound =
1882 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1883 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1884 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1885 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1886 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1887 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1888 for (int i = 0; i < 10; i++)
1889 object = LargeObject::create();
1891 HeapStats oneLargeObject;
1892 clearOutOldGarbage(&oneLargeObject);
1893 EXPECT_TRUE(oneLargeObject == afterAllocation);
1894 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1895 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1897 HeapStats backToInitial;
1898 clearOutOldGarbage(&backToInitial);
1899 EXPECT_TRUE(initialHeapSize == backToInitial);
1900 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1901 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1902 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1905 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1906 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1907 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1908 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1909 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1910 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1912 class Container : public GarbageCollected<Container> {
1914 static Container* create() { return new Container(); }
1915 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1916 HeapHashSet<Member<IntWrapper> > set;
1917 HeapHashSet<Member<IntWrapper> > set2;
1918 HeapHashCountedSet<Member<IntWrapper> > set3;
1919 HeapVector<Member<IntWrapper>, 2> vector;
1920 HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1921 HeapVector<PairUnwrappedWrapped, 2> vectorUW;
1922 HeapDeque<Member<IntWrapper>, 0> deque;
1923 HeapDeque<PairWrappedUnwrapped, 0> dequeWU;
1924 HeapDeque<PairUnwrappedWrapped, 0> dequeUW;
1925 void trace(Visitor* visitor)
1927 visitor->trace(map);
1928 visitor->trace(set);
1929 visitor->trace(set2);
1930 visitor->trace(set3);
1931 visitor->trace(vector);
1932 visitor->trace(vectorWU);
1933 visitor->trace(vectorUW);
1934 visitor->trace(deque);
1935 visitor->trace(dequeWU);
1936 visitor->trace(dequeUW);
1940 struct ShouldBeTraced {
1941 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
1942 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
1943 Member<IntWrapper> m_wrapper;
1946 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
1948 static OffHeapContainer* create() { return new OffHeapContainer(); }
1950 static const int iterations = 300;
1951 static const int deadWrappers = 2700;
1955 for (int i = 0; i < iterations; i++) {
1956 m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
1957 m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
1958 m_deque2.append(IntWrapper::create(i));
1959 m_vector2.append(IntWrapper::create(i));
1960 m_hashSet.add(IntWrapper::create(i));
1961 m_hashMap.add(i + 103, IntWrapper::create(i));
1962 m_listHashSet.add(IntWrapper::create(i));
1963 m_linkedHashSet.add(IntWrapper::create(i));
1964 m_ownedVector.append(adoptPtr(new ShouldBeTraced(IntWrapper::create(i))));
1967 Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
1968 Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
1969 Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
1970 Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
1971 HashSet<Member<IntWrapper> >::iterator setIterator(m_hashSet.begin());
1972 HashMap<int, Member<IntWrapper> >::iterator mapIterator(m_hashMap.begin());
1973 ListHashSet<Member<IntWrapper> >::iterator listSetIterator(m_listHashSet.begin());
1974 LinkedHashSet<Member<IntWrapper> >::iterator linkedSetIterator(m_linkedHashSet.begin());
1975 Vector<OwnPtr<ShouldBeTraced> >::iterator ownedVectorIterator(m_ownedVector.begin());
1977 for (int i = 0; i < iterations; i++) {
1978 EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
1979 EXPECT_EQ(i, m_vector2[i]->value());
1980 EXPECT_EQ(i, d1Iterator->m_wrapper->value());
1981 EXPECT_EQ(i, v1Iterator->m_wrapper->value());
1982 EXPECT_EQ(i, d2Iterator->get()->value());
1983 EXPECT_EQ(i, v2Iterator->get()->value());
1984 EXPECT_EQ(i, linkedSetIterator->get()->value());
1985 EXPECT_EQ(i, listSetIterator->get()->value());
1986 EXPECT_EQ(i, ownedVectorIterator->get()->m_wrapper->value());
1987 int value = setIterator->get()->value();
1988 EXPECT_LE(0, value);
1989 EXPECT_GT(iterations, value);
1990 value = mapIterator->value.get()->value();
1991 EXPECT_LE(0, value);
1992 EXPECT_GT(iterations, value);
2000 ++linkedSetIterator;
2001 ++ownedVectorIterator;
2003 EXPECT_EQ(d1Iterator, m_deque1.end());
2004 EXPECT_EQ(v1Iterator, m_vector1.end());
2005 EXPECT_EQ(d2Iterator, m_deque2.end());
2006 EXPECT_EQ(v2Iterator, m_vector2.end());
2007 EXPECT_EQ(setIterator, m_hashSet.end());
2008 EXPECT_EQ(mapIterator, m_hashMap.end());
2009 EXPECT_EQ(listSetIterator, m_listHashSet.end());
2010 EXPECT_EQ(linkedSetIterator, m_linkedHashSet.end());
2011 EXPECT_EQ(ownedVectorIterator, m_ownedVector.end());
2014 void trace(Visitor* visitor)
2016 visitor->trace(m_deque1);
2017 visitor->trace(m_vector1);
2018 visitor->trace(m_deque2);
2019 visitor->trace(m_vector2);
2020 visitor->trace(m_hashSet);
2021 visitor->trace(m_hashMap);
2022 visitor->trace(m_listHashSet);
2023 visitor->trace(m_linkedHashSet);
2024 visitor->trace(m_listHashSet);
2025 visitor->trace(m_ownedVector);
2028 Deque<ShouldBeTraced> m_deque1;
2029 Vector<ShouldBeTraced> m_vector1;
2030 Deque<Member<IntWrapper> > m_deque2;
2031 Vector<Member<IntWrapper> > m_vector2;
2032 HashSet<Member<IntWrapper> > m_hashSet;
2033 HashMap<int, Member<IntWrapper> > m_hashMap;
2034 ListHashSet<Member<IntWrapper> > m_listHashSet;
2035 LinkedHashSet<Member<IntWrapper> > m_linkedHashSet;
2036 Vector<OwnPtr<ShouldBeTraced> > m_ownedVector;
2039 const int OffHeapContainer::iterations;
2040 const int OffHeapContainer::deadWrappers;
2042 // These class definitions test compile-time asserts with transition
2043 // types. They are therefore unused in test code and just need to
2044 // compile. This is intentional; do not delete the A and B classes below.
2045 class A : public WillBeGarbageCollectedMixin {
2048 class B : public NoBaseWillBeGarbageCollected<B>, public A {
2049 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
2051 void trace(Visitor*) { }
2054 TEST(HeapTest, HeapVectorFilledWithValue)
2056 IntWrapper* val = IntWrapper::create(1);
2057 HeapVector<Member<IntWrapper> > vector(10, val);
2058 EXPECT_EQ(10u, vector.size());
2059 for (size_t i = 0; i < vector.size(); i++)
2060 EXPECT_EQ(val, vector[i]);
2063 TEST(HeapTest, HeapVectorWithInlineCapacity)
2065 IntWrapper* one = IntWrapper::create(1);
2066 IntWrapper* two = IntWrapper::create(2);
2067 IntWrapper* three = IntWrapper::create(3);
2068 IntWrapper* four = IntWrapper::create(4);
2069 IntWrapper* five = IntWrapper::create(5);
2070 IntWrapper* six = IntWrapper::create(6);
2072 HeapVector<Member<IntWrapper>, 2> vector;
2075 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2076 EXPECT_TRUE(vector.contains(one));
2077 EXPECT_TRUE(vector.contains(two));
2079 vector.append(three);
2080 vector.append(four);
2081 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2082 EXPECT_TRUE(vector.contains(one));
2083 EXPECT_TRUE(vector.contains(two));
2084 EXPECT_TRUE(vector.contains(three));
2085 EXPECT_TRUE(vector.contains(four));
2088 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2089 EXPECT_TRUE(vector.contains(one));
2090 EXPECT_FALSE(vector.contains(two));
2091 EXPECT_FALSE(vector.contains(three));
2092 EXPECT_FALSE(vector.contains(four));
2095 HeapVector<Member<IntWrapper>, 2> vector1;
2096 HeapVector<Member<IntWrapper>, 2> vector2;
2098 vector1.append(one);
2099 vector2.append(two);
2100 vector1.swap(vector2);
2101 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2102 EXPECT_TRUE(vector1.contains(two));
2103 EXPECT_TRUE(vector2.contains(one));
2106 HeapVector<Member<IntWrapper>, 2> vector1;
2107 HeapVector<Member<IntWrapper>, 2> vector2;
2109 vector1.append(one);
2110 vector1.append(two);
2111 vector2.append(three);
2112 vector2.append(four);
2113 vector2.append(five);
2114 vector2.append(six);
2115 vector1.swap(vector2);
2116 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2117 EXPECT_TRUE(vector1.contains(three));
2118 EXPECT_TRUE(vector1.contains(four));
2119 EXPECT_TRUE(vector1.contains(five));
2120 EXPECT_TRUE(vector1.contains(six));
2121 EXPECT_TRUE(vector2.contains(one));
2122 EXPECT_TRUE(vector2.contains(two));
2126 template<typename T, size_t inlineCapacity, typename U>
2127 bool dequeContains(HeapDeque<T, inlineCapacity>& deque, U u)
2129 typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
2130 for (iterator it = deque.begin(); it != deque.end(); ++it) {
2137 TEST(HeapTest, HeapCollectionTypes)
2139 HeapStats initialHeapSize;
2140 IntWrapper::s_destructorCalls = 0;
2142 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
2143 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2144 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
2146 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2147 typedef HeapHashCountedSet<Member<IntWrapper> > MemberCountedSet;
2149 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2150 typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
2152 typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2153 typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2154 typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
2155 typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
2157 Persistent<MemberMember> memberMember = new MemberMember();
2158 Persistent<MemberMember> memberMember2 = new MemberMember();
2159 Persistent<MemberMember> memberMember3 = new MemberMember();
2160 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2161 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2162 Persistent<MemberSet> set = new MemberSet();
2163 Persistent<MemberSet> set2 = new MemberSet();
2164 Persistent<MemberCountedSet> set3 = new MemberCountedSet();
2165 Persistent<MemberVector> vector = new MemberVector();
2166 Persistent<MemberVector> vector2 = new MemberVector();
2167 Persistent<VectorWU> vectorWU = new VectorWU();
2168 Persistent<VectorWU> vectorWU2 = new VectorWU();
2169 Persistent<VectorUW> vectorUW = new VectorUW();
2170 Persistent<VectorUW> vectorUW2 = new VectorUW();
2171 Persistent<MemberDeque> deque = new MemberDeque();
2172 Persistent<MemberDeque> deque2 = new MemberDeque();
2173 Persistent<DequeWU> dequeWU = new DequeWU();
2174 Persistent<DequeWU> dequeWU2 = new DequeWU();
2175 Persistent<DequeUW> dequeUW = new DequeUW();
2176 Persistent<DequeUW> dequeUW2 = new DequeUW();
2177 Persistent<Container> container = Container::create();
2179 clearOutOldGarbage(&initialHeapSize);
2181 Persistent<IntWrapper> one(IntWrapper::create(1));
2182 Persistent<IntWrapper> two(IntWrapper::create(2));
2183 Persistent<IntWrapper> oneB(IntWrapper::create(1));
2184 Persistent<IntWrapper> twoB(IntWrapper::create(2));
2185 Persistent<IntWrapper> oneC(IntWrapper::create(1));
2186 Persistent<IntWrapper> oneD(IntWrapper::create(1));
2187 Persistent<IntWrapper> oneE(IntWrapper::create(1));
2188 Persistent<IntWrapper> oneF(IntWrapper::create(1));
2190 IntWrapper* threeB(IntWrapper::create(3));
2191 IntWrapper* threeC(IntWrapper::create(3));
2192 IntWrapper* threeD(IntWrapper::create(3));
2193 IntWrapper* threeE(IntWrapper::create(3));
2194 IntWrapper* threeF(IntWrapper::create(3));
2195 IntWrapper* three(IntWrapper::create(3));
2196 IntWrapper* fourB(IntWrapper::create(4));
2197 IntWrapper* fourC(IntWrapper::create(4));
2198 IntWrapper* fourD(IntWrapper::create(4));
2199 IntWrapper* fourE(IntWrapper::create(4));
2200 IntWrapper* fourF(IntWrapper::create(4));
2201 IntWrapper* four(IntWrapper::create(4));
2202 IntWrapper* fiveC(IntWrapper::create(5));
2203 IntWrapper* fiveD(IntWrapper::create(5));
2204 IntWrapper* fiveE(IntWrapper::create(5));
2205 IntWrapper* fiveF(IntWrapper::create(5));
2207 // Member Collections.
2208 memberMember2->add(one, two);
2209 memberMember2->add(two, three);
2210 memberMember2->add(three, four);
2211 memberMember2->add(four, one);
2212 primitiveMember->add(1, two);
2213 primitiveMember->add(2, three);
2214 primitiveMember->add(3, four);
2215 primitiveMember->add(4, one);
2216 memberPrimitive->add(one, 2);
2217 memberPrimitive->add(two, 3);
2218 memberPrimitive->add(three, 4);
2219 memberPrimitive->add(four, 1);
2227 vector->append(oneB);
2228 deque->append(oneB);
2229 vector2->append(threeB);
2230 vector2->append(fourB);
2231 deque2->append(threeE);
2232 deque2->append(fourE);
2233 vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2234 dequeWU->append(PairWrappedUnwrapped(&*oneE, 42));
2235 vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2236 vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2237 vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2238 dequeWU2->append(PairWrappedUnwrapped(&*threeE, 43));
2239 dequeWU2->append(PairWrappedUnwrapped(&*fourE, 44));
2240 dequeWU2->append(PairWrappedUnwrapped(&*fiveE, 45));
2241 vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2242 vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2243 vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2244 vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2245 dequeUW->append(PairUnwrappedWrapped(1, &*oneF));
2246 dequeUW2->append(PairUnwrappedWrapped(103, &*threeF));
2247 dequeUW2->append(PairUnwrappedWrapped(104, &*fourF));
2248 dequeUW2->append(PairUnwrappedWrapped(105, &*fiveF));
2250 EXPECT_TRUE(dequeContains(*deque, oneB));
2252 // Collect garbage. This should change nothing since we are keeping
2253 // alive the IntWrapper objects with on-stack pointers.
2254 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2256 EXPECT_TRUE(dequeContains(*deque, oneB));
2258 EXPECT_EQ(0u, memberMember->size());
2259 EXPECT_EQ(4u, memberMember2->size());
2260 EXPECT_EQ(4u, primitiveMember->size());
2261 EXPECT_EQ(4u, memberPrimitive->size());
2262 EXPECT_EQ(1u, set->size());
2263 EXPECT_EQ(4u, set2->size());
2264 EXPECT_EQ(1u, set3->size());
2265 EXPECT_EQ(1u, vector->size());
2266 EXPECT_EQ(2u, vector2->size());
2267 EXPECT_EQ(1u, vectorWU->size());
2268 EXPECT_EQ(3u, vectorWU2->size());
2269 EXPECT_EQ(1u, vectorUW->size());
2270 EXPECT_EQ(3u, vectorUW2->size());
2271 EXPECT_EQ(1u, deque->size());
2272 EXPECT_EQ(2u, deque2->size());
2273 EXPECT_EQ(1u, dequeWU->size());
2274 EXPECT_EQ(3u, dequeWU2->size());
2275 EXPECT_EQ(1u, dequeUW->size());
2276 EXPECT_EQ(3u, dequeUW2->size());
2278 MemberVector& cvec = container->vector;
2279 cvec.swap(*vector.get());
2280 vector2->swap(cvec);
2283 VectorWU& cvecWU = container->vectorWU;
2284 cvecWU.swap(*vectorWU.get());
2285 vectorWU2->swap(cvecWU);
2286 vectorWU->swap(cvecWU);
2288 VectorUW& cvecUW = container->vectorUW;
2289 cvecUW.swap(*vectorUW.get());
2290 vectorUW2->swap(cvecUW);
2291 vectorUW->swap(cvecUW);
2293 MemberDeque& cDeque = container->deque;
2294 cDeque.swap(*deque.get());
2295 deque2->swap(cDeque);
2296 deque->swap(cDeque);
2298 DequeWU& cDequeWU = container->dequeWU;
2299 cDequeWU.swap(*dequeWU.get());
2300 dequeWU2->swap(cDequeWU);
2301 dequeWU->swap(cDequeWU);
2303 DequeUW& cDequeUW = container->dequeUW;
2304 cDequeUW.swap(*dequeUW.get());
2305 dequeUW2->swap(cDequeUW);
2306 dequeUW->swap(cDequeUW);
2308 // Swap set and set2 in a roundabout way.
2309 MemberSet& cset1 = container->set;
2310 MemberSet& cset2 = container->set2;
2317 MemberCountedSet& cCountedSet = container->set3;
2318 set3->swap(cCountedSet);
2319 EXPECT_EQ(0u, set3->size());
2320 set3->swap(cCountedSet);
2323 container->map.swap(memberMember2);
2324 MemberMember& containedMap = container->map;
2325 memberMember3->swap(containedMap);
2326 memberMember3->swap(memberMember);
2328 EXPECT_TRUE(memberMember->get(one) == two);
2329 EXPECT_TRUE(memberMember->get(two) == three);
2330 EXPECT_TRUE(memberMember->get(three) == four);
2331 EXPECT_TRUE(memberMember->get(four) == one);
2332 EXPECT_TRUE(primitiveMember->get(1) == two);
2333 EXPECT_TRUE(primitiveMember->get(2) == three);
2334 EXPECT_TRUE(primitiveMember->get(3) == four);
2335 EXPECT_TRUE(primitiveMember->get(4) == one);
2336 EXPECT_EQ(1, memberPrimitive->get(four));
2337 EXPECT_EQ(2, memberPrimitive->get(one));
2338 EXPECT_EQ(3, memberPrimitive->get(two));
2339 EXPECT_EQ(4, memberPrimitive->get(three));
2340 EXPECT_TRUE(set->contains(one));
2341 EXPECT_TRUE(set->contains(two));
2342 EXPECT_TRUE(set->contains(three));
2343 EXPECT_TRUE(set->contains(four));
2344 EXPECT_TRUE(set2->contains(oneB));
2345 EXPECT_TRUE(set3->contains(oneB));
2346 EXPECT_TRUE(vector->contains(threeB));
2347 EXPECT_TRUE(vector->contains(fourB));
2348 EXPECT_TRUE(dequeContains(*deque, threeE));
2349 EXPECT_TRUE(dequeContains(*deque, fourE));
2350 EXPECT_TRUE(vector2->contains(oneB));
2351 EXPECT_FALSE(vector2->contains(threeB));
2352 EXPECT_TRUE(dequeContains(*deque2, oneB));
2353 EXPECT_FALSE(dequeContains(*deque2, threeE));
2354 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2355 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2356 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2357 EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2358 EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2359 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2360 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2361 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2362 EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2363 EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2364 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*threeE, 43)));
2365 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fourE, 44)));
2366 EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fiveE, 45)));
2367 EXPECT_TRUE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*oneE, 42)));
2368 EXPECT_FALSE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*threeE, 43)));
2369 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(103, &*threeF)));
2370 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(104, &*fourF)));
2371 EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(105, &*fiveF)));
2372 EXPECT_TRUE(dequeContains(*dequeUW2, PairUnwrappedWrapped(1, &*oneF)));
2373 EXPECT_FALSE(dequeContains(*dequeUW2, PairUnwrappedWrapped(103, &*threeF)));
2376 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2378 EXPECT_EQ(4u, memberMember->size());
2379 EXPECT_EQ(0u, memberMember2->size());
2380 EXPECT_EQ(4u, primitiveMember->size());
2381 EXPECT_EQ(4u, memberPrimitive->size());
2382 EXPECT_EQ(4u, set->size());
2383 EXPECT_EQ(1u, set2->size());
2384 EXPECT_EQ(1u, set3->size());
2385 EXPECT_EQ(2u, vector->size());
2386 EXPECT_EQ(1u, vector2->size());
2387 EXPECT_EQ(3u, vectorUW->size());
2388 EXPECT_EQ(1u, vector2->size());
2389 EXPECT_EQ(2u, deque->size());
2390 EXPECT_EQ(1u, deque2->size());
2391 EXPECT_EQ(3u, dequeUW->size());
2392 EXPECT_EQ(1u, deque2->size());
2394 EXPECT_TRUE(memberMember->get(one) == two);
2395 EXPECT_TRUE(primitiveMember->get(1) == two);
2396 EXPECT_TRUE(primitiveMember->get(4) == one);
2397 EXPECT_EQ(2, memberPrimitive->get(one));
2398 EXPECT_EQ(3, memberPrimitive->get(two));
2399 EXPECT_TRUE(set->contains(one));
2400 EXPECT_TRUE(set->contains(two));
2401 EXPECT_FALSE(set->contains(oneB));
2402 EXPECT_TRUE(set2->contains(oneB));
2403 EXPECT_TRUE(set3->contains(oneB));
2404 EXPECT_EQ(2u, set3->find(oneB)->value);
2405 EXPECT_EQ(3, vector->at(0)->value());
2406 EXPECT_EQ(4, vector->at(1)->value());
2407 EXPECT_EQ(3, deque->begin()->get()->value());
2410 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2411 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2413 EXPECT_EQ(4u, memberMember->size());
2414 EXPECT_EQ(4u, primitiveMember->size());
2415 EXPECT_EQ(4u, memberPrimitive->size());
2416 EXPECT_EQ(4u, set->size());
2417 EXPECT_EQ(1u, set2->size());
2418 EXPECT_EQ(2u, vector->size());
2419 EXPECT_EQ(1u, vector2->size());
2420 EXPECT_EQ(3u, vectorWU->size());
2421 EXPECT_EQ(1u, vectorWU2->size());
2422 EXPECT_EQ(3u, vectorUW->size());
2423 EXPECT_EQ(1u, vectorUW2->size());
2424 EXPECT_EQ(2u, deque->size());
2425 EXPECT_EQ(1u, deque2->size());
2426 EXPECT_EQ(3u, dequeWU->size());
2427 EXPECT_EQ(1u, dequeWU2->size());
2428 EXPECT_EQ(3u, dequeUW->size());
2429 EXPECT_EQ(1u, dequeUW2->size());
2432 template<typename T>
2433 void MapIteratorCheck(T& it, const T& end, int expected)
2438 int key = it->key->value();
2439 int value = it->value->value();
2440 EXPECT_TRUE(key >= 0 && key < 1100);
2441 EXPECT_TRUE(value >= 0 && value < 1100);
2444 EXPECT_EQ(expected, found);
2447 template<typename T>
2448 void SetIteratorCheck(T& it, const T& end, int expected)
2453 int value = (*it)->value();
2454 EXPECT_TRUE(value >= 0 && value < 1100);
2457 EXPECT_EQ(expected, found);
2460 TEST(HeapTest, HeapWeakCollectionSimple)
2462 HeapStats initialHeapStats;
2463 clearOutOldGarbage(&initialHeapStats);
2464 IntWrapper::s_destructorCalls = 0;
2466 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2468 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2469 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2470 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2471 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2472 typedef HeapHashCountedSet<WeakMember<IntWrapper> > WeakCountedSet;
2474 Persistent<WeakStrong> weakStrong = new WeakStrong();
2475 Persistent<StrongWeak> strongWeak = new StrongWeak();
2476 Persistent<WeakWeak> weakWeak = new WeakWeak();
2477 Persistent<WeakSet> weakSet = new WeakSet();
2478 Persistent<WeakCountedSet> weakCountedSet = new WeakCountedSet();
2480 Persistent<IntWrapper> two = IntWrapper::create(2);
2482 keepNumbersAlive.append(IntWrapper::create(103));
2483 keepNumbersAlive.append(IntWrapper::create(10));
2486 weakStrong->add(IntWrapper::create(1), two);
2487 strongWeak->add(two, IntWrapper::create(1));
2488 weakWeak->add(two, IntWrapper::create(42));
2489 weakWeak->add(IntWrapper::create(42), two);
2490 weakSet->add(IntWrapper::create(0));
2492 weakSet->add(keepNumbersAlive[0]);
2493 weakSet->add(keepNumbersAlive[1]);
2494 weakCountedSet->add(IntWrapper::create(0));
2495 weakCountedSet->add(two);
2496 weakCountedSet->add(two);
2497 weakCountedSet->add(two);
2498 weakCountedSet->add(keepNumbersAlive[0]);
2499 weakCountedSet->add(keepNumbersAlive[1]);
2500 EXPECT_EQ(1u, weakStrong->size());
2501 EXPECT_EQ(1u, strongWeak->size());
2502 EXPECT_EQ(2u, weakWeak->size());
2503 EXPECT_EQ(4u, weakSet->size());
2504 EXPECT_EQ(4u, weakCountedSet->size());
2505 EXPECT_EQ(3u, weakCountedSet->find(two)->value);
2506 weakCountedSet->remove(two);
2507 EXPECT_EQ(2u, weakCountedSet->find(two)->value);
2510 keepNumbersAlive[0] = nullptr;
2512 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2514 EXPECT_EQ(0u, weakStrong->size());
2515 EXPECT_EQ(0u, strongWeak->size());
2516 EXPECT_EQ(0u, weakWeak->size());
2517 EXPECT_EQ(2u, weakSet->size());
2518 EXPECT_EQ(2u, weakCountedSet->size());
2521 template<typename Set>
2522 void orderedSetHelper(bool strong)
2524 HeapStats initialHeapStats;
2525 clearOutOldGarbage(&initialHeapStats);
2526 IntWrapper::s_destructorCalls = 0;
2528 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2530 Persistent<Set> set1 = new Set();
2531 Persistent<Set> set2 = new Set();
2533 const Set& constSet = *set1.get();
2535 keepNumbersAlive.append(IntWrapper::create(2));
2536 keepNumbersAlive.append(IntWrapper::create(103));
2537 keepNumbersAlive.append(IntWrapper::create(10));
2539 set1->add(IntWrapper::create(0));
2540 set1->add(keepNumbersAlive[0]);
2541 set1->add(keepNumbersAlive[1]);
2542 set1->add(keepNumbersAlive[2]);
2545 set2->add(IntWrapper::create(42));
2548 EXPECT_EQ(4u, set1->size());
2549 typename Set::iterator it(set1->begin());
2550 typename Set::reverse_iterator reverse(set1->rbegin());
2551 typename Set::const_iterator cit(constSet.begin());
2552 typename Set::const_reverse_iterator creverse(constSet.rbegin());
2554 EXPECT_EQ(0, (*it)->value());
2555 EXPECT_EQ(0, (*cit)->value());
2558 EXPECT_EQ(2, (*it)->value());
2559 EXPECT_EQ(2, (*cit)->value());
2562 EXPECT_EQ(0, (*it)->value());
2563 EXPECT_EQ(0, (*cit)->value());
2568 EXPECT_EQ(103, (*it)->value());
2569 EXPECT_EQ(103, (*cit)->value());
2572 EXPECT_EQ(10, (*it)->value());
2573 EXPECT_EQ(10, (*cit)->value());
2577 EXPECT_EQ(10, (*reverse)->value());
2578 EXPECT_EQ(10, (*creverse)->value());
2581 EXPECT_EQ(103, (*reverse)->value());
2582 EXPECT_EQ(103, (*creverse)->value());
2585 EXPECT_EQ(10, (*reverse)->value());
2586 EXPECT_EQ(10, (*creverse)->value());
2591 EXPECT_EQ(2, (*reverse)->value());
2592 EXPECT_EQ(2, (*creverse)->value());
2595 EXPECT_EQ(0, (*reverse)->value());
2596 EXPECT_EQ(0, (*creverse)->value());
2600 EXPECT_EQ(set1->end(), it);
2601 EXPECT_EQ(constSet.end(), cit);
2602 EXPECT_EQ(set1->rend(), reverse);
2603 EXPECT_EQ(constSet.rend(), creverse);
2605 typename Set::iterator iX(set2->begin());
2606 EXPECT_EQ(set2->end(), iX);
2609 set1->remove(keepNumbersAlive[0]);
2611 keepNumbersAlive[0] = nullptr;
2613 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2615 EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
2617 EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
2619 typename Set::iterator i2(set1->begin());
2621 EXPECT_EQ(0, (*i2)->value());
2623 EXPECT_NE(set1->end(), i2);
2625 EXPECT_EQ(103, (*i2)->value());
2627 EXPECT_NE(set1->end(), i2);
2628 EXPECT_EQ(10, (*i2)->value());
2630 EXPECT_EQ(set1->end(), i2);
2633 TEST(HeapTest, HeapWeakLinkedHashSet)
2635 orderedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
2636 orderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
2637 orderedSetHelper<HeapListHashSet<Member<IntWrapper> > >(true);
2640 class ThingWithDestructor {
2642 ThingWithDestructor()
2645 s_liveThingsWithDestructor++;
2648 ThingWithDestructor(int x)
2651 s_liveThingsWithDestructor++;
2654 ThingWithDestructor(const ThingWithDestructor&other)
2657 s_liveThingsWithDestructor++;
2660 ~ThingWithDestructor()
2662 s_liveThingsWithDestructor--;
2665 int value() { return m_x; }
2667 static int s_liveThingsWithDestructor;
2669 unsigned hash() { return IntHash<int>::hash(m_x); }
2672 static const int emptyValue = 0;
2676 int ThingWithDestructor::s_liveThingsWithDestructor;
2678 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2679 static const bool needsDestruction = true;
2682 static void heapMapDestructorHelper(bool clearMaps)
2684 HeapStats initialHeapStats;
2685 clearOutOldGarbage(&initialHeapStats);
2686 ThingWithDestructor::s_liveThingsWithDestructor = 0;
2688 typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageCollected> > RefMap;
2690 typedef HeapHashMap<
2691 WeakMember<IntWrapper>,
2692 ThingWithDestructor,
2693 DefaultHash<WeakMember<IntWrapper> >::Hash,
2694 HashTraits<WeakMember<IntWrapper> >,
2695 ThingWithDestructorTraits> Map;
2697 Persistent<Map> map(new Map());
2698 Persistent<RefMap> refMap(new RefMap());
2700 Persistent<IntWrapper> luck(IntWrapper::create(103));
2702 int baseLine, refBaseLine;
2708 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2709 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2711 stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2712 stackMap.add(luck, ThingWithDestructor(8128));
2713 stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2714 stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2716 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2717 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2719 // Although the heap maps are on-stack, we can't expect prompt
2720 // finalization of the elements, so when they go out of scope here we
2721 // will not necessarily have called the relevant destructors.
2724 // The RefCountedAndGarbageCollected things need an extra GC to discover
2725 // that they are no longer ref counted.
2726 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2727 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2728 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2729 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2731 // Now use maps kept alive with persistents. Here we don't expect any
2732 // destructors to be called before there have been GCs.
2734 map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2735 map->add(luck, ThingWithDestructor(8128));
2736 refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2737 refMap->add(luck, RefCountedAndGarbageCollected::create());
2739 baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2740 refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2744 map->clear(); // Clear map.
2745 refMap->clear(); // Clear map.
2747 map.clear(); // Clear Persistent handle, not map.
2748 refMap.clear(); // Clear Persistent handle, not map.
2749 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2750 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2753 EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2755 // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2756 // noticies it's been decremented to zero.
2757 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2758 EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2761 TEST(HeapTest, HeapMapDestructor)
2763 heapMapDestructorHelper(true);
2764 heapMapDestructorHelper(false);
2767 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2768 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2769 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2770 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2771 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
2772 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
2773 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
2774 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
2775 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
2776 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
2777 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
2778 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
2780 template<typename T>
2781 T& iteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair)
2786 template<typename T>
2787 T& iteratorExtractor(T& notAPair)
2792 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2794 Persistent<WSSet>& weakStrong,
2795 Persistent<SWSet>& strongWeak,
2796 Persistent<WUSet>& weakUnwrapped,
2797 Persistent<UWSet>& unwrappedWeak,
2799 Persistent<IntWrapper>& two)
2801 typename WSSet::iterator itWS = weakStrong->begin();
2802 typename SWSet::iterator itSW = strongWeak->begin();
2803 typename WUSet::iterator itWU = weakUnwrapped->begin();
2804 typename UWSet::iterator itUW = unwrappedWeak->begin();
2806 EXPECT_EQ(2u, weakStrong->size());
2807 EXPECT_EQ(2u, strongWeak->size());
2808 EXPECT_EQ(2u, weakUnwrapped->size());
2809 EXPECT_EQ(2u, unwrappedWeak->size());
2811 PairWeakStrong p = iteratorExtractor(*itWS);
2812 PairStrongWeak p2 = iteratorExtractor(*itSW);
2813 PairWeakUnwrapped p3 = iteratorExtractor(*itWU);
2814 PairUnwrappedWeak p4 = iteratorExtractor(*itUW);
2815 if (p.first == two && p.second == two)
2817 if (p2.first == two && p2.second == two)
2819 if (p3.first == two && p3.second == 2)
2821 if (p4.first == 2 && p4.second == two)
2823 p = iteratorExtractor(*itWS);
2824 p2 = iteratorExtractor(*itSW);
2825 p3 = iteratorExtractor(*itWU);
2826 p4 = iteratorExtractor(*itUW);
2827 IntWrapper* nullWrapper = 0;
2829 EXPECT_EQ(p.first->value(), 1);
2830 EXPECT_EQ(p2.second->value(), 1);
2831 EXPECT_EQ(p3.first->value(), 1);
2832 EXPECT_EQ(p4.second->value(), 1);
2834 EXPECT_EQ(p.first, nullWrapper);
2835 EXPECT_EQ(p2.second, nullWrapper);
2836 EXPECT_EQ(p3.first, nullWrapper);
2837 EXPECT_EQ(p4.second, nullWrapper);
2840 EXPECT_EQ(p.second->value(), 2);
2841 EXPECT_EQ(p2.first->value(), 2);
2842 EXPECT_EQ(p3.second, 2);
2843 EXPECT_EQ(p4.first, 2);
2845 EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2846 EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2847 EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2848 EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2851 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
2852 void weakPairsHelper()
2854 IntWrapper::s_destructorCalls = 0;
2856 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2858 Persistent<WSSet> weakStrong = new WSSet();
2859 Persistent<SWSet> strongWeak = new SWSet();
2860 Persistent<WUSet> weakUnwrapped = new WUSet();
2861 Persistent<UWSet> unwrappedWeak = new UWSet();
2863 Persistent<IntWrapper> two = IntWrapper::create(2);
2865 weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2866 weakStrong->add(PairWeakStrong(&*two, &*two));
2867 strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2868 strongWeak->add(PairStrongWeak(&*two, &*two));
2869 weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2870 weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2871 unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2872 unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2874 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2876 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2877 checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2880 TEST(HeapTest, HeapWeakPairs)
2883 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2884 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2885 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2886 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2887 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2891 typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
2892 typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2893 typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
2894 typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2895 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2899 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
2900 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2901 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
2902 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2903 weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2907 TEST(HeapTest, HeapWeakCollectionTypes)
2909 HeapStats initialHeapSize;
2910 IntWrapper::s_destructorCalls = 0;
2912 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2913 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2914 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2915 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2916 typedef HeapLinkedHashSet<WeakMember<IntWrapper> > WeakOrderedSet;
2918 clearOutOldGarbage(&initialHeapSize);
2920 const int weakStrongIndex = 0;
2921 const int strongWeakIndex = 1;
2922 const int weakWeakIndex = 2;
2923 const int numberOfMapIndices = 3;
2924 const int weakSetIndex = 3;
2925 const int weakOrderedSetIndex = 4;
2926 const int numberOfCollections = 5;
2928 for (int testRun = 0; testRun < 4; testRun++) {
2929 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2930 bool deleteAfterwards = (testRun == 1);
2931 bool addAfterwards = (testRun == 2);
2932 bool testThatIteratorsMakeStrong = (testRun == 3);
2934 // The test doesn't work for strongWeak with deleting because we lost
2935 // the key from the keepNumbersAlive array, so we can't do the lookup.
2936 if (deleteAfterwards && collectionNumber == strongWeakIndex)
2939 unsigned added = addAfterwards ? 100 : 0;
2941 Persistent<WeakStrong> weakStrong = new WeakStrong();
2942 Persistent<StrongWeak> strongWeak = new StrongWeak();
2943 Persistent<WeakWeak> weakWeak = new WeakWeak();
2945 Persistent<WeakSet> weakSet = new WeakSet();
2946 Persistent<WeakOrderedSet> weakOrderedSet = new WeakOrderedSet();
2948 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2949 for (int i = 0; i < 128; i += 2) {
2950 IntWrapper* wrapped = IntWrapper::create(i);
2951 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
2952 keepNumbersAlive.append(wrapped);
2953 keepNumbersAlive.append(wrapped2);
2954 weakStrong->add(wrapped, wrapped2);
2955 strongWeak->add(wrapped2, wrapped);
2956 weakWeak->add(wrapped, wrapped2);
2957 weakSet->add(wrapped);
2958 weakOrderedSet->add(wrapped);
2961 EXPECT_EQ(64u, weakStrong->size());
2962 EXPECT_EQ(64u, strongWeak->size());
2963 EXPECT_EQ(64u, weakWeak->size());
2964 EXPECT_EQ(64u, weakSet->size());
2965 EXPECT_EQ(64u, weakOrderedSet->size());
2967 // Collect garbage. This should change nothing since we are keeping
2968 // alive the IntWrapper objects.
2969 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2971 EXPECT_EQ(64u, weakStrong->size());
2972 EXPECT_EQ(64u, strongWeak->size());
2973 EXPECT_EQ(64u, weakWeak->size());
2974 EXPECT_EQ(64u, weakSet->size());
2975 EXPECT_EQ(64u, weakOrderedSet->size());
2977 for (int i = 0; i < 128; i += 2) {
2978 IntWrapper* wrapped = keepNumbersAlive[i];
2979 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
2980 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
2981 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
2982 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
2983 EXPECT_TRUE(weakSet->contains(wrapped));
2984 EXPECT_TRUE(weakOrderedSet->contains(wrapped));
2987 for (int i = 0; i < 128; i += 3)
2988 keepNumbersAlive[i] = nullptr;
2990 if (collectionNumber != weakStrongIndex)
2991 weakStrong->clear();
2992 if (collectionNumber != strongWeakIndex)
2993 strongWeak->clear();
2994 if (collectionNumber != weakWeakIndex)
2996 if (collectionNumber != weakSetIndex)
2998 if (collectionNumber != weakOrderedSetIndex)
2999 weakOrderedSet->clear();
3001 if (testThatIteratorsMakeStrong) {
3002 WeakStrong::iterator it1 = weakStrong->begin();
3003 StrongWeak::iterator it2 = strongWeak->begin();
3004 WeakWeak::iterator it3 = weakWeak->begin();
3005 WeakSet::iterator it4 = weakSet->begin();
3006 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3007 // Collect garbage. This should change nothing since the
3008 // iterators make the collections strong.
3009 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3010 if (collectionNumber == weakStrongIndex) {
3011 EXPECT_EQ(64u, weakStrong->size());
3012 MapIteratorCheck(it1, weakStrong->end(), 64);
3013 } else if (collectionNumber == strongWeakIndex) {
3014 EXPECT_EQ(64u, strongWeak->size());
3015 MapIteratorCheck(it2, strongWeak->end(), 64);
3016 } else if (collectionNumber == weakWeakIndex) {
3017 EXPECT_EQ(64u, weakWeak->size());
3018 MapIteratorCheck(it3, weakWeak->end(), 64);
3019 } else if (collectionNumber == weakSetIndex) {
3020 EXPECT_EQ(64u, weakSet->size());
3021 SetIteratorCheck(it4, weakSet->end(), 64);
3022 } else if (collectionNumber == weakOrderedSetIndex) {
3023 EXPECT_EQ(64u, weakOrderedSet->size());
3024 SetIteratorCheck(it5, weakOrderedSet->end(), 64);
3027 // Collect garbage. This causes weak processing to remove
3028 // things from the collections.
3029 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3031 for (int i = 0; i < 128; i += 2) {
3032 bool firstAlive = keepNumbersAlive[i];
3033 bool secondAlive = keepNumbersAlive[i + 1];
3034 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
3036 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
3037 if (collectionNumber == weakStrongIndex) {
3038 if (deleteAfterwards)
3039 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
3040 } else if (collectionNumber == strongWeakIndex) {
3041 if (deleteAfterwards)
3042 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
3043 } else if (collectionNumber == weakWeakIndex) {
3044 if (deleteAfterwards)
3045 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
3047 if (!deleteAfterwards)
3049 } else if (collectionNumber == weakSetIndex && firstAlive) {
3050 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
3051 if (deleteAfterwards)
3052 weakSet->remove(keepNumbersAlive[i]);
3055 } else if (collectionNumber == weakOrderedSetIndex && firstAlive) {
3056 ASSERT_TRUE(weakOrderedSet->contains(keepNumbersAlive[i]));
3057 if (deleteAfterwards)
3058 weakOrderedSet->remove(keepNumbersAlive[i]);
3063 if (addAfterwards) {
3064 for (int i = 1000; i < 1100; i++) {
3065 IntWrapper* wrapped = IntWrapper::create(i);
3066 keepNumbersAlive.append(wrapped);
3067 weakStrong->add(wrapped, wrapped);
3068 strongWeak->add(wrapped, wrapped);
3069 weakWeak->add(wrapped, wrapped);
3070 weakSet->add(wrapped);
3071 weakOrderedSet->add(wrapped);
3074 if (collectionNumber == weakStrongIndex)
3075 EXPECT_EQ(count + added, weakStrong->size());
3076 else if (collectionNumber == strongWeakIndex)
3077 EXPECT_EQ(count + added, strongWeak->size());
3078 else if (collectionNumber == weakWeakIndex)
3079 EXPECT_EQ(count + added, weakWeak->size());
3080 else if (collectionNumber == weakSetIndex)
3081 EXPECT_EQ(count + added, weakSet->size());
3082 else if (collectionNumber == weakOrderedSetIndex)
3083 EXPECT_EQ(count + added, weakOrderedSet->size());
3084 WeakStrong::iterator it1 = weakStrong->begin();
3085 StrongWeak::iterator it2 = strongWeak->begin();
3086 WeakWeak::iterator it3 = weakWeak->begin();
3087 WeakSet::iterator it4 = weakSet->begin();
3088 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3089 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
3090 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
3091 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
3092 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
3093 SetIteratorCheck(it5, weakOrderedSet->end(), (collectionNumber == weakOrderedSetIndex ? count : 0) + added);
3095 for (unsigned i = 0; i < 128 + added; i++)
3096 keepNumbersAlive[i] = nullptr;
3097 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3098 EXPECT_EQ(added, weakStrong->size());
3099 EXPECT_EQ(added, strongWeak->size());
3100 EXPECT_EQ(added, weakWeak->size());
3101 EXPECT_EQ(added, weakSet->size());
3102 EXPECT_EQ(added, weakOrderedSet->size());
3107 TEST(HeapTest, RefCountedGarbageCollected)
3109 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3111 RefPtr<RefCountedAndGarbageCollected> refPtr3;
3113 Persistent<RefCountedAndGarbageCollected> persistent;
3115 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
3116 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
3117 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3118 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3119 persistent = refPtr1.get();
3121 // Reference count is zero for both objects but one of
3122 // them is kept alive by a persistent handle.
3123 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3124 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3125 refPtr3 = persistent;
3127 // The persistent handle is gone but the ref count has been
3129 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3130 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3132 // Both persistent handle is gone and ref count is zero so the
3133 // object can be collected.
3134 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3135 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
3138 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
3140 RefCountedAndGarbageCollected::s_destructorCalls = 0;
3141 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
3143 RefCountedAndGarbageCollected* pointer1 = 0;
3144 RefCountedAndGarbageCollected2* pointer2 = 0;
3146 RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
3147 RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
3148 pointer1 = object1.get();
3149 pointer2 = object2.get();
3150 void* objects[2] = { object1.get(), object2.get() };
3151 RefCountedGarbageCollectedVisitor visitor(2, objects);
3152 ThreadState::current()->visitPersistents(&visitor);
3153 EXPECT_TRUE(visitor.validate());
3155 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3156 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3157 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3159 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3160 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3161 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3163 // At this point, the reference counts of object1 and object2 are 0.
3164 // Only pointer1 and pointer2 keep references to object1 and object2.
3165 void* objects[] = { 0 };
3166 RefCountedGarbageCollectedVisitor visitor(0, objects);
3167 ThreadState::current()->visitPersistents(&visitor);
3168 EXPECT_TRUE(visitor.validate());
3171 RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
3172 RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
3173 void* objects[2] = { object1.get(), object2.get() };
3174 RefCountedGarbageCollectedVisitor visitor(2, objects);
3175 ThreadState::current()->visitPersistents(&visitor);
3176 EXPECT_TRUE(visitor.validate());
3178 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3179 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3180 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3183 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3184 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3185 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3188 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3189 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3190 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
3193 TEST(HeapTest, WeakMembers)
3197 Persistent<Bar> h1 = Bar::create();
3198 Persistent<Weak> h4;
3199 Persistent<WithWeakMember> h5;
3200 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3201 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
3203 Bar* h2 = Bar::create();
3204 Bar* h3 = Bar::create();
3205 h4 = Weak::create(h2, h3);
3206 h5 = WithWeakMember::create(h2, h3);
3207 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3208 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
3209 EXPECT_TRUE(h4->strongIsThere());
3210 EXPECT_TRUE(h4->weakIsThere());
3211 EXPECT_TRUE(h5->strongIsThere());
3212 EXPECT_TRUE(h5->weakIsThere());
3214 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3215 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3216 EXPECT_EQ(4u, Bar::s_live);
3217 EXPECT_TRUE(h4->strongIsThere());
3218 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
3219 EXPECT_TRUE(h5->strongIsThere());
3220 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
3221 h1.release(); // Zero out h1.
3222 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3223 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
3224 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
3225 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
3227 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3228 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3229 EXPECT_EQ(0u, Bar::s_live); // All gone.
3232 TEST(HeapTest, FinalizationObserver)
3234 Persistent<FinalizationObserver<Observable> > o;
3236 Observable* foo = Observable::create(Bar::create());
3237 // |o| observes |foo|.
3238 o = FinalizationObserver<Observable>::create(foo);
3240 // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3241 // and its member will be collected.
3242 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3243 EXPECT_EQ(0u, Bar::s_live);
3244 EXPECT_TRUE(o->didCallWillFinalize());
3246 FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
3247 Observable* foo = Observable::create(Bar::create());
3248 FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
3249 EXPECT_EQ(1u, map.size());
3251 // FinalizationObserverWithHashMap doesn't have a strong reference to
3252 // |foo|. So |foo| and its member will be collected.
3253 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3254 EXPECT_EQ(0u, Bar::s_live);
3255 EXPECT_EQ(0u, map.size());
3256 EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
3259 TEST(HeapTest, Comparisons)
3261 Persistent<Bar> barPersistent = Bar::create();
3262 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
3263 EXPECT_TRUE(barPersistent != fooPersistent);
3264 barPersistent = fooPersistent;
3265 EXPECT_TRUE(barPersistent == fooPersistent);
3268 TEST(HeapTest, CheckAndMarkPointer)
3270 HeapStats initialHeapStats;
3271 clearOutOldGarbage(&initialHeapStats);
3273 Vector<Address> objectAddresses;
3274 Vector<Address> endAddresses;
3275 Address largeObjectAddress;
3276 Address largeObjectEndAddress;
3277 CountingVisitor visitor;
3278 for (int i = 0; i < 10; i++) {
3279 SimpleObject* object = SimpleObject::create();
3280 Address objectAddress = reinterpret_cast<Address>(object);
3281 objectAddresses.append(objectAddress);
3282 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
3284 LargeObject* largeObject = LargeObject::create();
3285 largeObjectAddress = reinterpret_cast<Address>(largeObject);
3286 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
3288 // This is a low-level test where we call checkAndMarkPointer. This method
3289 // causes the object start bitmap to be computed which requires the heap
3290 // to be in a consistent state (e.g. the free allocation area must be put
3291 // into a free list header). However when we call makeConsistentForGC it
3292 // also clears out the freelists so we have to rebuild those before trying
3293 // to allocate anything again. We do this by forcing a GC after doing the
3294 // checkAndMarkPointer tests.
3296 TestGCScope scope(ThreadState::HeapPointersOnStack);
3297 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3298 Heap::makeConsistentForGC();
3299 for (size_t i = 0; i < objectAddresses.size(); i++) {
3300 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3301 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3303 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3305 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3306 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3307 EXPECT_EQ(2ul, visitor.count());
3310 // This forces a GC without stack scanning which results in the objects
3311 // being collected. This will also rebuild the above mentioned freelists,
3312 // however we don't rely on that below since we don't have any allocations.
3313 clearOutOldGarbage(&initialHeapStats);
3315 TestGCScope scope(ThreadState::HeapPointersOnStack);
3316 EXPECT_TRUE(scope.allThreadsParked());
3317 Heap::makeConsistentForGC();
3318 for (size_t i = 0; i < objectAddresses.size(); i++) {
3319 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3320 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3322 EXPECT_EQ(0ul, visitor.count());
3323 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3324 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3325 EXPECT_EQ(0ul, visitor.count());
3327 // This round of GC is important to make sure that the object start
3328 // bitmap are cleared out and that the free lists are rebuild.
3329 clearOutOldGarbage(&initialHeapStats);
3332 TEST(HeapTest, VisitOffHeapCollections)
3334 HeapStats initialHeapStats;
3335 clearOutOldGarbage(&initialHeapStats);
3336 IntWrapper::s_destructorCalls = 0;
3337 Persistent<OffHeapContainer> container = OffHeapContainer::create();
3338 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3339 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3340 container = nullptr;
3341 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3342 EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
3345 TEST(HeapTest, PersistentHeapCollectionTypes)
3347 HeapStats initialHeapSize;
3348 IntWrapper::s_destructorCalls = 0;
3350 typedef HeapVector<Member<IntWrapper> > Vec;
3351 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
3352 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
3353 typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet;
3354 typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet;
3355 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
3356 typedef PersistentHeapDeque<Member<IntWrapper> > PDeque;
3358 clearOutOldGarbage(&initialHeapSize);
3364 PLinkedSet pLinkedSet;
3367 IntWrapper* one(IntWrapper::create(1));
3368 IntWrapper* two(IntWrapper::create(2));
3369 IntWrapper* three(IntWrapper::create(3));
3370 IntWrapper* four(IntWrapper::create(4));
3371 IntWrapper* five(IntWrapper::create(5));
3372 IntWrapper* six(IntWrapper::create(6));
3373 IntWrapper* seven(IntWrapper::create(7));
3374 IntWrapper* eight(IntWrapper::create(8));
3375 IntWrapper* nine(IntWrapper::create(9));
3380 pDeque.append(seven);
3383 Vec* vec = new Vec();
3390 pListSet.add(eight);
3391 pLinkedSet.add(nine);
3392 pMap.add(five, six);
3394 // Collect |vec| and |one|.
3396 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3397 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3399 EXPECT_EQ(2u, pVec.size());
3400 EXPECT_EQ(two, pVec.at(0));
3401 EXPECT_EQ(three, pVec.at(1));
3403 EXPECT_EQ(2u, pDeque.size());
3404 EXPECT_EQ(seven, pDeque.first());
3405 EXPECT_EQ(seven, pDeque.takeFirst());
3406 EXPECT_EQ(two, pDeque.first());
3408 EXPECT_EQ(1u, pDeque.size());
3410 EXPECT_EQ(1u, pSet.size());
3411 EXPECT_TRUE(pSet.contains(four));
3413 EXPECT_EQ(1u, pListSet.size());
3414 EXPECT_TRUE(pListSet.contains(eight));
3416 EXPECT_EQ(1u, pLinkedSet.size());
3417 EXPECT_TRUE(pLinkedSet.contains(nine));
3419 EXPECT_EQ(1u, pMap.size());
3420 EXPECT_EQ(six, pMap.get(five));
3423 // Collect previous roots.
3424 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3425 EXPECT_EQ(9, IntWrapper::s_destructorCalls);
3428 TEST(HeapTest, CollectionNesting)
3430 HeapStats initialStats;
3431 clearOutOldGarbage(&initialStats);
3432 int* key = &IntWrapper::s_destructorCalls;
3433 IntWrapper::s_destructorCalls = 0;
3434 typedef HeapVector<Member<IntWrapper> > IntVector;
3435 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3436 HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
3437 HeapHashMap<void*, IntDeque>* map2 = new HeapHashMap<void*, IntDeque>();
3439 map->add(key, IntVector());
3440 map2->add(key, IntDeque());
3442 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3443 EXPECT_EQ(0u, map->get(key).size());
3445 HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3446 EXPECT_EQ(0u, map2->get(key).size());
3448 it->value.append(IntWrapper::create(42));
3449 EXPECT_EQ(1u, map->get(key).size());
3451 it2->value.append(IntWrapper::create(42));
3452 EXPECT_EQ(1u, map2->get(key).size());
3454 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
3455 Persistent<HeapHashMap<void*, IntDeque> > keepAlive2(map2);
3457 for (int i = 0; i < 100; i++) {
3458 map->add(key + 1 + i, IntVector());
3459 map2->add(key + 1 + i, IntDeque());
3462 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3464 EXPECT_EQ(1u, map->get(key).size());
3465 EXPECT_EQ(1u, map2->get(key).size());
3466 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3468 keepAlive = nullptr;
3469 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3470 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3473 TEST(HeapTest, GarbageCollectedMixin)
3475 HeapStats initialHeapStats;
3476 clearOutOldGarbage(&initialHeapStats);
3478 Persistent<UseMixin> usemixin = UseMixin::create();
3479 EXPECT_EQ(0, UseMixin::s_traceCount);
3480 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3481 EXPECT_EQ(1, UseMixin::s_traceCount);
3483 Persistent<Mixin> mixin = usemixin;
3485 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3486 EXPECT_EQ(2, UseMixin::s_traceCount);
3488 PersistentHeapHashSet<WeakMember<Mixin> > weakMap;
3489 weakMap.add(UseMixin::create());
3490 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3491 EXPECT_EQ(0u, weakMap.size());
3494 TEST(HeapTest, CollectionNesting2)
3496 HeapStats initialStats;
3497 clearOutOldGarbage(&initialStats);
3498 void* key = &IntWrapper::s_destructorCalls;
3499 IntWrapper::s_destructorCalls = 0;
3500 typedef HeapHashSet<Member<IntWrapper> > IntSet;
3501 HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
3503 map->add(key, IntSet());
3505 HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3506 EXPECT_EQ(0u, map->get(key).size());
3508 it->value.add(IntWrapper::create(42));
3509 EXPECT_EQ(1u, map->get(key).size());
3511 Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
3512 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3513 EXPECT_EQ(1u, map->get(key).size());
3514 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3517 TEST(HeapTest, CollectionNesting3)
3519 HeapStats initialStats;
3520 clearOutOldGarbage(&initialStats);
3521 IntWrapper::s_destructorCalls = 0;
3522 typedef HeapVector<Member<IntWrapper> > IntVector;
3523 typedef HeapDeque<Member<IntWrapper> > IntDeque;
3524 HeapVector<IntVector>* vector = new HeapVector<IntVector>();
3525 HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
3527 vector->append(IntVector());
3528 deque->append(IntDeque());
3530 HeapVector<IntVector>::iterator it = vector->begin();
3531 HeapDeque<IntDeque>::iterator it2 = deque->begin();
3532 EXPECT_EQ(0u, it->size());
3533 EXPECT_EQ(0u, it2->size());
3535 it->append(IntWrapper::create(42));
3536 it2->append(IntWrapper::create(42));
3537 EXPECT_EQ(1u, it->size());
3538 EXPECT_EQ(1u, it2->size());
3540 Persistent<HeapVector<IntVector> > keepAlive(vector);
3541 Persistent<HeapDeque<IntDeque> > keepAlive2(deque);
3542 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3543 EXPECT_EQ(1u, it->size());
3544 EXPECT_EQ(1u, it2->size());
3545 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3548 TEST(HeapTest, EmbeddedInVector)
3550 HeapStats initialStats;
3551 clearOutOldGarbage(&initialStats);
3552 SimpleFinalizedObject::s_destructorCalls = 0;
3554 PersistentHeapVector<VectorObject, 2> inlineVector;
3555 PersistentHeapVector<VectorObject> outlineVector;
3556 VectorObject i1, i2;
3557 inlineVector.append(i1);
3558 inlineVector.append(i2);
3560 VectorObject o1, o2;
3561 outlineVector.append(o1);
3562 outlineVector.append(o2);
3564 PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
3565 VectorObjectInheritedTrace it1, it2;
3566 vectorInheritedTrace.append(it1);
3567 vectorInheritedTrace.append(it2);
3569 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3570 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3572 // Since VectorObjectNoTrace has no trace method it will
3573 // not be traced and hence be collected when doing GC.
3574 // We trace items in a collection braced on the item's
3575 // having a trace method. This is determined via the
3576 // NeedsTracing trait in wtf/TypeTraits.h.
3577 PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
3578 VectorObjectNoTrace n1, n2;
3579 vectorNoTrace.append(n1);
3580 vectorNoTrace.append(n2);
3581 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3582 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3584 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3585 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3588 TEST(HeapTest, EmbeddedInDeque)
3590 HeapStats initialStats;
3591 clearOutOldGarbage(&initialStats);
3592 SimpleFinalizedObject::s_destructorCalls = 0;
3594 PersistentHeapDeque<VectorObject, 2> inlineDeque;
3595 PersistentHeapDeque<VectorObject> outlineDeque;
3596 VectorObject i1, i2;
3597 inlineDeque.append(i1);
3598 inlineDeque.append(i2);
3600 VectorObject o1, o2;
3601 outlineDeque.append(o1);
3602 outlineDeque.append(o2);
3604 PersistentHeapDeque<VectorObjectInheritedTrace> dequeInheritedTrace;
3605 VectorObjectInheritedTrace it1, it2;
3606 dequeInheritedTrace.append(it1);
3607 dequeInheritedTrace.append(it2);
3609 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3610 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3612 // Since VectorObjectNoTrace has no trace method it will
3613 // not be traced and hence be collected when doing GC.
3614 // We trace items in a collection braced on the item's
3615 // having a trace method. This is determined via the
3616 // NeedsTracing trait in wtf/TypeTraits.h.
3617 PersistentHeapDeque<VectorObjectNoTrace> dequeNoTrace;
3618 VectorObjectNoTrace n1, n2;
3619 dequeNoTrace.append(n1);
3620 dequeNoTrace.append(n2);
3621 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3622 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3624 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3625 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3628 template<typename Set>
3629 void rawPtrInHashHelper()
3632 set.add(new int(42));
3633 set.add(new int(42));
3634 EXPECT_EQ(2u, set.size());
3635 for (typename Set::iterator it = set.begin(); it != set.end(); ++it)
3636 EXPECT_EQ(42, **it);
3639 TEST(HeapTest, RawPtrInHash)
3641 rawPtrInHashHelper<HashSet<RawPtr<int> > >();
3642 rawPtrInHashHelper<ListHashSet<RawPtr<int> > >();
3643 rawPtrInHashHelper<LinkedHashSet<RawPtr<int> > >();
3646 TEST(HeapTest, HeapTerminatedArray)
3648 HeapStats initialHeapSize;
3649 clearOutOldGarbage(&initialHeapSize);
3650 IntWrapper::s_destructorCalls = 0;
3652 HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
3654 const size_t prefixSize = 4;
3655 const size_t suffixSize = 4;
3658 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3659 builder.grow(prefixSize);
3660 for (size_t i = 0; i < prefixSize; i++)
3661 builder.append(TerminatedArrayItem(IntWrapper::create(i)));
3662 arr = builder.release();
3665 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3666 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3667 EXPECT_EQ(prefixSize, arr->size());
3668 for (size_t i = 0; i < prefixSize; i++)
3669 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3672 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3673 builder.grow(suffixSize);
3674 for (size_t i = 0; i < suffixSize; i++)
3675 builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
3676 arr = builder.release();
3679 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3680 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3681 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3682 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3683 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3686 Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3688 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3689 arr = persistentArr.get();
3690 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3691 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3692 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3693 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3697 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3698 EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3701 TEST(HeapTest, HeapLinkedStack)
3703 HeapStats initialHeapSize;
3704 clearOutOldGarbage(&initialHeapSize);
3705 IntWrapper::s_destructorCalls = 0;
3707 HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3709 const size_t stackSize = 10;
3711 for (size_t i = 0; i < stackSize; i++)
3712 stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3714 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3715 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3716 EXPECT_EQ(stackSize, stack->size());
3717 while (!stack->isEmpty()) {
3718 EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3722 Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3724 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3725 EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3726 EXPECT_EQ(0u, pStack->size());
3729 TEST(HeapTest, AllocationDuringFinalization)
3731 HeapStats initialHeapSize;
3732 clearOutOldGarbage(&initialHeapSize);
3733 IntWrapper::s_destructorCalls = 0;
3734 OneKiloByteObject::s_destructorCalls = 0;
3736 Persistent<IntWrapper> wrapper;
3737 new FinalizationAllocator(&wrapper);
3739 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3740 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3741 // Check that the wrapper allocated during finalization is not
3742 // swept away and zapped later in the same sweeping phase.
3743 EXPECT_EQ(42, wrapper->value());
3746 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3747 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3748 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3751 class SimpleClassWithDestructor {
3753 SimpleClassWithDestructor() { }
3754 ~SimpleClassWithDestructor()
3756 s_wasDestructed = true;
3758 static bool s_wasDestructed;
3761 bool SimpleClassWithDestructor::s_wasDestructed;
3763 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
3765 RefCountedWithDestructor() { }
3766 ~RefCountedWithDestructor()
3768 s_wasDestructed = true;
3770 static bool s_wasDestructed;
3773 bool RefCountedWithDestructor::s_wasDestructed;
3775 template<typename Set>
3776 void destructorsCalledOnGC(bool addLots)
3778 RefCountedWithDestructor::s_wasDestructed = false;
3781 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3782 set.add(adoptRef(hasDestructor));
3783 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3786 for (int i = 0; i < 1000; i++) {
3787 set.add(adoptRef(new RefCountedWithDestructor()));
3791 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3792 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3793 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3795 // The destructors of the sets don't call the destructors of the elements
3796 // in the heap sets. You have to actually remove the elments, call clear()
3797 // or have a GC to get the destructors called.
3798 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3799 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3800 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3803 template<typename Set>
3804 void destructorsCalledOnClear(bool addLots)
3806 RefCountedWithDestructor::s_wasDestructed = false;
3808 RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3809 set.add(adoptRef(hasDestructor));
3810 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3813 for (int i = 0; i < 1000; i++) {
3814 set.add(adoptRef(new RefCountedWithDestructor()));
3818 EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3820 EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3823 TEST(HeapTest, DestructorsCalled)
3825 HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3826 SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3827 map.add(hasDestructor, adoptPtr(hasDestructor));
3828 SimpleClassWithDestructor::s_wasDestructed = false;
3830 EXPECT_TRUE(SimpleClassWithDestructor::s_wasDestructed);
3832 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3833 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3834 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3835 destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3836 destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3837 destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3839 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3840 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3841 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3842 destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3843 destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3844 destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3847 class MixinA : public GarbageCollectedMixin {
3849 MixinA() : m_obj(IntWrapper::create(100)) { }
3850 virtual void trace(Visitor* visitor)
3852 visitor->trace(m_obj);
3854 Member<IntWrapper> m_obj;
3857 class MixinB : public GarbageCollectedMixin {
3859 MixinB() : m_obj(IntWrapper::create(101)) { }
3860 virtual void trace(Visitor* visitor)
3862 visitor->trace(m_obj);
3864 Member<IntWrapper> m_obj;
3867 class MultipleMixins : public GarbageCollected<MultipleMixins>, public MixinA, public MixinB {
3868 USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
3870 MultipleMixins() : m_obj(IntWrapper::create(102)) { }
3871 virtual void trace(Visitor* visitor)
3873 visitor->trace(m_obj);
3874 MixinA::trace(visitor);
3875 MixinB::trace(visitor);
3877 Member<IntWrapper> m_obj;
3880 static const bool s_isMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
3881 static const bool s_isMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
3883 TEST(HeapTest, MultipleMixins)
3885 EXPECT_TRUE(s_isMixinTrue);
3886 EXPECT_FALSE(s_isMixinFalse);
3888 HeapStats initialHeapSize;
3889 clearOutOldGarbage(&initialHeapSize);
3890 IntWrapper::s_destructorCalls = 0;
3891 MultipleMixins* obj = new MultipleMixins();
3893 Persistent<MixinA> a = obj;
3894 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3895 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3898 Persistent<MixinB> b = obj;
3899 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3900 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3902 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3903 EXPECT_EQ(3, IntWrapper::s_destructorCalls);
3906 class GCParkingThreadTester {
3910 createThread(&sleeperMainFunc, 0, "SleepingThread");
3912 // Wait for the sleeper to run.
3913 while (!s_sleeperRunning) {
3918 // Expect the first attempt to park the sleeping thread to fail
3919 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3920 EXPECT_FALSE(scope.allThreadsParked());
3923 s_sleeperDone = true;
3925 // Wait for the sleeper to finish.
3926 while (s_sleeperRunning) {
3927 // We enter the safepoint here since the sleeper thread will detach
3928 // causing it to GC.
3929 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
3933 // Since the sleeper thread has detached this is the only thread.
3934 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3935 EXPECT_TRUE(scope.allThreadsParked());
3940 static void sleeperMainFunc(void* data)
3942 ThreadState::attach();
3943 s_sleeperRunning = true;
3945 // Simulate a long running op that is not entering a safepoint.
3946 while (!s_sleeperDone) {
3950 ThreadState::detach();
3951 s_sleeperRunning = false;
3954 static volatile bool s_sleeperRunning;
3955 static volatile bool s_sleeperDone;
3958 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
3959 volatile bool GCParkingThreadTester::s_sleeperDone = false;
3961 TEST(HeapTest, GCParkingTimeout)
3963 GCParkingThreadTester::test();
3966 } // WebCore namespace