Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / heap / HeapTest.cpp
1 /*
2  * Copyright (C) 2013 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30
31 #include "config.h"
32
33 #include "heap/Handle.h"
34 #include "heap/Heap.h"
35 #include "heap/ThreadState.h"
36 #include "heap/Visitor.h"
37
38 #include <gtest/gtest.h>
39
40 namespace WebCore {
41
42 class TestGCScope {
43 public:
44     explicit TestGCScope(ThreadState::StackState state)
45         : m_state(ThreadState::current())
46         , m_safePointScope(state)
47     {
48         m_state->checkThread();
49         ASSERT(!m_state->isInGC());
50         ThreadState::stopThreads();
51         m_state->enterGC();
52     }
53
54     ~TestGCScope()
55     {
56         m_state->leaveGC();
57         ASSERT(!m_state->isInGC());
58         ThreadState::resumeThreads();
59     }
60
61 private:
62     ThreadState* m_state;
63     ThreadState::SafePointScope m_safePointScope;
64 };
65
66 static void getHeapStats(HeapStats* stats)
67 {
68     TestGCScope scope(ThreadState::NoHeapPointersOnStack);
69     Heap::getStats(stats);
70 }
71
72 #define DEFINE_VISITOR_METHODS(Type)                                       \
73     virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
74     {                                                                      \
75         if (object)                                                        \
76             m_count++;                                                     \
77     }                                                                      \
78     virtual bool isMarked(const Type*) OVERRIDE { return false; }
79
80 class CountingVisitor : public Visitor {
81 public:
82     CountingVisitor()
83         : m_count(0)
84     {
85     }
86
87     virtual void mark(const void* object, TraceCallback) OVERRIDE
88     {
89         if (object)
90             m_count++;
91     }
92
93     virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
94     {
95         ASSERT(header->payload());
96         m_count++;
97     }
98
99     virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
100     {
101         ASSERT(header->payload());
102         m_count++;
103     }
104
105     virtual void registerWeakMembers(const void*, WeakPointerCallback) OVERRIDE { }
106     virtual bool isMarked(const void*) OVERRIDE { return false; }
107
108     FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
109
110     size_t count() { return m_count; }
111     void reset() { m_count = 0; }
112
113 private:
114     size_t m_count;
115 };
116
117 class SimpleObject : public GarbageCollected<SimpleObject> {
118     DECLARE_GC_INFO;
119 public:
120     static SimpleObject* create() { return new SimpleObject(); }
121     void trace(Visitor*) { }
122     char getPayload(int i) { return payload[i]; }
123 private:
124     SimpleObject() { }
125     char payload[64];
126 };
127
128 #undef DEFINE_VISITOR_METHODS
129
130 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
131     DECLARE_GC_INFO
132 public:
133     static HeapTestSuperClass* create()
134     {
135         return new HeapTestSuperClass();
136     }
137
138     virtual ~HeapTestSuperClass()
139     {
140         ++s_destructorCalls;
141     }
142
143     static int s_destructorCalls;
144     void trace(Visitor*) { }
145
146 protected:
147     HeapTestSuperClass() { }
148 };
149
150 int HeapTestSuperClass::s_destructorCalls = 0;
151
152 class HeapTestOtherSuperClass {
153 public:
154     int payload;
155 };
156
157 static const size_t classMagic = 0xABCDDBCA;
158
159 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
160 public:
161     static HeapTestSubClass* create()
162     {
163         return new HeapTestSubClass();
164     }
165
166     virtual ~HeapTestSubClass()
167     {
168         EXPECT_EQ(classMagic, m_magic);
169         ++s_destructorCalls;
170     }
171
172     static int s_destructorCalls;
173
174 private:
175
176     HeapTestSubClass() : m_magic(classMagic) { }
177
178     const size_t m_magic;
179 };
180
181 int HeapTestSubClass::s_destructorCalls = 0;
182
183 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
184     DECLARE_GC_INFO
185 public:
186     HeapAllocatedArray()
187     {
188         for (int i = 0; i < s_arraySize; ++i) {
189             m_array[i] = i % 128;
190         }
191     }
192
193     int8_t at(size_t i) { return m_array[i]; }
194     void trace(Visitor*) { }
195 private:
196     static const int s_arraySize = 1000;
197     int8_t m_array[s_arraySize];
198 };
199
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)
203 {
204     while (true) {
205         getHeapStats(heapStats);
206         size_t used = heapStats->totalObjectSpace();
207         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
208         getHeapStats(heapStats);
209         if (heapStats->totalObjectSpace() >= used)
210             break;
211     }
212 }
213
214 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
215     DECLARE_GC_INFO
216 public:
217     static IntWrapper* create(int x)
218     {
219         return new IntWrapper(x);
220     }
221
222     virtual ~IntWrapper()
223     {
224         ++s_destructorCalls;
225     }
226
227     static int s_destructorCalls;
228     static void trace(Visitor*) { }
229
230     int value() const { return m_x; }
231
232     bool operator==(const IntWrapper& other) const { return other.value() == value(); }
233
234     unsigned hash() { return IntHash<int>::hash(m_x); }
235
236 protected:
237     IntWrapper(int x) : m_x(x) { }
238
239 private:
240     IntWrapper();
241     int m_x;
242 };
243
244 USED_FROM_MULTIPLE_THREADS(IntWrapper);
245
246 int IntWrapper::s_destructorCalls = 0;
247
248 class ThreadedHeapTester {
249 public:
250     static void test()
251     {
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);
257             yield();
258         }
259     }
260
261 private:
262     static const int numberOfThreads = 10;
263     static const int gcPerThread = 5;
264     static const int numberOfAllocations = 50;
265
266     inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
267
268     ThreadedHeapTester() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
269     {
270     }
271
272     static void threadFunc(void* data)
273     {
274         reinterpret_cast<ThreadedHeapTester*>(data)->runThread();
275     }
276
277     void runThread()
278     {
279         ThreadState::attach();
280
281         int gcCount = 0;
282         while (!done()) {
283             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
284             {
285                 IntWrapper* wrapper;
286
287                 for (int i = 0; i < numberOfAllocations; i++) {
288                     wrapper = IntWrapper::create(0x0bbac0de);
289                     if (!(i % 10))
290                         ThreadState::current()->safePoint(ThreadState::HeapPointersOnStack);
291                     yield();
292                 }
293
294                 if (gcCount < gcPerThread) {
295                     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
296                     gcCount++;
297                     atomicIncrement(&m_gcCount);
298                 }
299
300                 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
301             }
302             yield();
303         }
304         ThreadState::detach();
305         atomicDecrement(&m_threadsToFinish);
306     }
307
308     volatile int m_gcCount;
309     volatile int m_threadsToFinish;
310 };
311
312 // The accounting for memory includes the memory used by rounding up object
313 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
314 // have some slack in the tests.
315 template<typename T>
316 void CheckWithSlack(T expected, T actual, int slack)
317 {
318     EXPECT_LE(expected, actual);
319     EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
320 }
321
322 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
323     DECLARE_GC_INFO
324 public:
325     static TraceCounter* create()
326     {
327         return new TraceCounter();
328     }
329
330     void trace(Visitor*) { m_traceCount++; }
331
332     int traceCount() { return m_traceCount; }
333
334 private:
335     TraceCounter()
336         : m_traceCount(0)
337     {
338     }
339
340     int m_traceCount;
341 };
342
343 class ClassWithMember : public GarbageCollected<ClassWithMember> {
344     DECLARE_GC_INFO
345 public:
346     static ClassWithMember* create()
347     {
348         return new ClassWithMember();
349     }
350
351     void trace(Visitor* visitor)
352     {
353         EXPECT_TRUE(visitor->isMarked(this));
354         if (!traceCount())
355             EXPECT_FALSE(visitor->isMarked(m_traceCounter));
356         else
357             EXPECT_TRUE(visitor->isMarked(m_traceCounter));
358
359         visitor->trace(m_traceCounter);
360     }
361
362     int traceCount() { return m_traceCounter->traceCount(); }
363
364 private:
365     ClassWithMember()
366         : m_traceCounter(TraceCounter::create())
367     { }
368
369     Member<TraceCounter> m_traceCounter;
370 };
371
372 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
373     DECLARE_GC_INFO
374 public:
375     static SimpleFinalizedObject* create()
376     {
377         return new SimpleFinalizedObject();
378     }
379
380     ~SimpleFinalizedObject()
381     {
382         ++s_destructorCalls;
383     }
384
385     static int s_destructorCalls;
386
387     void trace(Visitor*) { }
388
389 private:
390     SimpleFinalizedObject() { }
391 };
392
393 int SimpleFinalizedObject::s_destructorCalls = 0;
394
395 class TestTypedHeapClass : public GarbageCollected<TestTypedHeapClass> {
396     DECLARE_GC_INFO
397 public:
398     static TestTypedHeapClass* create()
399     {
400         return new TestTypedHeapClass();
401     }
402
403     void trace(Visitor*) { }
404
405 private:
406     TestTypedHeapClass() { }
407 };
408
409 class Bar : public GarbageCollectedFinalized<Bar> {
410     DECLARE_GC_INFO
411 public:
412     static Bar* create()
413     {
414         return new Bar();
415     }
416
417     void finalize()
418     {
419         EXPECT_TRUE(m_magic == magic);
420         m_magic = 0;
421         s_live--;
422     }
423
424     virtual void trace(Visitor* visitor) { }
425     static unsigned s_live;
426
427 protected:
428     static const int magic = 1337;
429     int m_magic;
430
431     Bar()
432         : m_magic(magic)
433     {
434         s_live++;
435     }
436 };
437
438 unsigned Bar::s_live = 0;
439
440 class Baz : public GarbageCollected<Baz> {
441     DECLARE_GC_INFO
442 public:
443     static Baz* create(Bar* bar)
444     {
445         return new Baz(bar);
446     }
447
448     void trace(Visitor* visitor)
449     {
450         visitor->trace(m_bar);
451     }
452
453     void clear() { m_bar.release(); }
454
455 private:
456     explicit Baz(Bar* bar)
457         : m_bar(bar)
458     {
459     }
460
461     Member<Bar> m_bar;
462 };
463
464 class Foo : public Bar {
465 public:
466     static Foo* create(Bar* bar)
467     {
468         return new Foo(bar);
469     }
470
471     static Foo* create(Foo* foo)
472     {
473         return new Foo(foo);
474     }
475
476     virtual void trace(Visitor* visitor) OVERRIDE
477     {
478         if (m_pointsToFoo)
479             visitor->mark(static_cast<Foo*>(m_bar));
480         else
481             visitor->mark(m_bar);
482     }
483
484 private:
485     Foo(Bar* bar)
486         : Bar()
487         , m_bar(bar)
488         , m_pointsToFoo(false)
489     {
490     }
491
492     Foo(Foo* foo)
493         : Bar()
494         , m_bar(foo)
495         , m_pointsToFoo(true)
496     {
497     }
498
499     Bar* m_bar;
500     bool m_pointsToFoo;
501 };
502
503 class Bars : public Bar {
504 public:
505     static Bars* create()
506     {
507         return new Bars();
508     }
509
510     virtual void trace(Visitor* visitor) OVERRIDE
511     {
512         for (unsigned i = 0; i < m_width; i++)
513             visitor->trace(m_bars[i]);
514     }
515
516     unsigned getWidth() const
517     {
518         return m_width;
519     }
520
521     static const unsigned width = 7500;
522 private:
523     Bars() : m_width(0)
524     {
525         for (unsigned i = 0; i < width; i++) {
526             m_bars[i] = Bar::create();
527             m_width++;
528         }
529     }
530
531     unsigned m_width;
532     Member<Bar> m_bars[width];
533 };
534
535 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
536     DECLARE_GC_INFO
537 public:
538     static ConstructorAllocation* create() { return new ConstructorAllocation(); }
539
540     void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
541
542 private:
543     ConstructorAllocation()
544     {
545         m_intWrapper = IntWrapper::create(42);
546     }
547
548     Member<IntWrapper> m_intWrapper;
549 };
550
551 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
552     DECLARE_GC_INFO
553 public:
554     ~LargeObject()
555     {
556         s_destructorCalls++;
557     }
558     static LargeObject* create() { return new LargeObject(); }
559     char get(size_t i) { return m_data[i]; }
560     void set(size_t i, char c) { m_data[i] = c; }
561     size_t length() { return s_length; }
562     void trace(Visitor* visitor)
563     {
564         visitor->trace(m_intWrapper);
565     }
566     static int s_destructorCalls;
567
568 private:
569     static const size_t s_length = 1024*1024;
570     LargeObject()
571     {
572         m_intWrapper = IntWrapper::create(23);
573     }
574     Member<IntWrapper> m_intWrapper;
575     char m_data[s_length];
576 };
577
578 int LargeObject::s_destructorCalls = 0;
579
580 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
581     DECLARE_GC_INFO
582 public:
583     static PassRefPtr<RefCountedAndGarbageCollected> create()
584     {
585         return adoptRef(new RefCountedAndGarbageCollected());
586     }
587
588     ~RefCountedAndGarbageCollected()
589     {
590         ++s_destructorCalls;
591     }
592
593     void trace(Visitor*) { }
594
595     static int s_destructorCalls;
596
597 private:
598     RefCountedAndGarbageCollected()
599     {
600     }
601 };
602
603 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
604
605 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
606     DECLARE_GC_INFO
607 public:
608     static PassRefPtr<RefCountedAndGarbageCollected2> create()
609     {
610         return adoptRef(new RefCountedAndGarbageCollected2());
611     }
612
613     ~RefCountedAndGarbageCollected2()
614     {
615         ++s_destructorCalls;
616     }
617
618     void trace(Visitor*) { }
619
620     static int s_destructorCalls;
621
622 private:
623     RefCountedAndGarbageCollected2()
624     {
625     }
626 };
627
628 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
629
630 #define DEFINE_VISITOR_METHODS(Type)                                       \
631     virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
632     {                                                                      \
633         mark(object);                                                      \
634     }                                                                      \
635
636 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
637 public:
638     RefCountedGarbageCollectedVisitor(int expected, void** objects)
639         : m_count(0)
640         , m_expectedCount(expected)
641         , m_expectedObjects(objects)
642     {
643     }
644
645     void mark(const void* ptr) { markNoTrace(ptr); }
646
647     virtual void markNoTrace(const void* ptr)
648     {
649         if (!ptr)
650             return;
651         if (m_count < m_expectedCount)
652             EXPECT_TRUE(expectedObject(ptr));
653         else
654             EXPECT_FALSE(expectedObject(ptr));
655         m_count++;
656     }
657
658     virtual void mark(const void* ptr, TraceCallback) OVERRIDE
659     {
660         mark(ptr);
661     }
662
663     virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
664     {
665         mark(header->payload());
666     }
667
668     virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
669     {
670         mark(header->payload());
671     }
672
673     bool validate() { return m_count >= m_expectedCount; }
674     void reset() { m_count = 0; }
675
676     FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
677
678 private:
679     bool expectedObject(const void* ptr)
680     {
681         for (int i = 0; i < m_expectedCount; i++) {
682             if (m_expectedObjects[i] == ptr)
683                 return true;
684         }
685         return false;
686     }
687
688     int m_count;
689     int m_expectedCount;
690     void** m_expectedObjects;
691 };
692
693 #undef DEFINE_VISITOR_METHODS
694
695 class Weak : public Bar {
696 public:
697     static Weak* create(Bar* strong, Bar* weak)
698     {
699         return new Weak(strong, weak);
700     }
701
702     virtual void trace(Visitor* visitor) OVERRIDE
703     {
704         visitor->trace(m_strongBar);
705         visitor->registerWeakMembers(this, zapWeakMembers);
706     }
707
708     static void zapWeakMembers(Visitor* visitor, void* self)
709     {
710         reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
711     }
712
713     bool strongIsThere() { return !!m_strongBar; }
714     bool weakIsThere() { return !!m_weakBar; }
715
716 private:
717     Weak(Bar* strongBar, Bar* weakBar)
718         : Bar()
719         , m_strongBar(strongBar)
720         , m_weakBar(weakBar)
721     {
722     }
723
724     void zapWeakMembers(Visitor* visitor)
725     {
726         if (m_weakBar && !visitor->isAlive(m_weakBar))
727             m_weakBar = 0;
728     }
729
730     Member<Bar> m_strongBar;
731     Bar* m_weakBar;
732 };
733
734 class WithWeakMember : public Bar {
735 public:
736     static WithWeakMember* create(Bar* strong, Bar* weak)
737     {
738         return new WithWeakMember(strong, weak);
739     }
740
741     virtual void trace(Visitor* visitor) OVERRIDE
742     {
743         visitor->trace(m_strongBar);
744         visitor->trace(m_weakBar);
745     }
746
747     bool strongIsThere() { return !!m_strongBar; }
748     bool weakIsThere() { return !!m_weakBar; }
749
750 private:
751     WithWeakMember(Bar* strongBar, Bar* weakBar)
752         : Bar()
753         , m_strongBar(strongBar)
754         , m_weakBar(weakBar)
755     {
756     }
757
758     Member<Bar> m_strongBar;
759     WeakMember<Bar> m_weakBar;
760 };
761
762
763 class SuperClass;
764
765 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
766     DECLARE_GC_INFO;
767 public:
768     static PassRefPtrWillBePtr<PointsBack> create()
769     {
770         return adoptRefWillBeNoop(new PointsBack());
771     }
772
773     ~PointsBack()
774     {
775         --s_aliveCount;
776     }
777
778     void setBackPointer(SuperClass* backPointer)
779     {
780         m_backPointer = backPointer;
781     }
782
783     SuperClass* backPointer() const { return m_backPointer; }
784
785     void trace(Visitor* visitor)
786     {
787 #if ENABLE_OILPAN
788         visitor->trace(m_backPointer);
789 #endif
790     }
791
792     static int s_aliveCount;
793 private:
794     PointsBack() : m_backPointer(nullptr)
795     {
796         ++s_aliveCount;
797     }
798
799     PtrWillBeWeakMember<SuperClass> m_backPointer;
800 };
801
802 int PointsBack::s_aliveCount = 0;
803
804 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
805     DECLARE_GC_INFO;
806 public:
807     static PassRefPtrWillBePtr<SuperClass> create(PassRefPtrWillBePtr<PointsBack> pointsBack)
808     {
809         return adoptRefWillBeNoop(new SuperClass(pointsBack));
810     }
811
812     virtual ~SuperClass()
813     {
814 #if !ENABLE_OILPAN
815         m_pointsBack->setBackPointer(0);
816 #endif
817         --s_aliveCount;
818     }
819
820     void doStuff(PassRefPtrWillBePtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
821     {
822         RefPtrWillBePtr<SuperClass> target = targetPass;
823         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
824         EXPECT_EQ(pointsBack, target->pointsBack());
825         EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
826     }
827
828     virtual void trace(Visitor* visitor)
829     {
830 #if ENABLE_OILPAN
831         visitor->trace(m_pointsBack);
832 #endif
833     }
834
835     PointsBack* pointsBack() const { return m_pointsBack.get(); }
836
837     static int s_aliveCount;
838 protected:
839     explicit SuperClass(PassRefPtrWillBePtr<PointsBack> pointsBack)
840         : m_pointsBack(pointsBack)
841     {
842         m_pointsBack->setBackPointer(this);
843         ++s_aliveCount;
844     }
845
846 private:
847     RefPtrWillBeMember<PointsBack> m_pointsBack;
848 };
849
850 int SuperClass::s_aliveCount = 0;
851 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
852     DECLARE_GC_INFO
853 public:
854     SubData() { ++s_aliveCount; }
855     ~SubData() { --s_aliveCount; }
856
857     void trace(Visitor*) { }
858
859     static int s_aliveCount;
860 };
861
862 int SubData::s_aliveCount = 0;
863
864 class SubClass : public SuperClass {
865 public:
866     static PassRefPtrWillBePtr<SubClass> create(PassRefPtrWillBePtr<PointsBack> pointsBack)
867     {
868         return adoptRefWillBeNoop(new SubClass(pointsBack));
869     }
870
871     virtual ~SubClass()
872     {
873         --s_aliveCount;
874     }
875
876     virtual void trace(Visitor* visitor)
877     {
878 #if ENABLE_OILPAN
879         SuperClass::trace(visitor);
880         visitor->trace(m_data);
881 #endif
882     }
883
884     static int s_aliveCount;
885 private:
886     explicit SubClass(PassRefPtrWillBePtr<PointsBack> pointsBack)
887         : SuperClass(pointsBack)
888         , m_data(adoptPtrWillBeNoop(new SubData()))
889     {
890         ++s_aliveCount;
891     }
892
893 private:
894     OwnPtrWillBeMember<SubData> m_data;
895 };
896
897 int SubClass::s_aliveCount = 0;
898
899 TEST(HeapTest, Transition)
900 {
901     RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
902     RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
903     RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
904     RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
905     EXPECT_EQ(2, PointsBack::s_aliveCount);
906     EXPECT_EQ(2, SuperClass::s_aliveCount);
907     EXPECT_EQ(1, SubClass::s_aliveCount);
908     EXPECT_EQ(1, SubData::s_aliveCount);
909
910     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
911     EXPECT_EQ(2, PointsBack::s_aliveCount);
912     EXPECT_EQ(2, SuperClass::s_aliveCount);
913     EXPECT_EQ(1, SubClass::s_aliveCount);
914     EXPECT_EQ(1, SubData::s_aliveCount);
915
916     superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
917     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
918     EXPECT_EQ(2, PointsBack::s_aliveCount);
919     EXPECT_EQ(1, SuperClass::s_aliveCount);
920     EXPECT_EQ(1, SubClass::s_aliveCount);
921     EXPECT_EQ(1, SubData::s_aliveCount);
922     EXPECT_EQ(0, pointsBack1->backPointer());
923
924     pointsBack1.release();
925     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
926     EXPECT_EQ(1, PointsBack::s_aliveCount);
927     EXPECT_EQ(1, SuperClass::s_aliveCount);
928     EXPECT_EQ(1, SubClass::s_aliveCount);
929     EXPECT_EQ(1, SubData::s_aliveCount);
930
931     subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
932     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
933     EXPECT_EQ(1, PointsBack::s_aliveCount);
934     EXPECT_EQ(0, SuperClass::s_aliveCount);
935     EXPECT_EQ(0, SubClass::s_aliveCount);
936     EXPECT_EQ(0, SubData::s_aliveCount);
937     EXPECT_EQ(0, pointsBack2->backPointer());
938
939     pointsBack2.release();
940     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
941     EXPECT_EQ(0, PointsBack::s_aliveCount);
942     EXPECT_EQ(0, SuperClass::s_aliveCount);
943     EXPECT_EQ(0, SubClass::s_aliveCount);
944     EXPECT_EQ(0, SubData::s_aliveCount);
945
946     EXPECT_TRUE(superClass == subClass);
947 }
948
949 TEST(HeapTest, Threading)
950 {
951     ThreadedHeapTester::test();
952 }
953
954 TEST(HeapTest, BasicFunctionality)
955 {
956     HeapStats heapStats;
957     clearOutOldGarbage(&heapStats);
958     {
959         size_t slack = 0;
960
961         // When the test starts there may already have been leaked some memory
962         // on the heap, so we establish a base line.
963         size_t baseLevel = heapStats.totalObjectSpace();
964         bool testPagesAllocated = !baseLevel;
965         if (testPagesAllocated)
966             EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
967
968         // This allocates objects on the general heap which should add a page of memory.
969         uint8_t* alloc32(Heap::allocate<uint8_t>(32));
970         slack += 4;
971         memset(alloc32, 40, 32);
972         uint8_t* alloc64(Heap::allocate<uint8_t>(64));
973         slack += 4;
974         memset(alloc64, 27, 64);
975
976         size_t total = 96;
977
978         getHeapStats(&heapStats);
979         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
980         if (testPagesAllocated)
981             EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
982
983         CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
984
985         EXPECT_EQ(alloc32[0], 40);
986         EXPECT_EQ(alloc32[31], 40);
987         EXPECT_EQ(alloc64[0], 27);
988         EXPECT_EQ(alloc64[63], 27);
989
990         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
991
992         EXPECT_EQ(alloc32[0], 40);
993         EXPECT_EQ(alloc32[31], 40);
994         EXPECT_EQ(alloc64[0], 27);
995         EXPECT_EQ(alloc64[63], 27);
996     }
997
998     clearOutOldGarbage(&heapStats);
999     size_t total = 0;
1000     size_t slack = 0;
1001     size_t baseLevel = heapStats.totalObjectSpace();
1002     bool testPagesAllocated = !baseLevel;
1003     if (testPagesAllocated)
1004         EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1005
1006     const size_t big = 1008;
1007     Persistent<uint8_t> bigArea = Heap::allocate<uint8_t>(big);
1008     total += big;
1009     slack += 4;
1010
1011     size_t persistentCount = 0;
1012     const size_t numPersistents = 100000;
1013     Persistent<uint8_t>* persistents[numPersistents];
1014
1015     for (int i = 0; i < 1000; i++) {
1016         size_t size = 128 + i * 8;
1017         total += size;
1018         persistents[persistentCount++] = new Persistent<uint8_t>(Heap::allocate<uint8_t>(size));
1019         slack += 4;
1020         getHeapStats(&heapStats);
1021         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1022         if (testPagesAllocated)
1023             EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1024     }
1025
1026     {
1027         uint8_t* alloc32b(Heap::allocate<uint8_t>(32));
1028         slack += 4;
1029         memset(alloc32b, 40, 32);
1030         uint8_t* alloc64b(Heap::allocate<uint8_t>(64));
1031         slack += 4;
1032         memset(alloc64b, 27, 64);
1033         EXPECT_TRUE(alloc32b != alloc64b);
1034
1035         total += 96;
1036         getHeapStats(&heapStats);
1037         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1038         if (testPagesAllocated)
1039             EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1040     }
1041
1042     clearOutOldGarbage(&heapStats);
1043     total -= 96;
1044     slack -= 8;
1045     if (testPagesAllocated)
1046         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1047
1048     Address bigAreaRaw = bigArea;
1049     // Clear the persistent, so that the big area will be garbage collected.
1050     bigArea.release();
1051     clearOutOldGarbage(&heapStats);
1052
1053     total -= big;
1054     slack -= 4;
1055     getHeapStats(&heapStats);
1056     CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1057     if (testPagesAllocated)
1058         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1059
1060     // Endless loop unless we eventually get the memory back that we just freed.
1061     while (true) {
1062         Persistent<uint8_t>* alloc = new Persistent<uint8_t>(Heap::allocate<uint8_t>(big / 2));
1063         slack += 4;
1064         persistents[persistentCount++] = alloc;
1065         EXPECT_LT(persistentCount, numPersistents);
1066         total += big / 2;
1067         if (bigAreaRaw == alloc->get())
1068             break;
1069     }
1070
1071     getHeapStats(&heapStats);
1072     CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1073     if (testPagesAllocated)
1074         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1075
1076     for (size_t i = 0; i < persistentCount; i++)
1077         persistents[i]->release();
1078
1079     uint8_t* address = Heap::reallocate<uint8_t>(0, 100);
1080     for (int i = 0; i < 100; i++)
1081         address[i] = i;
1082     address = Heap::reallocate<uint8_t>(address, 100000);
1083     for (int i = 0; i < 100; i++)
1084         EXPECT_EQ(address[i], i);
1085     address = Heap::reallocate<uint8_t>(address, 50);
1086     for (int i = 0; i < 50; i++)
1087         EXPECT_EQ(address[i], i);
1088     // This should be equivalent to free(address).
1089     EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<uint8_t>(address, 0)), 0ul);
1090     // This should be equivalent to malloc(0).
1091     EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<uint8_t>(0, 0)), 0ul);
1092 }
1093
1094 TEST(HeapTest, SimpleAllocation)
1095 {
1096     HeapStats initialHeapStats;
1097     clearOutOldGarbage(&initialHeapStats);
1098     EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1099
1100     // Allocate an object in the heap.
1101     HeapAllocatedArray* array = new HeapAllocatedArray();
1102     HeapStats statsAfterAllocation;
1103     getHeapStats(&statsAfterAllocation);
1104     EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1105
1106     // Sanity check of the contents in the heap.
1107     EXPECT_EQ(0, array->at(0));
1108     EXPECT_EQ(42, array->at(42));
1109     EXPECT_EQ(0, array->at(128));
1110     EXPECT_EQ(999 % 128, array->at(999));
1111 }
1112
1113 TEST(HeapTest, SimplePersistent)
1114 {
1115     Persistent<TraceCounter> traceCounter = TraceCounter::create();
1116     EXPECT_EQ(0, traceCounter->traceCount());
1117
1118     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1119     EXPECT_EQ(1, traceCounter->traceCount());
1120
1121     Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1122     EXPECT_EQ(0, classWithMember->traceCount());
1123
1124     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1125     EXPECT_EQ(1, classWithMember->traceCount());
1126     EXPECT_EQ(2, traceCounter->traceCount());
1127 }
1128
1129 TEST(HeapTest, SimpleFinalization)
1130 {
1131     {
1132         Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1133         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1134         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1135         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1136     }
1137
1138     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1139     EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1140 }
1141
1142 TEST(HeapTest, Finalization)
1143 {
1144     {
1145         HeapTestSubClass* t1 = HeapTestSubClass::create();
1146         HeapTestSubClass* t2 = HeapTestSubClass::create();
1147         HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1148         // FIXME(oilpan): Ignore unused variables.
1149         (void)t1;
1150         (void)t2;
1151         (void)t3;
1152     }
1153     // Nothing is marked so the GC should free everything and call
1154     // the finalizer on all three objects.
1155     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1156     EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1157     EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1158     // Destructors not called again when GCing again.
1159     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1160     EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1161     EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1162 }
1163
1164 TEST(HeapTest, TypedHeapSanity)
1165 {
1166     // We use TraceCounter for allocating an object on the general heap.
1167     Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1168     Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create();
1169     EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get())),
1170         pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get())));
1171 }
1172
1173 TEST(HeapTest, NoAllocation)
1174 {
1175     EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1176     {
1177         // Disallow allocation
1178         NoAllocationScope<AnyThread> noAllocationScope;
1179         EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1180     }
1181     EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1182 }
1183
1184 TEST(HeapTest, Members)
1185 {
1186     Bar::s_live = 0;
1187     {
1188         Persistent<Baz> h1;
1189         Persistent<Baz> h2;
1190         {
1191             h1 = Baz::create(Bar::create());
1192             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1193             EXPECT_EQ(1u, Bar::s_live);
1194             h2 = Baz::create(Bar::create());
1195             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1196             EXPECT_EQ(2u, Bar::s_live);
1197         }
1198         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1199         EXPECT_EQ(2u, Bar::s_live);
1200         h1->clear();
1201         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1202         EXPECT_EQ(1u, Bar::s_live);
1203     }
1204     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1205     EXPECT_EQ(0u, Bar::s_live);
1206 }
1207
1208 TEST(HeapTest, MarkTest)
1209 {
1210     {
1211         Bar::s_live = 0;
1212         Persistent<Bar> bar = Bar::create();
1213         EXPECT_TRUE(ThreadState::current()->contains(bar));
1214         EXPECT_EQ(1u, Bar::s_live);
1215         {
1216             Foo* foo = Foo::create(bar);
1217             EXPECT_TRUE(ThreadState::current()->contains(foo));
1218             EXPECT_EQ(2u, Bar::s_live);
1219             EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1220             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1221             EXPECT_EQ(2u, Bar::s_live);
1222         }
1223         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1224         EXPECT_EQ(1u, Bar::s_live);
1225     }
1226     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1227     EXPECT_EQ(0u, Bar::s_live);
1228 }
1229
1230 TEST(HeapTest, DeepTest)
1231 {
1232     const unsigned depth = 100000;
1233     Bar::s_live = 0;
1234     {
1235         Bar* bar = Bar::create();
1236         EXPECT_TRUE(ThreadState::current()->contains(bar));
1237         Foo* foo = Foo::create(bar);
1238         EXPECT_TRUE(ThreadState::current()->contains(foo));
1239         EXPECT_EQ(2u, Bar::s_live);
1240         for (unsigned i = 0; i < depth; i++) {
1241             Foo* foo2 = Foo::create(foo);
1242             foo = foo2;
1243             EXPECT_TRUE(ThreadState::current()->contains(foo));
1244         }
1245         EXPECT_EQ(depth + 2, Bar::s_live);
1246         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1247         EXPECT_EQ(depth + 2, Bar::s_live);
1248     }
1249     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1250     EXPECT_EQ(0u, Bar::s_live);
1251 }
1252
1253 TEST(HeapTest, WideTest)
1254 {
1255     Bar::s_live = 0;
1256     {
1257         Bars* bars = Bars::create();
1258         unsigned width = Bars::width;
1259         EXPECT_EQ(width + 1, Bar::s_live);
1260         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1261         EXPECT_EQ(width + 1, Bar::s_live);
1262         // Use bars here to make sure that it will be on the stack
1263         // for the conservative stack scan to find.
1264         EXPECT_EQ(width, bars->getWidth());
1265     }
1266     EXPECT_EQ(Bars::width + 1, Bar::s_live);
1267     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1268     EXPECT_EQ(0u, Bar::s_live);
1269 }
1270
1271 TEST(HeapTest, HashMapOfMembers)
1272 {
1273     HeapStats initialHeapSize;
1274     IntWrapper::s_destructorCalls = 0;
1275
1276     clearOutOldGarbage(&initialHeapSize);
1277     {
1278         typedef HashMap<
1279             Member<IntWrapper>,
1280             Member<IntWrapper>,
1281             DefaultHash<Member<IntWrapper> >::Hash,
1282             HashTraits<Member<IntWrapper> >,
1283             HashTraits<Member<IntWrapper> >,
1284             HeapAllocator> HeapObjectIdentityMap;
1285
1286         HeapObjectIdentityMap* map(new HeapObjectIdentityMap());
1287
1288         map->clear();
1289         HeapStats afterSetWasCreated;
1290         getHeapStats(&afterSetWasCreated);
1291         EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1292
1293         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1294         HeapStats afterGC;
1295         getHeapStats(&afterGC);
1296         EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1297
1298         IntWrapper* one(IntWrapper::create(1));
1299         IntWrapper* anotherOne(IntWrapper::create(1));
1300         map->add(one, one);
1301         HeapStats afterOneAdd;
1302         getHeapStats(&afterOneAdd);
1303         EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1304
1305         HeapObjectIdentityMap::iterator it(map->begin());
1306         HeapObjectIdentityMap::iterator it2(map->begin());
1307         ++it;
1308         ++it2;
1309
1310         map->add(anotherOne, one);
1311
1312         EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1313
1314         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1315         EXPECT_TRUE(map->contains(one));
1316         EXPECT_TRUE(map->contains(anotherOne));
1317
1318         IntWrapper* gotten(map->get(one));
1319         EXPECT_EQ(gotten->value(), one->value());
1320         EXPECT_EQ(gotten, one);
1321
1322         HeapStats afterGC2;
1323         getHeapStats(&afterGC2);
1324         EXPECT_EQ(afterGC2.totalObjectSpace(), afterOneAdd.totalObjectSpace());
1325
1326         IntWrapper* dozen = 0;
1327
1328         for (int i = 1; i < 1000; i++) { // 999 iterations.
1329             IntWrapper* iWrapper(IntWrapper::create(i));
1330             IntWrapper* iSquared(IntWrapper::create(i * i));
1331             map->add(iWrapper, iSquared);
1332             if (i == 12)
1333                 dozen = iWrapper;
1334         }
1335         HeapStats afterAdding1000;
1336         getHeapStats(&afterAdding1000);
1337         EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1338
1339         IntWrapper* gross(map->get(dozen));
1340         EXPECT_EQ(gross->value(), 144);
1341
1342         // This should clear out junk created by all the adds.
1343         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1344         HeapStats afterGC3;
1345         getHeapStats(&afterGC3);
1346         EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1347     }
1348
1349     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1350     // The objects 'one', anotherOne, and the 999 other pairs.
1351     EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1352     HeapStats afterGC4;
1353     getHeapStats(&afterGC4);
1354     EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1355 }
1356
1357 TEST(HeapTest, NestedAllocation)
1358 {
1359     HeapStats initialHeapSize;
1360     clearOutOldGarbage(&initialHeapSize);
1361     {
1362         Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1363     }
1364     HeapStats afterFree;
1365     clearOutOldGarbage(&afterFree);
1366     EXPECT_TRUE(initialHeapSize == afterFree);
1367 }
1368
1369 TEST(HeapTest, LargeObjects)
1370 {
1371     HeapStats initialHeapSize;
1372     clearOutOldGarbage(&initialHeapSize);
1373     IntWrapper::s_destructorCalls = 0;
1374     LargeObject::s_destructorCalls = 0;
1375     {
1376         int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1377         Persistent<LargeObject> object = LargeObject::create();
1378         HeapStats afterAllocation;
1379         clearOutOldGarbage(&afterAllocation);
1380         {
1381             object->set(0, 'a');
1382             EXPECT_EQ('a', object->get(0));
1383             object->set(object->length() - 1, 'b');
1384             EXPECT_EQ('b', object->get(object->length() - 1));
1385             size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1386             size_t actualObjectSpace =
1387                 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1388             CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1389             // There is probably space for the IntWrapper in a heap page without
1390             // allocating extra pages. However, the IntWrapper allocation might cause
1391             // the addition of a heap page.
1392             size_t largeObjectAllocationSize =
1393                 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1394             size_t allocatedSpaceLowerBound =
1395                 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1396             size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1397             EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1398             EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1399             EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1400             EXPECT_EQ(0, LargeObject::s_destructorCalls);
1401             for (int i = 0; i < 10; i++)
1402                 object = LargeObject::create();
1403         }
1404         HeapStats oneLargeObject;
1405         clearOutOldGarbage(&oneLargeObject);
1406         EXPECT_TRUE(oneLargeObject == afterAllocation);
1407         EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1408         EXPECT_EQ(10, LargeObject::s_destructorCalls);
1409     }
1410     HeapStats backToInitial;
1411     clearOutOldGarbage(&backToInitial);
1412     EXPECT_TRUE(initialHeapSize == backToInitial);
1413     EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1414     EXPECT_EQ(11, LargeObject::s_destructorCalls);
1415     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1416 }
1417
1418 TEST(HeapTest, RefCountedGarbageCollected)
1419 {
1420     RefCountedAndGarbageCollected::s_destructorCalls = 0;
1421     {
1422         RefPtr<RefCountedAndGarbageCollected> refPtr3;
1423         {
1424             Persistent<RefCountedAndGarbageCollected> persistent;
1425             {
1426                 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
1427                 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
1428                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1429                 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
1430                 persistent = refPtr1.get();
1431             }
1432             // Reference count is zero for both objects but one of
1433             // them is kept alive by a persistent handle.
1434             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1435             EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
1436             refPtr3 = persistent;
1437         }
1438         // The persistent handle is gone but the ref count has been
1439         // increased to 1.
1440         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1441         EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
1442     }
1443     // Both persistent handle is gone and ref count is zero so the
1444     // object can be collected.
1445     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1446     EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
1447 }
1448
1449 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
1450 {
1451     RefCountedAndGarbageCollected::s_destructorCalls = 0;
1452     RefCountedAndGarbageCollected2::s_destructorCalls = 0;
1453     {
1454         RefCountedAndGarbageCollected* pointer1 = 0;
1455         RefCountedAndGarbageCollected* pointer2 = 0;
1456         {
1457             RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
1458             RefPtr<RefCountedAndGarbageCollected> object2 = RefCountedAndGarbageCollected::create();
1459             pointer1 = object1.get();
1460             pointer2 = object2.get();
1461             void* objects[2] = { object1.get(), object2.get() };
1462             RefCountedGarbageCollectedVisitor visitor(2, objects);
1463             ThreadState::current()->visitPersistents(&visitor);
1464             EXPECT_TRUE(visitor.validate());
1465
1466             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1467             EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
1468         }
1469         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1470         EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
1471
1472         // At this point, the reference counts of object1 and object2 are 0.
1473         // Only pointer1 and pointer2 keep references to object1 and object2.
1474         void* objects[] = { 0 };
1475         RefCountedGarbageCollectedVisitor visitor(0, objects);
1476         ThreadState::current()->visitPersistents(&visitor);
1477         EXPECT_TRUE(visitor.validate());
1478
1479         {
1480             RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
1481             RefPtr<RefCountedAndGarbageCollected> object2(pointer2);
1482             void* objects[2] = { object1.get(), object2.get() };
1483             RefCountedGarbageCollectedVisitor visitor(2, objects);
1484             ThreadState::current()->visitPersistents(&visitor);
1485             EXPECT_TRUE(visitor.validate());
1486
1487             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1488             EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
1489         }
1490
1491         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1492         EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
1493     }
1494
1495     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1496     EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
1497 }
1498
1499 TEST(HeapTest, WeakMembers)
1500 {
1501     Bar::s_live = 0;
1502     {
1503         Persistent<Bar> h1 = Bar::create();
1504         Persistent<Weak> h4;
1505         Persistent<WithWeakMember> h5;
1506         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1507         ASSERT_EQ(1u, Bar::s_live); // h1 is live.
1508         {
1509             Bar* h2 = Bar::create();
1510             Bar* h3 = Bar::create();
1511             h4 = Weak::create(h2, h3);
1512             h5 = WithWeakMember::create(h2, h3);
1513             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1514             EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
1515             EXPECT_TRUE(h4->strongIsThere());
1516             EXPECT_TRUE(h4->weakIsThere());
1517             EXPECT_TRUE(h5->strongIsThere());
1518             EXPECT_TRUE(h5->weakIsThere());
1519         }
1520         // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
1521         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1522         EXPECT_EQ(4u, Bar::s_live);
1523         EXPECT_TRUE(h4->strongIsThere());
1524         EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
1525         EXPECT_TRUE(h5->strongIsThere());
1526         EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
1527         h1.release(); // Zero out h1.
1528         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1529         EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
1530         EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
1531         EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
1532     }
1533     // h4 and h5 have gone out of scope now and they were keeping h2 alive.
1534     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1535     EXPECT_EQ(0u, Bar::s_live); // All gone.
1536 }
1537
1538 TEST(HeapTest, Comparisons)
1539 {
1540     Persistent<Bar> barPersistent = Bar::create();
1541     Persistent<Foo> fooPersistent = Foo::create(barPersistent);
1542     EXPECT_TRUE(barPersistent != fooPersistent);
1543     barPersistent = fooPersistent;
1544     EXPECT_TRUE(barPersistent == fooPersistent);
1545 }
1546
1547 TEST(HeapTest, CheckAndMarkPointer)
1548 {
1549     HeapStats initialHeapStats;
1550     clearOutOldGarbage(&initialHeapStats);
1551
1552     Vector<Address> objectAddresses;
1553     Vector<Address> endAddresses;
1554     Address largeObjectAddress;
1555     Address largeObjectEndAddress;
1556     CountingVisitor visitor;
1557     for (int i = 0; i < 10; i++) {
1558         SimpleObject* object = SimpleObject::create();
1559         Address objectAddress = reinterpret_cast<Address>(object);
1560         objectAddresses.append(objectAddress);
1561         endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
1562     }
1563     LargeObject* largeObject = LargeObject::create();
1564     largeObjectAddress = reinterpret_cast<Address>(largeObject);
1565     largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
1566
1567     // This is a low-level test where we call checkAndMarkPointer. This method
1568     // causes the object start bitmap to be computed which requires the heap
1569     // to be in a consistent state (e.g. the free allocation area must be put
1570     // into a free list header). However when we call makeConsistentForGC it
1571     // also clears out the freelists so we have to rebuild those before trying
1572     // to allocate anything again. We do this by forcing a GC after doing the
1573     // checkAndMarkPointer tests.
1574     {
1575         TestGCScope scope(ThreadState::HeapPointersOnStack);
1576         Heap::makeConsistentForGC();
1577         for (size_t i = 0; i < objectAddresses.size(); i++) {
1578             EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
1579             EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
1580         }
1581         EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
1582         visitor.reset();
1583         EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
1584         EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
1585         EXPECT_EQ(2ul, visitor.count());
1586         visitor.reset();
1587     }
1588     // This forces a GC without stack scanning which results in the objects
1589     // being collected. This will also rebuild the above mentioned freelists,
1590     // however we don't rely on that below since we don't have any allocations.
1591     clearOutOldGarbage(&initialHeapStats);
1592     {
1593         TestGCScope scope(ThreadState::HeapPointersOnStack);
1594         Heap::makeConsistentForGC();
1595         for (size_t i = 0; i < objectAddresses.size(); i++) {
1596             EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
1597             EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
1598         }
1599         EXPECT_EQ(0ul, visitor.count());
1600         EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
1601         EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
1602         EXPECT_EQ(0ul, visitor.count());
1603     }
1604     // This round of GC is important to make sure that the object start
1605     // bitmap are cleared out and that the free lists are rebuild.
1606     clearOutOldGarbage(&initialHeapStats);
1607 }
1608
1609 DEFINE_GC_INFO(Bar);
1610 DEFINE_GC_INFO(Baz);
1611 DEFINE_GC_INFO(ClassWithMember);
1612 DEFINE_GC_INFO(ConstructorAllocation);
1613 DEFINE_GC_INFO(HeapAllocatedArray);
1614 DEFINE_GC_INFO(HeapTestSuperClass);
1615 DEFINE_GC_INFO(IntWrapper);
1616 DEFINE_GC_INFO(LargeObject);
1617 DEFINE_GC_INFO(PointsBack);
1618 DEFINE_GC_INFO(RefCountedAndGarbageCollected);
1619 DEFINE_GC_INFO(RefCountedAndGarbageCollected2);
1620 DEFINE_GC_INFO(SimpleFinalizedObject);
1621 DEFINE_GC_INFO(SimpleObject);
1622 DEFINE_GC_INFO(SuperClass);
1623 DEFINE_GC_INFO(SubData);
1624 DEFINE_GC_INFO(TestTypedHeapClass);
1625 DEFINE_GC_INFO(TraceCounter);
1626
1627 } // namespace