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 "heap/Handle.h"
34 #include "heap/Heap.h"
35 #include "heap/HeapLinkedStack.h"
36 #include "heap/HeapTerminatedArrayBuilder.h"
37 #include "heap/ThreadState.h"
38 #include "heap/Visitor.h"
40 #include "wtf/HashTraits.h"
42 #include <gtest/gtest.h>
48 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(0) { }
49 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i) { }
50 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(reinterpret_cast<ThreadState*>(-1)), m_num(0) { }
53 EXPECT_TRUE((m_creatingThread == ThreadState::current())
54 || (m_creatingThread == reinterpret_cast<ThreadState*>(0))
55 || (m_creatingThread == reinterpret_cast<ThreadState*>(-1)));
57 bool isHashTableDeletedValue() const { return m_creatingThread == reinterpret_cast<ThreadState*>(-1); }
58 bool operator==(const ThreadMarker& other) const { return other.m_creatingThread == m_creatingThread && other.m_num == m_num; }
59 ThreadState* m_creatingThread;
63 struct ThreadMarkerHash {
64 static unsigned hash(const ThreadMarker& key)
66 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(key.m_creatingThread) + key.m_num);
69 static bool equal(const ThreadMarker& a, const ThreadMarker& b)
74 static const bool safeToCompareToEmptyOrDeleted = false;
81 template<typename T> struct DefaultHash;
82 template<> struct DefaultHash<WebCore::ThreadMarker> {
83 typedef WebCore::ThreadMarkerHash Hash;
86 // ThreadMarkerHash is the default hash for ThreadMarker
87 template<> struct HashTraits<WebCore::ThreadMarker> : GenericHashTraits<WebCore::ThreadMarker> {
88 static const bool emptyValueIsZero = true;
89 static void constructDeletedValue(WebCore::ThreadMarker& slot) { new (NotNull, &slot) WebCore::ThreadMarker(HashTableDeletedValue); }
90 static bool isDeletedValue(const WebCore::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
99 explicit TestGCScope(ThreadState::StackState state)
100 : m_state(ThreadState::current())
101 , m_safePointScope(state)
103 m_state->checkThread();
104 ASSERT(!m_state->isInGC());
105 ThreadState::stopThreads();
112 ASSERT(!m_state->isInGC());
113 ThreadState::resumeThreads();
117 ThreadState* m_state;
118 ThreadState::SafePointScope m_safePointScope;
121 static void getHeapStats(HeapStats* stats)
123 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
124 Heap::getStats(stats);
127 #define DEFINE_VISITOR_METHODS(Type) \
128 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
133 virtual bool isMarked(const Type*) OVERRIDE { return false; }
135 class CountingVisitor : public Visitor {
142 virtual void mark(const void* object, TraceCallback) OVERRIDE
148 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
150 ASSERT(header->payload());
154 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
156 ASSERT(header->payload());
160 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
161 virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
162 virtual bool isMarked(const void*) OVERRIDE { return false; }
164 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
166 size_t count() { return m_count; }
167 void reset() { m_count = 0; }
173 class SimpleObject : public GarbageCollected<SimpleObject> {
175 static SimpleObject* create() { return new SimpleObject(); }
176 void trace(Visitor*) { }
177 char getPayload(int i) { return payload[i]; }
183 #undef DEFINE_VISITOR_METHODS
185 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
187 static HeapTestSuperClass* create()
189 return new HeapTestSuperClass();
192 virtual ~HeapTestSuperClass()
197 static int s_destructorCalls;
198 void trace(Visitor*) { }
201 HeapTestSuperClass() { }
204 int HeapTestSuperClass::s_destructorCalls = 0;
206 class HeapTestOtherSuperClass {
211 static const size_t classMagic = 0xABCDDBCA;
213 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
215 static HeapTestSubClass* create()
217 return new HeapTestSubClass();
220 virtual ~HeapTestSubClass()
222 EXPECT_EQ(classMagic, m_magic);
226 static int s_destructorCalls;
230 HeapTestSubClass() : m_magic(classMagic) { }
232 const size_t m_magic;
235 int HeapTestSubClass::s_destructorCalls = 0;
237 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
241 for (int i = 0; i < s_arraySize; ++i) {
242 m_array[i] = i % 128;
246 int8_t at(size_t i) { return m_array[i]; }
247 void trace(Visitor*) { }
249 static const int s_arraySize = 1000;
250 int8_t m_array[s_arraySize];
253 // Do several GCs to make sure that later GCs don't free up old memory from
254 // previously run tests in this process.
255 static void clearOutOldGarbage(HeapStats* heapStats)
258 getHeapStats(heapStats);
259 size_t used = heapStats->totalObjectSpace();
260 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
261 getHeapStats(heapStats);
262 if (heapStats->totalObjectSpace() >= used)
267 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
269 static IntWrapper* create(int x)
271 return new IntWrapper(x);
274 virtual ~IntWrapper()
279 static int s_destructorCalls;
280 static void trace(Visitor*) { }
282 int value() const { return m_x; }
284 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
286 unsigned hash() { return IntHash<int>::hash(m_x); }
289 IntWrapper(int x) : m_x(x) { }
296 USED_FROM_MULTIPLE_THREADS(IntWrapper);
298 int IntWrapper::s_destructorCalls = 0;
300 class ThreadedTesterBase {
302 static void test(ThreadedTesterBase* tester)
304 for (int i = 0; i < numberOfThreads; i++)
305 createThread(&threadFunc, tester, "testing thread");
306 while (tester->m_threadsToFinish) {
307 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
313 virtual void runThread() = 0;
316 static const int numberOfThreads = 10;
317 static const int gcPerThread = 5;
318 static const int numberOfAllocations = 50;
320 ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
324 virtual ~ThreadedTesterBase()
328 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
330 volatile int m_gcCount;
331 volatile int m_threadsToFinish;
334 static void threadFunc(void* data)
336 reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
340 class ThreadedHeapTester : public ThreadedTesterBase {
344 ThreadedTesterBase::test(new ThreadedHeapTester);
348 virtual void runThread() OVERRIDE
350 ThreadState::attach();
354 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
356 Persistent<IntWrapper> wrapper;
358 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
359 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
361 for (int i = 0; i < numberOfAllocations; i++) {
362 wrapper = IntWrapper::create(0x0bbac0de);
364 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
365 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
370 if (gcCount < gcPerThread) {
371 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
373 atomicIncrement(&m_gcCount);
376 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
377 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
378 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
382 ThreadState::detach();
383 atomicDecrement(&m_threadsToFinish);
387 class ThreadedWeaknessTester : public ThreadedTesterBase {
391 ThreadedTesterBase::test(new ThreadedWeaknessTester);
395 virtual void runThread() OVERRIDE
397 ThreadState::attach();
401 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
403 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
404 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
406 for (int i = 0; i < numberOfAllocations; i++) {
407 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
408 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
410 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
415 if (gcCount < gcPerThread) {
416 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
418 atomicIncrement(&m_gcCount);
421 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
422 EXPECT_TRUE(weakMap->isEmpty());
423 EXPECT_TRUE(weakMap2.isEmpty());
427 ThreadState::detach();
428 atomicDecrement(&m_threadsToFinish);
432 // The accounting for memory includes the memory used by rounding up object
433 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
434 // have some slack in the tests.
436 void CheckWithSlack(T expected, T actual, int slack)
438 EXPECT_LE(expected, actual);
439 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
442 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
444 static TraceCounter* create()
446 return new TraceCounter();
449 void trace(Visitor*) { m_traceCount++; }
451 int traceCount() { return m_traceCount; }
462 class ClassWithMember : public GarbageCollected<ClassWithMember> {
464 static ClassWithMember* create()
466 return new ClassWithMember();
469 void trace(Visitor* visitor)
471 EXPECT_TRUE(visitor->isMarked(this));
473 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
475 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
477 visitor->trace(m_traceCounter);
480 int traceCount() { return m_traceCounter->traceCount(); }
484 : m_traceCounter(TraceCounter::create())
487 Member<TraceCounter> m_traceCounter;
490 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
492 static SimpleFinalizedObject* create()
494 return new SimpleFinalizedObject();
497 ~SimpleFinalizedObject()
502 static int s_destructorCalls;
504 void trace(Visitor*) { }
507 SimpleFinalizedObject() { }
510 int SimpleFinalizedObject::s_destructorCalls = 0;
512 class TestTypedHeapClass : public GarbageCollected<TestTypedHeapClass> {
514 static TestTypedHeapClass* create()
516 return new TestTypedHeapClass();
519 void trace(Visitor*) { }
522 TestTypedHeapClass() { }
525 class Bar : public GarbageCollectedFinalized<Bar> {
532 void finalizeGarbageCollectedObject()
534 EXPECT_TRUE(m_magic == magic);
538 bool hasBeenFinalized() const { return !m_magic; }
540 virtual void trace(Visitor* visitor) { }
541 static unsigned s_live;
544 static const int magic = 1337;
554 unsigned Bar::s_live = 0;
556 class Baz : public GarbageCollected<Baz> {
558 static Baz* create(Bar* bar)
563 void trace(Visitor* visitor)
565 visitor->trace(m_bar);
568 void clear() { m_bar.release(); }
570 // willFinalize is called by FinalizationObserver.
573 EXPECT_TRUE(!m_bar->hasBeenFinalized());
577 explicit Baz(Bar* bar)
585 class Foo : public Bar {
587 static Foo* create(Bar* bar)
592 static Foo* create(Foo* foo)
597 virtual void trace(Visitor* visitor) OVERRIDE
600 visitor->mark(static_cast<Foo*>(m_bar));
602 visitor->mark(m_bar);
609 , m_pointsToFoo(false)
616 , m_pointsToFoo(true)
624 class Bars : public Bar {
626 static Bars* create()
631 virtual void trace(Visitor* visitor) OVERRIDE
633 for (unsigned i = 0; i < m_width; i++)
634 visitor->trace(m_bars[i]);
637 unsigned getWidth() const
642 static const unsigned width = 7500;
646 for (unsigned i = 0; i < width; i++) {
647 m_bars[i] = Bar::create();
653 Member<Bar> m_bars[width];
656 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
658 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
660 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
663 ConstructorAllocation()
665 m_intWrapper = IntWrapper::create(42);
668 Member<IntWrapper> m_intWrapper;
671 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
677 static LargeObject* create() { return new LargeObject(); }
678 char get(size_t i) { return m_data[i]; }
679 void set(size_t i, char c) { m_data[i] = c; }
680 size_t length() { return s_length; }
681 void trace(Visitor* visitor)
683 visitor->trace(m_intWrapper);
685 static int s_destructorCalls;
688 static const size_t s_length = 1024*1024;
691 m_intWrapper = IntWrapper::create(23);
693 Member<IntWrapper> m_intWrapper;
694 char m_data[s_length];
697 int LargeObject::s_destructorCalls = 0;
699 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
701 static PassRefPtr<RefCountedAndGarbageCollected> create()
703 return adoptRef(new RefCountedAndGarbageCollected());
706 ~RefCountedAndGarbageCollected()
711 void trace(Visitor*) { }
713 static int s_destructorCalls;
716 RefCountedAndGarbageCollected()
721 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
723 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
725 static RefCountedAndGarbageCollected2* create()
727 return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
730 ~RefCountedAndGarbageCollected2()
735 void trace(Visitor*) { }
737 static int s_destructorCalls;
740 RefCountedAndGarbageCollected2()
745 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
747 #define DEFINE_VISITOR_METHODS(Type) \
748 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
753 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
755 RefCountedGarbageCollectedVisitor(int expected, void** objects)
757 , m_expectedCount(expected)
758 , m_expectedObjects(objects)
762 void mark(const void* ptr) { markNoTrace(ptr); }
764 virtual void markNoTrace(const void* ptr)
768 if (m_count < m_expectedCount)
769 EXPECT_TRUE(expectedObject(ptr));
771 EXPECT_FALSE(expectedObject(ptr));
775 virtual void mark(const void* ptr, TraceCallback) OVERRIDE
780 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
782 mark(header->payload());
785 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
787 mark(header->payload());
790 bool validate() { return m_count >= m_expectedCount; }
791 void reset() { m_count = 0; }
793 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
796 bool expectedObject(const void* ptr)
798 for (int i = 0; i < m_expectedCount; i++) {
799 if (m_expectedObjects[i] == ptr)
807 void** m_expectedObjects;
810 #undef DEFINE_VISITOR_METHODS
812 class Weak : public Bar {
814 static Weak* create(Bar* strong, Bar* weak)
816 return new Weak(strong, weak);
819 virtual void trace(Visitor* visitor) OVERRIDE
821 visitor->trace(m_strongBar);
822 visitor->registerWeakMembers(this, zapWeakMembers);
825 static void zapWeakMembers(Visitor* visitor, void* self)
827 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
830 bool strongIsThere() { return !!m_strongBar; }
831 bool weakIsThere() { return !!m_weakBar; }
834 Weak(Bar* strongBar, Bar* weakBar)
836 , m_strongBar(strongBar)
841 void zapWeakMembers(Visitor* visitor)
843 if (m_weakBar && !visitor->isAlive(m_weakBar))
847 Member<Bar> m_strongBar;
851 class WithWeakMember : public Bar {
853 static WithWeakMember* create(Bar* strong, Bar* weak)
855 return new WithWeakMember(strong, weak);
858 virtual void trace(Visitor* visitor) OVERRIDE
860 visitor->trace(m_strongBar);
861 visitor->trace(m_weakBar);
864 bool strongIsThere() { return !!m_strongBar; }
865 bool weakIsThere() { return !!m_weakBar; }
868 WithWeakMember(Bar* strongBar, Bar* weakBar)
870 , m_strongBar(strongBar)
875 Member<Bar> m_strongBar;
876 WeakMember<Bar> m_weakBar;
879 class Observable : public GarbageCollectedFinalized<Observable> {
881 static Observable* create(Bar* bar) { return new Observable(bar); }
882 ~Observable() { m_wasDestructed = true; }
883 void trace(Visitor* visitor) { visitor->trace(m_bar); }
885 // willFinalize is called by FinalizationObserver. willFinalize can touch
886 // other on-heap objects.
889 EXPECT_FALSE(m_wasDestructed);
890 EXPECT_FALSE(m_bar->hasBeenFinalized());
894 explicit Observable(Bar* bar)
896 , m_wasDestructed(false)
901 bool m_wasDestructed;
904 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
906 static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
907 bool didCallWillFinalize() const { return m_didCallWillFinalize; }
909 void trace(Visitor* visitor)
911 visitor->registerWeakMembers(this, zapWeakMembers);
915 FinalizationObserver(T* data)
917 , m_didCallWillFinalize(false)
921 static void zapWeakMembers(Visitor* visitor, void* self)
923 FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
924 if (o->m_data && !visitor->isAlive(o->m_data)) {
925 o->m_data->willFinalize();
927 o->m_didCallWillFinalize = true;
931 WeakMember<T> m_data;
932 bool m_didCallWillFinalize;
935 class FinalizationObserverWithHashMap {
937 typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
939 explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
940 ~FinalizationObserverWithHashMap()
942 m_target.willFinalize();
943 s_didCallWillFinalize = true;
946 static ObserverMap& observe(Observable& target)
948 ObserverMap& map = observers();
949 ObserverMap::AddResult result = map.add(&target, nullptr);
950 if (result.isNewEntry)
951 result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
953 ASSERT(result.storedValue->value);
957 static bool s_didCallWillFinalize;
960 static ObserverMap& observers()
962 DEFINE_STATIC_LOCAL(Persistent<ObserverMap>, observerMap, ());
964 observerMap = new ObserverMap();
968 Observable& m_target;
971 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
975 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
977 static PassRefPtrWillBeRawPtr<PointsBack> create()
979 return adoptRefWillBeNoop(new PointsBack());
987 void setBackPointer(SuperClass* backPointer)
989 m_backPointer = backPointer;
992 SuperClass* backPointer() const { return m_backPointer; }
994 void trace(Visitor* visitor)
997 visitor->trace(m_backPointer);
1001 static int s_aliveCount;
1003 PointsBack() : m_backPointer(nullptr)
1008 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1011 int PointsBack::s_aliveCount = 0;
1013 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1015 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1017 return adoptRefWillBeNoop(new SuperClass(pointsBack));
1020 virtual ~SuperClass()
1023 m_pointsBack->setBackPointer(0);
1028 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1030 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1031 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1032 EXPECT_EQ(pointsBack, target->pointsBack());
1033 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1036 virtual void trace(Visitor* visitor)
1039 visitor->trace(m_pointsBack);
1043 PointsBack* pointsBack() const { return m_pointsBack.get(); }
1045 static int s_aliveCount;
1047 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1048 : m_pointsBack(pointsBack)
1050 m_pointsBack->setBackPointer(this);
1055 RefPtrWillBeMember<PointsBack> m_pointsBack;
1058 int SuperClass::s_aliveCount = 0;
1059 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1061 SubData() { ++s_aliveCount; }
1062 ~SubData() { --s_aliveCount; }
1064 void trace(Visitor*) { }
1066 static int s_aliveCount;
1069 int SubData::s_aliveCount = 0;
1071 class SubClass : public SuperClass {
1073 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1075 return adoptRefWillBeNoop(new SubClass(pointsBack));
1083 virtual void trace(Visitor* visitor)
1086 SuperClass::trace(visitor);
1087 visitor->trace(m_data);
1091 static int s_aliveCount;
1093 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1094 : SuperClass(pointsBack)
1095 , m_data(adoptPtrWillBeNoop(new SubData()))
1101 OwnPtrWillBeMember<SubData> m_data;
1104 int SubClass::s_aliveCount = 0;
1106 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1108 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1110 return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
1113 ~TransitionRefCounted()
1118 void trace(Visitor* visitor) { }
1120 static int s_aliveCount;
1123 TransitionRefCounted()
1129 int TransitionRefCounted::s_aliveCount = 0;
1131 class Mixin : public GarbageCollectedMixin {
1133 virtual void trace(Visitor* visitor) { }
1135 char getPayload(int i) { return m_padding[i]; }
1138 // This is to force ptr diff for SimpleObject, Mixin, and UseMixin.
1142 class UseMixin : public SimpleObject, public Mixin {
1143 USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1145 static UseMixin* create()
1147 return new UseMixin();
1150 static int s_traceCount;
1151 virtual void trace(Visitor* visitor)
1153 SimpleObject::trace(visitor);
1154 Mixin::trace(visitor);
1165 int UseMixin::s_traceCount = 0;
1167 class VectorObject {
1168 ALLOW_ONLY_INLINE_ALLOCATION();
1172 m_value = SimpleFinalizedObject::create();
1175 void trace(Visitor* visitor)
1177 visitor->trace(m_value);
1181 Member<SimpleFinalizedObject> m_value;
1184 class VectorObjectInheritedTrace : public VectorObject { };
1186 class VectorObjectNoTrace {
1187 ALLOW_ONLY_INLINE_ALLOCATION();
1189 VectorObjectNoTrace()
1191 m_value = SimpleFinalizedObject::create();
1195 Member<SimpleFinalizedObject> m_value;
1198 class TerminatedArrayItem {
1199 ALLOW_ONLY_INLINE_ALLOCATION();
1201 TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1203 void trace(Visitor* visitor) { visitor->trace(m_payload); }
1205 bool isLastInArray() const { return m_isLast; }
1206 void setLastInArray(bool value) { m_isLast = value; }
1208 IntWrapper* payload() const { return m_payload; }
1211 Member<IntWrapper> m_payload;
1215 } // WebCore namespace
1219 // We need the below vector trait specialization for the above HeapVectors to behave correctly wrt. memset, memcmp etc.
1220 template<> struct VectorTraits<WebCore::VectorObject> : public SimpleClassVectorTraits<WebCore::VectorObject> { };
1221 template<> struct VectorTraits<WebCore::VectorObjectInheritedTrace> : public SimpleClassVectorTraits<WebCore::VectorObjectInheritedTrace> { };
1222 template<> struct VectorTraits<WebCore::VectorObjectNoTrace> : public SimpleClassVectorTraits<WebCore::VectorObjectNoTrace> { };
1228 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1230 ~OneKiloByteObject() { s_destructorCalls++; }
1231 char* data() { return m_data; }
1232 void trace(Visitor* visitor) { }
1233 static int s_destructorCalls;
1236 static const size_t s_length = 1024;
1237 char m_data[s_length];
1240 int OneKiloByteObject::s_destructorCalls = 0;
1242 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1244 static DynamicallySizedObject* create(size_t size)
1246 void* slot = Heap::allocate<DynamicallySizedObject>(size);
1247 return new (slot) DynamicallySizedObject();
1250 void* operator new(std::size_t, void* location)
1257 return *(reinterpret_cast<uint8_t*>(this) + i);
1260 void trace(Visitor*) { }
1263 DynamicallySizedObject() { }
1266 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1268 FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1269 : m_wrapper(wrapper)
1273 ~FinalizationAllocator()
1275 for (int i = 0; i < 10; ++i)
1276 *m_wrapper = IntWrapper::create(42);
1277 for (int i = 0; i < 512; ++i)
1278 new OneKiloByteObject();
1281 void trace(Visitor*) { }
1284 Persistent<IntWrapper>* m_wrapper;
1287 TEST(HeapTest, Transition)
1290 RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1291 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1292 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1293 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1295 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1296 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1298 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1299 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1300 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1301 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1302 EXPECT_EQ(2, PointsBack::s_aliveCount);
1303 EXPECT_EQ(2, SuperClass::s_aliveCount);
1304 EXPECT_EQ(1, SubClass::s_aliveCount);
1305 EXPECT_EQ(1, SubData::s_aliveCount);
1307 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1308 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1309 EXPECT_EQ(2, PointsBack::s_aliveCount);
1310 EXPECT_EQ(2, SuperClass::s_aliveCount);
1311 EXPECT_EQ(1, SubClass::s_aliveCount);
1312 EXPECT_EQ(1, SubData::s_aliveCount);
1314 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1315 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1316 EXPECT_EQ(2, PointsBack::s_aliveCount);
1317 EXPECT_EQ(1, SuperClass::s_aliveCount);
1318 EXPECT_EQ(1, SubClass::s_aliveCount);
1319 EXPECT_EQ(1, SubData::s_aliveCount);
1320 EXPECT_EQ(0, pointsBack1->backPointer());
1322 pointsBack1.release();
1323 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1324 EXPECT_EQ(1, PointsBack::s_aliveCount);
1325 EXPECT_EQ(1, SuperClass::s_aliveCount);
1326 EXPECT_EQ(1, SubClass::s_aliveCount);
1327 EXPECT_EQ(1, SubData::s_aliveCount);
1329 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1330 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1331 EXPECT_EQ(1, PointsBack::s_aliveCount);
1332 EXPECT_EQ(0, SuperClass::s_aliveCount);
1333 EXPECT_EQ(0, SubClass::s_aliveCount);
1334 EXPECT_EQ(0, SubData::s_aliveCount);
1335 EXPECT_EQ(0, pointsBack2->backPointer());
1337 pointsBack2.release();
1338 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1339 EXPECT_EQ(0, PointsBack::s_aliveCount);
1340 EXPECT_EQ(0, SuperClass::s_aliveCount);
1341 EXPECT_EQ(0, SubClass::s_aliveCount);
1342 EXPECT_EQ(0, SubData::s_aliveCount);
1344 EXPECT_TRUE(superClass == subClass);
1347 TEST(HeapTest, Threading)
1349 ThreadedHeapTester::test();
1352 TEST(HeapTest, ThreadedWeakness)
1354 ThreadedWeaknessTester::test();
1357 TEST(HeapTest, BasicFunctionality)
1359 HeapStats heapStats;
1360 clearOutOldGarbage(&heapStats);
1364 // When the test starts there may already have been leaked some memory
1365 // on the heap, so we establish a base line.
1366 size_t baseLevel = heapStats.totalObjectSpace();
1367 bool testPagesAllocated = !baseLevel;
1368 if (testPagesAllocated)
1369 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1371 // This allocates objects on the general heap which should add a page of memory.
1372 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1374 memset(alloc32, 40, 32);
1375 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1377 memset(alloc64, 27, 64);
1381 getHeapStats(&heapStats);
1382 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1383 if (testPagesAllocated)
1384 EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1386 CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
1388 EXPECT_EQ(alloc32->get(0), 40);
1389 EXPECT_EQ(alloc32->get(31), 40);
1390 EXPECT_EQ(alloc64->get(0), 27);
1391 EXPECT_EQ(alloc64->get(63), 27);
1393 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1395 EXPECT_EQ(alloc32->get(0), 40);
1396 EXPECT_EQ(alloc32->get(31), 40);
1397 EXPECT_EQ(alloc64->get(0), 27);
1398 EXPECT_EQ(alloc64->get(63), 27);
1401 clearOutOldGarbage(&heapStats);
1404 size_t baseLevel = heapStats.totalObjectSpace();
1405 bool testPagesAllocated = !baseLevel;
1406 if (testPagesAllocated)
1407 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1410 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1414 size_t persistentCount = 0;
1415 const size_t numPersistents = 100000;
1416 Persistent<DynamicallySizedObject>* persistents[numPersistents];
1418 for (int i = 0; i < 1000; i++) {
1419 size_t size = 128 + i * 8;
1421 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1423 getHeapStats(&heapStats);
1424 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1425 if (testPagesAllocated)
1426 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1430 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1432 memset(alloc32b, 40, 32);
1433 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1435 memset(alloc64b, 27, 64);
1436 EXPECT_TRUE(alloc32b != alloc64b);
1439 getHeapStats(&heapStats);
1440 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1441 if (testPagesAllocated)
1442 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1445 clearOutOldGarbage(&heapStats);
1448 if (testPagesAllocated)
1449 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1451 DynamicallySizedObject* bigAreaRaw = bigArea;
1452 // Clear the persistent, so that the big area will be garbage collected.
1454 clearOutOldGarbage(&heapStats);
1458 getHeapStats(&heapStats);
1459 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1460 if (testPagesAllocated)
1461 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1463 // Endless loop unless we eventually get the memory back that we just freed.
1465 Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
1467 persistents[persistentCount++] = alloc;
1468 EXPECT_LT(persistentCount, numPersistents);
1470 if (bigAreaRaw == alloc->get())
1474 getHeapStats(&heapStats);
1475 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1476 if (testPagesAllocated)
1477 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1479 for (size_t i = 0; i < persistentCount; i++) {
1480 delete persistents[i];
1484 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1485 for (int i = 0; i < 100; i++)
1487 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1488 for (int i = 0; i < 100; i++)
1489 EXPECT_EQ(address[i], i);
1490 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1491 for (int i = 0; i < 50; i++)
1492 EXPECT_EQ(address[i], i);
1493 // This should be equivalent to free(address).
1494 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1495 // This should be equivalent to malloc(0).
1496 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1499 TEST(HeapTest, SimpleAllocation)
1501 HeapStats initialHeapStats;
1502 clearOutOldGarbage(&initialHeapStats);
1503 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1505 // Allocate an object in the heap.
1506 HeapAllocatedArray* array = new HeapAllocatedArray();
1507 HeapStats statsAfterAllocation;
1508 getHeapStats(&statsAfterAllocation);
1509 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1511 // Sanity check of the contents in the heap.
1512 EXPECT_EQ(0, array->at(0));
1513 EXPECT_EQ(42, array->at(42));
1514 EXPECT_EQ(0, array->at(128));
1515 EXPECT_EQ(999 % 128, array->at(999));
1518 TEST(HeapTest, SimplePersistent)
1520 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1521 EXPECT_EQ(0, traceCounter->traceCount());
1523 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1524 EXPECT_EQ(1, traceCounter->traceCount());
1526 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1527 EXPECT_EQ(0, classWithMember->traceCount());
1529 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1530 EXPECT_EQ(1, classWithMember->traceCount());
1531 EXPECT_EQ(2, traceCounter->traceCount());
1534 TEST(HeapTest, SimpleFinalization)
1537 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1538 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1539 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1540 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1543 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1544 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1547 TEST(HeapTest, Finalization)
1550 HeapTestSubClass* t1 = HeapTestSubClass::create();
1551 HeapTestSubClass* t2 = HeapTestSubClass::create();
1552 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1553 // FIXME(oilpan): Ignore unused variables.
1558 // Nothing is marked so the GC should free everything and call
1559 // the finalizer on all three objects.
1560 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1561 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1562 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1563 // Destructors not called again when GCing again.
1564 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1565 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1566 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1569 TEST(HeapTest, TypedHeapSanity)
1571 // We use TraceCounter for allocating an object on the general heap.
1572 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1573 Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create();
1574 EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get())),
1575 pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get())));
1578 TEST(HeapTest, NoAllocation)
1580 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1582 // Disallow allocation
1583 NoAllocationScope<AnyThread> noAllocationScope;
1584 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1586 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1589 TEST(HeapTest, Members)
1596 h1 = Baz::create(Bar::create());
1597 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1598 EXPECT_EQ(1u, Bar::s_live);
1599 h2 = Baz::create(Bar::create());
1600 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1601 EXPECT_EQ(2u, Bar::s_live);
1603 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1604 EXPECT_EQ(2u, Bar::s_live);
1606 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1607 EXPECT_EQ(1u, Bar::s_live);
1609 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1610 EXPECT_EQ(0u, Bar::s_live);
1613 TEST(HeapTest, MarkTest)
1617 Persistent<Bar> bar = Bar::create();
1618 EXPECT_TRUE(ThreadState::current()->contains(bar));
1619 EXPECT_EQ(1u, Bar::s_live);
1621 Foo* foo = Foo::create(bar);
1622 EXPECT_TRUE(ThreadState::current()->contains(foo));
1623 EXPECT_EQ(2u, Bar::s_live);
1624 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1625 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1626 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1627 EXPECT_EQ(2u, Bar::s_live);
1629 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1630 EXPECT_EQ(1u, Bar::s_live);
1632 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1633 EXPECT_EQ(0u, Bar::s_live);
1636 TEST(HeapTest, DeepTest)
1638 const unsigned depth = 100000;
1641 Bar* bar = Bar::create();
1642 EXPECT_TRUE(ThreadState::current()->contains(bar));
1643 Foo* foo = Foo::create(bar);
1644 EXPECT_TRUE(ThreadState::current()->contains(foo));
1645 EXPECT_EQ(2u, Bar::s_live);
1646 for (unsigned i = 0; i < depth; i++) {
1647 Foo* foo2 = Foo::create(foo);
1649 EXPECT_TRUE(ThreadState::current()->contains(foo));
1651 EXPECT_EQ(depth + 2, Bar::s_live);
1652 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1653 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1654 EXPECT_EQ(depth + 2, Bar::s_live);
1656 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1657 EXPECT_EQ(0u, Bar::s_live);
1660 TEST(HeapTest, WideTest)
1664 Bars* bars = Bars::create();
1665 unsigned width = Bars::width;
1666 EXPECT_EQ(width + 1, Bar::s_live);
1667 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1668 EXPECT_EQ(width + 1, Bar::s_live);
1669 // Use bars here to make sure that it will be on the stack
1670 // for the conservative stack scan to find.
1671 EXPECT_EQ(width, bars->getWidth());
1673 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1674 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1675 EXPECT_EQ(0u, Bar::s_live);
1678 TEST(HeapTest, HashMapOfMembers)
1680 HeapStats initialHeapSize;
1681 IntWrapper::s_destructorCalls = 0;
1683 clearOutOldGarbage(&initialHeapSize);
1685 typedef HeapHashMap<
1688 DefaultHash<Member<IntWrapper> >::Hash,
1689 HashTraits<Member<IntWrapper> >,
1690 HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1692 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1695 HeapStats afterSetWasCreated;
1696 getHeapStats(&afterSetWasCreated);
1697 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1699 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1701 getHeapStats(&afterGC);
1702 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1704 // If the additions below cause garbage collections, these
1705 // pointers should be found by conservative stack scanning.
1706 IntWrapper* one(IntWrapper::create(1));
1707 IntWrapper* anotherOne(IntWrapper::create(1));
1711 HeapStats afterOneAdd;
1712 getHeapStats(&afterOneAdd);
1713 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1715 HeapObjectIdentityMap::iterator it(map->begin());
1716 HeapObjectIdentityMap::iterator it2(map->begin());
1720 map->add(anotherOne, one);
1722 // The addition above can cause an allocation of a new
1723 // backing store. We therefore garbage collect before
1724 // taking the heap stats in order to get rid of the old
1725 // backing store. We make sure to not use conservative
1726 // stack scanning as that could find a pointer to the
1728 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1729 HeapStats afterAddAndGC;
1730 getHeapStats(&afterAddAndGC);
1731 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1733 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1735 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1736 EXPECT_TRUE(map->contains(one));
1737 EXPECT_TRUE(map->contains(anotherOne));
1739 IntWrapper* gotten(map->get(one));
1740 EXPECT_EQ(gotten->value(), one->value());
1741 EXPECT_EQ(gotten, one);
1744 getHeapStats(&afterGC2);
1745 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1747 IntWrapper* dozen = 0;
1749 for (int i = 1; i < 1000; i++) { // 999 iterations.
1750 IntWrapper* iWrapper(IntWrapper::create(i));
1751 IntWrapper* iSquared(IntWrapper::create(i * i));
1752 map->add(iWrapper, iSquared);
1756 HeapStats afterAdding1000;
1757 getHeapStats(&afterAdding1000);
1758 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1760 IntWrapper* gross(map->get(dozen));
1761 EXPECT_EQ(gross->value(), 144);
1763 // This should clear out junk created by all the adds.
1764 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1766 getHeapStats(&afterGC3);
1767 EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1770 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1771 // The objects 'one', anotherOne, and the 999 other pairs.
1772 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1774 getHeapStats(&afterGC4);
1775 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1778 TEST(HeapTest, NestedAllocation)
1780 HeapStats initialHeapSize;
1781 clearOutOldGarbage(&initialHeapSize);
1783 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1785 HeapStats afterFree;
1786 clearOutOldGarbage(&afterFree);
1787 EXPECT_TRUE(initialHeapSize == afterFree);
1790 TEST(HeapTest, LargeObjects)
1792 HeapStats initialHeapSize;
1793 clearOutOldGarbage(&initialHeapSize);
1794 IntWrapper::s_destructorCalls = 0;
1795 LargeObject::s_destructorCalls = 0;
1797 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1798 Persistent<LargeObject> object = LargeObject::create();
1799 HeapStats afterAllocation;
1800 clearOutOldGarbage(&afterAllocation);
1802 object->set(0, 'a');
1803 EXPECT_EQ('a', object->get(0));
1804 object->set(object->length() - 1, 'b');
1805 EXPECT_EQ('b', object->get(object->length() - 1));
1806 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1807 size_t actualObjectSpace =
1808 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1809 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1810 // There is probably space for the IntWrapper in a heap page without
1811 // allocating extra pages. However, the IntWrapper allocation might cause
1812 // the addition of a heap page.
1813 size_t largeObjectAllocationSize =
1814 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1815 size_t allocatedSpaceLowerBound =
1816 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1817 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1818 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1819 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1820 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1821 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1822 for (int i = 0; i < 10; i++)
1823 object = LargeObject::create();
1825 HeapStats oneLargeObject;
1826 clearOutOldGarbage(&oneLargeObject);
1827 EXPECT_TRUE(oneLargeObject == afterAllocation);
1828 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1829 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1831 HeapStats backToInitial;
1832 clearOutOldGarbage(&backToInitial);
1833 EXPECT_TRUE(initialHeapSize == backToInitial);
1834 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1835 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1836 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1839 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1840 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1841 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1842 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1843 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1844 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1846 class Container : public GarbageCollected<Container> {
1848 static Container* create() { return new Container(); }
1849 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1850 HeapHashSet<Member<IntWrapper> > set;
1851 HeapHashSet<Member<IntWrapper> > set2;
1852 HeapVector<Member<IntWrapper>, 2> vector;
1853 HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1854 HeapVector<PairUnwrappedWrapped, 2> vectorUW;
1855 void trace(Visitor* visitor)
1857 visitor->trace(map);
1858 visitor->trace(set);
1859 visitor->trace(set2);
1860 visitor->trace(vector);
1864 struct ShouldBeTraced {
1865 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
1866 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
1867 Member<IntWrapper> m_wrapper;
1870 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
1872 static OffHeapContainer* create() { return new OffHeapContainer(); }
1876 m_deque1.append(ShouldBeTraced(IntWrapper::create(1)));
1877 m_vector1.append(ShouldBeTraced(IntWrapper::create(2)));
1878 m_deque2.append(IntWrapper::create(3));
1879 m_vector2.append(IntWrapper::create(4));
1880 m_hashSet.add(IntWrapper::create(5));
1881 m_hashMap.add(this, IntWrapper::create(6));
1882 m_listHashSet.add(IntWrapper::create(7));
1885 void trace(Visitor* visitor)
1887 visitor->trace(m_deque1);
1888 visitor->trace(m_vector1);
1889 visitor->trace(m_deque2);
1890 visitor->trace(m_vector2);
1891 visitor->trace(m_hashSet);
1892 visitor->trace(m_hashMap);
1893 visitor->trace(m_listHashSet);
1896 Deque<ShouldBeTraced> m_deque1;
1897 Vector<ShouldBeTraced> m_vector1;
1898 Deque<Member<IntWrapper> > m_deque2;
1899 Vector<Member<IntWrapper> > m_vector2;
1900 HashSet<Member<IntWrapper> > m_hashSet;
1901 HashMap<void*, Member<IntWrapper> > m_hashMap;
1902 ListHashSet<Member<IntWrapper> > m_listHashSet;
1906 // These class definitions test compile-time asserts with transition
1907 // types. They are therefore unused in test code and just need to
1908 // compile. This is intentional; do not delete the A and B classes below.
1909 class A : public WillBeGarbageCollectedMixin {
1912 class B : public NoBaseWillBeGarbageCollected<B>, public A {
1913 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
1915 void trace(Visitor*) { }
1918 TEST(HeapTest, HeapVectorFilledWithValue)
1920 IntWrapper* val = IntWrapper::create(1);
1921 HeapVector<Member<IntWrapper> > vector(10, val);
1922 EXPECT_EQ(10u, vector.size());
1923 for (size_t i = 0; i < vector.size(); i++)
1924 EXPECT_EQ(val, vector[i]);
1927 TEST(HeapTest, HeapVectorWithInlineCapacity)
1929 IntWrapper* one = IntWrapper::create(1);
1930 IntWrapper* two = IntWrapper::create(2);
1931 IntWrapper* three = IntWrapper::create(3);
1932 IntWrapper* four = IntWrapper::create(4);
1933 IntWrapper* five = IntWrapper::create(5);
1934 IntWrapper* six = IntWrapper::create(6);
1936 HeapVector<Member<IntWrapper>, 2> vector;
1939 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1940 EXPECT_TRUE(vector.contains(one));
1941 EXPECT_TRUE(vector.contains(two));
1943 vector.append(three);
1944 vector.append(four);
1945 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1946 EXPECT_TRUE(vector.contains(one));
1947 EXPECT_TRUE(vector.contains(two));
1948 EXPECT_TRUE(vector.contains(three));
1949 EXPECT_TRUE(vector.contains(four));
1952 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1953 EXPECT_TRUE(vector.contains(one));
1954 EXPECT_FALSE(vector.contains(two));
1955 EXPECT_FALSE(vector.contains(three));
1956 EXPECT_FALSE(vector.contains(four));
1959 HeapVector<Member<IntWrapper>, 2> vector1;
1960 HeapVector<Member<IntWrapper>, 2> vector2;
1962 vector1.append(one);
1963 vector2.append(two);
1964 vector1.swap(vector2);
1965 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1966 EXPECT_TRUE(vector1.contains(two));
1967 EXPECT_TRUE(vector2.contains(one));
1970 HeapVector<Member<IntWrapper>, 2> vector1;
1971 HeapVector<Member<IntWrapper>, 2> vector2;
1973 vector1.append(one);
1974 vector1.append(two);
1975 vector2.append(three);
1976 vector2.append(four);
1977 vector2.append(five);
1978 vector2.append(six);
1979 vector1.swap(vector2);
1980 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1981 EXPECT_TRUE(vector1.contains(three));
1982 EXPECT_TRUE(vector1.contains(four));
1983 EXPECT_TRUE(vector1.contains(five));
1984 EXPECT_TRUE(vector1.contains(six));
1985 EXPECT_TRUE(vector2.contains(one));
1986 EXPECT_TRUE(vector2.contains(two));
1990 TEST(HeapTest, HeapCollectionTypes)
1992 HeapStats initialHeapSize;
1993 IntWrapper::s_destructorCalls = 0;
1995 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
1996 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
1997 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
1999 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2000 typedef HeapHashSet<WeakMember<IntWrapper> > WeakMemberSet;
2002 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2004 typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2005 typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2007 Persistent<MemberMember> memberMember = new MemberMember();
2008 Persistent<MemberMember> memberMember2 = new MemberMember();
2009 Persistent<MemberMember> memberMember3 = new MemberMember();
2010 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2011 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2012 Persistent<MemberSet> set = new MemberSet();
2013 Persistent<MemberSet> set2 = new MemberSet();
2014 Persistent<MemberVector> vector = new MemberVector();
2015 Persistent<MemberVector> vector2 = new MemberVector();
2016 Persistent<VectorWU> vectorWU = new VectorWU();
2017 Persistent<VectorWU> vectorWU2 = new VectorWU();
2018 Persistent<VectorUW> vectorUW = new VectorUW();
2019 Persistent<VectorUW> vectorUW2 = new VectorUW();
2020 Persistent<Container> container = Container::create();
2022 clearOutOldGarbage(&initialHeapSize);
2024 Persistent<IntWrapper> one(IntWrapper::create(1));
2025 Persistent<IntWrapper> two(IntWrapper::create(2));
2026 Persistent<IntWrapper> oneB(IntWrapper::create(1));
2027 Persistent<IntWrapper> twoB(IntWrapper::create(2));
2028 Persistent<IntWrapper> oneC(IntWrapper::create(1));
2029 Persistent<IntWrapper> oneD(IntWrapper::create(1));
2031 IntWrapper* three(IntWrapper::create(3));
2032 IntWrapper* four(IntWrapper::create(4));
2033 IntWrapper* threeB(IntWrapper::create(3));
2034 IntWrapper* fourB(IntWrapper::create(4));
2035 IntWrapper* threeC(IntWrapper::create(3));
2036 IntWrapper* fourC(IntWrapper::create(4));
2037 IntWrapper* fiveC(IntWrapper::create(5));
2038 IntWrapper* threeD(IntWrapper::create(3));
2039 IntWrapper* fourD(IntWrapper::create(4));
2040 IntWrapper* fiveD(IntWrapper::create(5));
2042 // Member Collections.
2043 memberMember2->add(one, two);
2044 memberMember2->add(two, three);
2045 memberMember2->add(three, four);
2046 memberMember2->add(four, one);
2047 primitiveMember->add(1, two);
2048 primitiveMember->add(2, three);
2049 primitiveMember->add(3, four);
2050 primitiveMember->add(4, one);
2051 memberPrimitive->add(one, 2);
2052 memberPrimitive->add(two, 3);
2053 memberPrimitive->add(three, 4);
2054 memberPrimitive->add(four, 1);
2060 vector->append(oneB);
2061 vector2->append(threeB);
2062 vector2->append(fourB);
2063 vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2064 vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2065 vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2066 vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2067 vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2068 vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2069 vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2070 vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2072 // Collect garbage. This should change nothing since we are keeping
2073 // alive the IntWrapper objects with on-stack pointers.
2074 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2075 EXPECT_EQ(0u, memberMember->size());
2076 EXPECT_EQ(4u, memberMember2->size());
2077 EXPECT_EQ(4u, primitiveMember->size());
2078 EXPECT_EQ(4u, memberPrimitive->size());
2079 EXPECT_EQ(1u, set->size());
2080 EXPECT_EQ(4u, set2->size());
2081 EXPECT_EQ(1u, vector->size());
2082 EXPECT_EQ(2u, vector2->size());
2083 EXPECT_EQ(1u, vectorWU->size());
2084 EXPECT_EQ(3u, vectorWU2->size());
2085 EXPECT_EQ(1u, vectorUW->size());
2086 EXPECT_EQ(3u, vectorUW2->size());
2088 MemberVector& cvec = container->vector;
2089 cvec.swap(*vector.get());
2090 vector2->swap(cvec);
2093 VectorWU& cvecWU = container->vectorWU;
2094 cvecWU.swap(*vectorWU.get());
2095 vectorWU2->swap(cvecWU);
2096 vectorWU->swap(cvecWU);
2098 VectorUW& cvecUW = container->vectorUW;
2099 cvecUW.swap(*vectorUW.get());
2100 vectorUW2->swap(cvecUW);
2101 vectorUW->swap(cvecUW);
2103 // Swap set and set2 in a roundabout way.
2104 MemberSet& cset1 = container->set;
2105 MemberSet& cset2 = container->set2;
2113 container->map.swap(memberMember2);
2114 MemberMember& containedMap = container->map;
2115 memberMember3->swap(containedMap);
2116 memberMember3->swap(memberMember);
2118 EXPECT_TRUE(memberMember->get(one) == two);
2119 EXPECT_TRUE(memberMember->get(two) == three);
2120 EXPECT_TRUE(memberMember->get(three) == four);
2121 EXPECT_TRUE(memberMember->get(four) == one);
2122 EXPECT_TRUE(primitiveMember->get(1) == two);
2123 EXPECT_TRUE(primitiveMember->get(2) == three);
2124 EXPECT_TRUE(primitiveMember->get(3) == four);
2125 EXPECT_TRUE(primitiveMember->get(4) == one);
2126 EXPECT_EQ(1, memberPrimitive->get(four));
2127 EXPECT_EQ(2, memberPrimitive->get(one));
2128 EXPECT_EQ(3, memberPrimitive->get(two));
2129 EXPECT_EQ(4, memberPrimitive->get(three));
2130 EXPECT_TRUE(set->contains(one));
2131 EXPECT_TRUE(set->contains(two));
2132 EXPECT_TRUE(set->contains(three));
2133 EXPECT_TRUE(set->contains(four));
2134 EXPECT_TRUE(set2->contains(oneB));
2135 EXPECT_TRUE(vector->contains(threeB));
2136 EXPECT_TRUE(vector->contains(fourB));
2137 EXPECT_TRUE(vector2->contains(oneB));
2138 EXPECT_FALSE(vector2->contains(threeB));
2139 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2140 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2141 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2142 EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2143 EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2144 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2145 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2146 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2147 EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2148 EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2151 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2153 EXPECT_EQ(4u, memberMember->size());
2154 EXPECT_EQ(0u, memberMember2->size());
2155 EXPECT_EQ(4u, primitiveMember->size());
2156 EXPECT_EQ(4u, memberPrimitive->size());
2157 EXPECT_EQ(4u, set->size());
2158 EXPECT_EQ(1u, set2->size());
2159 EXPECT_EQ(2u, vector->size());
2160 EXPECT_EQ(1u, vector2->size());
2161 EXPECT_EQ(3u, vectorUW->size());
2162 EXPECT_EQ(1u, vector2->size());
2164 EXPECT_TRUE(memberMember->get(one) == two);
2165 EXPECT_TRUE(primitiveMember->get(1) == two);
2166 EXPECT_TRUE(primitiveMember->get(4) == one);
2167 EXPECT_EQ(2, memberPrimitive->get(one));
2168 EXPECT_EQ(3, memberPrimitive->get(two));
2169 EXPECT_TRUE(set->contains(one));
2170 EXPECT_TRUE(set->contains(two));
2171 EXPECT_FALSE(set->contains(oneB));
2172 EXPECT_TRUE(set2->contains(oneB));
2173 EXPECT_EQ(3, vector->at(0)->value());
2174 EXPECT_EQ(4, vector->at(1)->value());
2177 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2178 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2180 EXPECT_EQ(4u, memberMember->size());
2181 EXPECT_EQ(4u, primitiveMember->size());
2182 EXPECT_EQ(4u, memberPrimitive->size());
2183 EXPECT_EQ(4u, set->size());
2184 EXPECT_EQ(1u, set2->size());
2185 EXPECT_EQ(2u, vector->size());
2186 EXPECT_EQ(1u, vector2->size());
2187 EXPECT_EQ(3u, vectorWU->size());
2188 EXPECT_EQ(1u, vectorWU2->size());
2189 EXPECT_EQ(3u, vectorUW->size());
2190 EXPECT_EQ(1u, vectorUW2->size());
2193 template<typename T>
2194 void MapIteratorCheck(T& it, const T& end, int expected)
2199 int key = it->key->value();
2200 int value = it->value->value();
2201 EXPECT_TRUE(key >= 0 && key < 1100);
2202 EXPECT_TRUE(value >= 0 && value < 1100);
2205 EXPECT_EQ(expected, found);
2208 template<typename T>
2209 void SetIteratorCheck(T& it, const T& end, int expected)
2214 int value = (*it)->value();
2215 EXPECT_TRUE(value >= 0 && value < 1100);
2218 EXPECT_EQ(expected, found);
2221 TEST(HeapTest, HeapWeakCollectionSimple)
2224 IntWrapper::s_destructorCalls = 0;
2226 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2228 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2229 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2230 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2231 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2233 Persistent<WeakStrong> weakStrong = new WeakStrong();
2234 Persistent<StrongWeak> strongWeak = new StrongWeak();
2235 Persistent<WeakWeak> weakWeak = new WeakWeak();
2236 Persistent<WeakSet> weakSet = new WeakSet();
2238 Persistent<IntWrapper> two = IntWrapper::create(2);
2240 keepNumbersAlive.append(IntWrapper::create(103));
2241 keepNumbersAlive.append(IntWrapper::create(10));
2244 weakStrong->add(IntWrapper::create(1), two);
2245 strongWeak->add(two, IntWrapper::create(1));
2246 weakWeak->add(two, IntWrapper::create(42));
2247 weakWeak->add(IntWrapper::create(42), two);
2248 weakSet->add(IntWrapper::create(0));
2250 weakSet->add(keepNumbersAlive[0]);
2251 weakSet->add(keepNumbersAlive[1]);
2252 EXPECT_EQ(1u, weakStrong->size());
2253 EXPECT_EQ(1u, strongWeak->size());
2254 EXPECT_EQ(2u, weakWeak->size());
2255 EXPECT_EQ(4u, weakSet->size());
2258 keepNumbersAlive[0] = nullptr;
2260 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2262 EXPECT_EQ(0u, weakStrong->size());
2263 EXPECT_EQ(0u, strongWeak->size());
2264 EXPECT_EQ(0u, weakWeak->size());
2265 EXPECT_EQ(2u, weakSet->size());
2268 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2269 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2270 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2271 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2274 Persistent<WeakStrongSet>& weakStrong,
2275 Persistent<StrongWeakSet>& strongWeak,
2276 Persistent<WeakUnwrappedSet>& weakUnwrapped,
2277 Persistent<UnwrappedWeakSet>& unwrappedWeak,
2279 Persistent<IntWrapper>& two)
2281 WeakStrongSet::iterator itWS = weakStrong->begin();
2282 StrongWeakSet::iterator itSW = strongWeak->begin();
2283 WeakUnwrappedSet::iterator itWU = weakUnwrapped->begin();
2284 UnwrappedWeakSet::iterator itUW = unwrappedWeak->begin();
2286 EXPECT_EQ(2u, weakStrong->size());
2287 EXPECT_EQ(2u, strongWeak->size());
2288 EXPECT_EQ(2u, weakUnwrapped->size());
2289 EXPECT_EQ(2u, unwrappedWeak->size());
2291 PairWeakStrong p = *itWS;
2292 PairStrongWeak p2 = *itSW;
2293 PairWeakUnwrapped p3 = *itWU;
2294 PairUnwrappedWeak p4 = *itUW;
2295 if (p.first == two && p.second == two)
2297 if (p2.first == two && p2.second == two)
2299 if (p3.first == two && p3.second == 2)
2301 if (p4.first == 2 && p4.second == two)
2307 IntWrapper* nullWrapper = 0;
2309 EXPECT_EQ(p.first->value(), 1);
2310 EXPECT_EQ(p2.second->value(), 1);
2311 EXPECT_EQ(p3.first->value(), 1);
2312 EXPECT_EQ(p4.second->value(), 1);
2314 EXPECT_EQ(p.first, nullWrapper);
2315 EXPECT_EQ(p2.second, nullWrapper);
2316 EXPECT_EQ(p3.first, nullWrapper);
2317 EXPECT_EQ(p4.second, nullWrapper);
2320 EXPECT_EQ(p.second->value(), 2);
2321 EXPECT_EQ(p2.first->value(), 2);
2322 EXPECT_EQ(p3.second, 2);
2323 EXPECT_EQ(p4.first, 2);
2325 EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2326 EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2327 EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2328 EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2331 TEST(HeapTest, HeapWeakPairs)
2333 IntWrapper::s_destructorCalls = 0;
2335 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2337 Persistent<WeakStrongSet> weakStrong = new WeakStrongSet();
2338 Persistent<StrongWeakSet> strongWeak = new StrongWeakSet();
2339 Persistent<WeakUnwrappedSet> weakUnwrapped = new WeakUnwrappedSet();
2340 Persistent<UnwrappedWeakSet> unwrappedWeak = new UnwrappedWeakSet();
2342 Persistent<IntWrapper> two = IntWrapper::create(2);
2344 weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2345 weakStrong->add(PairWeakStrong(&*two, &*two));
2346 strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2347 strongWeak->add(PairStrongWeak(&*two, &*two));
2348 weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2349 weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2350 unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2351 unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2353 checkPairSets(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2355 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2356 checkPairSets(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2359 TEST(HeapTest, HeapWeakCollectionTypes)
2361 HeapStats initialHeapSize;
2362 IntWrapper::s_destructorCalls = 0;
2364 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2365 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2366 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2367 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2369 clearOutOldGarbage(&initialHeapSize);
2371 const int weakStrongIndex = 0;
2372 const int strongWeakIndex = 1;
2373 const int weakWeakIndex = 2;
2374 const int numberOfMapIndices = 3;
2375 const int weakSetIndex = 3;
2376 const int numberOfCollections = 4;
2378 for (int testRun = 0; testRun < 4; testRun++) {
2379 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2380 bool testThatIteratorsMakeStrong = (testRun == weakSetIndex);
2381 bool deleteAfterwards = (testRun == 1);
2382 bool addAfterwards = (testRun == weakWeakIndex);
2384 // The test doesn't work for strongWeak with deleting because we lost
2385 // the key from the keepNumbersAlive array, so we can't do the lookup.
2386 if (deleteAfterwards && collectionNumber == strongWeakIndex)
2389 unsigned added = addAfterwards ? 100 : 0;
2391 Persistent<WeakStrong> weakStrong = new WeakStrong();
2392 Persistent<StrongWeak> strongWeak = new StrongWeak();
2393 Persistent<WeakWeak> weakWeak = new WeakWeak();
2395 Persistent<WeakSet> weakSet = new WeakSet();
2397 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2398 for (int i = 0; i < 128; i += 2) {
2399 IntWrapper* wrapped = IntWrapper::create(i);
2400 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
2401 keepNumbersAlive.append(wrapped);
2402 keepNumbersAlive.append(wrapped2);
2403 weakStrong->add(wrapped, wrapped2);
2404 strongWeak->add(wrapped2, wrapped);
2405 weakWeak->add(wrapped, wrapped2);
2406 weakSet->add(wrapped);
2409 EXPECT_EQ(64u, weakStrong->size());
2410 EXPECT_EQ(64u, strongWeak->size());
2411 EXPECT_EQ(64u, weakWeak->size());
2412 EXPECT_EQ(64u, weakSet->size());
2414 // Collect garbage. This should change nothing since we are keeping
2415 // alive the IntWrapper objects.
2416 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2418 EXPECT_EQ(64u, weakStrong->size());
2419 EXPECT_EQ(64u, strongWeak->size());
2420 EXPECT_EQ(64u, weakWeak->size());
2421 EXPECT_EQ(64u, weakSet->size());
2423 for (int i = 0; i < 128; i += 2) {
2424 IntWrapper* wrapped = keepNumbersAlive[i];
2425 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
2426 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
2427 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
2428 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
2429 EXPECT_TRUE(weakSet->contains(wrapped));
2432 for (int i = 0; i < 128; i += 3)
2433 keepNumbersAlive[i] = nullptr;
2435 if (collectionNumber != weakStrongIndex)
2436 weakStrong->clear();
2437 if (collectionNumber != strongWeakIndex)
2438 strongWeak->clear();
2439 if (collectionNumber != weakWeakIndex)
2441 if (collectionNumber != weakSetIndex)
2444 if (testThatIteratorsMakeStrong) {
2445 WeakStrong::iterator it1 = weakStrong->begin();
2446 StrongWeak::iterator it2 = strongWeak->begin();
2447 WeakWeak::iterator it3 = weakWeak->begin();
2448 WeakSet::iterator it4 = weakSet->begin();
2449 // Collect garbage. This should change nothing since the
2450 // iterators make the collections strong.
2451 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2452 if (collectionNumber == weakStrongIndex) {
2453 EXPECT_EQ(64u, weakStrong->size());
2454 MapIteratorCheck(it1, weakStrong->end(), 64);
2455 } else if (collectionNumber == strongWeakIndex) {
2456 EXPECT_EQ(64u, strongWeak->size());
2457 MapIteratorCheck(it2, strongWeak->end(), 64);
2458 } else if (collectionNumber == weakWeakIndex) {
2459 EXPECT_EQ(64u, weakWeak->size());
2460 MapIteratorCheck(it3, weakWeak->end(), 64);
2461 } else if (collectionNumber == weakSetIndex) {
2462 EXPECT_EQ(64u, weakSet->size());
2463 SetIteratorCheck(it4, weakSet->end(), 64);
2466 // Collect garbage. This causes weak processing to remove
2467 // things from the collections.
2468 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2470 for (int i = 0; i < 128; i += 2) {
2471 bool firstAlive = keepNumbersAlive[i];
2472 bool secondAlive = keepNumbersAlive[i + 1];
2473 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
2475 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
2476 if (collectionNumber == weakStrongIndex) {
2477 if (deleteAfterwards)
2478 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
2479 } else if (collectionNumber == strongWeakIndex) {
2480 if (deleteAfterwards)
2481 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
2482 } else if (collectionNumber == weakWeakIndex) {
2483 if (deleteAfterwards)
2484 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
2486 if (!deleteAfterwards)
2488 } else if (collectionNumber == weakSetIndex && firstAlive) {
2489 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
2490 if (deleteAfterwards)
2491 weakSet->remove(keepNumbersAlive[i]);
2496 if (addAfterwards) {
2497 for (int i = 1000; i < 1100; i++) {
2498 IntWrapper* wrapped = IntWrapper::create(i);
2499 keepNumbersAlive.append(wrapped);
2500 weakStrong->add(wrapped, wrapped);
2501 strongWeak->add(wrapped, wrapped);
2502 weakWeak->add(wrapped, wrapped);
2503 weakSet->add(wrapped);
2506 if (collectionNumber == weakStrongIndex)
2507 EXPECT_EQ(count + added, weakStrong->size());
2508 else if (collectionNumber == strongWeakIndex)
2509 EXPECT_EQ(count + added, strongWeak->size());
2510 else if (collectionNumber == weakWeakIndex)
2511 EXPECT_EQ(count + added, weakWeak->size());
2512 else if (collectionNumber == weakSetIndex)
2513 EXPECT_EQ(count + added, weakSet->size());
2514 WeakStrong::iterator it1 = weakStrong->begin();
2515 StrongWeak::iterator it2 = strongWeak->begin();
2516 WeakWeak::iterator it3 = weakWeak->begin();
2517 WeakSet::iterator it4 = weakSet->begin();
2518 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
2519 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
2520 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
2521 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
2523 for (unsigned i = 0; i < 128 + added; i++)
2524 keepNumbersAlive[i] = nullptr;
2525 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2526 EXPECT_EQ(added, weakStrong->size());
2527 EXPECT_EQ(added, strongWeak->size());
2528 EXPECT_EQ(added, weakWeak->size());
2529 EXPECT_EQ(added, weakSet->size());
2534 TEST(HeapTest, RefCountedGarbageCollected)
2536 RefCountedAndGarbageCollected::s_destructorCalls = 0;
2538 RefPtr<RefCountedAndGarbageCollected> refPtr3;
2540 Persistent<RefCountedAndGarbageCollected> persistent;
2542 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
2543 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
2544 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2545 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2546 persistent = refPtr1.get();
2548 // Reference count is zero for both objects but one of
2549 // them is kept alive by a persistent handle.
2550 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2551 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2552 refPtr3 = persistent;
2554 // The persistent handle is gone but the ref count has been
2556 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2557 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2559 // Both persistent handle is gone and ref count is zero so the
2560 // object can be collected.
2561 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2562 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
2565 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
2567 RefCountedAndGarbageCollected::s_destructorCalls = 0;
2568 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
2570 RefCountedAndGarbageCollected* pointer1 = 0;
2571 RefCountedAndGarbageCollected2* pointer2 = 0;
2573 RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
2574 RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
2575 pointer1 = object1.get();
2576 pointer2 = object2.get();
2577 void* objects[2] = { object1.get(), object2.get() };
2578 RefCountedGarbageCollectedVisitor visitor(2, objects);
2579 ThreadState::current()->visitPersistents(&visitor);
2580 EXPECT_TRUE(visitor.validate());
2582 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2583 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2584 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2586 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2587 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2588 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2590 // At this point, the reference counts of object1 and object2 are 0.
2591 // Only pointer1 and pointer2 keep references to object1 and object2.
2592 void* objects[] = { 0 };
2593 RefCountedGarbageCollectedVisitor visitor(0, objects);
2594 ThreadState::current()->visitPersistents(&visitor);
2595 EXPECT_TRUE(visitor.validate());
2598 RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
2599 RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
2600 void* objects[2] = { object1.get(), object2.get() };
2601 RefCountedGarbageCollectedVisitor visitor(2, objects);
2602 ThreadState::current()->visitPersistents(&visitor);
2603 EXPECT_TRUE(visitor.validate());
2605 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2606 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2607 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2610 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2611 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2612 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2615 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2616 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2617 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
2620 TEST(HeapTest, WeakMembers)
2624 Persistent<Bar> h1 = Bar::create();
2625 Persistent<Weak> h4;
2626 Persistent<WithWeakMember> h5;
2627 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2628 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
2630 Bar* h2 = Bar::create();
2631 Bar* h3 = Bar::create();
2632 h4 = Weak::create(h2, h3);
2633 h5 = WithWeakMember::create(h2, h3);
2634 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2635 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
2636 EXPECT_TRUE(h4->strongIsThere());
2637 EXPECT_TRUE(h4->weakIsThere());
2638 EXPECT_TRUE(h5->strongIsThere());
2639 EXPECT_TRUE(h5->weakIsThere());
2641 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
2642 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2643 EXPECT_EQ(4u, Bar::s_live);
2644 EXPECT_TRUE(h4->strongIsThere());
2645 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
2646 EXPECT_TRUE(h5->strongIsThere());
2647 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
2648 h1.release(); // Zero out h1.
2649 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2650 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
2651 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
2652 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
2654 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
2655 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2656 EXPECT_EQ(0u, Bar::s_live); // All gone.
2659 TEST(HeapTest, FinalizationObserver)
2661 Persistent<FinalizationObserver<Observable> > o;
2663 Observable* foo = Observable::create(Bar::create());
2664 // |o| observes |foo|.
2665 o = FinalizationObserver<Observable>::create(foo);
2667 // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
2668 // and its member will be collected.
2669 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2670 EXPECT_EQ(0u, Bar::s_live);
2671 EXPECT_TRUE(o->didCallWillFinalize());
2673 FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
2674 Observable* foo = Observable::create(Bar::create());
2675 FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
2676 EXPECT_EQ(1u, map.size());
2678 // FinalizationObserverWithHashMap doesn't have a strong reference to
2679 // |foo|. So |foo| and its member will be collected.
2680 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2681 EXPECT_EQ(0u, Bar::s_live);
2682 EXPECT_EQ(0u, map.size());
2683 EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
2686 TEST(HeapTest, Comparisons)
2688 Persistent<Bar> barPersistent = Bar::create();
2689 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
2690 EXPECT_TRUE(barPersistent != fooPersistent);
2691 barPersistent = fooPersistent;
2692 EXPECT_TRUE(barPersistent == fooPersistent);
2695 TEST(HeapTest, CheckAndMarkPointer)
2697 HeapStats initialHeapStats;
2698 clearOutOldGarbage(&initialHeapStats);
2700 Vector<Address> objectAddresses;
2701 Vector<Address> endAddresses;
2702 Address largeObjectAddress;
2703 Address largeObjectEndAddress;
2704 CountingVisitor visitor;
2705 for (int i = 0; i < 10; i++) {
2706 SimpleObject* object = SimpleObject::create();
2707 Address objectAddress = reinterpret_cast<Address>(object);
2708 objectAddresses.append(objectAddress);
2709 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
2711 LargeObject* largeObject = LargeObject::create();
2712 largeObjectAddress = reinterpret_cast<Address>(largeObject);
2713 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
2715 // This is a low-level test where we call checkAndMarkPointer. This method
2716 // causes the object start bitmap to be computed which requires the heap
2717 // to be in a consistent state (e.g. the free allocation area must be put
2718 // into a free list header). However when we call makeConsistentForGC it
2719 // also clears out the freelists so we have to rebuild those before trying
2720 // to allocate anything again. We do this by forcing a GC after doing the
2721 // checkAndMarkPointer tests.
2723 TestGCScope scope(ThreadState::HeapPointersOnStack);
2724 Heap::makeConsistentForGC();
2725 for (size_t i = 0; i < objectAddresses.size(); i++) {
2726 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
2727 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
2729 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
2731 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
2732 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
2733 EXPECT_EQ(2ul, visitor.count());
2736 // This forces a GC without stack scanning which results in the objects
2737 // being collected. This will also rebuild the above mentioned freelists,
2738 // however we don't rely on that below since we don't have any allocations.
2739 clearOutOldGarbage(&initialHeapStats);
2741 TestGCScope scope(ThreadState::HeapPointersOnStack);
2742 Heap::makeConsistentForGC();
2743 for (size_t i = 0; i < objectAddresses.size(); i++) {
2744 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
2745 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
2747 EXPECT_EQ(0ul, visitor.count());
2748 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
2749 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
2750 EXPECT_EQ(0ul, visitor.count());
2752 // This round of GC is important to make sure that the object start
2753 // bitmap are cleared out and that the free lists are rebuild.
2754 clearOutOldGarbage(&initialHeapStats);
2757 TEST(HeapTest, VisitOffHeapCollections)
2759 HeapStats initialHeapStats;
2760 clearOutOldGarbage(&initialHeapStats);
2761 IntWrapper::s_destructorCalls = 0;
2762 Persistent<OffHeapContainer> container = OffHeapContainer::create();
2763 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2764 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2765 container = nullptr;
2766 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2767 EXPECT_EQ(7, IntWrapper::s_destructorCalls);
2770 TEST(HeapTest, PersistentHeapCollectionTypes)
2772 HeapStats initialHeapSize;
2773 IntWrapper::s_destructorCalls = 0;
2775 typedef HeapVector<Member<IntWrapper> > Vec;
2776 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
2777 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
2778 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
2780 clearOutOldGarbage(&initialHeapSize);
2786 IntWrapper* one(IntWrapper::create(1));
2787 IntWrapper* two(IntWrapper::create(2));
2788 IntWrapper* three(IntWrapper::create(3));
2789 IntWrapper* four(IntWrapper::create(4));
2790 IntWrapper* five(IntWrapper::create(5));
2791 IntWrapper* six(IntWrapper::create(6));
2796 Vec* vec = new Vec();
2803 pMap.add(five, six);
2805 // Collect |vec| and |one|.
2807 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2808 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
2810 EXPECT_EQ(2u, pVec.size());
2811 EXPECT_TRUE(pVec.at(0) == two);
2812 EXPECT_TRUE(pVec.at(1) == three);
2814 EXPECT_EQ(1u, pSet.size());
2815 EXPECT_TRUE(pSet.contains(four));
2817 EXPECT_EQ(1u, pMap.size());
2818 EXPECT_TRUE(pMap.get(five) == six);
2821 // Collect previous roots.
2822 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2823 EXPECT_EQ(6, IntWrapper::s_destructorCalls);
2826 TEST(HeapTest, CollectionNesting)
2828 HeapStats initialStats;
2829 clearOutOldGarbage(&initialStats);
2830 void* key = &IntWrapper::s_destructorCalls;
2831 IntWrapper::s_destructorCalls = 0;
2832 typedef HeapVector<Member<IntWrapper> > IntVector;
2833 HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
2835 map->add(key, IntVector());
2837 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
2838 EXPECT_EQ(0u, map->get(key).size());
2840 it->value.append(IntWrapper::create(42));
2841 EXPECT_EQ(1u, map->get(key).size());
2843 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
2844 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2845 EXPECT_EQ(1u, map->get(key).size());
2846 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2849 TEST(heap, GarbageCollectedMixin)
2851 HeapStats initialHeapStats;
2852 clearOutOldGarbage(&initialHeapStats);
2854 Persistent<UseMixin> usemixin = UseMixin::create();
2855 ASSERT_EQ(0, UseMixin::s_traceCount);
2856 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2857 ASSERT_EQ(1, UseMixin::s_traceCount);
2859 Persistent<Mixin> mixin = usemixin;
2861 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2862 ASSERT_EQ(2, UseMixin::s_traceCount);
2865 TEST(HeapTest, CollectionNesting2)
2867 HeapStats initialStats;
2868 clearOutOldGarbage(&initialStats);
2869 void* key = &IntWrapper::s_destructorCalls;
2870 IntWrapper::s_destructorCalls = 0;
2871 typedef HeapHashSet<Member<IntWrapper> > IntSet;
2872 HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
2874 map->add(key, IntSet());
2876 HeapHashMap<void*, IntSet>::iterator it = map->find(key);
2877 EXPECT_EQ(0u, map->get(key).size());
2879 it->value.add(IntWrapper::create(42));
2880 EXPECT_EQ(1u, map->get(key).size());
2882 Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
2883 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2884 EXPECT_EQ(1u, map->get(key).size());
2885 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2888 TEST(HeapTest, CollectionNesting3)
2890 HeapStats initialStats;
2891 clearOutOldGarbage(&initialStats);
2892 IntWrapper::s_destructorCalls = 0;
2893 typedef HeapVector<Member<IntWrapper> > IntVector;
2894 HeapVector<IntVector>* vector = new HeapVector<IntVector>();
2896 vector->append(IntVector());
2898 HeapVector<IntVector>::iterator it = vector->begin();
2899 EXPECT_EQ(0u, it->size());
2901 it->append(IntWrapper::create(42));
2902 EXPECT_EQ(1u, it->size());
2904 Persistent<HeapVector<IntVector> > keepAlive(vector);
2905 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2906 EXPECT_EQ(1u, it->size());
2907 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2910 TEST(HeapTest, EmbeddedInVector)
2912 HeapStats initialStats;
2913 clearOutOldGarbage(&initialStats);
2914 SimpleFinalizedObject::s_destructorCalls = 0;
2916 PersistentHeapVector<VectorObject, 2> inlineVector;
2917 PersistentHeapVector<VectorObject> outlineVector;
2918 VectorObject i1, i2;
2919 inlineVector.append(i1);
2920 inlineVector.append(i2);
2922 VectorObject o1, o2;
2923 outlineVector.append(o1);
2924 outlineVector.append(o2);
2926 PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
2927 VectorObjectInheritedTrace it1, it2;
2928 vectorInheritedTrace.append(it1);
2929 vectorInheritedTrace.append(it2);
2931 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2932 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
2934 // Since VectorObjectNoTrace has no trace method it will
2935 // not be traced and hence be collected when doing GC.
2936 // We trace items in a collection braced on the item's
2937 // having a trace method. This is determined via the
2938 // NeedsTracing trait in wtf/TypeTraits.h.
2939 PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
2940 VectorObjectNoTrace n1, n2;
2941 vectorNoTrace.append(n1);
2942 vectorNoTrace.append(n2);
2943 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2944 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
2946 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2947 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
2950 TEST(HeapTest, RawPtrInHash)
2952 HashSet<RawPtr<int> > set;
2953 set.add(new int(42));
2954 set.add(new int(42));
2955 EXPECT_EQ(2u, set.size());
2956 for (HashSet<RawPtr<int> >::iterator it = set.begin(); it != set.end(); ++it)
2957 EXPECT_EQ(42, **it);
2960 TEST(HeapTest, HeapTerminatedArray)
2962 HeapStats initialHeapSize;
2963 clearOutOldGarbage(&initialHeapSize);
2964 IntWrapper::s_destructorCalls = 0;
2966 HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
2968 const size_t prefixSize = 4;
2969 const size_t suffixSize = 4;
2972 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
2973 builder.grow(prefixSize);
2974 for (size_t i = 0; i < prefixSize; i++)
2975 builder.append(TerminatedArrayItem(IntWrapper::create(i)));
2976 arr = builder.release();
2979 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2980 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2981 EXPECT_EQ(prefixSize, arr->size());
2982 for (size_t i = 0; i < prefixSize; i++)
2983 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
2986 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
2987 builder.grow(suffixSize);
2988 for (size_t i = 0; i < suffixSize; i++)
2989 builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
2990 arr = builder.release();
2993 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2994 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2995 EXPECT_EQ(prefixSize + suffixSize, arr->size());
2996 for (size_t i = 0; i < prefixSize + suffixSize; i++)
2997 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3000 Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3002 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3003 arr = persistentArr.get();
3004 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3005 EXPECT_EQ(prefixSize + suffixSize, arr->size());
3006 for (size_t i = 0; i < prefixSize + suffixSize; i++)
3007 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3011 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3012 EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3015 TEST(HeapTest, HeapLinkedStack)
3017 HeapStats initialHeapSize;
3018 clearOutOldGarbage(&initialHeapSize);
3019 IntWrapper::s_destructorCalls = 0;
3021 HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3023 const size_t stackSize = 10;
3025 for (size_t i = 0; i < stackSize; i++)
3026 stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3028 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3029 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3030 EXPECT_EQ(stackSize, stack->size());
3031 while (!stack->isEmpty()) {
3032 EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3036 Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3038 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3039 EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3040 EXPECT_EQ(0u, pStack->size());
3043 TEST(HeapTest, AllocationDuringFinalization)
3045 HeapStats initialHeapSize;
3046 clearOutOldGarbage(&initialHeapSize);
3047 IntWrapper::s_destructorCalls = 0;
3048 OneKiloByteObject::s_destructorCalls = 0;
3050 Persistent<IntWrapper> wrapper;
3051 new FinalizationAllocator(&wrapper);
3053 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3054 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3055 // Check that the wrapper allocated during finalization is not
3056 // swept away and zapped later in the same sweeping phase.
3057 EXPECT_EQ(42, wrapper->value());
3060 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3061 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3062 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3065 } // WebCore namespace