• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "platform/heap/Handle.h"
34 #include "platform/heap/Heap.h"
35 #include "platform/heap/HeapLinkedStack.h"
36 #include "platform/heap/HeapTerminatedArrayBuilder.h"
37 #include "platform/heap/ThreadState.h"
38 #include "platform/heap/Visitor.h"
39 #include "public/platform/Platform.h"
40 #include "wtf/HashTraits.h"
41 #include "wtf/LinkedHashSet.h"
42 
43 #include <gtest/gtest.h>
44 
45 namespace WebCore {
46 
47 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
48 public:
create(int x)49     static IntWrapper* create(int x)
50     {
51         return new IntWrapper(x);
52     }
53 
~IntWrapper()54     virtual ~IntWrapper()
55     {
56         ++s_destructorCalls;
57     }
58 
59     static int s_destructorCalls;
trace(Visitor *)60     static void trace(Visitor*) { }
61 
value() const62     int value() const { return m_x; }
63 
operator ==(const IntWrapper & other) const64     bool operator==(const IntWrapper& other) const { return other.value() == value(); }
65 
hash()66     unsigned hash() { return IntHash<int>::hash(m_x); }
67 
68 protected:
IntWrapper(int x)69     IntWrapper(int x) : m_x(x) { }
70 
71 private:
72     IntWrapper();
73     int m_x;
74 };
75 
76 USED_FROM_MULTIPLE_THREADS(IntWrapper);
77 
78 class ThreadMarker {
79 public:
ThreadMarker()80     ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(0) { }
ThreadMarker(unsigned i)81     ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i) { }
ThreadMarker(WTF::HashTableDeletedValueType deleted)82     ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(reinterpret_cast<ThreadState*>(-1)), m_num(0) { }
~ThreadMarker()83     ~ThreadMarker()
84     {
85         EXPECT_TRUE((m_creatingThread == ThreadState::current())
86             || (m_creatingThread == reinterpret_cast<ThreadState*>(0))
87             || (m_creatingThread == reinterpret_cast<ThreadState*>(-1)));
88     }
isHashTableDeletedValue() const89     bool isHashTableDeletedValue() const { return m_creatingThread == reinterpret_cast<ThreadState*>(-1); }
operator ==(const ThreadMarker & other) const90     bool operator==(const ThreadMarker& other) const { return other.m_creatingThread == m_creatingThread && other.m_num == m_num; }
91     ThreadState* m_creatingThread;
92     unsigned m_num;
93 };
94 
95 struct ThreadMarkerHash {
hashWebCore::ThreadMarkerHash96     static unsigned hash(const ThreadMarker& key)
97     {
98         return static_cast<unsigned>(reinterpret_cast<uintptr_t>(key.m_creatingThread) + key.m_num);
99     }
100 
equalWebCore::ThreadMarkerHash101     static bool equal(const ThreadMarker& a, const ThreadMarker& b)
102     {
103         return a == b;
104     }
105 
106     static const bool safeToCompareToEmptyOrDeleted = false;
107 };
108 
109 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeakPair;
110 
111 struct PairWithWeakHandling : public StrongWeakPair {
112     ALLOW_ONLY_INLINE_ALLOCATION();
113 
114 public:
115     // Regular constructor.
PairWithWeakHandlingWebCore::PairWithWeakHandling116     PairWithWeakHandling(IntWrapper* one, IntWrapper* two)
117         : StrongWeakPair(one, two)
118     {
119         ASSERT(one); // We use null first field to indicate empty slots in the hash table.
120     }
121 
122     // The HashTable (via the HashTrait) calls this constructor with a
123     // placement new to mark slots in the hash table as being deleted. We will
124     // never call trace or the destructor on these slots. We mark ourselves deleted
125     // with a pointer to -1 in the first field.
PairWithWeakHandlingWebCore::PairWithWeakHandling126     PairWithWeakHandling(WTF::HashTableDeletedValueType)
127         : StrongWeakPair(reinterpret_cast<IntWrapper*>(-1), nullptr)
128     {
129     }
130 
131     // Used by the HashTable (via the HashTrait) to skip deleted slots in the
132     // table. Recognizes objects that were 'constructed' using the above
133     // constructor.
isHashTableDeletedValueWebCore::PairWithWeakHandling134     bool isHashTableDeletedValue() const { return first == reinterpret_cast<IntWrapper*>(-1); }
135 
136     // Since we don't allocate independent objects of this type, we don't need
137     // a regular trace method. Instead, we use a traceInCollection method.
traceInCollectionWebCore::PairWithWeakHandling138     void traceInCollection(Visitor* visitor, ShouldWeakPointersBeMarkedStrongly strongify)
139     {
140         visitor->trace(first);
141         visitor->traceInCollection(second, strongify);
142     }
143     // The traceInCollection may not trace the weak members, so it is vital
144     // that shouldRemoveFromCollection checks them so the entry can be removed
145     // from the collection (otherwise it would contain a dangling pointer).
shouldRemoveFromCollectionWebCore::PairWithWeakHandling146     bool shouldRemoveFromCollection(Visitor* visitor)
147     {
148         return !visitor->isAlive(second);
149     }
150 };
151 
152 }
153 
154 namespace WTF {
155 
156 template<typename T> struct DefaultHash;
157 template<> struct DefaultHash<WebCore::ThreadMarker> {
158     typedef WebCore::ThreadMarkerHash Hash;
159 };
160 
161 // ThreadMarkerHash is the default hash for ThreadMarker
162 template<> struct HashTraits<WebCore::ThreadMarker> : GenericHashTraits<WebCore::ThreadMarker> {
163     static const bool emptyValueIsZero = true;
constructDeletedValueWTF::HashTraits164     static void constructDeletedValue(WebCore::ThreadMarker& slot) { new (NotNull, &slot) WebCore::ThreadMarker(HashTableDeletedValue); }
isDeletedValueWTF::HashTraits165     static bool isDeletedValue(const WebCore::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
166 };
167 
168 // The hash algorithm for our custom pair class is just the standard double
169 // hash for pairs. Note that this means you can't mutate either of the parts of
170 // the pair while they are in the hash table, as that would change their hash
171 // code and thus their preferred placement in the table.
172 template<> struct DefaultHash<WebCore::PairWithWeakHandling> {
173     typedef PairHash<WebCore::Member<WebCore::IntWrapper>, WebCore::WeakMember<WebCore::IntWrapper> > Hash;
174 };
175 
176 // Custom traits for the pair. These are weakness handling traits, which means
177 // PairWithWeakHandling must implement the traceInCollection and
178 // shouldRemoveFromCollection methods. In addition, these traits are concerned
179 // with the two magic values for the object, that represent empty and deleted
180 // slots in the hash table. The SimpleClassHashTraits allow empty slots in the
181 // table to be initialzed with memset to zero, and we use -1 in the first part
182 // of the pair to represent deleted slots.
183 template<> struct HashTraits<WebCore::PairWithWeakHandling> : WebCore::WeakHandlingHashTraits<WebCore::PairWithWeakHandling> {
184     static const bool needsDestruction = false;
185     static const bool hasIsEmptyValueFunction = true;
isEmptyValueWTF::HashTraits186     static bool isEmptyValue(const WebCore::PairWithWeakHandling& value) { return !value.first; }
constructDeletedValueWTF::HashTraits187     static void constructDeletedValue(WebCore::PairWithWeakHandling& slot) { new (NotNull, &slot) WebCore::PairWithWeakHandling(HashTableDeletedValue); }
isDeletedValueWTF::HashTraits188     static bool isDeletedValue(const WebCore::PairWithWeakHandling& value) { return value.isHashTableDeletedValue(); }
189 };
190 
191 }
192 
193 namespace WebCore {
194 
195 class TestGCScope {
196 public:
TestGCScope(ThreadState::StackState state)197     explicit TestGCScope(ThreadState::StackState state)
198         : m_state(ThreadState::current())
199         , m_safePointScope(state)
200         , m_parkedAllThreads(false)
201     {
202         m_state->checkThread();
203         EXPECT_FALSE(m_state->isInGC());
204         if (LIKELY(ThreadState::stopThreads())) {
205             m_state->enterGC();
206             m_parkedAllThreads = true;
207         }
208     }
209 
allThreadsParked()210     bool allThreadsParked() { return m_parkedAllThreads; }
211 
~TestGCScope()212     ~TestGCScope()
213     {
214         // Only cleanup if we parked all threads in which case the GC happened
215         // and we need to resume the other threads.
216         if (LIKELY(m_parkedAllThreads)) {
217             m_state->leaveGC();
218             EXPECT_FALSE(m_state->isInGC());
219             ThreadState::resumeThreads();
220         }
221     }
222 
223 private:
224     ThreadState* m_state;
225     ThreadState::SafePointScope m_safePointScope;
226     bool m_parkedAllThreads; // False if we fail to park all threads
227 };
228 
getHeapStats(HeapStats * stats)229 static void getHeapStats(HeapStats* stats)
230 {
231     TestGCScope scope(ThreadState::NoHeapPointersOnStack);
232     EXPECT_TRUE(scope.allThreadsParked());
233     Heap::getStats(stats);
234 }
235 
236 #define DEFINE_VISITOR_METHODS(Type)                                       \
237     virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
238     {                                                                      \
239         if (object)                                                        \
240             m_count++;                                                     \
241     }                                                                      \
242     virtual bool isMarked(const Type*) OVERRIDE { return false; }
243 
244 class CountingVisitor : public Visitor {
245 public:
CountingVisitor()246     CountingVisitor()
247         : m_count(0)
248     {
249     }
250 
mark(const void * object,TraceCallback)251     virtual void mark(const void* object, TraceCallback) OVERRIDE
252     {
253         if (object)
254             m_count++;
255     }
256 
mark(HeapObjectHeader * header,TraceCallback callback)257     virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
258     {
259         ASSERT(header->payload());
260         m_count++;
261     }
262 
mark(FinalizedHeapObjectHeader * header,TraceCallback callback)263     virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
264     {
265         ASSERT(header->payload());
266         m_count++;
267     }
268 
markConservatively(HeapObjectHeader * header)269     virtual void markConservatively(HeapObjectHeader* header) OVERRIDE
270     {
271         ASSERT_NOT_REACHED();
272     }
273 
markConservatively(FinalizedHeapObjectHeader * header)274     virtual void markConservatively(FinalizedHeapObjectHeader* header) OVERRIDE
275     {
276         ASSERT_NOT_REACHED();
277     }
278 
registerWeakMembers(const void *,const void *,WeakPointerCallback)279     virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
registerWeakCell(void **,WeakPointerCallback)280     virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
isMarked(const void *)281     virtual bool isMarked(const void*) OVERRIDE { return false; }
282 
FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)283     FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
284 
285     size_t count() { return m_count; }
reset()286     void reset() { m_count = 0; }
287 
288 private:
289     size_t m_count;
290 };
291 
292 class SimpleObject : public GarbageCollected<SimpleObject> {
293 public:
create()294     static SimpleObject* create() { return new SimpleObject(); }
trace(Visitor *)295     void trace(Visitor*) { }
getPayload(int i)296     char getPayload(int i) { return payload[i]; }
297     // This virtual method is unused but it is here to make sure
298     // that this object has a vtable. This object is used
299     // as the super class for objects that also have garbage
300     // collected mixins and having a virtual here makes sure
301     // that adjustment is needed both for marking and for isAlive
302     // checks.
virtualMethod()303     virtual void virtualMethod() { }
304 protected:
SimpleObject()305     SimpleObject() { }
306     char payload[64];
307 };
308 
309 #undef DEFINE_VISITOR_METHODS
310 
311 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
312 public:
create()313     static HeapTestSuperClass* create()
314     {
315         return new HeapTestSuperClass();
316     }
317 
~HeapTestSuperClass()318     virtual ~HeapTestSuperClass()
319     {
320         ++s_destructorCalls;
321     }
322 
323     static int s_destructorCalls;
trace(Visitor *)324     void trace(Visitor*) { }
325 
326 protected:
HeapTestSuperClass()327     HeapTestSuperClass() { }
328 };
329 
330 int HeapTestSuperClass::s_destructorCalls = 0;
331 
332 class HeapTestOtherSuperClass {
333 public:
334     int payload;
335 };
336 
337 static const size_t classMagic = 0xABCDDBCA;
338 
339 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
340 public:
create()341     static HeapTestSubClass* create()
342     {
343         return new HeapTestSubClass();
344     }
345 
~HeapTestSubClass()346     virtual ~HeapTestSubClass()
347     {
348         EXPECT_EQ(classMagic, m_magic);
349         ++s_destructorCalls;
350     }
351 
352     static int s_destructorCalls;
353 
354 private:
355 
HeapTestSubClass()356     HeapTestSubClass() : m_magic(classMagic) { }
357 
358     const size_t m_magic;
359 };
360 
361 int HeapTestSubClass::s_destructorCalls = 0;
362 
363 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
364 public:
HeapAllocatedArray()365     HeapAllocatedArray()
366     {
367         for (int i = 0; i < s_arraySize; ++i) {
368             m_array[i] = i % 128;
369         }
370     }
371 
at(size_t i)372     int8_t at(size_t i) { return m_array[i]; }
trace(Visitor *)373     void trace(Visitor*) { }
374 private:
375     static const int s_arraySize = 1000;
376     int8_t m_array[s_arraySize];
377 };
378 
379 // Do several GCs to make sure that later GCs don't free up old memory from
380 // previously run tests in this process.
clearOutOldGarbage(HeapStats * heapStats)381 static void clearOutOldGarbage(HeapStats* heapStats)
382 {
383     while (true) {
384         getHeapStats(heapStats);
385         size_t used = heapStats->totalObjectSpace();
386         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
387         getHeapStats(heapStats);
388         if (heapStats->totalObjectSpace() >= used)
389             break;
390     }
391 }
392 
393 class OffHeapInt : public RefCounted<OffHeapInt> {
394 public:
create(int x)395     static RefPtr<OffHeapInt> create(int x)
396     {
397         return adoptRef(new OffHeapInt(x));
398     }
399 
~OffHeapInt()400     virtual ~OffHeapInt()
401     {
402         ++s_destructorCalls;
403     }
404 
405     static int s_destructorCalls;
406 
value() const407     int value() const { return m_x; }
408 
operator ==(const OffHeapInt & other) const409     bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
410 
hash()411     unsigned hash() { return IntHash<int>::hash(m_x); }
voidFunction()412     void voidFunction() { }
413 
414 protected:
OffHeapInt(int x)415     OffHeapInt(int x) : m_x(x) { }
416 
417 private:
418     OffHeapInt();
419     int m_x;
420 };
421 
422 int IntWrapper::s_destructorCalls = 0;
423 int OffHeapInt::s_destructorCalls = 0;
424 
425 class ThreadedTesterBase {
426 protected:
test(ThreadedTesterBase * tester)427     static void test(ThreadedTesterBase* tester)
428     {
429         for (int i = 0; i < numberOfThreads; i++)
430             createThread(&threadFunc, tester, "testing thread");
431         while (tester->m_threadsToFinish) {
432             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
433             yield();
434         }
435         delete tester;
436     }
437 
438     virtual void runThread() = 0;
439 
440 protected:
441     static const int numberOfThreads = 10;
442     static const int gcPerThread = 5;
443     static const int numberOfAllocations = 50;
444 
ThreadedTesterBase()445     ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
446     {
447     }
448 
~ThreadedTesterBase()449     virtual ~ThreadedTesterBase()
450     {
451     }
452 
done() const453     inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
454 
455     volatile int m_gcCount;
456     volatile int m_threadsToFinish;
457 
458 private:
threadFunc(void * data)459     static void threadFunc(void* data)
460     {
461         reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
462     }
463 };
464 
465 class ThreadedHeapTester : public ThreadedTesterBase {
466 public:
test()467     static void test()
468     {
469         ThreadedTesterBase::test(new ThreadedHeapTester);
470     }
471 
472 protected:
runThread()473     virtual void runThread() OVERRIDE
474     {
475         ThreadState::attach();
476 
477         int gcCount = 0;
478         while (!done()) {
479             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
480             {
481                 Persistent<IntWrapper> wrapper;
482 
483                 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
484                 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
485 
486                 for (int i = 0; i < numberOfAllocations; i++) {
487                     wrapper = IntWrapper::create(0x0bbac0de);
488                     if (!(i % 10)) {
489                         globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
490                     }
491                     ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
492                     yield();
493                 }
494 
495                 if (gcCount < gcPerThread) {
496                     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
497                     gcCount++;
498                     atomicIncrement(&m_gcCount);
499                 }
500 
501                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
502                 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
503                 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
504             }
505             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
506             yield();
507         }
508         ThreadState::detach();
509         atomicDecrement(&m_threadsToFinish);
510     }
511 };
512 
513 class ThreadedWeaknessTester : public ThreadedTesterBase {
514 public:
test()515     static void test()
516     {
517         ThreadedTesterBase::test(new ThreadedWeaknessTester);
518     }
519 
520 private:
runThread()521     virtual void runThread() OVERRIDE
522     {
523         ThreadState::attach();
524 
525         int gcCount = 0;
526         while (!done()) {
527             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
528             {
529                 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
530                 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
531 
532                 for (int i = 0; i < numberOfAllocations; i++) {
533                     weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
534                     weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
535                     ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
536                     yield();
537                 }
538 
539                 if (gcCount < gcPerThread) {
540                     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
541                     gcCount++;
542                     atomicIncrement(&m_gcCount);
543                 }
544 
545                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
546                 EXPECT_TRUE(weakMap->isEmpty());
547                 EXPECT_TRUE(weakMap2.isEmpty());
548             }
549             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
550             yield();
551         }
552         ThreadState::detach();
553         atomicDecrement(&m_threadsToFinish);
554     }
555 };
556 
557 // The accounting for memory includes the memory used by rounding up object
558 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
559 // have some slack in the tests.
560 template<typename T>
CheckWithSlack(T expected,T actual,int slack)561 void CheckWithSlack(T expected, T actual, int slack)
562 {
563     EXPECT_LE(expected, actual);
564     EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
565 }
566 
567 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
568 public:
create()569     static TraceCounter* create()
570     {
571         return new TraceCounter();
572     }
573 
trace(Visitor *)574     void trace(Visitor*) { m_traceCount++; }
575 
traceCount()576     int traceCount() { return m_traceCount; }
577 
578 private:
TraceCounter()579     TraceCounter()
580         : m_traceCount(0)
581     {
582     }
583 
584     int m_traceCount;
585 };
586 
587 class ClassWithMember : public GarbageCollected<ClassWithMember> {
588 public:
create()589     static ClassWithMember* create()
590     {
591         return new ClassWithMember();
592     }
593 
trace(Visitor * visitor)594     void trace(Visitor* visitor)
595     {
596         EXPECT_TRUE(visitor->isMarked(this));
597         if (!traceCount())
598             EXPECT_FALSE(visitor->isMarked(m_traceCounter));
599         else
600             EXPECT_TRUE(visitor->isMarked(m_traceCounter));
601 
602         visitor->trace(m_traceCounter);
603     }
604 
traceCount()605     int traceCount() { return m_traceCounter->traceCount(); }
606 
607 private:
ClassWithMember()608     ClassWithMember()
609         : m_traceCounter(TraceCounter::create())
610     { }
611 
612     Member<TraceCounter> m_traceCounter;
613 };
614 
615 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
616 public:
create()617     static SimpleFinalizedObject* create()
618     {
619         return new SimpleFinalizedObject();
620     }
621 
~SimpleFinalizedObject()622     ~SimpleFinalizedObject()
623     {
624         ++s_destructorCalls;
625     }
626 
627     static int s_destructorCalls;
628 
trace(Visitor *)629     void trace(Visitor*) { }
630 
631 private:
SimpleFinalizedObject()632     SimpleFinalizedObject() { }
633 };
634 
635 int SimpleFinalizedObject::s_destructorCalls = 0;
636 
637 class TestTypedHeapClass : public GarbageCollected<TestTypedHeapClass> {
638 public:
create()639     static TestTypedHeapClass* create()
640     {
641         return new TestTypedHeapClass();
642     }
643 
trace(Visitor *)644     void trace(Visitor*) { }
645 
646 private:
TestTypedHeapClass()647     TestTypedHeapClass() { }
648 };
649 
650 class Bar : public GarbageCollectedFinalized<Bar> {
651 public:
create()652     static Bar* create()
653     {
654         return new Bar();
655     }
656 
finalizeGarbageCollectedObject()657     void finalizeGarbageCollectedObject()
658     {
659         EXPECT_TRUE(m_magic == magic);
660         m_magic = 0;
661         s_live--;
662     }
hasBeenFinalized() const663     bool hasBeenFinalized() const { return !m_magic; }
664 
trace(Visitor * visitor)665     virtual void trace(Visitor* visitor) { }
666     static unsigned s_live;
667 
668 protected:
669     static const int magic = 1337;
670     int m_magic;
671 
Bar()672     Bar()
673         : m_magic(magic)
674     {
675         s_live++;
676     }
677 };
678 
679 unsigned Bar::s_live = 0;
680 
681 class Baz : public GarbageCollected<Baz> {
682 public:
create(Bar * bar)683     static Baz* create(Bar* bar)
684     {
685         return new Baz(bar);
686     }
687 
trace(Visitor * visitor)688     void trace(Visitor* visitor)
689     {
690         visitor->trace(m_bar);
691     }
692 
clear()693     void clear() { m_bar.release(); }
694 
695     // willFinalize is called by FinalizationObserver.
willFinalize()696     void willFinalize()
697     {
698         EXPECT_TRUE(!m_bar->hasBeenFinalized());
699     }
700 
701 private:
Baz(Bar * bar)702     explicit Baz(Bar* bar)
703         : m_bar(bar)
704     {
705     }
706 
707     Member<Bar> m_bar;
708 };
709 
710 class Foo : public Bar {
711 public:
create(Bar * bar)712     static Foo* create(Bar* bar)
713     {
714         return new Foo(bar);
715     }
716 
create(Foo * foo)717     static Foo* create(Foo* foo)
718     {
719         return new Foo(foo);
720     }
721 
trace(Visitor * visitor)722     virtual void trace(Visitor* visitor) OVERRIDE
723     {
724         if (m_pointsToFoo)
725             visitor->mark(static_cast<Foo*>(m_bar));
726         else
727             visitor->mark(m_bar);
728     }
729 
730 private:
Foo(Bar * bar)731     Foo(Bar* bar)
732         : Bar()
733         , m_bar(bar)
734         , m_pointsToFoo(false)
735     {
736     }
737 
Foo(Foo * foo)738     Foo(Foo* foo)
739         : Bar()
740         , m_bar(foo)
741         , m_pointsToFoo(true)
742     {
743     }
744 
745     Bar* m_bar;
746     bool m_pointsToFoo;
747 };
748 
749 class Bars : public Bar {
750 public:
create()751     static Bars* create()
752     {
753         return new Bars();
754     }
755 
trace(Visitor * visitor)756     virtual void trace(Visitor* visitor) OVERRIDE
757     {
758         for (unsigned i = 0; i < m_width; i++)
759             visitor->trace(m_bars[i]);
760     }
761 
getWidth() const762     unsigned getWidth() const
763     {
764         return m_width;
765     }
766 
767     static const unsigned width = 7500;
768 private:
Bars()769     Bars() : m_width(0)
770     {
771         for (unsigned i = 0; i < width; i++) {
772             m_bars[i] = Bar::create();
773             m_width++;
774         }
775     }
776 
777     unsigned m_width;
778     Member<Bar> m_bars[width];
779 };
780 
781 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
782 public:
create()783     static ConstructorAllocation* create() { return new ConstructorAllocation(); }
784 
trace(Visitor * visitor)785     void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
786 
787 private:
ConstructorAllocation()788     ConstructorAllocation()
789     {
790         m_intWrapper = IntWrapper::create(42);
791     }
792 
793     Member<IntWrapper> m_intWrapper;
794 };
795 
796 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
797 public:
~LargeObject()798     ~LargeObject()
799     {
800         s_destructorCalls++;
801     }
create()802     static LargeObject* create() { return new LargeObject(); }
get(size_t i)803     char get(size_t i) { return m_data[i]; }
set(size_t i,char c)804     void set(size_t i, char c) { m_data[i] = c; }
length()805     size_t length() { return s_length; }
trace(Visitor * visitor)806     void trace(Visitor* visitor)
807     {
808         visitor->trace(m_intWrapper);
809     }
810     static int s_destructorCalls;
811 
812 private:
813     static const size_t s_length = 1024*1024;
LargeObject()814     LargeObject()
815     {
816         m_intWrapper = IntWrapper::create(23);
817     }
818     Member<IntWrapper> m_intWrapper;
819     char m_data[s_length];
820 };
821 
822 int LargeObject::s_destructorCalls = 0;
823 
824 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
825 public:
create()826     static PassRefPtr<RefCountedAndGarbageCollected> create()
827     {
828         return adoptRef(new RefCountedAndGarbageCollected());
829     }
830 
~RefCountedAndGarbageCollected()831     ~RefCountedAndGarbageCollected()
832     {
833         ++s_destructorCalls;
834     }
835 
836     // These are here with their default implementations so you can break in
837     // them in the debugger.
ref()838     void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref(); }
deref()839     void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::deref(); }
840 
trace(Visitor *)841     void trace(Visitor*) { }
842 
843     static int s_destructorCalls;
844 
845 private:
RefCountedAndGarbageCollected()846     RefCountedAndGarbageCollected()
847     {
848     }
849 };
850 
851 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
852 
853 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
854 public:
create()855     static RefCountedAndGarbageCollected2* create()
856     {
857         return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
858     }
859 
~RefCountedAndGarbageCollected2()860     ~RefCountedAndGarbageCollected2()
861     {
862         ++s_destructorCalls;
863     }
864 
trace(Visitor *)865     void trace(Visitor*) { }
866 
867     static int s_destructorCalls;
868 
869 private:
RefCountedAndGarbageCollected2()870     RefCountedAndGarbageCollected2()
871     {
872     }
873 };
874 
875 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
876 
877 #define DEFINE_VISITOR_METHODS(Type)                                       \
878     virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
879     {                                                                      \
880         mark(object);                                                      \
881     }                                                                      \
882 
883 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
884 public:
RefCountedGarbageCollectedVisitor(int expected,void ** objects)885     RefCountedGarbageCollectedVisitor(int expected, void** objects)
886         : m_count(0)
887         , m_expectedCount(expected)
888         , m_expectedObjects(objects)
889     {
890     }
891 
mark(const void * ptr)892     void mark(const void* ptr) { markNoTrace(ptr); }
893 
markNoTrace(const void * ptr)894     virtual void markNoTrace(const void* ptr)
895     {
896         if (!ptr)
897             return;
898         if (m_count < m_expectedCount)
899             EXPECT_TRUE(expectedObject(ptr));
900         else
901             EXPECT_FALSE(expectedObject(ptr));
902         m_count++;
903     }
904 
mark(const void * ptr,TraceCallback)905     virtual void mark(const void* ptr, TraceCallback) OVERRIDE
906     {
907         mark(ptr);
908     }
909 
mark(HeapObjectHeader * header,TraceCallback callback)910     virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
911     {
912         mark(header->payload());
913     }
914 
mark(FinalizedHeapObjectHeader * header,TraceCallback callback)915     virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
916     {
917         mark(header->payload());
918     }
919 
validate()920     bool validate() { return m_count >= m_expectedCount; }
reset()921     void reset() { m_count = 0; }
922 
923     FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
924 
925 private:
expectedObject(const void * ptr)926     bool expectedObject(const void* ptr)
927     {
928         for (int i = 0; i < m_expectedCount; i++) {
929             if (m_expectedObjects[i] == ptr)
930                 return true;
931         }
932         return false;
933     }
934 
935     int m_count;
936     int m_expectedCount;
937     void** m_expectedObjects;
938 };
939 
940 #undef DEFINE_VISITOR_METHODS
941 
942 class Weak : public Bar {
943 public:
create(Bar * strong,Bar * weak)944     static Weak* create(Bar* strong, Bar* weak)
945     {
946         return new Weak(strong, weak);
947     }
948 
trace(Visitor * visitor)949     virtual void trace(Visitor* visitor) OVERRIDE
950     {
951         visitor->trace(m_strongBar);
952         visitor->registerWeakMembers(this, zapWeakMembers);
953     }
954 
zapWeakMembers(Visitor * visitor,void * self)955     static void zapWeakMembers(Visitor* visitor, void* self)
956     {
957         reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
958     }
959 
strongIsThere()960     bool strongIsThere() { return !!m_strongBar; }
weakIsThere()961     bool weakIsThere() { return !!m_weakBar; }
962 
963 private:
Weak(Bar * strongBar,Bar * weakBar)964     Weak(Bar* strongBar, Bar* weakBar)
965         : Bar()
966         , m_strongBar(strongBar)
967         , m_weakBar(weakBar)
968     {
969     }
970 
zapWeakMembers(Visitor * visitor)971     void zapWeakMembers(Visitor* visitor)
972     {
973         if (!visitor->isAlive(m_weakBar))
974             m_weakBar = 0;
975     }
976 
977     Member<Bar> m_strongBar;
978     Bar* m_weakBar;
979 };
980 
981 class WithWeakMember : public Bar {
982 public:
create(Bar * strong,Bar * weak)983     static WithWeakMember* create(Bar* strong, Bar* weak)
984     {
985         return new WithWeakMember(strong, weak);
986     }
987 
trace(Visitor * visitor)988     virtual void trace(Visitor* visitor) OVERRIDE
989     {
990         visitor->trace(m_strongBar);
991         visitor->trace(m_weakBar);
992     }
993 
strongIsThere()994     bool strongIsThere() { return !!m_strongBar; }
weakIsThere()995     bool weakIsThere() { return !!m_weakBar; }
996 
997 private:
WithWeakMember(Bar * strongBar,Bar * weakBar)998     WithWeakMember(Bar* strongBar, Bar* weakBar)
999         : Bar()
1000         , m_strongBar(strongBar)
1001         , m_weakBar(weakBar)
1002     {
1003     }
1004 
1005     Member<Bar> m_strongBar;
1006     WeakMember<Bar> m_weakBar;
1007 };
1008 
1009 class Observable : public GarbageCollectedFinalized<Observable> {
1010 public:
create(Bar * bar)1011     static Observable* create(Bar* bar) { return new Observable(bar);  }
~Observable()1012     ~Observable() { m_wasDestructed = true; }
trace(Visitor * visitor)1013     void trace(Visitor* visitor) { visitor->trace(m_bar); }
1014 
1015     // willFinalize is called by FinalizationObserver. willFinalize can touch
1016     // other on-heap objects.
willFinalize()1017     void willFinalize()
1018     {
1019         EXPECT_FALSE(m_wasDestructed);
1020         EXPECT_FALSE(m_bar->hasBeenFinalized());
1021     }
1022 
1023 private:
Observable(Bar * bar)1024     explicit Observable(Bar* bar)
1025         : m_bar(bar)
1026         , m_wasDestructed(false)
1027     {
1028     }
1029 
1030     Member<Bar> m_bar;
1031     bool m_wasDestructed;
1032 };
1033 
1034 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
1035 public:
create(T * data)1036     static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
didCallWillFinalize() const1037     bool didCallWillFinalize() const { return m_didCallWillFinalize; }
1038 
trace(Visitor * visitor)1039     void trace(Visitor* visitor)
1040     {
1041         visitor->registerWeakMembers(this, zapWeakMembers);
1042     }
1043 
1044 private:
FinalizationObserver(T * data)1045     FinalizationObserver(T* data)
1046         : m_data(data)
1047         , m_didCallWillFinalize(false)
1048     {
1049     }
1050 
zapWeakMembers(Visitor * visitor,void * self)1051     static void zapWeakMembers(Visitor* visitor, void* self)
1052     {
1053         FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
1054         if (o->m_data && !visitor->isAlive(o->m_data)) {
1055             o->m_data->willFinalize();
1056             o->m_data = nullptr;
1057             o->m_didCallWillFinalize = true;
1058         }
1059     }
1060 
1061     WeakMember<T> m_data;
1062     bool m_didCallWillFinalize;
1063 };
1064 
1065 class FinalizationObserverWithHashMap {
1066 public:
1067     typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
1068 
FinalizationObserverWithHashMap(Observable & target)1069     explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
~FinalizationObserverWithHashMap()1070     ~FinalizationObserverWithHashMap()
1071     {
1072         m_target.willFinalize();
1073         s_didCallWillFinalize = true;
1074     }
1075 
observe(Observable & target)1076     static ObserverMap& observe(Observable& target)
1077     {
1078         ObserverMap& map = observers();
1079         ObserverMap::AddResult result = map.add(&target, nullptr);
1080         if (result.isNewEntry)
1081             result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
1082         else
1083             ASSERT(result.storedValue->value);
1084         return map;
1085     }
1086 
1087     static bool s_didCallWillFinalize;
1088 
1089 private:
observers()1090     static ObserverMap& observers()
1091     {
1092         DEFINE_STATIC_LOCAL(Persistent<ObserverMap>, observerMap, ());
1093         if (!observerMap)
1094             observerMap = new ObserverMap();
1095         return *observerMap;
1096     }
1097 
1098     Observable& m_target;
1099 };
1100 
1101 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
1102 
1103 class SuperClass;
1104 
1105 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
1106 public:
create()1107     static PassRefPtrWillBeRawPtr<PointsBack> create()
1108     {
1109         return adoptRefWillBeNoop(new PointsBack());
1110     }
1111 
~PointsBack()1112     ~PointsBack()
1113     {
1114         --s_aliveCount;
1115     }
1116 
setBackPointer(SuperClass * backPointer)1117     void setBackPointer(SuperClass* backPointer)
1118     {
1119         m_backPointer = backPointer;
1120     }
1121 
backPointer() const1122     SuperClass* backPointer() const { return m_backPointer; }
1123 
trace(Visitor * visitor)1124     void trace(Visitor* visitor)
1125     {
1126 #if ENABLE_OILPAN
1127         visitor->trace(m_backPointer);
1128 #endif
1129     }
1130 
1131     static int s_aliveCount;
1132 private:
PointsBack()1133     PointsBack() : m_backPointer(nullptr)
1134     {
1135         ++s_aliveCount;
1136     }
1137 
1138     RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1139 };
1140 
1141 int PointsBack::s_aliveCount = 0;
1142 
1143 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1144 public:
create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1145     static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1146     {
1147         return adoptRefWillBeNoop(new SuperClass(pointsBack));
1148     }
1149 
~SuperClass()1150     virtual ~SuperClass()
1151     {
1152 #if !ENABLE_OILPAN
1153         m_pointsBack->setBackPointer(0);
1154 #endif
1155         --s_aliveCount;
1156     }
1157 
doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass,PointsBack * pointsBack,int superClassCount)1158     void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1159     {
1160         RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1161         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1162         EXPECT_EQ(pointsBack, target->pointsBack());
1163         EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1164     }
1165 
trace(Visitor * visitor)1166     virtual void trace(Visitor* visitor)
1167     {
1168 #if ENABLE_OILPAN
1169         visitor->trace(m_pointsBack);
1170 #endif
1171     }
1172 
pointsBack() const1173     PointsBack* pointsBack() const { return m_pointsBack.get(); }
1174 
1175     static int s_aliveCount;
1176 protected:
SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1177     explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1178         : m_pointsBack(pointsBack)
1179     {
1180         m_pointsBack->setBackPointer(this);
1181         ++s_aliveCount;
1182     }
1183 
1184 private:
1185     RefPtrWillBeMember<PointsBack> m_pointsBack;
1186 };
1187 
1188 int SuperClass::s_aliveCount = 0;
1189 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1190 public:
SubData()1191     SubData() { ++s_aliveCount; }
~SubData()1192     ~SubData() { --s_aliveCount; }
1193 
trace(Visitor *)1194     void trace(Visitor*) { }
1195 
1196     static int s_aliveCount;
1197 };
1198 
1199 int SubData::s_aliveCount = 0;
1200 
1201 class SubClass : public SuperClass {
1202 public:
create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1203     static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1204     {
1205         return adoptRefWillBeNoop(new SubClass(pointsBack));
1206     }
1207 
~SubClass()1208     virtual ~SubClass()
1209     {
1210         --s_aliveCount;
1211     }
1212 
trace(Visitor * visitor)1213     virtual void trace(Visitor* visitor)
1214     {
1215 #if ENABLE_OILPAN
1216         SuperClass::trace(visitor);
1217         visitor->trace(m_data);
1218 #endif
1219     }
1220 
1221     static int s_aliveCount;
1222 private:
SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1223     explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1224         : SuperClass(pointsBack)
1225         , m_data(adoptPtrWillBeNoop(new SubData()))
1226     {
1227         ++s_aliveCount;
1228     }
1229 
1230 private:
1231     OwnPtrWillBeMember<SubData> m_data;
1232 };
1233 
1234 int SubClass::s_aliveCount = 0;
1235 
1236 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1237 public:
create()1238     static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1239     {
1240         return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
1241     }
1242 
~TransitionRefCounted()1243     ~TransitionRefCounted()
1244     {
1245         --s_aliveCount;
1246     }
1247 
trace(Visitor * visitor)1248     void trace(Visitor* visitor) { }
1249 
1250     static int s_aliveCount;
1251 
1252 private:
TransitionRefCounted()1253     TransitionRefCounted()
1254     {
1255         ++s_aliveCount;
1256     }
1257 };
1258 
1259 int TransitionRefCounted::s_aliveCount = 0;
1260 
1261 class Mixin : public GarbageCollectedMixin {
1262 public:
trace(Visitor * visitor)1263     virtual void trace(Visitor* visitor) { }
1264 
getPayload(int i)1265     virtual char getPayload(int i) { return m_padding[i]; }
1266 
1267 protected:
1268     int m_padding[8];
1269 };
1270 
1271 class UseMixin : public SimpleObject, public Mixin {
1272     USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1273 public:
create()1274     static UseMixin* create()
1275     {
1276         return new UseMixin();
1277     }
1278 
1279     static int s_traceCount;
trace(Visitor * visitor)1280     virtual void trace(Visitor* visitor)
1281     {
1282         SimpleObject::trace(visitor);
1283         Mixin::trace(visitor);
1284         ++s_traceCount;
1285     }
1286 
1287 private:
UseMixin()1288     UseMixin()
1289     {
1290         s_traceCount = 0;
1291     }
1292 };
1293 
1294 int UseMixin::s_traceCount = 0;
1295 
1296 class VectorObject {
1297     ALLOW_ONLY_INLINE_ALLOCATION();
1298 public:
VectorObject()1299     VectorObject()
1300     {
1301         m_value = SimpleFinalizedObject::create();
1302     }
1303 
trace(Visitor * visitor)1304     void trace(Visitor* visitor)
1305     {
1306         visitor->trace(m_value);
1307     }
1308 
1309 private:
1310     Member<SimpleFinalizedObject> m_value;
1311 };
1312 
1313 class VectorObjectInheritedTrace : public VectorObject { };
1314 
1315 class VectorObjectNoTrace {
1316     ALLOW_ONLY_INLINE_ALLOCATION();
1317 public:
VectorObjectNoTrace()1318     VectorObjectNoTrace()
1319     {
1320         m_value = SimpleFinalizedObject::create();
1321     }
1322 
1323 private:
1324     Member<SimpleFinalizedObject> m_value;
1325 };
1326 
1327 class TerminatedArrayItem {
1328     ALLOW_ONLY_INLINE_ALLOCATION();
1329 public:
TerminatedArrayItem(IntWrapper * payload)1330     TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1331 
trace(Visitor * visitor)1332     void trace(Visitor* visitor) { visitor->trace(m_payload); }
1333 
isLastInArray() const1334     bool isLastInArray() const { return m_isLast; }
setLastInArray(bool value)1335     void setLastInArray(bool value) { m_isLast = value; }
1336 
payload() const1337     IntWrapper* payload() const { return m_payload; }
1338 
1339 private:
1340     Member<IntWrapper> m_payload;
1341     bool m_isLast;
1342 };
1343 
1344 } // WebCore namespace
1345 
1346 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::VectorObject);
1347 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::VectorObjectInheritedTrace);
1348 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(WebCore::VectorObjectNoTrace);
1349 
1350 namespace WebCore {
1351 
1352 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1353 public:
~OneKiloByteObject()1354     ~OneKiloByteObject() { s_destructorCalls++; }
data()1355     char* data() { return m_data; }
trace(Visitor * visitor)1356     void trace(Visitor* visitor) { }
1357     static int s_destructorCalls;
1358 
1359 private:
1360     static const size_t s_length = 1024;
1361     char m_data[s_length];
1362 };
1363 
1364 int OneKiloByteObject::s_destructorCalls = 0;
1365 
1366 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1367 public:
create(size_t size)1368     static DynamicallySizedObject* create(size_t size)
1369     {
1370         void* slot = Heap::allocate<DynamicallySizedObject>(size);
1371         return new (slot) DynamicallySizedObject();
1372     }
1373 
operator new(std::size_t,void * location)1374     void* operator new(std::size_t, void* location)
1375     {
1376         return location;
1377     }
1378 
get(int i)1379     uint8_t get(int i)
1380     {
1381         return *(reinterpret_cast<uint8_t*>(this) + i);
1382     }
1383 
trace(Visitor *)1384     void trace(Visitor*) { }
1385 
1386 private:
DynamicallySizedObject()1387     DynamicallySizedObject() { }
1388 };
1389 
1390 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1391 public:
FinalizationAllocator(Persistent<IntWrapper> * wrapper)1392     FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1393         : m_wrapper(wrapper)
1394     {
1395     }
1396 
~FinalizationAllocator()1397     ~FinalizationAllocator()
1398     {
1399         for (int i = 0; i < 10; ++i)
1400             *m_wrapper = IntWrapper::create(42);
1401         for (int i = 0; i < 512; ++i)
1402             new OneKiloByteObject();
1403     }
1404 
trace(Visitor *)1405     void trace(Visitor*) { }
1406 
1407 private:
1408     Persistent<IntWrapper>* m_wrapper;
1409 };
1410 
TEST(HeapTest,Transition)1411 TEST(HeapTest, Transition)
1412 {
1413     {
1414         RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1415         EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1416         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1417         EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1418     }
1419     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1420     EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1421 
1422     RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1423     RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1424     RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1425     RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1426     EXPECT_EQ(2, PointsBack::s_aliveCount);
1427     EXPECT_EQ(2, SuperClass::s_aliveCount);
1428     EXPECT_EQ(1, SubClass::s_aliveCount);
1429     EXPECT_EQ(1, SubData::s_aliveCount);
1430 
1431     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1432     EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1433     EXPECT_EQ(2, PointsBack::s_aliveCount);
1434     EXPECT_EQ(2, SuperClass::s_aliveCount);
1435     EXPECT_EQ(1, SubClass::s_aliveCount);
1436     EXPECT_EQ(1, SubData::s_aliveCount);
1437 
1438     superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1439     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1440     EXPECT_EQ(2, PointsBack::s_aliveCount);
1441     EXPECT_EQ(1, SuperClass::s_aliveCount);
1442     EXPECT_EQ(1, SubClass::s_aliveCount);
1443     EXPECT_EQ(1, SubData::s_aliveCount);
1444     EXPECT_EQ(0, pointsBack1->backPointer());
1445 
1446     pointsBack1.release();
1447     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1448     EXPECT_EQ(1, PointsBack::s_aliveCount);
1449     EXPECT_EQ(1, SuperClass::s_aliveCount);
1450     EXPECT_EQ(1, SubClass::s_aliveCount);
1451     EXPECT_EQ(1, SubData::s_aliveCount);
1452 
1453     subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1454     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1455     EXPECT_EQ(1, PointsBack::s_aliveCount);
1456     EXPECT_EQ(0, SuperClass::s_aliveCount);
1457     EXPECT_EQ(0, SubClass::s_aliveCount);
1458     EXPECT_EQ(0, SubData::s_aliveCount);
1459     EXPECT_EQ(0, pointsBack2->backPointer());
1460 
1461     pointsBack2.release();
1462     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1463     EXPECT_EQ(0, PointsBack::s_aliveCount);
1464     EXPECT_EQ(0, SuperClass::s_aliveCount);
1465     EXPECT_EQ(0, SubClass::s_aliveCount);
1466     EXPECT_EQ(0, SubData::s_aliveCount);
1467 
1468     EXPECT_TRUE(superClass == subClass);
1469 }
1470 
TEST(HeapTest,Threading)1471 TEST(HeapTest, Threading)
1472 {
1473     ThreadedHeapTester::test();
1474 }
1475 
TEST(HeapTest,ThreadedWeakness)1476 TEST(HeapTest, ThreadedWeakness)
1477 {
1478     ThreadedWeaknessTester::test();
1479 }
1480 
TEST(HeapTest,BasicFunctionality)1481 TEST(HeapTest, BasicFunctionality)
1482 {
1483     HeapStats heapStats;
1484     clearOutOldGarbage(&heapStats);
1485     {
1486         size_t slack = 0;
1487 
1488         // When the test starts there may already have been leaked some memory
1489         // on the heap, so we establish a base line.
1490         size_t baseLevel = heapStats.totalObjectSpace();
1491         bool testPagesAllocated = !baseLevel;
1492         if (testPagesAllocated)
1493             EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1494 
1495         // This allocates objects on the general heap which should add a page of memory.
1496         DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1497         slack += 4;
1498         memset(alloc32, 40, 32);
1499         DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1500         slack += 4;
1501         memset(alloc64, 27, 64);
1502 
1503         size_t total = 96;
1504 
1505         getHeapStats(&heapStats);
1506         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1507         if (testPagesAllocated)
1508             EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1509 
1510         CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
1511 
1512         EXPECT_EQ(alloc32->get(0), 40);
1513         EXPECT_EQ(alloc32->get(31), 40);
1514         EXPECT_EQ(alloc64->get(0), 27);
1515         EXPECT_EQ(alloc64->get(63), 27);
1516 
1517         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1518 
1519         EXPECT_EQ(alloc32->get(0), 40);
1520         EXPECT_EQ(alloc32->get(31), 40);
1521         EXPECT_EQ(alloc64->get(0), 27);
1522         EXPECT_EQ(alloc64->get(63), 27);
1523     }
1524 
1525     clearOutOldGarbage(&heapStats);
1526     size_t total = 0;
1527     size_t slack = 0;
1528     size_t baseLevel = heapStats.totalObjectSpace();
1529     bool testPagesAllocated = !baseLevel;
1530     if (testPagesAllocated)
1531         EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1532 
1533     size_t big = 1008;
1534     Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1535     total += big;
1536     slack += 4;
1537 
1538     size_t persistentCount = 0;
1539     const size_t numPersistents = 100000;
1540     Persistent<DynamicallySizedObject>* persistents[numPersistents];
1541 
1542     for (int i = 0; i < 1000; i++) {
1543         size_t size = 128 + i * 8;
1544         total += size;
1545         persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1546         slack += 4;
1547         getHeapStats(&heapStats);
1548         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1549         if (testPagesAllocated)
1550             EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1551     }
1552 
1553     {
1554         DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1555         slack += 4;
1556         memset(alloc32b, 40, 32);
1557         DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1558         slack += 4;
1559         memset(alloc64b, 27, 64);
1560         EXPECT_TRUE(alloc32b != alloc64b);
1561 
1562         total += 96;
1563         getHeapStats(&heapStats);
1564         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1565         if (testPagesAllocated)
1566             EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1567     }
1568 
1569     clearOutOldGarbage(&heapStats);
1570     total -= 96;
1571     slack -= 8;
1572     if (testPagesAllocated)
1573         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1574 
1575     DynamicallySizedObject* bigAreaRaw = bigArea;
1576     // Clear the persistent, so that the big area will be garbage collected.
1577     bigArea.release();
1578     clearOutOldGarbage(&heapStats);
1579 
1580     total -= big;
1581     slack -= 4;
1582     getHeapStats(&heapStats);
1583     CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1584     if (testPagesAllocated)
1585         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1586 
1587     // Endless loop unless we eventually get the memory back that we just freed.
1588     while (true) {
1589         Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
1590         slack += 4;
1591         persistents[persistentCount++] = alloc;
1592         EXPECT_LT(persistentCount, numPersistents);
1593         total += big / 2;
1594         if (bigAreaRaw == alloc->get())
1595             break;
1596     }
1597 
1598     getHeapStats(&heapStats);
1599     CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1600     if (testPagesAllocated)
1601         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1602 
1603     for (size_t i = 0; i < persistentCount; i++) {
1604         delete persistents[i];
1605         persistents[i] = 0;
1606     }
1607 
1608     uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1609     for (int i = 0; i < 100; i++)
1610         address[i] = i;
1611     address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1612     for (int i = 0; i < 100; i++)
1613         EXPECT_EQ(address[i], i);
1614     address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1615     for (int i = 0; i < 50; i++)
1616         EXPECT_EQ(address[i], i);
1617     // This should be equivalent to free(address).
1618     EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1619     // This should be equivalent to malloc(0).
1620     EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1621 }
1622 
TEST(HeapTest,SimpleAllocation)1623 TEST(HeapTest, SimpleAllocation)
1624 {
1625     HeapStats initialHeapStats;
1626     clearOutOldGarbage(&initialHeapStats);
1627     EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1628 
1629     // Allocate an object in the heap.
1630     HeapAllocatedArray* array = new HeapAllocatedArray();
1631     HeapStats statsAfterAllocation;
1632     getHeapStats(&statsAfterAllocation);
1633     EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1634 
1635     // Sanity check of the contents in the heap.
1636     EXPECT_EQ(0, array->at(0));
1637     EXPECT_EQ(42, array->at(42));
1638     EXPECT_EQ(0, array->at(128));
1639     EXPECT_EQ(999 % 128, array->at(999));
1640 }
1641 
TEST(HeapTest,SimplePersistent)1642 TEST(HeapTest, SimplePersistent)
1643 {
1644     Persistent<TraceCounter> traceCounter = TraceCounter::create();
1645     EXPECT_EQ(0, traceCounter->traceCount());
1646 
1647     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1648     EXPECT_EQ(1, traceCounter->traceCount());
1649 
1650     Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1651     EXPECT_EQ(0, classWithMember->traceCount());
1652 
1653     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1654     EXPECT_EQ(1, classWithMember->traceCount());
1655     EXPECT_EQ(2, traceCounter->traceCount());
1656 }
1657 
TEST(HeapTest,SimpleFinalization)1658 TEST(HeapTest, SimpleFinalization)
1659 {
1660     {
1661         Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1662         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1663         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1664         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1665     }
1666 
1667     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1668     EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1669 }
1670 
TEST(HeapTest,Finalization)1671 TEST(HeapTest, Finalization)
1672 {
1673     {
1674         HeapTestSubClass* t1 = HeapTestSubClass::create();
1675         HeapTestSubClass* t2 = HeapTestSubClass::create();
1676         HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1677         // FIXME(oilpan): Ignore unused variables.
1678         (void)t1;
1679         (void)t2;
1680         (void)t3;
1681     }
1682     // Nothing is marked so the GC should free everything and call
1683     // the finalizer on all three objects.
1684     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1685     EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1686     EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1687     // Destructors not called again when GCing again.
1688     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1689     EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1690     EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1691 }
1692 
TEST(HeapTest,TypedHeapSanity)1693 TEST(HeapTest, TypedHeapSanity)
1694 {
1695     // We use TraceCounter for allocating an object on the general heap.
1696     Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1697     Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create();
1698     EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get())),
1699         pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get())));
1700 }
1701 
TEST(HeapTest,NoAllocation)1702 TEST(HeapTest, NoAllocation)
1703 {
1704     EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1705     {
1706         // Disallow allocation
1707         NoAllocationScope<AnyThread> noAllocationScope;
1708         EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1709     }
1710     EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1711 }
1712 
TEST(HeapTest,Members)1713 TEST(HeapTest, Members)
1714 {
1715     Bar::s_live = 0;
1716     {
1717         Persistent<Baz> h1;
1718         Persistent<Baz> h2;
1719         {
1720             h1 = Baz::create(Bar::create());
1721             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1722             EXPECT_EQ(1u, Bar::s_live);
1723             h2 = Baz::create(Bar::create());
1724             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1725             EXPECT_EQ(2u, Bar::s_live);
1726         }
1727         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1728         EXPECT_EQ(2u, Bar::s_live);
1729         h1->clear();
1730         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1731         EXPECT_EQ(1u, Bar::s_live);
1732     }
1733     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1734     EXPECT_EQ(0u, Bar::s_live);
1735 }
1736 
TEST(HeapTest,MarkTest)1737 TEST(HeapTest, MarkTest)
1738 {
1739     {
1740         Bar::s_live = 0;
1741         Persistent<Bar> bar = Bar::create();
1742         EXPECT_TRUE(ThreadState::current()->contains(bar));
1743         EXPECT_EQ(1u, Bar::s_live);
1744         {
1745             Foo* foo = Foo::create(bar);
1746             EXPECT_TRUE(ThreadState::current()->contains(foo));
1747             EXPECT_EQ(2u, Bar::s_live);
1748             EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1749             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1750             EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1751             EXPECT_EQ(2u, Bar::s_live);
1752         }
1753         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1754         EXPECT_EQ(1u, Bar::s_live);
1755     }
1756     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1757     EXPECT_EQ(0u, Bar::s_live);
1758 }
1759 
TEST(HeapTest,DeepTest)1760 TEST(HeapTest, DeepTest)
1761 {
1762     const unsigned depth = 100000;
1763     Bar::s_live = 0;
1764     {
1765         Bar* bar = Bar::create();
1766         EXPECT_TRUE(ThreadState::current()->contains(bar));
1767         Foo* foo = Foo::create(bar);
1768         EXPECT_TRUE(ThreadState::current()->contains(foo));
1769         EXPECT_EQ(2u, Bar::s_live);
1770         for (unsigned i = 0; i < depth; i++) {
1771             Foo* foo2 = Foo::create(foo);
1772             foo = foo2;
1773             EXPECT_TRUE(ThreadState::current()->contains(foo));
1774         }
1775         EXPECT_EQ(depth + 2, Bar::s_live);
1776         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1777         EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1778         EXPECT_EQ(depth + 2, Bar::s_live);
1779     }
1780     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1781     EXPECT_EQ(0u, Bar::s_live);
1782 }
1783 
TEST(HeapTest,WideTest)1784 TEST(HeapTest, WideTest)
1785 {
1786     Bar::s_live = 0;
1787     {
1788         Bars* bars = Bars::create();
1789         unsigned width = Bars::width;
1790         EXPECT_EQ(width + 1, Bar::s_live);
1791         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1792         EXPECT_EQ(width + 1, Bar::s_live);
1793         // Use bars here to make sure that it will be on the stack
1794         // for the conservative stack scan to find.
1795         EXPECT_EQ(width, bars->getWidth());
1796     }
1797     EXPECT_EQ(Bars::width + 1, Bar::s_live);
1798     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1799     EXPECT_EQ(0u, Bar::s_live);
1800 }
1801 
TEST(HeapTest,HashMapOfMembers)1802 TEST(HeapTest, HashMapOfMembers)
1803 {
1804     HeapStats initialHeapSize;
1805     IntWrapper::s_destructorCalls = 0;
1806 
1807     clearOutOldGarbage(&initialHeapSize);
1808     {
1809         typedef HeapHashMap<
1810             Member<IntWrapper>,
1811             Member<IntWrapper>,
1812             DefaultHash<Member<IntWrapper> >::Hash,
1813             HashTraits<Member<IntWrapper> >,
1814             HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1815 
1816         Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1817 
1818         map->clear();
1819         HeapStats afterSetWasCreated;
1820         getHeapStats(&afterSetWasCreated);
1821         EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1822 
1823         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1824         HeapStats afterGC;
1825         getHeapStats(&afterGC);
1826         EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1827 
1828         // If the additions below cause garbage collections, these
1829         // pointers should be found by conservative stack scanning.
1830         IntWrapper* one(IntWrapper::create(1));
1831         IntWrapper* anotherOne(IntWrapper::create(1));
1832 
1833         map->add(one, one);
1834 
1835         HeapStats afterOneAdd;
1836         getHeapStats(&afterOneAdd);
1837         EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1838 
1839         HeapObjectIdentityMap::iterator it(map->begin());
1840         HeapObjectIdentityMap::iterator it2(map->begin());
1841         ++it;
1842         ++it2;
1843 
1844         map->add(anotherOne, one);
1845 
1846         // The addition above can cause an allocation of a new
1847         // backing store. We therefore garbage collect before
1848         // taking the heap stats in order to get rid of the old
1849         // backing store. We make sure to not use conservative
1850         // stack scanning as that could find a pointer to the
1851         // old backing.
1852         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1853         HeapStats afterAddAndGC;
1854         getHeapStats(&afterAddAndGC);
1855         EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1856 
1857         EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1858 
1859         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1860         EXPECT_TRUE(map->contains(one));
1861         EXPECT_TRUE(map->contains(anotherOne));
1862 
1863         IntWrapper* gotten(map->get(one));
1864         EXPECT_EQ(gotten->value(), one->value());
1865         EXPECT_EQ(gotten, one);
1866 
1867         HeapStats afterGC2;
1868         getHeapStats(&afterGC2);
1869         EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1870 
1871         IntWrapper* dozen = 0;
1872 
1873         for (int i = 1; i < 1000; i++) { // 999 iterations.
1874             IntWrapper* iWrapper(IntWrapper::create(i));
1875             IntWrapper* iSquared(IntWrapper::create(i * i));
1876             map->add(iWrapper, iSquared);
1877             if (i == 12)
1878                 dozen = iWrapper;
1879         }
1880         HeapStats afterAdding1000;
1881         getHeapStats(&afterAdding1000);
1882         EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1883 
1884         IntWrapper* gross(map->get(dozen));
1885         EXPECT_EQ(gross->value(), 144);
1886 
1887         // This should clear out junk created by all the adds.
1888         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1889         HeapStats afterGC3;
1890         getHeapStats(&afterGC3);
1891         EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1892     }
1893 
1894     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1895     // The objects 'one', anotherOne, and the 999 other pairs.
1896     EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1897     HeapStats afterGC4;
1898     getHeapStats(&afterGC4);
1899     EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1900 }
1901 
TEST(HeapTest,NestedAllocation)1902 TEST(HeapTest, NestedAllocation)
1903 {
1904     HeapStats initialHeapSize;
1905     clearOutOldGarbage(&initialHeapSize);
1906     {
1907         Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1908     }
1909     HeapStats afterFree;
1910     clearOutOldGarbage(&afterFree);
1911     EXPECT_TRUE(initialHeapSize == afterFree);
1912 }
1913 
TEST(HeapTest,LargeObjects)1914 TEST(HeapTest, LargeObjects)
1915 {
1916     HeapStats initialHeapSize;
1917     clearOutOldGarbage(&initialHeapSize);
1918     IntWrapper::s_destructorCalls = 0;
1919     LargeObject::s_destructorCalls = 0;
1920     {
1921         int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1922         Persistent<LargeObject> object = LargeObject::create();
1923         EXPECT_TRUE(ThreadState::current()->contains(object));
1924         EXPECT_TRUE(ThreadState::current()->contains(reinterpret_cast<char*>(object.get()) + sizeof(LargeObject) - 1));
1925 #if ENABLE(GC_TRACING)
1926         const GCInfo* info = ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()));
1927         EXPECT_NE(reinterpret_cast<const GCInfo*>(0), info);
1928         EXPECT_EQ(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject) - 1));
1929         EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject)));
1930         EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) - 1));
1931 #endif
1932         HeapStats afterAllocation;
1933         clearOutOldGarbage(&afterAllocation);
1934         {
1935             object->set(0, 'a');
1936             EXPECT_EQ('a', object->get(0));
1937             object->set(object->length() - 1, 'b');
1938             EXPECT_EQ('b', object->get(object->length() - 1));
1939             size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1940             size_t actualObjectSpace =
1941                 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1942             CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1943             // There is probably space for the IntWrapper in a heap page without
1944             // allocating extra pages. However, the IntWrapper allocation might cause
1945             // the addition of a heap page.
1946             size_t largeObjectAllocationSize =
1947                 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1948             size_t allocatedSpaceLowerBound =
1949                 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1950             size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1951             EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1952             EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1953             EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1954             EXPECT_EQ(0, LargeObject::s_destructorCalls);
1955             for (int i = 0; i < 10; i++)
1956                 object = LargeObject::create();
1957         }
1958         HeapStats oneLargeObject;
1959         clearOutOldGarbage(&oneLargeObject);
1960         EXPECT_TRUE(oneLargeObject == afterAllocation);
1961         EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1962         EXPECT_EQ(10, LargeObject::s_destructorCalls);
1963     }
1964     HeapStats backToInitial;
1965     clearOutOldGarbage(&backToInitial);
1966     EXPECT_TRUE(initialHeapSize == backToInitial);
1967     EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1968     EXPECT_EQ(11, LargeObject::s_destructorCalls);
1969     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1970 }
1971 
1972 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1973 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1974 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1975 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1976 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1977 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1978 
1979 class Container : public GarbageCollected<Container> {
1980 public:
create()1981     static Container* create() { return new Container(); }
1982     HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1983     HeapHashSet<Member<IntWrapper> > set;
1984     HeapHashSet<Member<IntWrapper> > set2;
1985     HeapHashCountedSet<Member<IntWrapper> > set3;
1986     HeapVector<Member<IntWrapper>, 2> vector;
1987     HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1988     HeapVector<PairUnwrappedWrapped, 2> vectorUW;
1989     HeapDeque<Member<IntWrapper>, 0> deque;
1990     HeapDeque<PairWrappedUnwrapped, 0> dequeWU;
1991     HeapDeque<PairUnwrappedWrapped, 0> dequeUW;
trace(Visitor * visitor)1992     void trace(Visitor* visitor)
1993     {
1994         visitor->trace(map);
1995         visitor->trace(set);
1996         visitor->trace(set2);
1997         visitor->trace(set3);
1998         visitor->trace(vector);
1999         visitor->trace(vectorWU);
2000         visitor->trace(vectorUW);
2001         visitor->trace(deque);
2002         visitor->trace(dequeWU);
2003         visitor->trace(dequeUW);
2004     }
2005 };
2006 
2007 struct ShouldBeTraced {
ShouldBeTracedWebCore::ShouldBeTraced2008     explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
traceWebCore::ShouldBeTraced2009     void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
2010     Member<IntWrapper> m_wrapper;
2011 };
2012 
2013 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
2014 public:
create()2015     static OffHeapContainer* create() { return new OffHeapContainer(); }
2016 
2017     static const int iterations = 300;
2018     static const int deadWrappers = 2700;
2019 
OffHeapContainer()2020     OffHeapContainer()
2021     {
2022         for (int i = 0; i < iterations; i++) {
2023             m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
2024             m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
2025             m_deque2.append(IntWrapper::create(i));
2026             m_vector2.append(IntWrapper::create(i));
2027             m_hashSet.add(IntWrapper::create(i));
2028             m_hashMap.add(i + 103, IntWrapper::create(i));
2029             m_listHashSet.add(IntWrapper::create(i));
2030             m_linkedHashSet.add(IntWrapper::create(i));
2031             m_ownedVector.append(adoptPtr(new ShouldBeTraced(IntWrapper::create(i))));
2032         }
2033 
2034         Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
2035         Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
2036         Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
2037         Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
2038         HashSet<Member<IntWrapper> >::iterator setIterator(m_hashSet.begin());
2039         HashMap<int, Member<IntWrapper> >::iterator mapIterator(m_hashMap.begin());
2040         ListHashSet<Member<IntWrapper> >::iterator listSetIterator(m_listHashSet.begin());
2041         LinkedHashSet<Member<IntWrapper> >::iterator linkedSetIterator(m_linkedHashSet.begin());
2042         Vector<OwnPtr<ShouldBeTraced> >::iterator ownedVectorIterator(m_ownedVector.begin());
2043 
2044         for (int i = 0; i < iterations; i++) {
2045             EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
2046             EXPECT_EQ(i, m_vector2[i]->value());
2047             EXPECT_EQ(i, d1Iterator->m_wrapper->value());
2048             EXPECT_EQ(i, v1Iterator->m_wrapper->value());
2049             EXPECT_EQ(i, d2Iterator->get()->value());
2050             EXPECT_EQ(i, v2Iterator->get()->value());
2051             EXPECT_EQ(i, linkedSetIterator->get()->value());
2052             EXPECT_EQ(i, listSetIterator->get()->value());
2053             EXPECT_EQ(i, ownedVectorIterator->get()->m_wrapper->value());
2054             int value = setIterator->get()->value();
2055             EXPECT_LE(0, value);
2056             EXPECT_GT(iterations, value);
2057             value = mapIterator->value.get()->value();
2058             EXPECT_LE(0, value);
2059             EXPECT_GT(iterations, value);
2060             ++d1Iterator;
2061             ++v1Iterator;
2062             ++d2Iterator;
2063             ++v2Iterator;
2064             ++setIterator;
2065             ++mapIterator;
2066             ++listSetIterator;
2067             ++linkedSetIterator;
2068             ++ownedVectorIterator;
2069         }
2070         EXPECT_EQ(d1Iterator, m_deque1.end());
2071         EXPECT_EQ(v1Iterator, m_vector1.end());
2072         EXPECT_EQ(d2Iterator, m_deque2.end());
2073         EXPECT_EQ(v2Iterator, m_vector2.end());
2074         EXPECT_EQ(setIterator, m_hashSet.end());
2075         EXPECT_EQ(mapIterator, m_hashMap.end());
2076         EXPECT_EQ(listSetIterator, m_listHashSet.end());
2077         EXPECT_EQ(linkedSetIterator, m_linkedHashSet.end());
2078         EXPECT_EQ(ownedVectorIterator, m_ownedVector.end());
2079     }
2080 
trace(Visitor * visitor)2081     void trace(Visitor* visitor)
2082     {
2083         visitor->trace(m_deque1);
2084         visitor->trace(m_vector1);
2085         visitor->trace(m_deque2);
2086         visitor->trace(m_vector2);
2087         visitor->trace(m_hashSet);
2088         visitor->trace(m_hashMap);
2089         visitor->trace(m_listHashSet);
2090         visitor->trace(m_linkedHashSet);
2091         visitor->trace(m_listHashSet);
2092         visitor->trace(m_ownedVector);
2093     }
2094 
2095     Deque<ShouldBeTraced> m_deque1;
2096     Vector<ShouldBeTraced> m_vector1;
2097     Deque<Member<IntWrapper> > m_deque2;
2098     Vector<Member<IntWrapper> > m_vector2;
2099     HashSet<Member<IntWrapper> > m_hashSet;
2100     HashMap<int, Member<IntWrapper> > m_hashMap;
2101     ListHashSet<Member<IntWrapper> > m_listHashSet;
2102     LinkedHashSet<Member<IntWrapper> > m_linkedHashSet;
2103     Vector<OwnPtr<ShouldBeTraced> > m_ownedVector;
2104 };
2105 
2106 const int OffHeapContainer::iterations;
2107 const int OffHeapContainer::deadWrappers;
2108 
2109 // These class definitions test compile-time asserts with transition
2110 // types. They are therefore unused in test code and just need to
2111 // compile. This is intentional; do not delete the A and B classes below.
2112 class A : public WillBeGarbageCollectedMixin {
2113 };
2114 
2115 class B : public NoBaseWillBeGarbageCollected<B>, public A {
2116     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
2117 public:
trace(Visitor *)2118     void trace(Visitor*) { }
2119 };
2120 
TEST(HeapTest,HeapVectorFilledWithValue)2121 TEST(HeapTest, HeapVectorFilledWithValue)
2122 {
2123     IntWrapper* val = IntWrapper::create(1);
2124     HeapVector<Member<IntWrapper> > vector(10, val);
2125     EXPECT_EQ(10u, vector.size());
2126     for (size_t i = 0; i < vector.size(); i++)
2127         EXPECT_EQ(val, vector[i]);
2128 }
2129 
TEST(HeapTest,HeapVectorWithInlineCapacity)2130 TEST(HeapTest, HeapVectorWithInlineCapacity)
2131 {
2132     IntWrapper* one = IntWrapper::create(1);
2133     IntWrapper* two = IntWrapper::create(2);
2134     IntWrapper* three = IntWrapper::create(3);
2135     IntWrapper* four = IntWrapper::create(4);
2136     IntWrapper* five = IntWrapper::create(5);
2137     IntWrapper* six = IntWrapper::create(6);
2138     {
2139         HeapVector<Member<IntWrapper>, 2> vector;
2140         vector.append(one);
2141         vector.append(two);
2142         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2143         EXPECT_TRUE(vector.contains(one));
2144         EXPECT_TRUE(vector.contains(two));
2145 
2146         vector.append(three);
2147         vector.append(four);
2148         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2149         EXPECT_TRUE(vector.contains(one));
2150         EXPECT_TRUE(vector.contains(two));
2151         EXPECT_TRUE(vector.contains(three));
2152         EXPECT_TRUE(vector.contains(four));
2153 
2154         vector.shrink(1);
2155         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2156         EXPECT_TRUE(vector.contains(one));
2157         EXPECT_FALSE(vector.contains(two));
2158         EXPECT_FALSE(vector.contains(three));
2159         EXPECT_FALSE(vector.contains(four));
2160     }
2161     {
2162         HeapVector<Member<IntWrapper>, 2> vector1;
2163         HeapVector<Member<IntWrapper>, 2> vector2;
2164 
2165         vector1.append(one);
2166         vector2.append(two);
2167         vector1.swap(vector2);
2168         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2169         EXPECT_TRUE(vector1.contains(two));
2170         EXPECT_TRUE(vector2.contains(one));
2171     }
2172     {
2173         HeapVector<Member<IntWrapper>, 2> vector1;
2174         HeapVector<Member<IntWrapper>, 2> vector2;
2175 
2176         vector1.append(one);
2177         vector1.append(two);
2178         vector2.append(three);
2179         vector2.append(four);
2180         vector2.append(five);
2181         vector2.append(six);
2182         vector1.swap(vector2);
2183         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2184         EXPECT_TRUE(vector1.contains(three));
2185         EXPECT_TRUE(vector1.contains(four));
2186         EXPECT_TRUE(vector1.contains(five));
2187         EXPECT_TRUE(vector1.contains(six));
2188         EXPECT_TRUE(vector2.contains(one));
2189         EXPECT_TRUE(vector2.contains(two));
2190     }
2191 }
2192 
2193 template<typename T, size_t inlineCapacity, typename U>
dequeContains(HeapDeque<T,inlineCapacity> & deque,U u)2194 bool dequeContains(HeapDeque<T, inlineCapacity>& deque, U u)
2195 {
2196     typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
2197     for (iterator it = deque.begin(); it != deque.end(); ++it) {
2198         if (*it == u)
2199             return true;
2200     }
2201     return false;
2202 }
2203 
TEST(HeapTest,HeapCollectionTypes)2204 TEST(HeapTest, HeapCollectionTypes)
2205 {
2206     HeapStats initialHeapSize;
2207     IntWrapper::s_destructorCalls = 0;
2208 
2209     typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
2210     typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2211     typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
2212 
2213     typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2214     typedef HeapHashCountedSet<Member<IntWrapper> > MemberCountedSet;
2215 
2216     typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2217     typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
2218 
2219     typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2220     typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2221     typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
2222     typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
2223 
2224     Persistent<MemberMember> memberMember = new MemberMember();
2225     Persistent<MemberMember> memberMember2 = new MemberMember();
2226     Persistent<MemberMember> memberMember3 = new MemberMember();
2227     Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2228     Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2229     Persistent<MemberSet> set = new MemberSet();
2230     Persistent<MemberSet> set2 = new MemberSet();
2231     Persistent<MemberCountedSet> set3 = new MemberCountedSet();
2232     Persistent<MemberVector> vector = new MemberVector();
2233     Persistent<MemberVector> vector2 = new MemberVector();
2234     Persistent<VectorWU> vectorWU = new VectorWU();
2235     Persistent<VectorWU> vectorWU2 = new VectorWU();
2236     Persistent<VectorUW> vectorUW = new VectorUW();
2237     Persistent<VectorUW> vectorUW2 = new VectorUW();
2238     Persistent<MemberDeque> deque = new MemberDeque();
2239     Persistent<MemberDeque> deque2 = new MemberDeque();
2240     Persistent<DequeWU> dequeWU = new DequeWU();
2241     Persistent<DequeWU> dequeWU2 = new DequeWU();
2242     Persistent<DequeUW> dequeUW = new DequeUW();
2243     Persistent<DequeUW> dequeUW2 = new DequeUW();
2244     Persistent<Container> container = Container::create();
2245 
2246     clearOutOldGarbage(&initialHeapSize);
2247     {
2248         Persistent<IntWrapper> one(IntWrapper::create(1));
2249         Persistent<IntWrapper> two(IntWrapper::create(2));
2250         Persistent<IntWrapper> oneB(IntWrapper::create(1));
2251         Persistent<IntWrapper> twoB(IntWrapper::create(2));
2252         Persistent<IntWrapper> oneC(IntWrapper::create(1));
2253         Persistent<IntWrapper> oneD(IntWrapper::create(1));
2254         Persistent<IntWrapper> oneE(IntWrapper::create(1));
2255         Persistent<IntWrapper> oneF(IntWrapper::create(1));
2256         {
2257             IntWrapper* threeB(IntWrapper::create(3));
2258             IntWrapper* threeC(IntWrapper::create(3));
2259             IntWrapper* threeD(IntWrapper::create(3));
2260             IntWrapper* threeE(IntWrapper::create(3));
2261             IntWrapper* threeF(IntWrapper::create(3));
2262             IntWrapper* three(IntWrapper::create(3));
2263             IntWrapper* fourB(IntWrapper::create(4));
2264             IntWrapper* fourC(IntWrapper::create(4));
2265             IntWrapper* fourD(IntWrapper::create(4));
2266             IntWrapper* fourE(IntWrapper::create(4));
2267             IntWrapper* fourF(IntWrapper::create(4));
2268             IntWrapper* four(IntWrapper::create(4));
2269             IntWrapper* fiveC(IntWrapper::create(5));
2270             IntWrapper* fiveD(IntWrapper::create(5));
2271             IntWrapper* fiveE(IntWrapper::create(5));
2272             IntWrapper* fiveF(IntWrapper::create(5));
2273 
2274             // Member Collections.
2275             memberMember2->add(one, two);
2276             memberMember2->add(two, three);
2277             memberMember2->add(three, four);
2278             memberMember2->add(four, one);
2279             primitiveMember->add(1, two);
2280             primitiveMember->add(2, three);
2281             primitiveMember->add(3, four);
2282             primitiveMember->add(4, one);
2283             memberPrimitive->add(one, 2);
2284             memberPrimitive->add(two, 3);
2285             memberPrimitive->add(three, 4);
2286             memberPrimitive->add(four, 1);
2287             set2->add(one);
2288             set2->add(two);
2289             set2->add(three);
2290             set2->add(four);
2291             set->add(oneB);
2292             set3->add(oneB);
2293             set3->add(oneB);
2294             vector->append(oneB);
2295             deque->append(oneB);
2296             vector2->append(threeB);
2297             vector2->append(fourB);
2298             deque2->append(threeE);
2299             deque2->append(fourE);
2300             vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2301             dequeWU->append(PairWrappedUnwrapped(&*oneE, 42));
2302             vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2303             vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2304             vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2305             dequeWU2->append(PairWrappedUnwrapped(&*threeE, 43));
2306             dequeWU2->append(PairWrappedUnwrapped(&*fourE, 44));
2307             dequeWU2->append(PairWrappedUnwrapped(&*fiveE, 45));
2308             vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2309             vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2310             vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2311             vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2312             dequeUW->append(PairUnwrappedWrapped(1, &*oneF));
2313             dequeUW2->append(PairUnwrappedWrapped(103, &*threeF));
2314             dequeUW2->append(PairUnwrappedWrapped(104, &*fourF));
2315             dequeUW2->append(PairUnwrappedWrapped(105, &*fiveF));
2316 
2317             EXPECT_TRUE(dequeContains(*deque, oneB));
2318 
2319             // Collect garbage. This should change nothing since we are keeping
2320             // alive the IntWrapper objects with on-stack pointers.
2321             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2322 
2323             EXPECT_TRUE(dequeContains(*deque, oneB));
2324 
2325             EXPECT_EQ(0u, memberMember->size());
2326             EXPECT_EQ(4u, memberMember2->size());
2327             EXPECT_EQ(4u, primitiveMember->size());
2328             EXPECT_EQ(4u, memberPrimitive->size());
2329             EXPECT_EQ(1u, set->size());
2330             EXPECT_EQ(4u, set2->size());
2331             EXPECT_EQ(1u, set3->size());
2332             EXPECT_EQ(1u, vector->size());
2333             EXPECT_EQ(2u, vector2->size());
2334             EXPECT_EQ(1u, vectorWU->size());
2335             EXPECT_EQ(3u, vectorWU2->size());
2336             EXPECT_EQ(1u, vectorUW->size());
2337             EXPECT_EQ(3u, vectorUW2->size());
2338             EXPECT_EQ(1u, deque->size());
2339             EXPECT_EQ(2u, deque2->size());
2340             EXPECT_EQ(1u, dequeWU->size());
2341             EXPECT_EQ(3u, dequeWU2->size());
2342             EXPECT_EQ(1u, dequeUW->size());
2343             EXPECT_EQ(3u, dequeUW2->size());
2344 
2345             MemberVector& cvec = container->vector;
2346             cvec.swap(*vector.get());
2347             vector2->swap(cvec);
2348             vector->swap(cvec);
2349 
2350             VectorWU& cvecWU = container->vectorWU;
2351             cvecWU.swap(*vectorWU.get());
2352             vectorWU2->swap(cvecWU);
2353             vectorWU->swap(cvecWU);
2354 
2355             VectorUW& cvecUW = container->vectorUW;
2356             cvecUW.swap(*vectorUW.get());
2357             vectorUW2->swap(cvecUW);
2358             vectorUW->swap(cvecUW);
2359 
2360             MemberDeque& cDeque = container->deque;
2361             cDeque.swap(*deque.get());
2362             deque2->swap(cDeque);
2363             deque->swap(cDeque);
2364 
2365             DequeWU& cDequeWU = container->dequeWU;
2366             cDequeWU.swap(*dequeWU.get());
2367             dequeWU2->swap(cDequeWU);
2368             dequeWU->swap(cDequeWU);
2369 
2370             DequeUW& cDequeUW = container->dequeUW;
2371             cDequeUW.swap(*dequeUW.get());
2372             dequeUW2->swap(cDequeUW);
2373             dequeUW->swap(cDequeUW);
2374 
2375             // Swap set and set2 in a roundabout way.
2376             MemberSet& cset1 = container->set;
2377             MemberSet& cset2 = container->set2;
2378             set->swap(cset1);
2379             set2->swap(cset2);
2380             set->swap(cset2);
2381             cset1.swap(cset2);
2382             cset2.swap(set2);
2383 
2384             MemberCountedSet& cCountedSet = container->set3;
2385             set3->swap(cCountedSet);
2386             EXPECT_EQ(0u, set3->size());
2387             set3->swap(cCountedSet);
2388 
2389             // Triple swap.
2390             container->map.swap(memberMember2);
2391             MemberMember& containedMap = container->map;
2392             memberMember3->swap(containedMap);
2393             memberMember3->swap(memberMember);
2394 
2395             EXPECT_TRUE(memberMember->get(one) == two);
2396             EXPECT_TRUE(memberMember->get(two) == three);
2397             EXPECT_TRUE(memberMember->get(three) == four);
2398             EXPECT_TRUE(memberMember->get(four) == one);
2399             EXPECT_TRUE(primitiveMember->get(1) == two);
2400             EXPECT_TRUE(primitiveMember->get(2) == three);
2401             EXPECT_TRUE(primitiveMember->get(3) == four);
2402             EXPECT_TRUE(primitiveMember->get(4) == one);
2403             EXPECT_EQ(1, memberPrimitive->get(four));
2404             EXPECT_EQ(2, memberPrimitive->get(one));
2405             EXPECT_EQ(3, memberPrimitive->get(two));
2406             EXPECT_EQ(4, memberPrimitive->get(three));
2407             EXPECT_TRUE(set->contains(one));
2408             EXPECT_TRUE(set->contains(two));
2409             EXPECT_TRUE(set->contains(three));
2410             EXPECT_TRUE(set->contains(four));
2411             EXPECT_TRUE(set2->contains(oneB));
2412             EXPECT_TRUE(set3->contains(oneB));
2413             EXPECT_TRUE(vector->contains(threeB));
2414             EXPECT_TRUE(vector->contains(fourB));
2415             EXPECT_TRUE(dequeContains(*deque, threeE));
2416             EXPECT_TRUE(dequeContains(*deque, fourE));
2417             EXPECT_TRUE(vector2->contains(oneB));
2418             EXPECT_FALSE(vector2->contains(threeB));
2419             EXPECT_TRUE(dequeContains(*deque2, oneB));
2420             EXPECT_FALSE(dequeContains(*deque2, threeE));
2421             EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2422             EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2423             EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2424             EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2425             EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2426             EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2427             EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2428             EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2429             EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2430             EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2431             EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*threeE, 43)));
2432             EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fourE, 44)));
2433             EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fiveE, 45)));
2434             EXPECT_TRUE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*oneE, 42)));
2435             EXPECT_FALSE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*threeE, 43)));
2436             EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(103, &*threeF)));
2437             EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(104, &*fourF)));
2438             EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(105, &*fiveF)));
2439             EXPECT_TRUE(dequeContains(*dequeUW2, PairUnwrappedWrapped(1, &*oneF)));
2440             EXPECT_FALSE(dequeContains(*dequeUW2, PairUnwrappedWrapped(103, &*threeF)));
2441         }
2442 
2443         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2444 
2445         EXPECT_EQ(4u, memberMember->size());
2446         EXPECT_EQ(0u, memberMember2->size());
2447         EXPECT_EQ(4u, primitiveMember->size());
2448         EXPECT_EQ(4u, memberPrimitive->size());
2449         EXPECT_EQ(4u, set->size());
2450         EXPECT_EQ(1u, set2->size());
2451         EXPECT_EQ(1u, set3->size());
2452         EXPECT_EQ(2u, vector->size());
2453         EXPECT_EQ(1u, vector2->size());
2454         EXPECT_EQ(3u, vectorUW->size());
2455         EXPECT_EQ(1u, vector2->size());
2456         EXPECT_EQ(2u, deque->size());
2457         EXPECT_EQ(1u, deque2->size());
2458         EXPECT_EQ(3u, dequeUW->size());
2459         EXPECT_EQ(1u, deque2->size());
2460 
2461         EXPECT_TRUE(memberMember->get(one) == two);
2462         EXPECT_TRUE(primitiveMember->get(1) == two);
2463         EXPECT_TRUE(primitiveMember->get(4) == one);
2464         EXPECT_EQ(2, memberPrimitive->get(one));
2465         EXPECT_EQ(3, memberPrimitive->get(two));
2466         EXPECT_TRUE(set->contains(one));
2467         EXPECT_TRUE(set->contains(two));
2468         EXPECT_FALSE(set->contains(oneB));
2469         EXPECT_TRUE(set2->contains(oneB));
2470         EXPECT_TRUE(set3->contains(oneB));
2471         EXPECT_EQ(2u, set3->find(oneB)->value);
2472         EXPECT_EQ(3, vector->at(0)->value());
2473         EXPECT_EQ(4, vector->at(1)->value());
2474         EXPECT_EQ(3, deque->begin()->get()->value());
2475     }
2476 
2477     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2478     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2479 
2480     EXPECT_EQ(4u, memberMember->size());
2481     EXPECT_EQ(4u, primitiveMember->size());
2482     EXPECT_EQ(4u, memberPrimitive->size());
2483     EXPECT_EQ(4u, set->size());
2484     EXPECT_EQ(1u, set2->size());
2485     EXPECT_EQ(2u, vector->size());
2486     EXPECT_EQ(1u, vector2->size());
2487     EXPECT_EQ(3u, vectorWU->size());
2488     EXPECT_EQ(1u, vectorWU2->size());
2489     EXPECT_EQ(3u, vectorUW->size());
2490     EXPECT_EQ(1u, vectorUW2->size());
2491     EXPECT_EQ(2u, deque->size());
2492     EXPECT_EQ(1u, deque2->size());
2493     EXPECT_EQ(3u, dequeWU->size());
2494     EXPECT_EQ(1u, dequeWU2->size());
2495     EXPECT_EQ(3u, dequeUW->size());
2496     EXPECT_EQ(1u, dequeUW2->size());
2497 }
2498 
2499 template<typename T>
MapIteratorCheck(T & it,const T & end,int expected)2500 void MapIteratorCheck(T& it, const T& end, int expected)
2501 {
2502     int found = 0;
2503     while (it != end) {
2504         found++;
2505         int key = it->key->value();
2506         int value = it->value->value();
2507         EXPECT_TRUE(key >= 0 && key < 1100);
2508         EXPECT_TRUE(value >= 0 && value < 1100);
2509         ++it;
2510     }
2511     EXPECT_EQ(expected, found);
2512 }
2513 
2514 template<typename T>
SetIteratorCheck(T & it,const T & end,int expected)2515 void SetIteratorCheck(T& it, const T& end, int expected)
2516 {
2517     int found = 0;
2518     while (it != end) {
2519         found++;
2520         int value = (*it)->value();
2521         EXPECT_TRUE(value >= 0 && value < 1100);
2522         ++it;
2523     }
2524     EXPECT_EQ(expected, found);
2525 }
2526 
TEST(HeapTest,HeapWeakCollectionSimple)2527 TEST(HeapTest, HeapWeakCollectionSimple)
2528 {
2529     HeapStats initialHeapStats;
2530     clearOutOldGarbage(&initialHeapStats);
2531     IntWrapper::s_destructorCalls = 0;
2532 
2533     PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2534 
2535     typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2536     typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2537     typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2538     typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2539     typedef HeapHashCountedSet<WeakMember<IntWrapper> > WeakCountedSet;
2540 
2541     Persistent<WeakStrong> weakStrong = new WeakStrong();
2542     Persistent<StrongWeak> strongWeak = new StrongWeak();
2543     Persistent<WeakWeak> weakWeak = new WeakWeak();
2544     Persistent<WeakSet> weakSet = new WeakSet();
2545     Persistent<WeakCountedSet> weakCountedSet = new WeakCountedSet();
2546 
2547     Persistent<IntWrapper> two = IntWrapper::create(2);
2548 
2549     keepNumbersAlive.append(IntWrapper::create(103));
2550     keepNumbersAlive.append(IntWrapper::create(10));
2551 
2552     {
2553         weakStrong->add(IntWrapper::create(1), two);
2554         strongWeak->add(two, IntWrapper::create(1));
2555         weakWeak->add(two, IntWrapper::create(42));
2556         weakWeak->add(IntWrapper::create(42), two);
2557         weakSet->add(IntWrapper::create(0));
2558         weakSet->add(two);
2559         weakSet->add(keepNumbersAlive[0]);
2560         weakSet->add(keepNumbersAlive[1]);
2561         weakCountedSet->add(IntWrapper::create(0));
2562         weakCountedSet->add(two);
2563         weakCountedSet->add(two);
2564         weakCountedSet->add(two);
2565         weakCountedSet->add(keepNumbersAlive[0]);
2566         weakCountedSet->add(keepNumbersAlive[1]);
2567         EXPECT_EQ(1u, weakStrong->size());
2568         EXPECT_EQ(1u, strongWeak->size());
2569         EXPECT_EQ(2u, weakWeak->size());
2570         EXPECT_EQ(4u, weakSet->size());
2571         EXPECT_EQ(4u, weakCountedSet->size());
2572         EXPECT_EQ(3u, weakCountedSet->find(two)->value);
2573         weakCountedSet->remove(two);
2574         EXPECT_EQ(2u, weakCountedSet->find(two)->value);
2575     }
2576 
2577     keepNumbersAlive[0] = nullptr;
2578 
2579     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2580 
2581     EXPECT_EQ(0u, weakStrong->size());
2582     EXPECT_EQ(0u, strongWeak->size());
2583     EXPECT_EQ(0u, weakWeak->size());
2584     EXPECT_EQ(2u, weakSet->size());
2585     EXPECT_EQ(2u, weakCountedSet->size());
2586 }
2587 
2588 template<typename Set>
orderedSetHelper(bool strong)2589 void orderedSetHelper(bool strong)
2590 {
2591     HeapStats initialHeapStats;
2592     clearOutOldGarbage(&initialHeapStats);
2593     IntWrapper::s_destructorCalls = 0;
2594 
2595     PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2596 
2597     Persistent<Set> set1 = new Set();
2598     Persistent<Set> set2 = new Set();
2599 
2600     const Set& constSet = *set1.get();
2601 
2602     keepNumbersAlive.append(IntWrapper::create(2));
2603     keepNumbersAlive.append(IntWrapper::create(103));
2604     keepNumbersAlive.append(IntWrapper::create(10));
2605 
2606     set1->add(IntWrapper::create(0));
2607     set1->add(keepNumbersAlive[0]);
2608     set1->add(keepNumbersAlive[1]);
2609     set1->add(keepNumbersAlive[2]);
2610 
2611     set2->clear();
2612     set2->add(IntWrapper::create(42));
2613     set2->clear();
2614 
2615     EXPECT_EQ(4u, set1->size());
2616     typename Set::iterator it(set1->begin());
2617     typename Set::reverse_iterator reverse(set1->rbegin());
2618     typename Set::const_iterator cit(constSet.begin());
2619     typename Set::const_reverse_iterator creverse(constSet.rbegin());
2620 
2621     EXPECT_EQ(0, (*it)->value());
2622     EXPECT_EQ(0, (*cit)->value());
2623     ++it;
2624     ++cit;
2625     EXPECT_EQ(2, (*it)->value());
2626     EXPECT_EQ(2, (*cit)->value());
2627     --it;
2628     --cit;
2629     EXPECT_EQ(0, (*it)->value());
2630     EXPECT_EQ(0, (*cit)->value());
2631     ++it;
2632     ++cit;
2633     ++it;
2634     ++cit;
2635     EXPECT_EQ(103, (*it)->value());
2636     EXPECT_EQ(103, (*cit)->value());
2637     ++it;
2638     ++cit;
2639     EXPECT_EQ(10, (*it)->value());
2640     EXPECT_EQ(10, (*cit)->value());
2641     ++it;
2642     ++cit;
2643 
2644     EXPECT_EQ(10, (*reverse)->value());
2645     EXPECT_EQ(10, (*creverse)->value());
2646     ++reverse;
2647     ++creverse;
2648     EXPECT_EQ(103, (*reverse)->value());
2649     EXPECT_EQ(103, (*creverse)->value());
2650     --reverse;
2651     --creverse;
2652     EXPECT_EQ(10, (*reverse)->value());
2653     EXPECT_EQ(10, (*creverse)->value());
2654     ++reverse;
2655     ++creverse;
2656     ++reverse;
2657     ++creverse;
2658     EXPECT_EQ(2, (*reverse)->value());
2659     EXPECT_EQ(2, (*creverse)->value());
2660     ++reverse;
2661     ++creverse;
2662     EXPECT_EQ(0, (*reverse)->value());
2663     EXPECT_EQ(0, (*creverse)->value());
2664     ++reverse;
2665     ++creverse;
2666 
2667     EXPECT_EQ(set1->end(), it);
2668     EXPECT_EQ(constSet.end(), cit);
2669     EXPECT_EQ(set1->rend(), reverse);
2670     EXPECT_EQ(constSet.rend(), creverse);
2671 
2672     typename Set::iterator iX(set2->begin());
2673     EXPECT_EQ(set2->end(), iX);
2674 
2675     if (strong)
2676         set1->remove(keepNumbersAlive[0]);
2677 
2678     keepNumbersAlive[0] = nullptr;
2679 
2680     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2681 
2682     EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
2683 
2684     EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
2685 
2686     typename Set::iterator i2(set1->begin());
2687     if (strong) {
2688         EXPECT_EQ(0, (*i2)->value());
2689         ++i2;
2690         EXPECT_NE(set1->end(), i2);
2691     }
2692     EXPECT_EQ(103, (*i2)->value());
2693     ++i2;
2694     EXPECT_NE(set1->end(), i2);
2695     EXPECT_EQ(10, (*i2)->value());
2696     ++i2;
2697     EXPECT_EQ(set1->end(), i2);
2698 }
2699 
TEST(HeapTest,HeapWeakLinkedHashSet)2700 TEST(HeapTest, HeapWeakLinkedHashSet)
2701 {
2702     orderedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
2703     orderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
2704     orderedSetHelper<HeapListHashSet<Member<IntWrapper> > >(true);
2705 }
2706 
2707 class ThingWithDestructor {
2708 public:
ThingWithDestructor()2709     ThingWithDestructor()
2710         : m_x(emptyValue)
2711     {
2712         s_liveThingsWithDestructor++;
2713     }
2714 
ThingWithDestructor(int x)2715     ThingWithDestructor(int x)
2716         : m_x(x)
2717     {
2718         s_liveThingsWithDestructor++;
2719     }
2720 
ThingWithDestructor(const ThingWithDestructor & other)2721     ThingWithDestructor(const ThingWithDestructor&other)
2722     {
2723         *this = other;
2724         s_liveThingsWithDestructor++;
2725     }
2726 
~ThingWithDestructor()2727     ~ThingWithDestructor()
2728     {
2729         s_liveThingsWithDestructor--;
2730     }
2731 
value()2732     int value() { return m_x; }
2733 
2734     static int s_liveThingsWithDestructor;
2735 
hash()2736     unsigned hash() { return IntHash<int>::hash(m_x); }
2737 
2738 private:
2739     static const int emptyValue = 0;
2740     int m_x;
2741 };
2742 
2743 int ThingWithDestructor::s_liveThingsWithDestructor;
2744 
2745 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2746     static const bool needsDestruction = true;
2747 };
2748 
heapMapDestructorHelper(bool clearMaps)2749 static void heapMapDestructorHelper(bool clearMaps)
2750 {
2751     HeapStats initialHeapStats;
2752     clearOutOldGarbage(&initialHeapStats);
2753     ThingWithDestructor::s_liveThingsWithDestructor = 0;
2754 
2755     typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageCollected> > RefMap;
2756 
2757     typedef HeapHashMap<
2758         WeakMember<IntWrapper>,
2759         ThingWithDestructor,
2760         DefaultHash<WeakMember<IntWrapper> >::Hash,
2761         HashTraits<WeakMember<IntWrapper> >,
2762         ThingWithDestructorTraits> Map;
2763 
2764     Persistent<Map> map(new Map());
2765     Persistent<RefMap> refMap(new RefMap());
2766 
2767     Persistent<IntWrapper> luck(IntWrapper::create(103));
2768 
2769     int baseLine, refBaseLine;
2770 
2771     {
2772         Map stackMap;
2773         RefMap stackRefMap;
2774 
2775         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2776         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2777 
2778         stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2779         stackMap.add(luck, ThingWithDestructor(8128));
2780         stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2781         stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2782 
2783         baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2784         refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2785 
2786         // Although the heap maps are on-stack, we can't expect prompt
2787         // finalization of the elements, so when they go out of scope here we
2788         // will not necessarily have called the relevant destructors.
2789     }
2790 
2791     // The RefCountedAndGarbageCollected things need an extra GC to discover
2792     // that they are no longer ref counted.
2793     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2794     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2795     EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2796     EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2797 
2798     // Now use maps kept alive with persistents. Here we don't expect any
2799     // destructors to be called before there have been GCs.
2800 
2801     map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2802     map->add(luck, ThingWithDestructor(8128));
2803     refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2804     refMap->add(luck, RefCountedAndGarbageCollected::create());
2805 
2806     baseLine  =  ThingWithDestructor::s_liveThingsWithDestructor;
2807     refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2808 
2809     luck.clear();
2810     if (clearMaps) {
2811         map->clear(); // Clear map.
2812         refMap->clear(); // Clear map.
2813     } else {
2814         map.clear(); // Clear Persistent handle, not map.
2815         refMap.clear(); // Clear Persistent handle, not map.
2816         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2817         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2818     }
2819 
2820     EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2821 
2822     // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2823     // noticies it's been decremented to zero.
2824     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2825     EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2826 }
2827 
TEST(HeapTest,HeapMapDestructor)2828 TEST(HeapTest, HeapMapDestructor)
2829 {
2830     heapMapDestructorHelper(true);
2831     heapMapDestructorHelper(false);
2832 }
2833 
2834 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2835 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2836 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2837 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2838 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
2839 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
2840 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
2841 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
2842 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
2843 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
2844 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
2845 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
2846 
2847 template<typename T>
iteratorExtractor(WTF::KeyValuePair<T,unsigned> & pair)2848 T& iteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair)
2849 {
2850     return pair.key;
2851 }
2852 
2853 template<typename T>
iteratorExtractor(T & notAPair)2854 T& iteratorExtractor(T& notAPair)
2855 {
2856     return notAPair;
2857 }
2858 
2859 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
checkPairSets(Persistent<WSSet> & weakStrong,Persistent<SWSet> & strongWeak,Persistent<WUSet> & weakUnwrapped,Persistent<UWSet> & unwrappedWeak,bool ones,Persistent<IntWrapper> & two)2860 void checkPairSets(
2861     Persistent<WSSet>& weakStrong,
2862     Persistent<SWSet>& strongWeak,
2863     Persistent<WUSet>& weakUnwrapped,
2864     Persistent<UWSet>& unwrappedWeak,
2865     bool ones,
2866     Persistent<IntWrapper>& two)
2867 {
2868     typename WSSet::iterator itWS = weakStrong->begin();
2869     typename SWSet::iterator itSW = strongWeak->begin();
2870     typename WUSet::iterator itWU = weakUnwrapped->begin();
2871     typename UWSet::iterator itUW = unwrappedWeak->begin();
2872 
2873     EXPECT_EQ(2u, weakStrong->size());
2874     EXPECT_EQ(2u, strongWeak->size());
2875     EXPECT_EQ(2u, weakUnwrapped->size());
2876     EXPECT_EQ(2u, unwrappedWeak->size());
2877 
2878     PairWeakStrong p = iteratorExtractor(*itWS);
2879     PairStrongWeak p2 = iteratorExtractor(*itSW);
2880     PairWeakUnwrapped p3 = iteratorExtractor(*itWU);
2881     PairUnwrappedWeak p4 = iteratorExtractor(*itUW);
2882     if (p.first == two && p.second == two)
2883         ++itWS;
2884     if (p2.first == two && p2.second == two)
2885         ++itSW;
2886     if (p3.first == two && p3.second == 2)
2887         ++itWU;
2888     if (p4.first == 2 && p4.second == two)
2889         ++itUW;
2890     p = iteratorExtractor(*itWS);
2891     p2 = iteratorExtractor(*itSW);
2892     p3 = iteratorExtractor(*itWU);
2893     p4 = iteratorExtractor(*itUW);
2894     IntWrapper* nullWrapper = 0;
2895     if (ones) {
2896         EXPECT_EQ(p.first->value(), 1);
2897         EXPECT_EQ(p2.second->value(), 1);
2898         EXPECT_EQ(p3.first->value(), 1);
2899         EXPECT_EQ(p4.second->value(), 1);
2900     } else {
2901         EXPECT_EQ(p.first, nullWrapper);
2902         EXPECT_EQ(p2.second, nullWrapper);
2903         EXPECT_EQ(p3.first, nullWrapper);
2904         EXPECT_EQ(p4.second, nullWrapper);
2905     }
2906 
2907     EXPECT_EQ(p.second->value(), 2);
2908     EXPECT_EQ(p2.first->value(), 2);
2909     EXPECT_EQ(p3.second, 2);
2910     EXPECT_EQ(p4.first, 2);
2911 
2912     EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2913     EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2914     EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2915     EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2916 }
2917 
2918 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
weakPairsHelper()2919 void weakPairsHelper()
2920 {
2921     IntWrapper::s_destructorCalls = 0;
2922 
2923     PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2924 
2925     Persistent<WSSet> weakStrong = new WSSet();
2926     Persistent<SWSet> strongWeak = new SWSet();
2927     Persistent<WUSet> weakUnwrapped = new WUSet();
2928     Persistent<UWSet> unwrappedWeak = new UWSet();
2929 
2930     Persistent<IntWrapper> two = IntWrapper::create(2);
2931 
2932     weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2933     weakStrong->add(PairWeakStrong(&*two, &*two));
2934     strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2935     strongWeak->add(PairStrongWeak(&*two, &*two));
2936     weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2937     weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2938     unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2939     unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2940 
2941     checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2942 
2943     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2944     checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2945 }
2946 
TEST(HeapTest,HeapWeakPairs)2947 TEST(HeapTest, HeapWeakPairs)
2948 {
2949     {
2950         typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2951         typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2952         typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2953         typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2954         weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2955     }
2956 
2957     {
2958         typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
2959         typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2960         typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
2961         typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2962         weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2963     }
2964 
2965     {
2966         typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
2967         typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2968         typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
2969         typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2970         weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2971     }
2972 }
2973 
TEST(HeapTest,HeapWeakCollectionTypes)2974 TEST(HeapTest, HeapWeakCollectionTypes)
2975 {
2976     HeapStats initialHeapSize;
2977     IntWrapper::s_destructorCalls = 0;
2978 
2979     typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2980     typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2981     typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2982     typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2983     typedef HeapLinkedHashSet<WeakMember<IntWrapper> > WeakOrderedSet;
2984 
2985     clearOutOldGarbage(&initialHeapSize);
2986 
2987     const int weakStrongIndex = 0;
2988     const int strongWeakIndex = 1;
2989     const int weakWeakIndex = 2;
2990     const int numberOfMapIndices = 3;
2991     const int weakSetIndex = 3;
2992     const int weakOrderedSetIndex = 4;
2993     const int numberOfCollections = 5;
2994 
2995     for (int testRun = 0; testRun < 4; testRun++) {
2996         for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2997             bool deleteAfterwards = (testRun == 1);
2998             bool addAfterwards = (testRun == 2);
2999             bool testThatIteratorsMakeStrong = (testRun == 3);
3000 
3001             // The test doesn't work for strongWeak with deleting because we lost
3002             // the key from the keepNumbersAlive array, so we can't do the lookup.
3003             if (deleteAfterwards && collectionNumber == strongWeakIndex)
3004                 continue;
3005 
3006             unsigned added = addAfterwards ? 100 : 0;
3007 
3008             Persistent<WeakStrong> weakStrong = new WeakStrong();
3009             Persistent<StrongWeak> strongWeak = new StrongWeak();
3010             Persistent<WeakWeak> weakWeak = new WeakWeak();
3011 
3012             Persistent<WeakSet> weakSet = new WeakSet();
3013             Persistent<WeakOrderedSet> weakOrderedSet = new WeakOrderedSet();
3014 
3015             PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
3016             for (int i = 0; i < 128; i += 2) {
3017                 IntWrapper* wrapped = IntWrapper::create(i);
3018                 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
3019                 keepNumbersAlive.append(wrapped);
3020                 keepNumbersAlive.append(wrapped2);
3021                 weakStrong->add(wrapped, wrapped2);
3022                 strongWeak->add(wrapped2, wrapped);
3023                 weakWeak->add(wrapped, wrapped2);
3024                 weakSet->add(wrapped);
3025                 weakOrderedSet->add(wrapped);
3026             }
3027 
3028             EXPECT_EQ(64u, weakStrong->size());
3029             EXPECT_EQ(64u, strongWeak->size());
3030             EXPECT_EQ(64u, weakWeak->size());
3031             EXPECT_EQ(64u, weakSet->size());
3032             EXPECT_EQ(64u, weakOrderedSet->size());
3033 
3034             // Collect garbage. This should change nothing since we are keeping
3035             // alive the IntWrapper objects.
3036             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3037 
3038             EXPECT_EQ(64u, weakStrong->size());
3039             EXPECT_EQ(64u, strongWeak->size());
3040             EXPECT_EQ(64u, weakWeak->size());
3041             EXPECT_EQ(64u, weakSet->size());
3042             EXPECT_EQ(64u, weakOrderedSet->size());
3043 
3044             for (int i = 0; i < 128; i += 2) {
3045                 IntWrapper* wrapped = keepNumbersAlive[i];
3046                 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
3047                 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
3048                 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
3049                 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
3050                 EXPECT_TRUE(weakSet->contains(wrapped));
3051                 EXPECT_TRUE(weakOrderedSet->contains(wrapped));
3052             }
3053 
3054             for (int i = 0; i < 128; i += 3)
3055                 keepNumbersAlive[i] = nullptr;
3056 
3057             if (collectionNumber != weakStrongIndex)
3058                 weakStrong->clear();
3059             if (collectionNumber != strongWeakIndex)
3060                 strongWeak->clear();
3061             if (collectionNumber != weakWeakIndex)
3062                 weakWeak->clear();
3063             if (collectionNumber != weakSetIndex)
3064                 weakSet->clear();
3065             if (collectionNumber != weakOrderedSetIndex)
3066                 weakOrderedSet->clear();
3067 
3068             if (testThatIteratorsMakeStrong) {
3069                 WeakStrong::iterator it1 = weakStrong->begin();
3070                 StrongWeak::iterator it2 = strongWeak->begin();
3071                 WeakWeak::iterator it3 = weakWeak->begin();
3072                 WeakSet::iterator it4 = weakSet->begin();
3073                 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3074                 // Collect garbage. This should change nothing since the
3075                 // iterators make the collections strong.
3076                 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3077                 if (collectionNumber == weakStrongIndex) {
3078                     EXPECT_EQ(64u, weakStrong->size());
3079                     MapIteratorCheck(it1, weakStrong->end(), 64);
3080                 } else if (collectionNumber == strongWeakIndex) {
3081                     EXPECT_EQ(64u, strongWeak->size());
3082                     MapIteratorCheck(it2, strongWeak->end(), 64);
3083                 } else if (collectionNumber == weakWeakIndex) {
3084                     EXPECT_EQ(64u, weakWeak->size());
3085                     MapIteratorCheck(it3, weakWeak->end(), 64);
3086                 } else if (collectionNumber == weakSetIndex) {
3087                     EXPECT_EQ(64u, weakSet->size());
3088                     SetIteratorCheck(it4, weakSet->end(), 64);
3089                 } else if (collectionNumber == weakOrderedSetIndex) {
3090                     EXPECT_EQ(64u, weakOrderedSet->size());
3091                     SetIteratorCheck(it5, weakOrderedSet->end(), 64);
3092                 }
3093             } else {
3094                 // Collect garbage. This causes weak processing to remove
3095                 // things from the collections.
3096                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3097                 unsigned count = 0;
3098                 for (int i = 0; i < 128; i += 2) {
3099                     bool firstAlive = keepNumbersAlive[i];
3100                     bool secondAlive = keepNumbersAlive[i + 1];
3101                     if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
3102                         secondAlive = true;
3103                     if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
3104                         if (collectionNumber == weakStrongIndex) {
3105                             if (deleteAfterwards)
3106                                 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
3107                         } else if (collectionNumber == strongWeakIndex) {
3108                             if (deleteAfterwards)
3109                                 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
3110                         } else if (collectionNumber == weakWeakIndex) {
3111                             if (deleteAfterwards)
3112                                 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
3113                         }
3114                         if (!deleteAfterwards)
3115                             count++;
3116                     } else if (collectionNumber == weakSetIndex && firstAlive) {
3117                         ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
3118                         if (deleteAfterwards)
3119                             weakSet->remove(keepNumbersAlive[i]);
3120                         else
3121                             count++;
3122                     } else if (collectionNumber == weakOrderedSetIndex && firstAlive) {
3123                         ASSERT_TRUE(weakOrderedSet->contains(keepNumbersAlive[i]));
3124                         if (deleteAfterwards)
3125                             weakOrderedSet->remove(keepNumbersAlive[i]);
3126                         else
3127                             count++;
3128                     }
3129                 }
3130                 if (addAfterwards) {
3131                     for (int i = 1000; i < 1100; i++) {
3132                         IntWrapper* wrapped = IntWrapper::create(i);
3133                         keepNumbersAlive.append(wrapped);
3134                         weakStrong->add(wrapped, wrapped);
3135                         strongWeak->add(wrapped, wrapped);
3136                         weakWeak->add(wrapped, wrapped);
3137                         weakSet->add(wrapped);
3138                         weakOrderedSet->add(wrapped);
3139                     }
3140                 }
3141                 if (collectionNumber == weakStrongIndex)
3142                     EXPECT_EQ(count + added, weakStrong->size());
3143                 else if (collectionNumber == strongWeakIndex)
3144                     EXPECT_EQ(count + added, strongWeak->size());
3145                 else if (collectionNumber == weakWeakIndex)
3146                     EXPECT_EQ(count + added, weakWeak->size());
3147                 else if (collectionNumber == weakSetIndex)
3148                     EXPECT_EQ(count + added, weakSet->size());
3149                 else if (collectionNumber == weakOrderedSetIndex)
3150                     EXPECT_EQ(count + added, weakOrderedSet->size());
3151                 WeakStrong::iterator it1 = weakStrong->begin();
3152                 StrongWeak::iterator it2 = strongWeak->begin();
3153                 WeakWeak::iterator it3 = weakWeak->begin();
3154                 WeakSet::iterator it4 = weakSet->begin();
3155                 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3156                 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
3157                 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
3158                 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
3159                 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
3160                 SetIteratorCheck(it5, weakOrderedSet->end(), (collectionNumber == weakOrderedSetIndex ? count : 0) + added);
3161             }
3162             for (unsigned i = 0; i < 128 + added; i++)
3163                 keepNumbersAlive[i] = nullptr;
3164             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3165             EXPECT_EQ(added, weakStrong->size());
3166             EXPECT_EQ(added, strongWeak->size());
3167             EXPECT_EQ(added, weakWeak->size());
3168             EXPECT_EQ(added, weakSet->size());
3169             EXPECT_EQ(added, weakOrderedSet->size());
3170         }
3171     }
3172 }
3173 
TEST(HeapTest,RefCountedGarbageCollected)3174 TEST(HeapTest, RefCountedGarbageCollected)
3175 {
3176     RefCountedAndGarbageCollected::s_destructorCalls = 0;
3177     {
3178         RefPtr<RefCountedAndGarbageCollected> refPtr3;
3179         {
3180             Persistent<RefCountedAndGarbageCollected> persistent;
3181             {
3182                 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
3183                 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
3184                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3185                 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3186                 persistent = refPtr1.get();
3187             }
3188             // Reference count is zero for both objects but one of
3189             // them is kept alive by a persistent handle.
3190             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3191             EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3192             refPtr3 = persistent.get();
3193         }
3194         // The persistent handle is gone but the ref count has been
3195         // increased to 1.
3196         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3197         EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3198     }
3199     // Both persistent handle is gone and ref count is zero so the
3200     // object can be collected.
3201     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3202     EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
3203 }
3204 
TEST(HeapTest,RefCountedGarbageCollectedWithStackPointers)3205 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
3206 {
3207     RefCountedAndGarbageCollected::s_destructorCalls = 0;
3208     RefCountedAndGarbageCollected2::s_destructorCalls = 0;
3209     {
3210         RefCountedAndGarbageCollected* pointer1 = 0;
3211         RefCountedAndGarbageCollected2* pointer2 = 0;
3212         {
3213             RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
3214             RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
3215             pointer1 = object1.get();
3216             pointer2 = object2.get();
3217             void* objects[2] = { object1.get(), object2.get() };
3218             RefCountedGarbageCollectedVisitor visitor(2, objects);
3219             ThreadState::current()->visitPersistents(&visitor);
3220             EXPECT_TRUE(visitor.validate());
3221 
3222             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3223             EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3224             EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3225         }
3226         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3227         EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3228         EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3229 
3230         // At this point, the reference counts of object1 and object2 are 0.
3231         // Only pointer1 and pointer2 keep references to object1 and object2.
3232         void* objects[] = { 0 };
3233         RefCountedGarbageCollectedVisitor visitor(0, objects);
3234         ThreadState::current()->visitPersistents(&visitor);
3235         EXPECT_TRUE(visitor.validate());
3236 
3237         {
3238             RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
3239             RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
3240             void* objects[2] = { object1.get(), object2.get() };
3241             RefCountedGarbageCollectedVisitor visitor(2, objects);
3242             ThreadState::current()->visitPersistents(&visitor);
3243             EXPECT_TRUE(visitor.validate());
3244 
3245             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3246             EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3247             EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3248         }
3249 
3250         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3251         EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3252         EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3253     }
3254 
3255     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3256     EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3257     EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
3258 }
3259 
TEST(HeapTest,WeakMembers)3260 TEST(HeapTest, WeakMembers)
3261 {
3262     Bar::s_live = 0;
3263     {
3264         Persistent<Bar> h1 = Bar::create();
3265         Persistent<Weak> h4;
3266         Persistent<WithWeakMember> h5;
3267         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3268         ASSERT_EQ(1u, Bar::s_live); // h1 is live.
3269         {
3270             Bar* h2 = Bar::create();
3271             Bar* h3 = Bar::create();
3272             h4 = Weak::create(h2, h3);
3273             h5 = WithWeakMember::create(h2, h3);
3274             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3275             EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
3276             EXPECT_TRUE(h4->strongIsThere());
3277             EXPECT_TRUE(h4->weakIsThere());
3278             EXPECT_TRUE(h5->strongIsThere());
3279             EXPECT_TRUE(h5->weakIsThere());
3280         }
3281         // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3282         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3283         EXPECT_EQ(4u, Bar::s_live);
3284         EXPECT_TRUE(h4->strongIsThere());
3285         EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
3286         EXPECT_TRUE(h5->strongIsThere());
3287         EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
3288         h1.release(); // Zero out h1.
3289         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3290         EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
3291         EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
3292         EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
3293     }
3294     // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3295     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3296     EXPECT_EQ(0u, Bar::s_live); // All gone.
3297 }
3298 
TEST(HeapTest,FinalizationObserver)3299 TEST(HeapTest, FinalizationObserver)
3300 {
3301     Persistent<FinalizationObserver<Observable> > o;
3302     {
3303         Observable* foo = Observable::create(Bar::create());
3304         // |o| observes |foo|.
3305         o = FinalizationObserver<Observable>::create(foo);
3306     }
3307     // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3308     // and its member will be collected.
3309     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3310     EXPECT_EQ(0u, Bar::s_live);
3311     EXPECT_TRUE(o->didCallWillFinalize());
3312 
3313     FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
3314     Observable* foo = Observable::create(Bar::create());
3315     FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
3316     EXPECT_EQ(1u, map.size());
3317     foo = 0;
3318     // FinalizationObserverWithHashMap doesn't have a strong reference to
3319     // |foo|. So |foo| and its member will be collected.
3320     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3321     EXPECT_EQ(0u, Bar::s_live);
3322     EXPECT_EQ(0u, map.size());
3323     EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
3324 }
3325 
TEST(HeapTest,Comparisons)3326 TEST(HeapTest, Comparisons)
3327 {
3328     Persistent<Bar> barPersistent = Bar::create();
3329     Persistent<Foo> fooPersistent = Foo::create(barPersistent);
3330     EXPECT_TRUE(barPersistent != fooPersistent);
3331     barPersistent = fooPersistent;
3332     EXPECT_TRUE(barPersistent == fooPersistent);
3333 }
3334 
TEST(HeapTest,CheckAndMarkPointer)3335 TEST(HeapTest, CheckAndMarkPointer)
3336 {
3337     HeapStats initialHeapStats;
3338     clearOutOldGarbage(&initialHeapStats);
3339 
3340     Vector<Address> objectAddresses;
3341     Vector<Address> endAddresses;
3342     Address largeObjectAddress;
3343     Address largeObjectEndAddress;
3344     CountingVisitor visitor;
3345     for (int i = 0; i < 10; i++) {
3346         SimpleObject* object = SimpleObject::create();
3347         Address objectAddress = reinterpret_cast<Address>(object);
3348         objectAddresses.append(objectAddress);
3349         endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
3350     }
3351     LargeObject* largeObject = LargeObject::create();
3352     largeObjectAddress = reinterpret_cast<Address>(largeObject);
3353     largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
3354 
3355     // This is a low-level test where we call checkAndMarkPointer. This method
3356     // causes the object start bitmap to be computed which requires the heap
3357     // to be in a consistent state (e.g. the free allocation area must be put
3358     // into a free list header). However when we call makeConsistentForGC it
3359     // also clears out the freelists so we have to rebuild those before trying
3360     // to allocate anything again. We do this by forcing a GC after doing the
3361     // checkAndMarkPointer tests.
3362     {
3363         TestGCScope scope(ThreadState::HeapPointersOnStack);
3364         EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3365         Heap::makeConsistentForGC();
3366         for (size_t i = 0; i < objectAddresses.size(); i++) {
3367             EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3368             EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3369         }
3370         EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3371         visitor.reset();
3372         EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3373         EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3374         EXPECT_EQ(2ul, visitor.count());
3375         visitor.reset();
3376     }
3377     // This forces a GC without stack scanning which results in the objects
3378     // being collected. This will also rebuild the above mentioned freelists,
3379     // however we don't rely on that below since we don't have any allocations.
3380     clearOutOldGarbage(&initialHeapStats);
3381     {
3382         TestGCScope scope(ThreadState::HeapPointersOnStack);
3383         EXPECT_TRUE(scope.allThreadsParked());
3384         Heap::makeConsistentForGC();
3385         for (size_t i = 0; i < objectAddresses.size(); i++) {
3386             // We would like to assert that checkAndMarkPointer returned false
3387             // here because the pointers no longer point into a valid object
3388             // (it's been freed by the GCs. But checkAndMarkPointer will return
3389             // true for any pointer that points into a heap page, regardless of
3390             // whether it points at a valid object (this ensures the
3391             // correctness of the page-based on-heap address caches), so we
3392             // can't make that assert.
3393             Heap::checkAndMarkPointer(&visitor, objectAddresses[i]);
3394             Heap::checkAndMarkPointer(&visitor, endAddresses[i]);
3395         }
3396         EXPECT_EQ(0ul, visitor.count());
3397         Heap::checkAndMarkPointer(&visitor, largeObjectAddress);
3398         Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress);
3399         EXPECT_EQ(0ul, visitor.count());
3400     }
3401     // This round of GC is important to make sure that the object start
3402     // bitmap are cleared out and that the free lists are rebuild.
3403     clearOutOldGarbage(&initialHeapStats);
3404 }
3405 
TEST(HeapTest,VisitOffHeapCollections)3406 TEST(HeapTest, VisitOffHeapCollections)
3407 {
3408     HeapStats initialHeapStats;
3409     clearOutOldGarbage(&initialHeapStats);
3410     IntWrapper::s_destructorCalls = 0;
3411     Persistent<OffHeapContainer> container = OffHeapContainer::create();
3412     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3413     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3414     container = nullptr;
3415     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3416     EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
3417 }
3418 
TEST(HeapTest,PersistentHeapCollectionTypes)3419 TEST(HeapTest, PersistentHeapCollectionTypes)
3420 {
3421     HeapStats initialHeapSize;
3422     IntWrapper::s_destructorCalls = 0;
3423 
3424     typedef HeapVector<Member<IntWrapper> > Vec;
3425     typedef PersistentHeapVector<Member<IntWrapper> > PVec;
3426     typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
3427     typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet;
3428     typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet;
3429     typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
3430     typedef PersistentHeapDeque<Member<IntWrapper> > PDeque;
3431 
3432     clearOutOldGarbage(&initialHeapSize);
3433     {
3434         PVec pVec;
3435         PDeque pDeque;
3436         PSet pSet;
3437         PListSet pListSet;
3438         PLinkedSet pLinkedSet;
3439         PMap pMap;
3440 
3441         IntWrapper* one(IntWrapper::create(1));
3442         IntWrapper* two(IntWrapper::create(2));
3443         IntWrapper* three(IntWrapper::create(3));
3444         IntWrapper* four(IntWrapper::create(4));
3445         IntWrapper* five(IntWrapper::create(5));
3446         IntWrapper* six(IntWrapper::create(6));
3447         IntWrapper* seven(IntWrapper::create(7));
3448         IntWrapper* eight(IntWrapper::create(8));
3449         IntWrapper* nine(IntWrapper::create(9));
3450 
3451         pVec.append(one);
3452         pVec.append(two);
3453 
3454         pDeque.append(seven);
3455         pDeque.append(two);
3456 
3457         Vec* vec = new Vec();
3458         vec->swap(pVec);
3459 
3460         pVec.append(two);
3461         pVec.append(three);
3462 
3463         pSet.add(four);
3464         pListSet.add(eight);
3465         pLinkedSet.add(nine);
3466         pMap.add(five, six);
3467 
3468         // Collect |vec| and |one|.
3469         vec = 0;
3470         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3471         EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3472 
3473         EXPECT_EQ(2u, pVec.size());
3474         EXPECT_EQ(two, pVec.at(0));
3475         EXPECT_EQ(three, pVec.at(1));
3476 
3477         EXPECT_EQ(2u, pDeque.size());
3478         EXPECT_EQ(seven, pDeque.first());
3479         EXPECT_EQ(seven, pDeque.takeFirst());
3480         EXPECT_EQ(two, pDeque.first());
3481 
3482         EXPECT_EQ(1u, pDeque.size());
3483 
3484         EXPECT_EQ(1u, pSet.size());
3485         EXPECT_TRUE(pSet.contains(four));
3486 
3487         EXPECT_EQ(1u, pListSet.size());
3488         EXPECT_TRUE(pListSet.contains(eight));
3489 
3490         EXPECT_EQ(1u, pLinkedSet.size());
3491         EXPECT_TRUE(pLinkedSet.contains(nine));
3492 
3493         EXPECT_EQ(1u, pMap.size());
3494         EXPECT_EQ(six, pMap.get(five));
3495     }
3496 
3497     // Collect previous roots.
3498     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3499     EXPECT_EQ(9, IntWrapper::s_destructorCalls);
3500 }
3501 
TEST(HeapTest,CollectionNesting)3502 TEST(HeapTest, CollectionNesting)
3503 {
3504     HeapStats initialStats;
3505     clearOutOldGarbage(&initialStats);
3506     int* key = &IntWrapper::s_destructorCalls;
3507     IntWrapper::s_destructorCalls = 0;
3508     typedef HeapVector<Member<IntWrapper> > IntVector;
3509     typedef HeapDeque<Member<IntWrapper> > IntDeque;
3510     HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
3511     HeapHashMap<void*, IntDeque>* map2 = new HeapHashMap<void*, IntDeque>();
3512 
3513     map->add(key, IntVector());
3514     map2->add(key, IntDeque());
3515 
3516     HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3517     EXPECT_EQ(0u, map->get(key).size());
3518 
3519     HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3520     EXPECT_EQ(0u, map2->get(key).size());
3521 
3522     it->value.append(IntWrapper::create(42));
3523     EXPECT_EQ(1u, map->get(key).size());
3524 
3525     it2->value.append(IntWrapper::create(42));
3526     EXPECT_EQ(1u, map2->get(key).size());
3527 
3528     Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
3529     Persistent<HeapHashMap<void*, IntDeque> > keepAlive2(map2);
3530 
3531     for (int i = 0; i < 100; i++) {
3532         map->add(key + 1 + i, IntVector());
3533         map2->add(key + 1 + i, IntDeque());
3534     }
3535 
3536     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3537 
3538     EXPECT_EQ(1u, map->get(key).size());
3539     EXPECT_EQ(1u, map2->get(key).size());
3540     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3541 
3542     keepAlive = nullptr;
3543     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3544     EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3545 }
3546 
TEST(HeapTest,GarbageCollectedMixin)3547 TEST(HeapTest, GarbageCollectedMixin)
3548 {
3549     HeapStats initialHeapStats;
3550     clearOutOldGarbage(&initialHeapStats);
3551 
3552     Persistent<UseMixin> usemixin = UseMixin::create();
3553     EXPECT_EQ(0, UseMixin::s_traceCount);
3554     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3555     EXPECT_EQ(1, UseMixin::s_traceCount);
3556 
3557     Persistent<Mixin> mixin = usemixin;
3558     usemixin = nullptr;
3559     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3560     EXPECT_EQ(2, UseMixin::s_traceCount);
3561 
3562     PersistentHeapHashSet<WeakMember<Mixin> > weakMap;
3563     weakMap.add(UseMixin::create());
3564     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3565     EXPECT_EQ(0u, weakMap.size());
3566 }
3567 
TEST(HeapTest,CollectionNesting2)3568 TEST(HeapTest, CollectionNesting2)
3569 {
3570     HeapStats initialStats;
3571     clearOutOldGarbage(&initialStats);
3572     void* key = &IntWrapper::s_destructorCalls;
3573     IntWrapper::s_destructorCalls = 0;
3574     typedef HeapHashSet<Member<IntWrapper> > IntSet;
3575     HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
3576 
3577     map->add(key, IntSet());
3578 
3579     HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3580     EXPECT_EQ(0u, map->get(key).size());
3581 
3582     it->value.add(IntWrapper::create(42));
3583     EXPECT_EQ(1u, map->get(key).size());
3584 
3585     Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
3586     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3587     EXPECT_EQ(1u, map->get(key).size());
3588     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3589 }
3590 
TEST(HeapTest,CollectionNesting3)3591 TEST(HeapTest, CollectionNesting3)
3592 {
3593     HeapStats initialStats;
3594     clearOutOldGarbage(&initialStats);
3595     IntWrapper::s_destructorCalls = 0;
3596     typedef HeapVector<Member<IntWrapper> > IntVector;
3597     typedef HeapDeque<Member<IntWrapper> > IntDeque;
3598     HeapVector<IntVector>* vector = new HeapVector<IntVector>();
3599     HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
3600 
3601     vector->append(IntVector());
3602     deque->append(IntDeque());
3603 
3604     HeapVector<IntVector>::iterator it = vector->begin();
3605     HeapDeque<IntDeque>::iterator it2 = deque->begin();
3606     EXPECT_EQ(0u, it->size());
3607     EXPECT_EQ(0u, it2->size());
3608 
3609     it->append(IntWrapper::create(42));
3610     it2->append(IntWrapper::create(42));
3611     EXPECT_EQ(1u, it->size());
3612     EXPECT_EQ(1u, it2->size());
3613 
3614     Persistent<HeapVector<IntVector> > keepAlive(vector);
3615     Persistent<HeapDeque<IntDeque> > keepAlive2(deque);
3616     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3617     EXPECT_EQ(1u, it->size());
3618     EXPECT_EQ(1u, it2->size());
3619     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3620 }
3621 
TEST(HeapTest,EmbeddedInVector)3622 TEST(HeapTest, EmbeddedInVector)
3623 {
3624     HeapStats initialStats;
3625     clearOutOldGarbage(&initialStats);
3626     SimpleFinalizedObject::s_destructorCalls = 0;
3627     {
3628         PersistentHeapVector<VectorObject, 2> inlineVector;
3629         PersistentHeapVector<VectorObject> outlineVector;
3630         VectorObject i1, i2;
3631         inlineVector.append(i1);
3632         inlineVector.append(i2);
3633 
3634         VectorObject o1, o2;
3635         outlineVector.append(o1);
3636         outlineVector.append(o2);
3637 
3638         PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
3639         VectorObjectInheritedTrace it1, it2;
3640         vectorInheritedTrace.append(it1);
3641         vectorInheritedTrace.append(it2);
3642 
3643         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3644         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3645 
3646         // Since VectorObjectNoTrace has no trace method it will
3647         // not be traced and hence be collected when doing GC.
3648         // We trace items in a collection braced on the item's
3649         // having a trace method. This is determined via the
3650         // NeedsTracing trait in wtf/TypeTraits.h.
3651         PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
3652         VectorObjectNoTrace n1, n2;
3653         vectorNoTrace.append(n1);
3654         vectorNoTrace.append(n2);
3655         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3656         EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3657     }
3658     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3659     EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3660 }
3661 
TEST(HeapTest,EmbeddedInDeque)3662 TEST(HeapTest, EmbeddedInDeque)
3663 {
3664     HeapStats initialStats;
3665     clearOutOldGarbage(&initialStats);
3666     SimpleFinalizedObject::s_destructorCalls = 0;
3667     {
3668         PersistentHeapDeque<VectorObject, 2> inlineDeque;
3669         PersistentHeapDeque<VectorObject> outlineDeque;
3670         VectorObject i1, i2;
3671         inlineDeque.append(i1);
3672         inlineDeque.append(i2);
3673 
3674         VectorObject o1, o2;
3675         outlineDeque.append(o1);
3676         outlineDeque.append(o2);
3677 
3678         PersistentHeapDeque<VectorObjectInheritedTrace> dequeInheritedTrace;
3679         VectorObjectInheritedTrace it1, it2;
3680         dequeInheritedTrace.append(it1);
3681         dequeInheritedTrace.append(it2);
3682 
3683         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3684         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3685 
3686         // Since VectorObjectNoTrace has no trace method it will
3687         // not be traced and hence be collected when doing GC.
3688         // We trace items in a collection braced on the item's
3689         // having a trace method. This is determined via the
3690         // NeedsTracing trait in wtf/TypeTraits.h.
3691         PersistentHeapDeque<VectorObjectNoTrace> dequeNoTrace;
3692         VectorObjectNoTrace n1, n2;
3693         dequeNoTrace.append(n1);
3694         dequeNoTrace.append(n2);
3695         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3696         EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3697     }
3698     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3699     EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3700 }
3701 
3702 template<typename Set>
rawPtrInHashHelper()3703 void rawPtrInHashHelper()
3704 {
3705     Set set;
3706     set.add(new int(42));
3707     set.add(new int(42));
3708     EXPECT_EQ(2u, set.size());
3709     for (typename Set::iterator it = set.begin(); it != set.end(); ++it)
3710         EXPECT_EQ(42, **it);
3711 }
3712 
TEST(HeapTest,RawPtrInHash)3713 TEST(HeapTest, RawPtrInHash)
3714 {
3715     rawPtrInHashHelper<HashSet<RawPtr<int> > >();
3716     rawPtrInHashHelper<ListHashSet<RawPtr<int> > >();
3717     rawPtrInHashHelper<LinkedHashSet<RawPtr<int> > >();
3718 }
3719 
TEST(HeapTest,HeapTerminatedArray)3720 TEST(HeapTest, HeapTerminatedArray)
3721 {
3722     HeapStats initialHeapSize;
3723     clearOutOldGarbage(&initialHeapSize);
3724     IntWrapper::s_destructorCalls = 0;
3725 
3726     HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
3727 
3728     const size_t prefixSize = 4;
3729     const size_t suffixSize = 4;
3730 
3731     {
3732         HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3733         builder.grow(prefixSize);
3734         for (size_t i = 0; i < prefixSize; i++)
3735             builder.append(TerminatedArrayItem(IntWrapper::create(i)));
3736         arr = builder.release();
3737     }
3738 
3739     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3740     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3741     EXPECT_EQ(prefixSize, arr->size());
3742     for (size_t i = 0; i < prefixSize; i++)
3743         EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3744 
3745     {
3746         HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3747         builder.grow(suffixSize);
3748         for (size_t i = 0; i < suffixSize; i++)
3749             builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
3750         arr = builder.release();
3751     }
3752 
3753     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3754     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3755     EXPECT_EQ(prefixSize + suffixSize, arr->size());
3756     for (size_t i = 0; i < prefixSize + suffixSize; i++)
3757         EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3758 
3759     {
3760         Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3761         arr = 0;
3762         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3763         arr = persistentArr.get();
3764         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3765         EXPECT_EQ(prefixSize + suffixSize, arr->size());
3766         for (size_t i = 0; i < prefixSize + suffixSize; i++)
3767             EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3768     }
3769 
3770     arr = 0;
3771     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3772     EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3773 }
3774 
TEST(HeapTest,HeapLinkedStack)3775 TEST(HeapTest, HeapLinkedStack)
3776 {
3777     HeapStats initialHeapSize;
3778     clearOutOldGarbage(&initialHeapSize);
3779     IntWrapper::s_destructorCalls = 0;
3780 
3781     HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3782 
3783     const size_t stackSize = 10;
3784 
3785     for (size_t i = 0; i < stackSize; i++)
3786         stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3787 
3788     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3789     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3790     EXPECT_EQ(stackSize, stack->size());
3791     while (!stack->isEmpty()) {
3792         EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3793         stack->pop();
3794     }
3795 
3796     Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3797 
3798     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3799     EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3800     EXPECT_EQ(0u, pStack->size());
3801 }
3802 
TEST(HeapTest,AllocationDuringFinalization)3803 TEST(HeapTest, AllocationDuringFinalization)
3804 {
3805     HeapStats initialHeapSize;
3806     clearOutOldGarbage(&initialHeapSize);
3807     IntWrapper::s_destructorCalls = 0;
3808     OneKiloByteObject::s_destructorCalls = 0;
3809 
3810     Persistent<IntWrapper> wrapper;
3811     new FinalizationAllocator(&wrapper);
3812 
3813     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3814     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3815     // Check that the wrapper allocated during finalization is not
3816     // swept away and zapped later in the same sweeping phase.
3817     EXPECT_EQ(42, wrapper->value());
3818 
3819     wrapper.clear();
3820     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3821     EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3822     EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3823 }
3824 
3825 class SimpleClassWithDestructor {
3826 public:
SimpleClassWithDestructor()3827     SimpleClassWithDestructor() { }
~SimpleClassWithDestructor()3828     ~SimpleClassWithDestructor()
3829     {
3830         s_wasDestructed = true;
3831     }
3832     static bool s_wasDestructed;
3833 };
3834 
3835 bool SimpleClassWithDestructor::s_wasDestructed;
3836 
3837 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
3838 public:
RefCountedWithDestructor()3839     RefCountedWithDestructor() { }
~RefCountedWithDestructor()3840     ~RefCountedWithDestructor()
3841     {
3842         s_wasDestructed = true;
3843     }
3844     static bool s_wasDestructed;
3845 };
3846 
3847 bool RefCountedWithDestructor::s_wasDestructed;
3848 
3849 template<typename Set>
destructorsCalledOnGC(bool addLots)3850 void destructorsCalledOnGC(bool addLots)
3851 {
3852     RefCountedWithDestructor::s_wasDestructed = false;
3853     {
3854         Set set;
3855         RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3856         set.add(adoptRef(hasDestructor));
3857         EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3858 
3859         if (addLots) {
3860             for (int i = 0; i < 1000; i++) {
3861                 set.add(adoptRef(new RefCountedWithDestructor()));
3862             }
3863         }
3864 
3865         EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3866         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3867         EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3868     }
3869     // The destructors of the sets don't call the destructors of the elements
3870     // in the heap sets. You have to actually remove the elments, call clear()
3871     // or have a GC to get the destructors called.
3872     EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3873     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3874     EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3875 }
3876 
3877 template<typename Set>
destructorsCalledOnClear(bool addLots)3878 void destructorsCalledOnClear(bool addLots)
3879 {
3880     RefCountedWithDestructor::s_wasDestructed = false;
3881     Set set;
3882     RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3883     set.add(adoptRef(hasDestructor));
3884     EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3885 
3886     if (addLots) {
3887         for (int i = 0; i < 1000; i++) {
3888             set.add(adoptRef(new RefCountedWithDestructor()));
3889         }
3890     }
3891 
3892     EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3893     set.clear();
3894     EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3895 }
3896 
TEST(HeapTest,DestructorsCalled)3897 TEST(HeapTest, DestructorsCalled)
3898 {
3899     HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3900     SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3901     map.add(hasDestructor, adoptPtr(hasDestructor));
3902     SimpleClassWithDestructor::s_wasDestructed = false;
3903     map.clear();
3904     EXPECT_TRUE(SimpleClassWithDestructor::s_wasDestructed);
3905 
3906     destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3907     destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3908     destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3909     destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3910     destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3911     destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3912 
3913     destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3914     destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3915     destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3916     destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3917     destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3918     destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3919 }
3920 
3921 class MixinA : public GarbageCollectedMixin {
3922 public:
MixinA()3923     MixinA() : m_obj(IntWrapper::create(100)) { }
trace(Visitor * visitor)3924     virtual void trace(Visitor* visitor)
3925     {
3926         visitor->trace(m_obj);
3927     }
3928     Member<IntWrapper> m_obj;
3929 };
3930 
3931 class MixinB : public GarbageCollectedMixin {
3932 public:
MixinB()3933     MixinB() : m_obj(IntWrapper::create(101)) { }
trace(Visitor * visitor)3934     virtual void trace(Visitor* visitor)
3935     {
3936         visitor->trace(m_obj);
3937     }
3938     Member<IntWrapper> m_obj;
3939 };
3940 
3941 class MultipleMixins : public GarbageCollected<MultipleMixins>, public MixinA, public MixinB {
3942     USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
3943 public:
MultipleMixins()3944     MultipleMixins() : m_obj(IntWrapper::create(102)) { }
trace(Visitor * visitor)3945     virtual void trace(Visitor* visitor)
3946     {
3947         visitor->trace(m_obj);
3948         MixinA::trace(visitor);
3949         MixinB::trace(visitor);
3950     }
3951     Member<IntWrapper> m_obj;
3952 };
3953 
3954 static const bool s_isMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
3955 static const bool s_isMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
3956 
TEST(HeapTest,MultipleMixins)3957 TEST(HeapTest, MultipleMixins)
3958 {
3959     EXPECT_TRUE(s_isMixinTrue);
3960     EXPECT_FALSE(s_isMixinFalse);
3961 
3962     HeapStats initialHeapSize;
3963     clearOutOldGarbage(&initialHeapSize);
3964     IntWrapper::s_destructorCalls = 0;
3965     MultipleMixins* obj = new MultipleMixins();
3966     {
3967         Persistent<MixinA> a = obj;
3968         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3969         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3970     }
3971     {
3972         Persistent<MixinB> b = obj;
3973         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3974         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3975     }
3976     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3977     EXPECT_EQ(3, IntWrapper::s_destructorCalls);
3978 }
3979 
3980 class GCParkingThreadTester {
3981 public:
test()3982     static void test()
3983     {
3984         createThread(&sleeperMainFunc, 0, "SleepingThread");
3985 
3986         // Wait for the sleeper to run.
3987         while (!s_sleeperRunning) {
3988             yield();
3989         }
3990 
3991         {
3992             // Expect the first attempt to park the sleeping thread to fail
3993             TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3994             EXPECT_FALSE(scope.allThreadsParked());
3995         }
3996 
3997         s_sleeperDone = true;
3998 
3999         // Wait for the sleeper to finish.
4000         while (s_sleeperRunning) {
4001             // We enter the safepoint here since the sleeper thread will detach
4002             // causing it to GC.
4003             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
4004             yield();
4005         }
4006         {
4007             // Since the sleeper thread has detached this is the only thread.
4008             TestGCScope scope(ThreadState::NoHeapPointersOnStack);
4009             EXPECT_TRUE(scope.allThreadsParked());
4010         }
4011     }
4012 
4013 private:
sleeperMainFunc(void * data)4014     static void sleeperMainFunc(void* data)
4015     {
4016         ThreadState::attach();
4017         s_sleeperRunning = true;
4018 
4019         // Simulate a long running op that is not entering a safepoint.
4020         while (!s_sleeperDone) {
4021             yield();
4022         }
4023 
4024         ThreadState::detach();
4025         s_sleeperRunning = false;
4026     }
4027 
4028     static volatile bool s_sleeperRunning;
4029     static volatile bool s_sleeperDone;
4030 };
4031 
4032 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
4033 volatile bool GCParkingThreadTester::s_sleeperDone = false;
4034 
TEST(HeapTest,GCParkingTimeout)4035 TEST(HeapTest, GCParkingTimeout)
4036 {
4037     GCParkingThreadTester::test();
4038 }
4039 
TEST(HeapTest,NeedsAdjustAndMark)4040 TEST(HeapTest, NeedsAdjustAndMark)
4041 {
4042     // class Mixin : public GarbageCollectedMixin {};
4043     EXPECT_TRUE(NeedsAdjustAndMark<Mixin>::value);
4044     EXPECT_TRUE(NeedsAdjustAndMark<const Mixin>::value);
4045 
4046     // class SimpleObject : public GarbageCollected<SimpleObject> {};
4047     EXPECT_FALSE(NeedsAdjustAndMark<SimpleObject>::value);
4048     EXPECT_FALSE(NeedsAdjustAndMark<const SimpleObject>::value);
4049 
4050     // class UseMixin : public SimpleObject, public Mixin {};
4051     EXPECT_FALSE(NeedsAdjustAndMark<UseMixin>::value);
4052     EXPECT_FALSE(NeedsAdjustAndMark<const UseMixin>::value);
4053 }
4054 
4055 template<typename Set>
setWithCustomWeaknessHandling()4056 void setWithCustomWeaknessHandling()
4057 {
4058     typedef typename Set::iterator Iterator;
4059     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4060     Persistent<Set> set1(new Set());
4061     {
4062         Set set2;
4063         Set* set3 = new Set();
4064         set2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4065         set3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4066         set1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4067         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4068         // The first set is pointed to from a persistent, so it's referenced, but
4069         // the weak processing may have taken place.
4070         if (set1->size()) {
4071             Iterator i1 = set1->begin();
4072             EXPECT_EQ(4, i1->first->value());
4073             EXPECT_EQ(5, i1->second->value());
4074         }
4075         // The second set is on-stack, so its backing store must be referenced from
4076         // the stack. That makes the weak references strong.
4077         Iterator i2 = set2.begin();
4078         EXPECT_EQ(0, i2->first->value());
4079         EXPECT_EQ(1, i2->second->value());
4080         // The third set is pointed to from the stack, so it's referenced, but the
4081         // weak processing may have taken place.
4082         if (set3->size()) {
4083             Iterator i3 = set3->begin();
4084             EXPECT_EQ(2, i3->first->value());
4085             EXPECT_EQ(3, i3->second->value());
4086         }
4087     }
4088     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4089     EXPECT_EQ(0u, set1->size());
4090     set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt));
4091     set1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4092     set1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4093     set1->add(PairWithWeakHandling(livingInt, livingInt));
4094     set1->add(PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4095     EXPECT_EQ(4u, set1->size());
4096     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4097     EXPECT_EQ(2u, set1->size());
4098     Iterator i1 = set1->begin();
4099     EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4100     EXPECT_EQ(livingInt, i1->second);
4101     ++i1;
4102     EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4103     EXPECT_EQ(livingInt, i1->second);
4104 }
4105 
TEST(HeapTest,SetWithCustomWeaknessHandling)4106 TEST(HeapTest, SetWithCustomWeaknessHandling)
4107 {
4108     setWithCustomWeaknessHandling<HeapHashSet<PairWithWeakHandling> >();
4109     setWithCustomWeaknessHandling<HeapLinkedHashSet<PairWithWeakHandling> >();
4110 }
4111 
TEST(HeapTest,MapWithCustomWeaknessHandling)4112 TEST(HeapTest, MapWithCustomWeaknessHandling)
4113 {
4114     typedef HeapHashMap<PairWithWeakHandling, RefPtr<OffHeapInt> > Map;
4115     typedef Map::iterator Iterator;
4116     HeapStats initialHeapSize;
4117     clearOutOldGarbage(&initialHeapSize);
4118     OffHeapInt::s_destructorCalls = 0;
4119 
4120     Persistent<Map> map1(new Map());
4121     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4122     {
4123         Map map2;
4124         Map* map3 = new Map();
4125         map2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)), OffHeapInt::create(1001));
4126         map3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)), OffHeapInt::create(1002));
4127         map1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)), OffHeapInt::create(1003));
4128         EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4129 
4130         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4131         // The first map2 is pointed to from a persistent, so it's referenced, but
4132         // the weak processing may have taken place.
4133         if (map1->size()) {
4134             Iterator i1 = map1->begin();
4135             EXPECT_EQ(4, i1->key.first->value());
4136             EXPECT_EQ(5, i1->key.second->value());
4137             EXPECT_EQ(1003, i1->value->value());
4138         }
4139         // The second map2 is on-stack, so its backing store must be referenced from
4140         // the stack. That makes the weak references strong.
4141         Iterator i2 = map2.begin();
4142         EXPECT_EQ(0, i2->key.first->value());
4143         EXPECT_EQ(1, i2->key.second->value());
4144         EXPECT_EQ(1001, i2->value->value());
4145         // The third map2 is pointed to from the stack, so it's referenced, but the
4146         // weak processing may have taken place.
4147         if (map3->size()) {
4148             Iterator i3 = map3->begin();
4149             EXPECT_EQ(2, i3->key.first->value());
4150             EXPECT_EQ(3, i3->key.second->value());
4151             EXPECT_EQ(1002, i3->value->value());
4152         }
4153     }
4154     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4155 
4156     EXPECT_EQ(0u, map1->size());
4157     EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4158 
4159     OffHeapInt::s_destructorCalls = 0;
4160 
4161     map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), OffHeapInt::create(2000));
4162     map1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103)), OffHeapInt::create(2001)); // This one gets zapped at GC time because nothing holds the 103 alive.
4163     map1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), OffHeapInt::create(2002)); // This one gets zapped too.
4164     RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4165     map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt);
4166     map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); // This one is identical to the previous and doesn't add anything.
4167     dupeInt.clear();
4168 
4169     EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4170     EXPECT_EQ(4u, map1->size());
4171     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4172     EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4173     EXPECT_EQ(2u, map1->size());
4174     Iterator i1 = map1->begin();
4175     EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4176     EXPECT_EQ(livingInt, i1->key.second);
4177     ++i1;
4178     EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4179     EXPECT_EQ(livingInt, i1->key.second);
4180 }
4181 
TEST(HeapTest,MapWithCustomWeaknessHandling2)4182 TEST(HeapTest, MapWithCustomWeaknessHandling2)
4183 {
4184     typedef HeapHashMap<RefPtr<OffHeapInt>, PairWithWeakHandling> Map;
4185     typedef Map::iterator Iterator;
4186     HeapStats initialHeapSize;
4187     clearOutOldGarbage(&initialHeapSize);
4188     OffHeapInt::s_destructorCalls = 0;
4189 
4190     Persistent<Map> map1(new Map());
4191     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4192 
4193     {
4194         Map map2;
4195         Map* map3 = new Map();
4196         map2.add(OffHeapInt::create(1001), PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4197         map3->add(OffHeapInt::create(1002), PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4198         map1->add(OffHeapInt::create(1003), PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4199         EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4200 
4201         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4202         // The first map2 is pointed to from a persistent, so it's referenced, but
4203         // the weak processing may have taken place.
4204         if (map1->size()) {
4205             Iterator i1 = map1->begin();
4206             EXPECT_EQ(4, i1->value.first->value());
4207             EXPECT_EQ(5, i1->value.second->value());
4208             EXPECT_EQ(1003, i1->key->value());
4209         }
4210         // The second map2 is on-stack, so its backing store must be referenced from
4211         // the stack. That makes the weak references strong.
4212         Iterator i2 = map2.begin();
4213         EXPECT_EQ(0, i2->value.first->value());
4214         EXPECT_EQ(1, i2->value.second->value());
4215         EXPECT_EQ(1001, i2->key->value());
4216         // The third map2 is pointed to from the stack, so it's referenced, but the
4217         // weak processing may have taken place.
4218         if (map3->size()) {
4219             Iterator i3 = map3->begin();
4220             EXPECT_EQ(2, i3->value.first->value());
4221             EXPECT_EQ(3, i3->value.second->value());
4222             EXPECT_EQ(1002, i3->key->value());
4223         }
4224     }
4225     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4226 
4227     EXPECT_EQ(0u, map1->size());
4228     EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4229 
4230     OffHeapInt::s_destructorCalls = 0;
4231 
4232     map1->add(OffHeapInt::create(2000), PairWithWeakHandling(IntWrapper::create(103), livingInt));
4233     map1->add(OffHeapInt::create(2001), PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4234     map1->add(OffHeapInt::create(2002), PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4235     RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4236     map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt));
4237     map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4238     dupeInt.clear();
4239 
4240     EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4241     EXPECT_EQ(4u, map1->size());
4242     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4243     EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4244     EXPECT_EQ(2u, map1->size());
4245     Iterator i1 = map1->begin();
4246     EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4247     EXPECT_EQ(livingInt, i1->value.second);
4248     ++i1;
4249     EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4250     EXPECT_EQ(livingInt, i1->value.second);
4251 }
4252 
TEST(HeapTest,Bind)4253 TEST(HeapTest, Bind)
4254 {
4255     Closure closure = bind(&Bar::trace, Bar::create(), static_cast<Visitor*>(0));
4256     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4257     // The closure should have a persistent handle to the Bar.
4258     EXPECT_EQ(1u, Bar::s_live);
4259 
4260     Closure closure2 = bind(&Bar::trace, RawPtr<Bar>(Bar::create()), static_cast<Visitor*>(0));
4261     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4262     // The closure should have a persistent handle to the Bar.
4263     EXPECT_EQ(2u, Bar::s_live);
4264     // RawPtr<OffHeapInt> should not make Persistent.
4265     Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHeapInt::create(1).get()));
4266 
4267     UseMixin::s_traceCount = 0;
4268     Mixin* mixin = UseMixin::create();
4269     Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0));
4270     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4271     // The closure should have a persistent handle to the mixin.
4272     EXPECT_EQ(1, UseMixin::s_traceCount);
4273 }
4274 
4275 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
4276 
4277 // These special traits will remove a set from a map when the set is empty.
4278 struct EmptyClearingHastSetTraits : HashTraits<WeakSet> {
4279     static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
shouldRemoveFromCollectionWebCore::EmptyClearingHastSetTraits4280     static bool shouldRemoveFromCollection(Visitor* visitor, WeakSet& set)
4281     {
4282         return set.isEmpty(); // Remove this set from any maps it is in.
4283     }
traceInCollectionWebCore::EmptyClearingHastSetTraits4284     static void traceInCollection(Visitor* visitor, WeakSet& set, WebCore::ShouldWeakPointersBeMarkedStrongly strongify)
4285     {
4286         // We just trace normally, which will invoke the normal weak handling
4287         // of the set, removing individual items.
4288         set.trace(visitor);
4289     }
4290 };
4291 
4292 // This is an example to show how you can remove entries from a T->WeakSet map
4293 // when the weak sets become empty. For this example we are using a type that
4294 // is given to use (HeapHashSet) rather than a type of our own. This means:
4295 // 1) We can't just override the HashTrait for the type since this would affect
4296 //    all collections that use this kind of weak set. Instead we have our own
4297 //    traits and use a map with custom traits for the value type. These traits
4298 //    are the 5th template parameter, so we have to supply default values for
4299 //    the 3rd and 4th template parameters
4300 // 2) We can't just inherit from WeakHandlingHashTraits, since that trait
4301 //    assumes we can add methods to the type, but we can't add methods to
4302 //    HeapHashSet.
TEST(HeapTest,RemoveEmptySets)4303 TEST(HeapTest, RemoveEmptySets)
4304 {
4305     HeapStats initialHeapSize;
4306     clearOutOldGarbage(&initialHeapSize);
4307     OffHeapInt::s_destructorCalls = 0;
4308 
4309     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4310 
4311     typedef RefPtr<OffHeapInt> Key;
4312     typedef HeapHashMap<Key, WeakSet, WTF::DefaultHash<Key>::Hash, HashTraits<Key>, EmptyClearingHastSetTraits> Map;
4313     Persistent<Map> map(new Map());
4314     map->add(OffHeapInt::create(1), WeakSet());
4315     {
4316         WeakSet& set = map->begin()->value;
4317         set.add(IntWrapper::create(103)); // Weak set can't hold this long.
4318         set.add(livingInt); // This prevents the set from being emptied.
4319         EXPECT_EQ(2u, set.size());
4320     }
4321 
4322     // The set we add here is empty, so the entry will be removed from the map
4323     // at the next GC.
4324     map->add(OffHeapInt::create(2), WeakSet());
4325     EXPECT_EQ(2u, map->size());
4326 
4327     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4328     EXPECT_EQ(1u, map->size()); // The one with key 2 was removed.
4329     EXPECT_EQ(1, OffHeapInt::s_destructorCalls);
4330     {
4331         WeakSet& set = map->begin()->value;
4332         EXPECT_EQ(1u, set.size());
4333     }
4334 
4335     livingInt.clear(); // The weak set can no longer keep the '42' alive now.
4336     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4337     if (map->size() == 1u) {
4338         // If the weak processing for the set ran after the weak processing for
4339         // the map, then the set was not empty, and so the entry in the map was
4340         // not removed yet.
4341         WeakSet& set = map->begin()->value;
4342         EXPECT_EQ(0u, set.size());
4343     }
4344 
4345     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4346     EXPECT_EQ(0u, map->size());
4347 }
4348 
4349 } // WebCore namespace
4350