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/ThreadState.h"
36 #include "heap/Visitor.h"
38 #include <gtest/gtest.h>
44 explicit TestGCScope(ThreadState::StackState state)
45 : m_state(ThreadState::current())
46 , m_safePointScope(state)
48 m_state->checkThread();
49 ASSERT(!m_state->isInGC());
50 ThreadState::stopThreads();
57 ASSERT(!m_state->isInGC());
58 ThreadState::resumeThreads();
63 ThreadState::SafePointScope m_safePointScope;
66 static void getHeapStats(HeapStats* stats)
68 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
69 Heap::getStats(stats);
72 #define DEFINE_VISITOR_METHODS(Type) \
73 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
78 virtual bool isMarked(const Type*) OVERRIDE { return false; }
80 class CountingVisitor : public Visitor {
87 virtual void mark(const void* object, TraceCallback) OVERRIDE
93 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
95 ASSERT(header->payload());
99 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
101 ASSERT(header->payload());
105 virtual void registerWeakMembers(const void*, WeakPointerCallback) OVERRIDE { }
106 virtual bool isMarked(const void*) OVERRIDE { return false; }
108 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
110 size_t count() { return m_count; }
111 void reset() { m_count = 0; }
117 class SimpleObject : public GarbageCollected<SimpleObject> {
120 static SimpleObject* create() { return new SimpleObject(); }
121 void trace(Visitor*) { }
122 char getPayload(int i) { return payload[i]; }
128 #undef DEFINE_VISITOR_METHODS
130 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
133 static HeapTestSuperClass* create()
135 return new HeapTestSuperClass();
138 virtual ~HeapTestSuperClass()
143 static int s_destructorCalls;
144 void trace(Visitor*) { }
147 HeapTestSuperClass() { }
150 int HeapTestSuperClass::s_destructorCalls = 0;
152 class HeapTestOtherSuperClass {
157 static const size_t classMagic = 0xABCDDBCA;
159 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
161 static HeapTestSubClass* create()
163 return new HeapTestSubClass();
166 virtual ~HeapTestSubClass()
168 EXPECT_EQ(classMagic, m_magic);
172 static int s_destructorCalls;
176 HeapTestSubClass() : m_magic(classMagic) { }
178 const size_t m_magic;
181 int HeapTestSubClass::s_destructorCalls = 0;
183 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
188 for (int i = 0; i < s_arraySize; ++i) {
189 m_array[i] = i % 128;
193 int8_t at(size_t i) { return m_array[i]; }
194 void trace(Visitor*) { }
196 static const int s_arraySize = 1000;
197 int8_t m_array[s_arraySize];
200 // Do several GCs to make sure that later GCs don't free up old memory from
201 // previously run tests in this process.
202 static void clearOutOldGarbage(HeapStats* heapStats)
205 getHeapStats(heapStats);
206 size_t used = heapStats->totalObjectSpace();
207 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
208 getHeapStats(heapStats);
209 if (heapStats->totalObjectSpace() >= used)
214 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
217 static IntWrapper* create(int x)
219 return new IntWrapper(x);
222 virtual ~IntWrapper()
227 static int s_destructorCalls;
228 static void trace(Visitor*) { }
230 int value() const { return m_x; }
232 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
234 unsigned hash() { return IntHash<int>::hash(m_x); }
237 IntWrapper(int x) : m_x(x) { }
244 USED_FROM_MULTIPLE_THREADS(IntWrapper);
246 int IntWrapper::s_destructorCalls = 0;
248 class ThreadedHeapTester {
252 ThreadedHeapTester* tester = new ThreadedHeapTester();
253 for (int i = 0; i < numberOfThreads; i++)
254 createThread(&threadFunc, tester, "testing thread");
255 while (tester->m_threadsToFinish) {
256 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
262 static const int numberOfThreads = 10;
263 static const int gcPerThread = 5;
264 static const int numberOfAllocations = 50;
266 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
268 ThreadedHeapTester() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
272 static void threadFunc(void* data)
274 reinterpret_cast<ThreadedHeapTester*>(data)->runThread();
279 ThreadState::attach();
283 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
287 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
288 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
290 for (int i = 0; i < numberOfAllocations; i++) {
291 wrapper = IntWrapper::create(0x0bbac0de);
293 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
294 ThreadState::current()->safePoint(ThreadState::HeapPointersOnStack);
299 if (gcCount < gcPerThread) {
300 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
302 atomicIncrement(&m_gcCount);
305 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
306 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
310 ThreadState::current()->cleanup();
311 ThreadState::detach();
312 atomicDecrement(&m_threadsToFinish);
315 volatile int m_gcCount;
316 volatile int m_threadsToFinish;
319 // The accounting for memory includes the memory used by rounding up object
320 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
321 // have some slack in the tests.
323 void CheckWithSlack(T expected, T actual, int slack)
325 EXPECT_LE(expected, actual);
326 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
329 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
332 static TraceCounter* create()
334 return new TraceCounter();
337 void trace(Visitor*) { m_traceCount++; }
339 int traceCount() { return m_traceCount; }
350 class ClassWithMember : public GarbageCollected<ClassWithMember> {
353 static ClassWithMember* create()
355 return new ClassWithMember();
358 void trace(Visitor* visitor)
360 EXPECT_TRUE(visitor->isMarked(this));
362 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
364 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
366 visitor->trace(m_traceCounter);
369 int traceCount() { return m_traceCounter->traceCount(); }
373 : m_traceCounter(TraceCounter::create())
376 Member<TraceCounter> m_traceCounter;
379 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
382 static SimpleFinalizedObject* create()
384 return new SimpleFinalizedObject();
387 ~SimpleFinalizedObject()
392 static int s_destructorCalls;
394 void trace(Visitor*) { }
397 SimpleFinalizedObject() { }
400 int SimpleFinalizedObject::s_destructorCalls = 0;
402 class TestTypedHeapClass : public GarbageCollected<TestTypedHeapClass> {
405 static TestTypedHeapClass* create()
407 return new TestTypedHeapClass();
410 void trace(Visitor*) { }
413 TestTypedHeapClass() { }
416 class Bar : public GarbageCollectedFinalized<Bar> {
426 EXPECT_TRUE(m_magic == magic);
431 virtual void trace(Visitor* visitor) { }
432 static unsigned s_live;
435 static const int magic = 1337;
445 unsigned Bar::s_live = 0;
447 class Baz : public GarbageCollected<Baz> {
450 static Baz* create(Bar* bar)
455 void trace(Visitor* visitor)
457 visitor->trace(m_bar);
460 void clear() { m_bar.release(); }
463 explicit Baz(Bar* bar)
471 class Foo : public Bar {
473 static Foo* create(Bar* bar)
478 static Foo* create(Foo* foo)
483 virtual void trace(Visitor* visitor) OVERRIDE
486 visitor->mark(static_cast<Foo*>(m_bar));
488 visitor->mark(m_bar);
495 , m_pointsToFoo(false)
502 , m_pointsToFoo(true)
510 class Bars : public Bar {
512 static Bars* create()
517 virtual void trace(Visitor* visitor) OVERRIDE
519 for (unsigned i = 0; i < m_width; i++)
520 visitor->trace(m_bars[i]);
523 unsigned getWidth() const
528 static const unsigned width = 7500;
532 for (unsigned i = 0; i < width; i++) {
533 m_bars[i] = Bar::create();
539 Member<Bar> m_bars[width];
542 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
545 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
547 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
550 ConstructorAllocation()
552 m_intWrapper = IntWrapper::create(42);
555 Member<IntWrapper> m_intWrapper;
558 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
565 static LargeObject* create() { return new LargeObject(); }
566 char get(size_t i) { return m_data[i]; }
567 void set(size_t i, char c) { m_data[i] = c; }
568 size_t length() { return s_length; }
569 void trace(Visitor* visitor)
571 visitor->trace(m_intWrapper);
573 static int s_destructorCalls;
576 static const size_t s_length = 1024*1024;
579 m_intWrapper = IntWrapper::create(23);
581 Member<IntWrapper> m_intWrapper;
582 char m_data[s_length];
585 int LargeObject::s_destructorCalls = 0;
587 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
590 static PassRefPtr<RefCountedAndGarbageCollected> create()
592 return adoptRef(new RefCountedAndGarbageCollected());
595 ~RefCountedAndGarbageCollected()
600 void trace(Visitor*) { }
602 static int s_destructorCalls;
605 RefCountedAndGarbageCollected()
610 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
612 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
615 static RefCountedAndGarbageCollected2* create()
617 return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
620 ~RefCountedAndGarbageCollected2()
625 void trace(Visitor*) { }
627 static int s_destructorCalls;
630 RefCountedAndGarbageCollected2()
635 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
637 #define DEFINE_VISITOR_METHODS(Type) \
638 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
643 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
645 RefCountedGarbageCollectedVisitor(int expected, void** objects)
647 , m_expectedCount(expected)
648 , m_expectedObjects(objects)
652 void mark(const void* ptr) { markNoTrace(ptr); }
654 virtual void markNoTrace(const void* ptr)
658 if (m_count < m_expectedCount)
659 EXPECT_TRUE(expectedObject(ptr));
661 EXPECT_FALSE(expectedObject(ptr));
665 virtual void mark(const void* ptr, TraceCallback) OVERRIDE
670 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
672 mark(header->payload());
675 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
677 mark(header->payload());
680 bool validate() { return m_count >= m_expectedCount; }
681 void reset() { m_count = 0; }
683 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
686 bool expectedObject(const void* ptr)
688 for (int i = 0; i < m_expectedCount; i++) {
689 if (m_expectedObjects[i] == ptr)
697 void** m_expectedObjects;
700 #undef DEFINE_VISITOR_METHODS
702 class Weak : public Bar {
704 static Weak* create(Bar* strong, Bar* weak)
706 return new Weak(strong, weak);
709 virtual void trace(Visitor* visitor) OVERRIDE
711 visitor->trace(m_strongBar);
712 visitor->registerWeakMembers(this, zapWeakMembers);
715 static void zapWeakMembers(Visitor* visitor, void* self)
717 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
720 bool strongIsThere() { return !!m_strongBar; }
721 bool weakIsThere() { return !!m_weakBar; }
724 Weak(Bar* strongBar, Bar* weakBar)
726 , m_strongBar(strongBar)
731 void zapWeakMembers(Visitor* visitor)
733 if (m_weakBar && !visitor->isAlive(m_weakBar))
737 Member<Bar> m_strongBar;
741 class WithWeakMember : public Bar {
743 static WithWeakMember* create(Bar* strong, Bar* weak)
745 return new WithWeakMember(strong, weak);
748 virtual void trace(Visitor* visitor) OVERRIDE
750 visitor->trace(m_strongBar);
751 visitor->trace(m_weakBar);
754 bool strongIsThere() { return !!m_strongBar; }
755 bool weakIsThere() { return !!m_weakBar; }
758 WithWeakMember(Bar* strongBar, Bar* weakBar)
760 , m_strongBar(strongBar)
765 Member<Bar> m_strongBar;
766 WeakMember<Bar> m_weakBar;
772 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
775 static PassRefPtrWillBeRawPtr<PointsBack> create()
777 return adoptRefWillBeNoop(new PointsBack());
785 void setBackPointer(SuperClass* backPointer)
787 m_backPointer = backPointer;
790 SuperClass* backPointer() const { return m_backPointer; }
792 void trace(Visitor* visitor)
795 visitor->trace(m_backPointer);
799 static int s_aliveCount;
801 PointsBack() : m_backPointer(0)
806 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
809 int PointsBack::s_aliveCount = 0;
811 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
814 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
816 return adoptRefWillBeNoop(new SuperClass(pointsBack));
819 virtual ~SuperClass()
822 m_pointsBack->setBackPointer(0);
827 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
829 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
830 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
831 EXPECT_EQ(pointsBack, target->pointsBack());
832 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
835 virtual void trace(Visitor* visitor)
838 visitor->trace(m_pointsBack);
842 PointsBack* pointsBack() const { return m_pointsBack.get(); }
844 static int s_aliveCount;
846 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
847 : m_pointsBack(pointsBack)
849 m_pointsBack->setBackPointer(this);
854 RefPtrWillBeMember<PointsBack> m_pointsBack;
857 int SuperClass::s_aliveCount = 0;
858 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
861 SubData() { ++s_aliveCount; }
862 ~SubData() { --s_aliveCount; }
864 void trace(Visitor*) { }
866 static int s_aliveCount;
869 int SubData::s_aliveCount = 0;
871 class SubClass : public SuperClass {
873 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
875 return adoptRefWillBeNoop(new SubClass(pointsBack));
883 virtual void trace(Visitor* visitor)
886 SuperClass::trace(visitor);
887 visitor->trace(m_data);
891 static int s_aliveCount;
893 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
894 : SuperClass(pointsBack)
895 , m_data(adoptPtrWillBeNoop(new SubData()))
901 OwnPtrWillBeMember<SubData> m_data;
904 int SubClass::s_aliveCount = 0;
906 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
909 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
911 return adoptRefCountedWillBeRefCountedGarbageCollected(new TransitionRefCounted());
914 ~TransitionRefCounted()
919 void trace(Visitor* visitor) { }
921 static int s_aliveCount;
924 TransitionRefCounted()
930 int TransitionRefCounted::s_aliveCount = 0;
932 TEST(HeapTest, Transition)
935 RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
936 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
937 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
938 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
940 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
941 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
943 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
944 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
945 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
946 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
947 EXPECT_EQ(2, PointsBack::s_aliveCount);
948 EXPECT_EQ(2, SuperClass::s_aliveCount);
949 EXPECT_EQ(1, SubClass::s_aliveCount);
950 EXPECT_EQ(1, SubData::s_aliveCount);
952 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
953 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
954 EXPECT_EQ(2, PointsBack::s_aliveCount);
955 EXPECT_EQ(2, SuperClass::s_aliveCount);
956 EXPECT_EQ(1, SubClass::s_aliveCount);
957 EXPECT_EQ(1, SubData::s_aliveCount);
959 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
960 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
961 EXPECT_EQ(2, PointsBack::s_aliveCount);
962 EXPECT_EQ(1, SuperClass::s_aliveCount);
963 EXPECT_EQ(1, SubClass::s_aliveCount);
964 EXPECT_EQ(1, SubData::s_aliveCount);
965 EXPECT_EQ(0, pointsBack1->backPointer());
967 pointsBack1.release();
968 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
969 EXPECT_EQ(1, PointsBack::s_aliveCount);
970 EXPECT_EQ(1, SuperClass::s_aliveCount);
971 EXPECT_EQ(1, SubClass::s_aliveCount);
972 EXPECT_EQ(1, SubData::s_aliveCount);
974 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
975 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
976 EXPECT_EQ(1, PointsBack::s_aliveCount);
977 EXPECT_EQ(0, SuperClass::s_aliveCount);
978 EXPECT_EQ(0, SubClass::s_aliveCount);
979 EXPECT_EQ(0, SubData::s_aliveCount);
980 EXPECT_EQ(0, pointsBack2->backPointer());
982 pointsBack2.release();
983 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
984 EXPECT_EQ(0, PointsBack::s_aliveCount);
985 EXPECT_EQ(0, SuperClass::s_aliveCount);
986 EXPECT_EQ(0, SubClass::s_aliveCount);
987 EXPECT_EQ(0, SubData::s_aliveCount);
989 EXPECT_TRUE(superClass == subClass);
992 TEST(HeapTest, Threading)
994 ThreadedHeapTester::test();
997 TEST(HeapTest, BasicFunctionality)
1000 clearOutOldGarbage(&heapStats);
1004 // When the test starts there may already have been leaked some memory
1005 // on the heap, so we establish a base line.
1006 size_t baseLevel = heapStats.totalObjectSpace();
1007 bool testPagesAllocated = !baseLevel;
1008 if (testPagesAllocated)
1009 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1011 // This allocates objects on the general heap which should add a page of memory.
1012 uint8_t* alloc32(Heap::allocate<uint8_t>(32));
1014 memset(alloc32, 40, 32);
1015 uint8_t* alloc64(Heap::allocate<uint8_t>(64));
1017 memset(alloc64, 27, 64);
1021 getHeapStats(&heapStats);
1022 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1023 if (testPagesAllocated)
1024 EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1026 CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
1028 EXPECT_EQ(alloc32[0], 40);
1029 EXPECT_EQ(alloc32[31], 40);
1030 EXPECT_EQ(alloc64[0], 27);
1031 EXPECT_EQ(alloc64[63], 27);
1033 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1035 EXPECT_EQ(alloc32[0], 40);
1036 EXPECT_EQ(alloc32[31], 40);
1037 EXPECT_EQ(alloc64[0], 27);
1038 EXPECT_EQ(alloc64[63], 27);
1041 clearOutOldGarbage(&heapStats);
1044 size_t baseLevel = heapStats.totalObjectSpace();
1045 bool testPagesAllocated = !baseLevel;
1046 if (testPagesAllocated)
1047 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1049 const size_t big = 1008;
1050 Persistent<uint8_t> bigArea = Heap::allocate<uint8_t>(big);
1054 size_t persistentCount = 0;
1055 const size_t numPersistents = 100000;
1056 Persistent<uint8_t>* persistents[numPersistents];
1058 for (int i = 0; i < 1000; i++) {
1059 size_t size = 128 + i * 8;
1061 persistents[persistentCount++] = new Persistent<uint8_t>(Heap::allocate<uint8_t>(size));
1063 getHeapStats(&heapStats);
1064 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1065 if (testPagesAllocated)
1066 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1070 uint8_t* alloc32b(Heap::allocate<uint8_t>(32));
1072 memset(alloc32b, 40, 32);
1073 uint8_t* alloc64b(Heap::allocate<uint8_t>(64));
1075 memset(alloc64b, 27, 64);
1076 EXPECT_TRUE(alloc32b != alloc64b);
1079 getHeapStats(&heapStats);
1080 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1081 if (testPagesAllocated)
1082 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1085 clearOutOldGarbage(&heapStats);
1088 if (testPagesAllocated)
1089 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1091 Address bigAreaRaw = bigArea;
1092 // Clear the persistent, so that the big area will be garbage collected.
1094 clearOutOldGarbage(&heapStats);
1098 getHeapStats(&heapStats);
1099 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1100 if (testPagesAllocated)
1101 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1103 // Endless loop unless we eventually get the memory back that we just freed.
1105 Persistent<uint8_t>* alloc = new Persistent<uint8_t>(Heap::allocate<uint8_t>(big / 2));
1107 persistents[persistentCount++] = alloc;
1108 EXPECT_LT(persistentCount, numPersistents);
1110 if (bigAreaRaw == alloc->get())
1114 getHeapStats(&heapStats);
1115 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1116 if (testPagesAllocated)
1117 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1119 for (size_t i = 0; i < persistentCount; i++) {
1120 delete persistents[i];
1124 uint8_t* address = Heap::reallocate<uint8_t>(0, 100);
1125 for (int i = 0; i < 100; i++)
1127 address = Heap::reallocate<uint8_t>(address, 100000);
1128 for (int i = 0; i < 100; i++)
1129 EXPECT_EQ(address[i], i);
1130 address = Heap::reallocate<uint8_t>(address, 50);
1131 for (int i = 0; i < 50; i++)
1132 EXPECT_EQ(address[i], i);
1133 // This should be equivalent to free(address).
1134 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<uint8_t>(address, 0)), 0ul);
1135 // This should be equivalent to malloc(0).
1136 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<uint8_t>(0, 0)), 0ul);
1139 TEST(HeapTest, SimpleAllocation)
1141 HeapStats initialHeapStats;
1142 clearOutOldGarbage(&initialHeapStats);
1143 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1145 // Allocate an object in the heap.
1146 HeapAllocatedArray* array = new HeapAllocatedArray();
1147 HeapStats statsAfterAllocation;
1148 getHeapStats(&statsAfterAllocation);
1149 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1151 // Sanity check of the contents in the heap.
1152 EXPECT_EQ(0, array->at(0));
1153 EXPECT_EQ(42, array->at(42));
1154 EXPECT_EQ(0, array->at(128));
1155 EXPECT_EQ(999 % 128, array->at(999));
1158 TEST(HeapTest, SimplePersistent)
1160 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1161 EXPECT_EQ(0, traceCounter->traceCount());
1163 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1164 EXPECT_EQ(1, traceCounter->traceCount());
1166 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1167 EXPECT_EQ(0, classWithMember->traceCount());
1169 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1170 EXPECT_EQ(1, classWithMember->traceCount());
1171 EXPECT_EQ(2, traceCounter->traceCount());
1174 TEST(HeapTest, SimpleFinalization)
1177 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1178 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1179 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1180 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1183 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1184 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1187 TEST(HeapTest, Finalization)
1190 HeapTestSubClass* t1 = HeapTestSubClass::create();
1191 HeapTestSubClass* t2 = HeapTestSubClass::create();
1192 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1193 // FIXME(oilpan): Ignore unused variables.
1198 // Nothing is marked so the GC should free everything and call
1199 // the finalizer on all three objects.
1200 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1201 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1202 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1203 // Destructors not called again when GCing again.
1204 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1205 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1206 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1209 TEST(HeapTest, TypedHeapSanity)
1211 // We use TraceCounter for allocating an object on the general heap.
1212 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1213 Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create();
1214 EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get())),
1215 pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get())));
1218 TEST(HeapTest, NoAllocation)
1220 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1222 // Disallow allocation
1223 NoAllocationScope<AnyThread> noAllocationScope;
1224 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1226 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1229 TEST(HeapTest, Members)
1236 h1 = Baz::create(Bar::create());
1237 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1238 EXPECT_EQ(1u, Bar::s_live);
1239 h2 = Baz::create(Bar::create());
1240 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1241 EXPECT_EQ(2u, Bar::s_live);
1243 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1244 EXPECT_EQ(2u, Bar::s_live);
1246 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1247 EXPECT_EQ(1u, Bar::s_live);
1249 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1250 EXPECT_EQ(0u, Bar::s_live);
1253 TEST(HeapTest, MarkTest)
1257 Persistent<Bar> bar = Bar::create();
1258 EXPECT_TRUE(ThreadState::current()->contains(bar));
1259 EXPECT_EQ(1u, Bar::s_live);
1261 Foo* foo = Foo::create(bar);
1262 EXPECT_TRUE(ThreadState::current()->contains(foo));
1263 EXPECT_EQ(2u, Bar::s_live);
1264 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1265 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1266 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1267 EXPECT_EQ(2u, Bar::s_live);
1269 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1270 EXPECT_EQ(1u, Bar::s_live);
1272 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1273 EXPECT_EQ(0u, Bar::s_live);
1276 TEST(HeapTest, DeepTest)
1278 const unsigned depth = 100000;
1281 Bar* bar = Bar::create();
1282 EXPECT_TRUE(ThreadState::current()->contains(bar));
1283 Foo* foo = Foo::create(bar);
1284 EXPECT_TRUE(ThreadState::current()->contains(foo));
1285 EXPECT_EQ(2u, Bar::s_live);
1286 for (unsigned i = 0; i < depth; i++) {
1287 Foo* foo2 = Foo::create(foo);
1289 EXPECT_TRUE(ThreadState::current()->contains(foo));
1291 EXPECT_EQ(depth + 2, Bar::s_live);
1292 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1293 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1294 EXPECT_EQ(depth + 2, Bar::s_live);
1296 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1297 EXPECT_EQ(0u, Bar::s_live);
1300 TEST(HeapTest, WideTest)
1304 Bars* bars = Bars::create();
1305 unsigned width = Bars::width;
1306 EXPECT_EQ(width + 1, Bar::s_live);
1307 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1308 EXPECT_EQ(width + 1, Bar::s_live);
1309 // Use bars here to make sure that it will be on the stack
1310 // for the conservative stack scan to find.
1311 EXPECT_EQ(width, bars->getWidth());
1313 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1314 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1315 EXPECT_EQ(0u, Bar::s_live);
1318 TEST(HeapTest, HashMapOfMembers)
1320 HeapStats initialHeapSize;
1321 IntWrapper::s_destructorCalls = 0;
1323 clearOutOldGarbage(&initialHeapSize);
1328 DefaultHash<Member<IntWrapper> >::Hash,
1329 HashTraits<Member<IntWrapper> >,
1330 HashTraits<Member<IntWrapper> >,
1331 HeapAllocator> HeapObjectIdentityMap;
1333 HeapObjectIdentityMap* map(new HeapObjectIdentityMap());
1336 HeapStats afterSetWasCreated;
1337 getHeapStats(&afterSetWasCreated);
1338 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1340 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1342 getHeapStats(&afterGC);
1343 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1345 IntWrapper* one(IntWrapper::create(1));
1346 IntWrapper* anotherOne(IntWrapper::create(1));
1349 HeapStats afterOneAdd;
1350 getHeapStats(&afterOneAdd);
1351 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1353 HeapObjectIdentityMap::iterator it(map->begin());
1354 HeapObjectIdentityMap::iterator it2(map->begin());
1358 map->add(anotherOne, one);
1360 // the addition above can cause an allocation of a new
1361 // backing store. We therefore garbage collect before
1362 // taking the heap stats in order to get rid of the old
1364 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1365 HeapStats afterAddAndGC;
1366 getHeapStats(&afterAddAndGC);
1367 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1369 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1371 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1372 EXPECT_TRUE(map->contains(one));
1373 EXPECT_TRUE(map->contains(anotherOne));
1375 IntWrapper* gotten(map->get(one));
1376 EXPECT_EQ(gotten->value(), one->value());
1377 EXPECT_EQ(gotten, one);
1380 getHeapStats(&afterGC2);
1381 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1383 IntWrapper* dozen = 0;
1385 for (int i = 1; i < 1000; i++) { // 999 iterations.
1386 IntWrapper* iWrapper(IntWrapper::create(i));
1387 IntWrapper* iSquared(IntWrapper::create(i * i));
1388 map->add(iWrapper, iSquared);
1392 HeapStats afterAdding1000;
1393 getHeapStats(&afterAdding1000);
1394 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1396 IntWrapper* gross(map->get(dozen));
1397 EXPECT_EQ(gross->value(), 144);
1399 // This should clear out junk created by all the adds.
1400 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1402 getHeapStats(&afterGC3);
1403 EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1406 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1407 // The objects 'one', anotherOne, and the 999 other pairs.
1408 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1410 getHeapStats(&afterGC4);
1411 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1414 TEST(HeapTest, NestedAllocation)
1416 HeapStats initialHeapSize;
1417 clearOutOldGarbage(&initialHeapSize);
1419 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1421 HeapStats afterFree;
1422 clearOutOldGarbage(&afterFree);
1423 EXPECT_TRUE(initialHeapSize == afterFree);
1426 TEST(HeapTest, LargeObjects)
1428 HeapStats initialHeapSize;
1429 clearOutOldGarbage(&initialHeapSize);
1430 IntWrapper::s_destructorCalls = 0;
1431 LargeObject::s_destructorCalls = 0;
1433 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1434 Persistent<LargeObject> object = LargeObject::create();
1435 HeapStats afterAllocation;
1436 clearOutOldGarbage(&afterAllocation);
1438 object->set(0, 'a');
1439 EXPECT_EQ('a', object->get(0));
1440 object->set(object->length() - 1, 'b');
1441 EXPECT_EQ('b', object->get(object->length() - 1));
1442 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1443 size_t actualObjectSpace =
1444 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1445 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1446 // There is probably space for the IntWrapper in a heap page without
1447 // allocating extra pages. However, the IntWrapper allocation might cause
1448 // the addition of a heap page.
1449 size_t largeObjectAllocationSize =
1450 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1451 size_t allocatedSpaceLowerBound =
1452 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1453 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1454 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1455 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1456 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1457 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1458 for (int i = 0; i < 10; i++)
1459 object = LargeObject::create();
1461 HeapStats oneLargeObject;
1462 clearOutOldGarbage(&oneLargeObject);
1463 EXPECT_TRUE(oneLargeObject == afterAllocation);
1464 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1465 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1467 HeapStats backToInitial;
1468 clearOutOldGarbage(&backToInitial);
1469 EXPECT_TRUE(initialHeapSize == backToInitial);
1470 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1471 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1472 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1475 class Container : public GarbageCollected<Container> {
1478 static Container* create() { return new Container(); }
1479 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1480 HeapHashSet<Member<IntWrapper> > set;
1481 HeapHashSet<Member<IntWrapper> > set2;
1482 HeapVector<Member<IntWrapper>, 2> vector;
1483 void trace(Visitor* visitor)
1485 visitor->trace(map);
1486 visitor->trace(set);
1487 visitor->trace(set2);
1488 visitor->trace(vector);
1492 struct ShouldBeTraced {
1493 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
1494 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
1495 Member<IntWrapper> m_wrapper;
1498 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
1501 static OffHeapContainer* create() { return new OffHeapContainer(); }
1505 m_deque1.append(ShouldBeTraced(IntWrapper::create(1)));
1506 m_vector1.append(ShouldBeTraced(IntWrapper::create(2)));
1507 m_deque2.append(IntWrapper::create(3));
1508 m_vector2.append(IntWrapper::create(4));
1509 m_hashSet.add(IntWrapper::create(5));
1510 m_hashMap.add(this, IntWrapper::create(6));
1511 m_listHashSet.add(IntWrapper::create(7));
1514 void trace(Visitor* visitor)
1516 visitor->trace(m_deque1);
1517 visitor->trace(m_vector1);
1518 visitor->trace(m_deque2);
1519 visitor->trace(m_vector2);
1520 visitor->trace(m_hashSet);
1521 visitor->trace(m_hashMap);
1522 visitor->trace(m_listHashSet);
1525 Deque<ShouldBeTraced> m_deque1;
1526 Vector<ShouldBeTraced> m_vector1;
1527 Deque<Member<IntWrapper> > m_deque2;
1528 Vector<Member<IntWrapper> > m_vector2;
1529 HashSet<Member<IntWrapper> > m_hashSet;
1530 HashMap<void*, Member<IntWrapper> > m_hashMap;
1531 ListHashSet<Member<IntWrapper> > m_listHashSet;
1534 TEST(HeapTest, HeapVectorWithInlineCapacity)
1536 IntWrapper* one = IntWrapper::create(1);
1537 IntWrapper* two = IntWrapper::create(2);
1538 IntWrapper* three = IntWrapper::create(3);
1539 IntWrapper* four = IntWrapper::create(4);
1540 IntWrapper* five = IntWrapper::create(5);
1541 IntWrapper* six = IntWrapper::create(6);
1543 HeapVector<Member<IntWrapper>, 2> vector;
1546 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1547 EXPECT_TRUE(vector.contains(one));
1548 EXPECT_TRUE(vector.contains(two));
1550 vector.append(three);
1551 vector.append(four);
1552 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1553 EXPECT_TRUE(vector.contains(one));
1554 EXPECT_TRUE(vector.contains(two));
1555 EXPECT_TRUE(vector.contains(three));
1556 EXPECT_TRUE(vector.contains(four));
1559 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1560 EXPECT_TRUE(vector.contains(one));
1561 EXPECT_FALSE(vector.contains(two));
1562 EXPECT_FALSE(vector.contains(three));
1563 EXPECT_FALSE(vector.contains(four));
1566 HeapVector<Member<IntWrapper>, 2> vector1;
1567 HeapVector<Member<IntWrapper>, 2> vector2;
1569 vector1.append(one);
1570 vector2.append(two);
1571 vector1.swap(vector2);
1572 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1573 EXPECT_TRUE(vector1.contains(two));
1574 EXPECT_TRUE(vector2.contains(one));
1577 HeapVector<Member<IntWrapper>, 2> vector1;
1578 HeapVector<Member<IntWrapper>, 2> vector2;
1580 vector1.append(one);
1581 vector1.append(two);
1582 vector2.append(three);
1583 vector2.append(four);
1584 vector2.append(five);
1585 vector2.append(six);
1586 vector1.swap(vector2);
1587 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1588 EXPECT_TRUE(vector1.contains(three));
1589 EXPECT_TRUE(vector1.contains(four));
1590 EXPECT_TRUE(vector1.contains(five));
1591 EXPECT_TRUE(vector1.contains(six));
1592 EXPECT_TRUE(vector2.contains(one));
1593 EXPECT_TRUE(vector2.contains(two));
1597 TEST(HeapTest, HeapCollectionTypes)
1599 HeapStats initialHeapSize;
1600 IntWrapper::s_destructorCalls = 0;
1602 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
1603 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
1604 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
1606 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
1607 typedef HeapHashSet<WeakMember<IntWrapper> > WeakMemberSet;
1609 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
1611 Persistent<MemberMember> memberMember = new MemberMember();
1612 Persistent<MemberMember> memberMember2 = new MemberMember();
1613 Persistent<MemberMember> memberMember3 = new MemberMember();
1614 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
1615 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
1616 Persistent<MemberSet> set = new MemberSet();
1617 Persistent<MemberSet> set2 = new MemberSet();
1618 Persistent<MemberVector> vector = new MemberVector();
1619 Persistent<MemberVector> vector2 = new MemberVector();
1620 Persistent<Container> container = Container::create();
1622 clearOutOldGarbage(&initialHeapSize);
1624 Persistent<IntWrapper> one(IntWrapper::create(1));
1625 Persistent<IntWrapper> two(IntWrapper::create(2));
1626 Persistent<IntWrapper> oneB(IntWrapper::create(1));
1627 Persistent<IntWrapper> twoB(IntWrapper::create(2));
1628 Persistent<IntWrapper> oneC(IntWrapper::create(1));
1629 Persistent<IntWrapper> twoC(IntWrapper::create(2));
1631 IntWrapper* three(IntWrapper::create(3));
1632 IntWrapper* four(IntWrapper::create(4));
1633 IntWrapper* threeB(IntWrapper::create(3));
1634 IntWrapper* fourB(IntWrapper::create(4));
1636 // Member Collections.
1637 memberMember2->add(one, two);
1638 memberMember2->add(two, three);
1639 memberMember2->add(three, four);
1640 memberMember2->add(four, one);
1641 primitiveMember->add(1, two);
1642 primitiveMember->add(2, three);
1643 primitiveMember->add(3, four);
1644 primitiveMember->add(4, one);
1645 memberPrimitive->add(one, 2);
1646 memberPrimitive->add(two, 3);
1647 memberPrimitive->add(three, 4);
1648 memberPrimitive->add(four, 1);
1654 vector->append(oneB);
1655 vector2->append(threeB);
1656 vector2->append(fourB);
1658 // Collect garbage. This should change nothing since we are keeping
1659 // alive the IntWrapper objects with on-stack pointers.
1660 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1661 EXPECT_EQ(0u, memberMember->size());
1662 EXPECT_EQ(4u, memberMember2->size());
1663 EXPECT_EQ(4u, primitiveMember->size());
1664 EXPECT_EQ(4u, memberPrimitive->size());
1665 EXPECT_EQ(1u, set->size());
1666 EXPECT_EQ(4u, set2->size());
1667 EXPECT_EQ(1u, vector->size());
1668 EXPECT_EQ(2u, vector2->size());
1670 MemberVector& cvec = container->vector;
1671 cvec.swap(*vector.get());
1672 vector2->swap(cvec);
1675 // Swap set and set2 in a roundabout way.
1676 MemberSet& cset1 = container->set;
1677 MemberSet& cset2 = container->set2;
1685 container->map.swap(memberMember2);
1686 MemberMember& containedMap = container->map;
1687 memberMember3->swap(containedMap);
1688 memberMember3->swap(memberMember);
1690 EXPECT_TRUE(memberMember->get(one) == two);
1691 EXPECT_TRUE(memberMember->get(two) == three);
1692 EXPECT_TRUE(memberMember->get(three) == four);
1693 EXPECT_TRUE(memberMember->get(four) == one);
1694 EXPECT_TRUE(primitiveMember->get(1) == two);
1695 EXPECT_TRUE(primitiveMember->get(2) == three);
1696 EXPECT_TRUE(primitiveMember->get(3) == four);
1697 EXPECT_TRUE(primitiveMember->get(4) == one);
1698 EXPECT_EQ(1, memberPrimitive->get(four));
1699 EXPECT_EQ(2, memberPrimitive->get(one));
1700 EXPECT_EQ(3, memberPrimitive->get(two));
1701 EXPECT_EQ(4, memberPrimitive->get(three));
1702 EXPECT_TRUE(set->contains(one));
1703 EXPECT_TRUE(set->contains(two));
1704 EXPECT_TRUE(set->contains(three));
1705 EXPECT_TRUE(set->contains(four));
1706 EXPECT_TRUE(set2->contains(oneB));
1707 EXPECT_TRUE(vector->contains(threeB));
1708 EXPECT_TRUE(vector->contains(fourB));
1709 EXPECT_TRUE(vector2->contains(oneB));
1710 EXPECT_FALSE(vector2->contains(threeB));
1713 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1715 EXPECT_EQ(4u, memberMember->size());
1716 EXPECT_EQ(0u, memberMember2->size());
1717 EXPECT_EQ(4u, primitiveMember->size());
1718 EXPECT_EQ(4u, memberPrimitive->size());
1719 EXPECT_EQ(4u, set->size());
1720 EXPECT_EQ(1u, set2->size());
1721 EXPECT_EQ(2u, vector->size());
1722 EXPECT_EQ(1u, vector2->size());
1724 EXPECT_TRUE(memberMember->get(one) == two);
1725 EXPECT_TRUE(primitiveMember->get(1) == two);
1726 EXPECT_TRUE(primitiveMember->get(4) == one);
1727 EXPECT_EQ(2, memberPrimitive->get(one));
1728 EXPECT_EQ(3, memberPrimitive->get(two));
1729 EXPECT_TRUE(set->contains(one));
1730 EXPECT_TRUE(set->contains(two));
1731 EXPECT_FALSE(set->contains(oneB));
1732 EXPECT_TRUE(set2->contains(oneB));
1733 EXPECT_EQ(3, vector->at(0)->value());
1734 EXPECT_EQ(4, vector->at(1)->value());
1737 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1738 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1740 EXPECT_EQ(4u, memberMember->size());
1741 EXPECT_EQ(4u, primitiveMember->size());
1742 EXPECT_EQ(4u, memberPrimitive->size());
1743 EXPECT_EQ(4u, set->size());
1744 EXPECT_EQ(1u, set2->size());
1745 EXPECT_EQ(2u, vector->size());
1746 EXPECT_EQ(1u, vector2->size());
1747 EXPECT_EQ(2u, vector->size());
1748 EXPECT_EQ(1u, vector2->size());
1751 template<typename T>
1752 void MapIteratorCheck(T& it, const T& end, int expected)
1757 int key = it->key->value();
1758 int value = it->value->value();
1759 EXPECT_TRUE(key >= 0 && key < 1100);
1760 EXPECT_TRUE(value >= 0 && value < 1100);
1763 EXPECT_EQ(expected, found);
1766 template<typename T>
1767 void SetIteratorCheck(T& it, const T& end, int expected)
1772 int value = (*it)->value();
1773 EXPECT_TRUE(value >= 0 && value < 1100);
1776 EXPECT_EQ(expected, found);
1779 TEST(HeapTest, CollectionPersistent)
1782 clearOutOldGarbage(&empty);
1783 IntWrapper::s_destructorCalls = 0;
1785 CollectionPersistent<Vector<Member<IntWrapper> > > vector;
1786 CollectionPersistent<HashSet<Member<IntWrapper> > > set;
1787 CollectionPersistent<HashMap<Member<IntWrapper>, Member<IntWrapper> > > map;
1788 CollectionPersistent<ListHashSet<Member<IntWrapper> > > listSet;
1790 vector->append(IntWrapper::create(42));
1791 set->add(IntWrapper::create(103));
1792 map->add(IntWrapper::create(137), IntWrapper::create(139));
1793 listSet->add(IntWrapper::create(167));
1794 listSet->add(IntWrapper::create(671));
1795 listSet->add(IntWrapper::create(176));
1797 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1799 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1801 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1803 typedef HashSet<Member<IntWrapper> >::iterator SetIterator;
1804 typedef HashMap<Member<IntWrapper>, Member<IntWrapper> >::iterator MapIterator;
1805 typedef ListHashSet<Member<IntWrapper> >::iterator ListSetIterator;
1807 SetIterator setIterator = set->begin();
1808 MapIterator mapIterator = map->begin();
1809 ListSetIterator listSetIterator = listSet->begin();
1811 EXPECT_EQ(42, vector[0]->value());
1812 EXPECT_EQ(103, (*setIterator)->value());
1813 EXPECT_EQ(137, mapIterator->key->value());
1814 EXPECT_EQ(139, mapIterator->value->value());
1815 EXPECT_EQ(167, (*listSetIterator)->value());
1818 TEST(HeapTest, HeapWeakCollectionSimple)
1821 IntWrapper::s_destructorCalls = 0;
1823 CollectionPersistent<Vector<Member<IntWrapper> > > keepNumbersAlive;
1825 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
1826 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
1827 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
1828 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
1830 Persistent<WeakStrong> weakStrong = new WeakStrong();
1831 Persistent<StrongWeak> strongWeak = new StrongWeak();
1832 Persistent<WeakWeak> weakWeak = new WeakWeak();
1833 Persistent<WeakSet> weakSet = new WeakSet();
1835 Persistent<IntWrapper> two = IntWrapper::create(2);
1837 keepNumbersAlive->append(IntWrapper::create(103));
1838 keepNumbersAlive->append(IntWrapper::create(10));
1841 weakStrong->add(IntWrapper::create(1), two);
1842 strongWeak->add(two, IntWrapper::create(1));
1843 weakWeak->add(two, IntWrapper::create(42));
1844 weakWeak->add(IntWrapper::create(42), two);
1845 weakSet->add(IntWrapper::create(0));
1847 weakSet->add(keepNumbersAlive[0]);
1848 weakSet->add(keepNumbersAlive[1]);
1849 EXPECT_EQ(1u, weakStrong->size());
1850 EXPECT_EQ(1u, strongWeak->size());
1851 EXPECT_EQ(2u, weakWeak->size());
1852 EXPECT_EQ(4u, weakSet->size());
1855 keepNumbersAlive[0] = 0;
1857 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1859 EXPECT_EQ(0u, weakStrong->size());
1860 EXPECT_EQ(0u, strongWeak->size());
1861 EXPECT_EQ(0u, weakWeak->size());
1862 EXPECT_EQ(2u, weakSet->size());
1865 TEST(HeapTest, HeapWeakCollectionTypes)
1867 HeapStats initialHeapSize;
1868 IntWrapper::s_destructorCalls = 0;
1870 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
1871 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
1872 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
1873 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
1875 clearOutOldGarbage(&initialHeapSize);
1877 const int weakStrongIndex = 0;
1878 const int strongWeakIndex = 1;
1879 const int weakWeakIndex = 2;
1880 const int numberOfMapIndices = 3;
1881 const int weakSetIndex = 3;
1882 const int numberOfCollections = 4;
1884 for (int testRun = 0; testRun < 4; testRun++) {
1885 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
1886 bool testThatIteratorsMakeStrong = (testRun == weakSetIndex);
1887 bool deleteAfterwards = (testRun == 1);
1888 bool addAfterwards = (testRun == weakWeakIndex);
1890 // The test doesn't work for strongWeak with deleting because we lost
1891 // the key from the keepNumbersAlive array, so we can't do the lookup.
1892 if (deleteAfterwards && collectionNumber == strongWeakIndex)
1895 unsigned added = addAfterwards ? 100 : 0;
1897 Persistent<WeakStrong> weakStrong = new WeakStrong();
1898 Persistent<StrongWeak> strongWeak = new StrongWeak();
1899 Persistent<WeakWeak> weakWeak = new WeakWeak();
1901 Persistent<WeakSet> weakSet = new WeakSet();
1903 CollectionPersistent<Vector<Member<IntWrapper> > > keepNumbersAlive;
1904 for (int i = 0; i < 128; i += 2) {
1905 IntWrapper* wrapped = IntWrapper::create(i);
1906 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
1907 keepNumbersAlive->append(wrapped);
1908 keepNumbersAlive->append(wrapped2);
1909 weakStrong->add(wrapped, wrapped2);
1910 strongWeak->add(wrapped2, wrapped);
1911 weakWeak->add(wrapped, wrapped2);
1912 weakSet->add(wrapped);
1915 EXPECT_EQ(64u, weakStrong->size());
1916 EXPECT_EQ(64u, strongWeak->size());
1917 EXPECT_EQ(64u, weakWeak->size());
1918 EXPECT_EQ(64u, weakSet->size());
1920 // Collect garbage. This should change nothing since we are keeping
1921 // alive the IntWrapper objects.
1922 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1924 EXPECT_EQ(64u, weakStrong->size());
1925 EXPECT_EQ(64u, strongWeak->size());
1926 EXPECT_EQ(64u, weakWeak->size());
1927 EXPECT_EQ(64u, weakSet->size());
1929 for (int i = 0; i < 128; i += 2) {
1930 IntWrapper* wrapped = keepNumbersAlive[i];
1931 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
1932 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
1933 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
1934 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
1935 EXPECT_TRUE(weakSet->contains(wrapped));
1938 for (int i = 0; i < 128; i += 3)
1939 keepNumbersAlive[i] = 0;
1941 if (collectionNumber != weakStrongIndex)
1942 weakStrong->clear();
1943 if (collectionNumber != strongWeakIndex)
1944 strongWeak->clear();
1945 if (collectionNumber != weakWeakIndex)
1947 if (collectionNumber != weakSetIndex)
1950 if (testThatIteratorsMakeStrong) {
1951 WeakStrong::iterator it1 = weakStrong->begin();
1952 StrongWeak::iterator it2 = strongWeak->begin();
1953 WeakWeak::iterator it3 = weakWeak->begin();
1954 WeakSet::iterator it4 = weakSet->begin();
1955 // Collect garbage. This should change nothing since the
1956 // iterators make the collections strong.
1957 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1958 if (collectionNumber == weakStrongIndex) {
1959 EXPECT_EQ(64u, weakStrong->size());
1960 MapIteratorCheck(it1, weakStrong->end(), 64);
1961 } else if (collectionNumber == strongWeakIndex) {
1962 EXPECT_EQ(64u, strongWeak->size());
1963 MapIteratorCheck(it2, strongWeak->end(), 64);
1964 } else if (collectionNumber == weakWeakIndex) {
1965 EXPECT_EQ(64u, weakWeak->size());
1966 MapIteratorCheck(it3, weakWeak->end(), 64);
1967 } else if (collectionNumber == weakSetIndex) {
1968 EXPECT_EQ(64u, weakSet->size());
1969 SetIteratorCheck(it4, weakSet->end(), 64);
1972 // Collect garbage. This causes weak processing to remove
1973 // things from the collections.
1974 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1976 for (int i = 0; i < 128; i += 2) {
1977 bool firstAlive = keepNumbersAlive[i];
1978 bool secondAlive = keepNumbersAlive[i + 1];
1979 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
1981 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
1982 if (collectionNumber == weakStrongIndex) {
1983 if (deleteAfterwards)
1984 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
1985 } else if (collectionNumber == strongWeakIndex) {
1986 if (deleteAfterwards)
1987 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
1988 } else if (collectionNumber == weakWeakIndex) {
1989 if (deleteAfterwards)
1990 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
1992 if (!deleteAfterwards)
1994 } else if (collectionNumber == weakSetIndex && firstAlive) {
1995 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
1996 if (deleteAfterwards)
1997 weakSet->remove(keepNumbersAlive[i]);
2002 if (addAfterwards) {
2003 for (int i = 1000; i < 1100; i++) {
2004 IntWrapper* wrapped = IntWrapper::create(i);
2005 keepNumbersAlive->append(wrapped);
2006 weakStrong->add(wrapped, wrapped);
2007 strongWeak->add(wrapped, wrapped);
2008 weakWeak->add(wrapped, wrapped);
2009 weakSet->add(wrapped);
2012 if (collectionNumber == weakStrongIndex)
2013 EXPECT_EQ(count + added, weakStrong->size());
2014 else if (collectionNumber == strongWeakIndex)
2015 EXPECT_EQ(count + added, strongWeak->size());
2016 else if (collectionNumber == weakWeakIndex)
2017 EXPECT_EQ(count + added, weakWeak->size());
2018 else if (collectionNumber == weakSetIndex)
2019 EXPECT_EQ(count + added, weakSet->size());
2020 WeakStrong::iterator it1 = weakStrong->begin();
2021 StrongWeak::iterator it2 = strongWeak->begin();
2022 WeakWeak::iterator it3 = weakWeak->begin();
2023 WeakSet::iterator it4 = weakSet->begin();
2024 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
2025 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
2026 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
2027 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
2029 for (unsigned i = 0; i < 128 + added; i++)
2030 keepNumbersAlive[i] = 0;
2031 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2032 EXPECT_EQ(added, weakStrong->size());
2033 EXPECT_EQ(added, strongWeak->size());
2034 EXPECT_EQ(added, weakWeak->size());
2035 EXPECT_EQ(added, weakSet->size());
2040 TEST(HeapTest, RefCountedGarbageCollected)
2042 RefCountedAndGarbageCollected::s_destructorCalls = 0;
2044 RefPtr<RefCountedAndGarbageCollected> refPtr3;
2046 Persistent<RefCountedAndGarbageCollected> persistent;
2048 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
2049 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
2050 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2051 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2052 persistent = refPtr1.get();
2054 // Reference count is zero for both objects but one of
2055 // them is kept alive by a persistent handle.
2056 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2057 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2058 refPtr3 = persistent;
2060 // The persistent handle is gone but the ref count has been
2062 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2063 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2065 // Both persistent handle is gone and ref count is zero so the
2066 // object can be collected.
2067 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2068 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
2071 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
2073 RefCountedAndGarbageCollected::s_destructorCalls = 0;
2074 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
2076 RefCountedAndGarbageCollected* pointer1 = 0;
2077 RefCountedAndGarbageCollected2* pointer2 = 0;
2079 RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
2080 RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
2081 pointer1 = object1.get();
2082 pointer2 = object2.get();
2083 void* objects[2] = { object1.get(), object2.get() };
2084 RefCountedGarbageCollectedVisitor visitor(2, objects);
2085 ThreadState::current()->visitPersistents(&visitor);
2086 EXPECT_TRUE(visitor.validate());
2088 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2089 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2090 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2092 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2093 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2094 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2096 // At this point, the reference counts of object1 and object2 are 0.
2097 // Only pointer1 and pointer2 keep references to object1 and object2.
2098 void* objects[] = { 0 };
2099 RefCountedGarbageCollectedVisitor visitor(0, objects);
2100 ThreadState::current()->visitPersistents(&visitor);
2101 EXPECT_TRUE(visitor.validate());
2104 RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
2105 RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
2106 void* objects[2] = { object1.get(), object2.get() };
2107 RefCountedGarbageCollectedVisitor visitor(2, objects);
2108 ThreadState::current()->visitPersistents(&visitor);
2109 EXPECT_TRUE(visitor.validate());
2111 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2112 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2113 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2116 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2117 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2118 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2121 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2122 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2123 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
2126 TEST(HeapTest, WeakMembers)
2130 Persistent<Bar> h1 = Bar::create();
2131 Persistent<Weak> h4;
2132 Persistent<WithWeakMember> h5;
2133 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2134 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
2136 Bar* h2 = Bar::create();
2137 Bar* h3 = Bar::create();
2138 h4 = Weak::create(h2, h3);
2139 h5 = WithWeakMember::create(h2, h3);
2140 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2141 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
2142 EXPECT_TRUE(h4->strongIsThere());
2143 EXPECT_TRUE(h4->weakIsThere());
2144 EXPECT_TRUE(h5->strongIsThere());
2145 EXPECT_TRUE(h5->weakIsThere());
2147 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
2148 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2149 EXPECT_EQ(4u, Bar::s_live);
2150 EXPECT_TRUE(h4->strongIsThere());
2151 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
2152 EXPECT_TRUE(h5->strongIsThere());
2153 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
2154 h1.release(); // Zero out h1.
2155 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2156 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
2157 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
2158 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
2160 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
2161 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2162 EXPECT_EQ(0u, Bar::s_live); // All gone.
2165 TEST(HeapTest, Comparisons)
2167 Persistent<Bar> barPersistent = Bar::create();
2168 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
2169 EXPECT_TRUE(barPersistent != fooPersistent);
2170 barPersistent = fooPersistent;
2171 EXPECT_TRUE(barPersistent == fooPersistent);
2174 TEST(HeapTest, CheckAndMarkPointer)
2176 HeapStats initialHeapStats;
2177 clearOutOldGarbage(&initialHeapStats);
2179 Vector<Address> objectAddresses;
2180 Vector<Address> endAddresses;
2181 Address largeObjectAddress;
2182 Address largeObjectEndAddress;
2183 CountingVisitor visitor;
2184 for (int i = 0; i < 10; i++) {
2185 SimpleObject* object = SimpleObject::create();
2186 Address objectAddress = reinterpret_cast<Address>(object);
2187 objectAddresses.append(objectAddress);
2188 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
2190 LargeObject* largeObject = LargeObject::create();
2191 largeObjectAddress = reinterpret_cast<Address>(largeObject);
2192 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
2194 // This is a low-level test where we call checkAndMarkPointer. This method
2195 // causes the object start bitmap to be computed which requires the heap
2196 // to be in a consistent state (e.g. the free allocation area must be put
2197 // into a free list header). However when we call makeConsistentForGC it
2198 // also clears out the freelists so we have to rebuild those before trying
2199 // to allocate anything again. We do this by forcing a GC after doing the
2200 // checkAndMarkPointer tests.
2202 TestGCScope scope(ThreadState::HeapPointersOnStack);
2203 Heap::makeConsistentForGC();
2204 for (size_t i = 0; i < objectAddresses.size(); i++) {
2205 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
2206 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
2208 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
2210 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
2211 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
2212 EXPECT_EQ(2ul, visitor.count());
2215 // This forces a GC without stack scanning which results in the objects
2216 // being collected. This will also rebuild the above mentioned freelists,
2217 // however we don't rely on that below since we don't have any allocations.
2218 clearOutOldGarbage(&initialHeapStats);
2220 TestGCScope scope(ThreadState::HeapPointersOnStack);
2221 Heap::makeConsistentForGC();
2222 for (size_t i = 0; i < objectAddresses.size(); i++) {
2223 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
2224 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
2226 EXPECT_EQ(0ul, visitor.count());
2227 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
2228 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
2229 EXPECT_EQ(0ul, visitor.count());
2231 // This round of GC is important to make sure that the object start
2232 // bitmap are cleared out and that the free lists are rebuild.
2233 clearOutOldGarbage(&initialHeapStats);
2236 TEST(HeapTest, VisitOffHeapCollections)
2238 HeapStats initialHeapStats;
2239 clearOutOldGarbage(&initialHeapStats);
2240 IntWrapper::s_destructorCalls = 0;
2241 Persistent<OffHeapContainer> container = OffHeapContainer::create();
2242 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2243 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2245 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2246 EXPECT_EQ(7, IntWrapper::s_destructorCalls);
2249 TEST(HeapTest, PersistentHeapCollectionTypes)
2251 HeapStats initialHeapSize;
2252 IntWrapper::s_destructorCalls = 0;
2254 typedef HeapVector<Member<IntWrapper> > Vec;
2255 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
2256 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
2257 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
2259 clearOutOldGarbage(&initialHeapSize);
2265 IntWrapper* one(IntWrapper::create(1));
2266 IntWrapper* two(IntWrapper::create(2));
2267 IntWrapper* three(IntWrapper::create(3));
2268 IntWrapper* four(IntWrapper::create(4));
2269 IntWrapper* five(IntWrapper::create(5));
2270 IntWrapper* six(IntWrapper::create(6));
2275 Vec* vec = new Vec();
2282 pMap.add(five, six);
2284 // Collect |vec| and |one|.
2286 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2287 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
2289 EXPECT_EQ(2u, pVec.size());
2290 EXPECT_TRUE(pVec.at(0) == two);
2291 EXPECT_TRUE(pVec.at(1) == three);
2293 EXPECT_EQ(1u, pSet.size());
2294 EXPECT_TRUE(pSet.contains(four));
2296 EXPECT_EQ(1u, pMap.size());
2297 EXPECT_TRUE(pMap.get(five) == six);
2300 // Collect previous roots.
2301 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2302 EXPECT_EQ(6, IntWrapper::s_destructorCalls);
2305 DEFINE_GC_INFO(Bar);
2306 DEFINE_GC_INFO(Baz);
2307 DEFINE_GC_INFO(ClassWithMember);
2308 DEFINE_GC_INFO(ConstructorAllocation);
2309 DEFINE_GC_INFO(Container);
2310 DEFINE_GC_INFO(HeapAllocatedArray);
2311 DEFINE_GC_INFO(HeapTestSuperClass);
2312 DEFINE_GC_INFO(IntWrapper);
2313 DEFINE_GC_INFO(LargeObject);
2314 DEFINE_GC_INFO(OffHeapContainer);
2315 DEFINE_GC_INFO(PointsBack);
2316 DEFINE_GC_INFO(RefCountedAndGarbageCollected);
2317 DEFINE_GC_INFO(RefCountedAndGarbageCollected2);
2318 DEFINE_GC_INFO(SimpleFinalizedObject);
2319 DEFINE_GC_INFO(SimpleObject);
2320 DEFINE_GC_INFO(SuperClass);
2321 DEFINE_GC_INFO(SubData);
2322 DEFINE_GC_INFO(TestTypedHeapClass);
2323 DEFINE_GC_INFO(TraceCounter);
2324 DEFINE_GC_INFO(TransitionRefCounted);