• 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/Task.h"
34 #include "platform/heap/Handle.h"
35 #include "platform/heap/Heap.h"
36 #include "platform/heap/HeapLinkedStack.h"
37 #include "platform/heap/HeapTerminatedArrayBuilder.h"
38 #include "platform/heap/ThreadState.h"
39 #include "platform/heap/Visitor.h"
40 #include "public/platform/Platform.h"
41 #include "wtf/HashTraits.h"
42 #include "wtf/LinkedHashSet.h"
43 
44 #include <gtest/gtest.h>
45 
46 namespace blink {
47 
48 class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
49 public:
create(int x)50     static IntWrapper* create(int x)
51     {
52         return new IntWrapper(x);
53     }
54 
~IntWrapper()55     virtual ~IntWrapper()
56     {
57         ++s_destructorCalls;
58     }
59 
60     static int s_destructorCalls;
trace(Visitor *)61     static void trace(Visitor*) { }
62 
value() const63     int value() const { return m_x; }
64 
operator ==(const IntWrapper & other) const65     bool operator==(const IntWrapper& other) const { return other.value() == value(); }
66 
hash()67     unsigned hash() { return IntHash<int>::hash(m_x); }
68 
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 {
hashblink::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 
equalblink::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.
PairWithWeakHandlingblink::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.
PairWithWeakHandlingblink::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.
isHashTableDeletedValueblink::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. If
138     // the entry should be deleted from the collection we return true and don't
139     // trace the strong pointer.
traceInCollectionblink::PairWithWeakHandling140     bool traceInCollection(Visitor* visitor, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
141     {
142         visitor->traceInCollection(second, strongify);
143         if (!visitor->isAlive(second))
144             return true;
145         visitor->trace(first);
146         return false;
147     }
148 };
149 
150 }
151 
152 namespace WTF {
153 
154 template<typename T> struct DefaultHash;
155 template<> struct DefaultHash<blink::ThreadMarker> {
156     typedef blink::ThreadMarkerHash Hash;
157 };
158 
159 // ThreadMarkerHash is the default hash for ThreadMarker
160 template<> struct HashTraits<blink::ThreadMarker> : GenericHashTraits<blink::ThreadMarker> {
161     static const bool emptyValueIsZero = true;
constructDeletedValueWTF::HashTraits162     static void constructDeletedValue(blink::ThreadMarker& slot, bool) { new (NotNull, &slot) blink::ThreadMarker(HashTableDeletedValue); }
isDeletedValueWTF::HashTraits163     static bool isDeletedValue(const blink::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
164 };
165 
166 // The hash algorithm for our custom pair class is just the standard double
167 // hash for pairs. Note that this means you can't mutate either of the parts of
168 // the pair while they are in the hash table, as that would change their hash
169 // code and thus their preferred placement in the table.
170 template<> struct DefaultHash<blink::PairWithWeakHandling> {
171     typedef PairHash<blink::Member<blink::IntWrapper>, blink::WeakMember<blink::IntWrapper> > Hash;
172 };
173 
174 // Custom traits for the pair. These are weakness handling traits, which means
175 // PairWithWeakHandling must implement the traceInCollection method.
176 // In addition, these traits are concerned with the two magic values for the
177 // object, that represent empty and deleted slots in the hash table. The
178 // SimpleClassHashTraits allow empty slots in the table to be initialzed with
179 // memset to zero, and we use -1 in the first part of the pair to represent
180 // deleted slots.
181 template<> struct HashTraits<blink::PairWithWeakHandling> : blink::WeakHandlingHashTraits<blink::PairWithWeakHandling> {
182     static const bool needsDestruction = false;
183     static const bool hasIsEmptyValueFunction = true;
isEmptyValueWTF::HashTraits184     static bool isEmptyValue(const blink::PairWithWeakHandling& value) { return !value.first; }
constructDeletedValueWTF::HashTraits185     static void constructDeletedValue(blink::PairWithWeakHandling& slot, bool) { new (NotNull, &slot) blink::PairWithWeakHandling(HashTableDeletedValue); }
isDeletedValueWTF::HashTraits186     static bool isDeletedValue(const blink::PairWithWeakHandling& value) { return value.isHashTableDeletedValue(); }
187 };
188 
189 }
190 
191 namespace blink {
192 
193 class TestGCScope {
194 public:
TestGCScope(ThreadState::StackState state)195     explicit TestGCScope(ThreadState::StackState state)
196         : m_state(ThreadState::current())
197         , m_safePointScope(state)
198         , m_parkedAllThreads(false)
199     {
200         m_state->checkThread();
201         EXPECT_FALSE(m_state->isInGC());
202         if (LIKELY(ThreadState::stopThreads())) {
203             m_state->enterGC();
204             m_parkedAllThreads = true;
205         }
206     }
207 
allThreadsParked()208     bool allThreadsParked() { return m_parkedAllThreads; }
209 
~TestGCScope()210     ~TestGCScope()
211     {
212         // Only cleanup if we parked all threads in which case the GC happened
213         // and we need to resume the other threads.
214         if (LIKELY(m_parkedAllThreads)) {
215             m_state->leaveGC();
216             EXPECT_FALSE(m_state->isInGC());
217             ThreadState::resumeThreads();
218         }
219     }
220 
221 private:
222     ThreadState* m_state;
223     ThreadState::SafePointScope m_safePointScope;
224     bool m_parkedAllThreads; // False if we fail to park all threads
225 };
226 
getHeapStats(HeapStats * stats)227 static void getHeapStats(HeapStats* stats)
228 {
229     TestGCScope scope(ThreadState::NoHeapPointersOnStack);
230     EXPECT_TRUE(scope.allThreadsParked());
231     Heap::getStats(stats);
232 }
233 
234 #define DEFINE_VISITOR_METHODS(Type)                                       \
235     virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
236     {                                                                      \
237         if (object)                                                        \
238             m_count++;                                                     \
239     }                                                                      \
240     virtual bool isMarked(const Type*) OVERRIDE { return false; }
241 
242 class CountingVisitor : public Visitor {
243 public:
CountingVisitor()244     CountingVisitor()
245         : m_count(0)
246     {
247     }
248 
mark(const void * object,TraceCallback)249     virtual void mark(const void* object, TraceCallback) OVERRIDE
250     {
251         if (object)
252             m_count++;
253     }
254 
mark(HeapObjectHeader * header,TraceCallback callback)255     virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
256     {
257         ASSERT(header->payload());
258         m_count++;
259     }
260 
mark(FinalizedHeapObjectHeader * header,TraceCallback callback)261     virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
262     {
263         ASSERT(header->payload());
264         m_count++;
265     }
266 
registerDelayedMarkNoTracing(const void *)267     virtual void registerDelayedMarkNoTracing(const void*) OVERRIDE { }
registerWeakMembers(const void *,const void *,WeakPointerCallback)268     virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
registerWeakTable(const void *,EphemeronCallback,EphemeronCallback)269     virtual void registerWeakTable(const void*, EphemeronCallback, EphemeronCallback) OVERRIDE { }
270 #if ENABLE(ASSERT)
weakTableRegistered(const void *)271     virtual bool weakTableRegistered(const void*) OVERRIDE { return false; }
272 #endif
registerWeakCell(void **,WeakPointerCallback)273     virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
isMarked(const void *)274     virtual bool isMarked(const void*) OVERRIDE { return false; }
275 
FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)276     FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
277 
278     size_t count() { return m_count; }
reset()279     void reset() { m_count = 0; }
280 
281 private:
282     size_t m_count;
283 };
284 
285 class SimpleObject : public GarbageCollected<SimpleObject> {
286 public:
create()287     static SimpleObject* create() { return new SimpleObject(); }
trace(Visitor *)288     void trace(Visitor*) { }
getPayload(int i)289     char getPayload(int i) { return payload[i]; }
290     // This virtual method is unused but it is here to make sure
291     // that this object has a vtable. This object is used
292     // as the super class for objects that also have garbage
293     // collected mixins and having a virtual here makes sure
294     // that adjustment is needed both for marking and for isAlive
295     // checks.
virtualMethod()296     virtual void virtualMethod() { }
297 protected:
SimpleObject()298     SimpleObject() { }
299     char payload[64];
300 };
301 
302 #undef DEFINE_VISITOR_METHODS
303 
304 class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
305 public:
create()306     static HeapTestSuperClass* create()
307     {
308         return new HeapTestSuperClass();
309     }
310 
~HeapTestSuperClass()311     virtual ~HeapTestSuperClass()
312     {
313         ++s_destructorCalls;
314     }
315 
316     static int s_destructorCalls;
trace(Visitor *)317     void trace(Visitor*) { }
318 
319 protected:
HeapTestSuperClass()320     HeapTestSuperClass() { }
321 };
322 
323 int HeapTestSuperClass::s_destructorCalls = 0;
324 
325 class HeapTestOtherSuperClass {
326 public:
327     int payload;
328 };
329 
330 static const size_t classMagic = 0xABCDDBCA;
331 
332 class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
333 public:
create()334     static HeapTestSubClass* create()
335     {
336         return new HeapTestSubClass();
337     }
338 
~HeapTestSubClass()339     virtual ~HeapTestSubClass()
340     {
341         EXPECT_EQ(classMagic, m_magic);
342         ++s_destructorCalls;
343     }
344 
345     static int s_destructorCalls;
346 
347 private:
348 
HeapTestSubClass()349     HeapTestSubClass() : m_magic(classMagic) { }
350 
351     const size_t m_magic;
352 };
353 
354 int HeapTestSubClass::s_destructorCalls = 0;
355 
356 class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
357 public:
HeapAllocatedArray()358     HeapAllocatedArray()
359     {
360         for (int i = 0; i < s_arraySize; ++i) {
361             m_array[i] = i % 128;
362         }
363     }
364 
at(size_t i)365     int8_t at(size_t i) { return m_array[i]; }
trace(Visitor *)366     void trace(Visitor*) { }
367 private:
368     static const int s_arraySize = 1000;
369     int8_t m_array[s_arraySize];
370 };
371 
372 // Do several GCs to make sure that later GCs don't free up old memory from
373 // previously run tests in this process.
clearOutOldGarbage(HeapStats * heapStats)374 static void clearOutOldGarbage(HeapStats* heapStats)
375 {
376     while (true) {
377         getHeapStats(heapStats);
378         size_t used = heapStats->totalObjectSpace();
379         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
380         getHeapStats(heapStats);
381         if (heapStats->totalObjectSpace() >= used)
382             break;
383     }
384 }
385 
386 class OffHeapInt : public RefCounted<OffHeapInt> {
387 public:
create(int x)388     static RefPtr<OffHeapInt> create(int x)
389     {
390         return adoptRef(new OffHeapInt(x));
391     }
392 
~OffHeapInt()393     virtual ~OffHeapInt()
394     {
395         ++s_destructorCalls;
396     }
397 
398     static int s_destructorCalls;
399 
value() const400     int value() const { return m_x; }
401 
operator ==(const OffHeapInt & other) const402     bool operator==(const OffHeapInt& other) const { return other.value() == value(); }
403 
hash()404     unsigned hash() { return IntHash<int>::hash(m_x); }
voidFunction()405     void voidFunction() { }
406 
407 protected:
OffHeapInt(int x)408     OffHeapInt(int x) : m_x(x) { }
409 
410 private:
411     OffHeapInt();
412     int m_x;
413 };
414 
415 int IntWrapper::s_destructorCalls = 0;
416 int OffHeapInt::s_destructorCalls = 0;
417 
418 class ThreadedTesterBase {
419 protected:
test(ThreadedTesterBase * tester)420     static void test(ThreadedTesterBase* tester)
421     {
422         Vector<OwnPtr<WebThread>, numberOfThreads> m_threads;
423         for (int i = 0; i < numberOfThreads; i++) {
424             m_threads.append(adoptPtr(Platform::current()->createThread("blink gc testing thread")));
425             m_threads.last()->postTask(new Task(WTF::bind(threadFunc, tester)));
426         }
427         while (tester->m_threadsToFinish) {
428             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
429             Platform::current()->yieldCurrentThread();
430         }
431         delete tester;
432     }
433 
434     virtual void runThread() = 0;
435 
436 protected:
437     static const int numberOfThreads = 10;
438     static const int gcPerThread = 5;
439     static const int numberOfAllocations = 50;
440 
ThreadedTesterBase()441     ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
442     {
443     }
444 
~ThreadedTesterBase()445     virtual ~ThreadedTesterBase()
446     {
447     }
448 
done() const449     inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
450 
451     volatile int m_gcCount;
452     volatile int m_threadsToFinish;
453 
454 private:
threadFunc(void * data)455     static void threadFunc(void* data)
456     {
457         reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
458     }
459 };
460 
461 class ThreadedHeapTester : public ThreadedTesterBase {
462 public:
test()463     static void test()
464     {
465         ThreadedTesterBase::test(new ThreadedHeapTester);
466     }
467 
468 protected:
runThread()469     virtual void runThread() OVERRIDE
470     {
471         ThreadState::attach();
472 
473         int gcCount = 0;
474         while (!done()) {
475             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
476             {
477                 Persistent<IntWrapper> wrapper;
478 
479                 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
480                 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
481 
482                 for (int i = 0; i < numberOfAllocations; i++) {
483                     wrapper = IntWrapper::create(0x0bbac0de);
484                     if (!(i % 10)) {
485                         globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
486                     }
487                     ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
488                     Platform::current()->yieldCurrentThread();
489                 }
490 
491                 if (gcCount < gcPerThread) {
492                     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
493                     gcCount++;
494                     atomicIncrement(&m_gcCount);
495                 }
496 
497                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
498                 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
499                 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
500             }
501             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
502             Platform::current()->yieldCurrentThread();
503         }
504         ThreadState::detach();
505         atomicDecrement(&m_threadsToFinish);
506     }
507 };
508 
509 class ThreadedWeaknessTester : public ThreadedTesterBase {
510 public:
test()511     static void test()
512     {
513         ThreadedTesterBase::test(new ThreadedWeaknessTester);
514     }
515 
516 private:
runThread()517     virtual void runThread() OVERRIDE
518     {
519         ThreadState::attach();
520 
521         int gcCount = 0;
522         while (!done()) {
523             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
524             {
525                 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
526                 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
527 
528                 for (int i = 0; i < numberOfAllocations; i++) {
529                     weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
530                     weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
531                     ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
532                     Platform::current()->yieldCurrentThread();
533                 }
534 
535                 if (gcCount < gcPerThread) {
536                     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
537                     gcCount++;
538                     atomicIncrement(&m_gcCount);
539                 }
540 
541                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
542                 EXPECT_TRUE(weakMap->isEmpty());
543                 EXPECT_TRUE(weakMap2.isEmpty());
544             }
545             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
546             Platform::current()->yieldCurrentThread();
547         }
548         ThreadState::detach();
549         atomicDecrement(&m_threadsToFinish);
550     }
551 };
552 
553 // The accounting for memory includes the memory used by rounding up object
554 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to
555 // have some slack in the tests.
556 template<typename T>
CheckWithSlack(T expected,T actual,int slack)557 void CheckWithSlack(T expected, T actual, int slack)
558 {
559     EXPECT_LE(expected, actual);
560     EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
561 }
562 
563 class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
564 public:
create()565     static TraceCounter* create()
566     {
567         return new TraceCounter();
568     }
569 
trace(Visitor *)570     void trace(Visitor*) { m_traceCount++; }
571 
traceCount()572     int traceCount() { return m_traceCount; }
573 
574 private:
TraceCounter()575     TraceCounter()
576         : m_traceCount(0)
577     {
578     }
579 
580     int m_traceCount;
581 };
582 
583 class ClassWithMember : public GarbageCollected<ClassWithMember> {
584 public:
create()585     static ClassWithMember* create()
586     {
587         return new ClassWithMember();
588     }
589 
trace(Visitor * visitor)590     void trace(Visitor* visitor)
591     {
592         EXPECT_TRUE(visitor->isMarked(this));
593         if (!traceCount())
594             EXPECT_FALSE(visitor->isMarked(m_traceCounter));
595         else
596             EXPECT_TRUE(visitor->isMarked(m_traceCounter));
597 
598         visitor->trace(m_traceCounter);
599     }
600 
traceCount()601     int traceCount() { return m_traceCounter->traceCount(); }
602 
603 private:
ClassWithMember()604     ClassWithMember()
605         : m_traceCounter(TraceCounter::create())
606     { }
607 
608     Member<TraceCounter> m_traceCounter;
609 };
610 
611 class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
612 public:
create()613     static SimpleFinalizedObject* create()
614     {
615         return new SimpleFinalizedObject();
616     }
617 
~SimpleFinalizedObject()618     ~SimpleFinalizedObject()
619     {
620         ++s_destructorCalls;
621     }
622 
623     static int s_destructorCalls;
624 
trace(Visitor *)625     void trace(Visitor*) { }
626 
627 private:
SimpleFinalizedObject()628     SimpleFinalizedObject() { }
629 };
630 
631 int SimpleFinalizedObject::s_destructorCalls = 0;
632 
633 class Node : public GarbageCollected<Node> {
634 public:
create(int i)635     static Node* create(int i)
636     {
637         return new Node(i);
638     }
639 
trace(Visitor *)640     void trace(Visitor*) { }
641 
value()642     int value() { return m_value; }
643 
644 private:
Node(int i)645     Node(int i) : m_value(i) { }
646     int m_value;
647 };
648 
649 class Bar : public GarbageCollectedFinalized<Bar> {
650 public:
create()651     static Bar* create()
652     {
653         return new Bar();
654     }
655 
finalizeGarbageCollectedObject()656     void finalizeGarbageCollectedObject()
657     {
658         EXPECT_TRUE(m_magic == magic);
659         m_magic = 0;
660         s_live--;
661     }
hasBeenFinalized() const662     bool hasBeenFinalized() const { return !m_magic; }
663 
trace(Visitor * visitor)664     virtual void trace(Visitor* visitor) { }
665     static unsigned s_live;
666 
667 protected:
668     static const int magic = 1337;
669     int m_magic;
670 
Bar()671     Bar()
672         : m_magic(magic)
673     {
674         s_live++;
675     }
676 };
677 
678 unsigned Bar::s_live = 0;
679 
680 class Baz : public GarbageCollected<Baz> {
681 public:
create(Bar * bar)682     static Baz* create(Bar* bar)
683     {
684         return new Baz(bar);
685     }
686 
trace(Visitor * visitor)687     void trace(Visitor* visitor)
688     {
689         visitor->trace(m_bar);
690     }
691 
clear()692     void clear() { m_bar.release(); }
693 
694     // willFinalize is called by FinalizationObserver.
willFinalize()695     void willFinalize()
696     {
697         EXPECT_TRUE(!m_bar->hasBeenFinalized());
698     }
699 
700 private:
Baz(Bar * bar)701     explicit Baz(Bar* bar)
702         : m_bar(bar)
703     {
704     }
705 
706     Member<Bar> m_bar;
707 };
708 
709 class Foo : public Bar {
710 public:
create(Bar * bar)711     static Foo* create(Bar* bar)
712     {
713         return new Foo(bar);
714     }
715 
create(Foo * foo)716     static Foo* create(Foo* foo)
717     {
718         return new Foo(foo);
719     }
720 
trace(Visitor * visitor)721     virtual void trace(Visitor* visitor) OVERRIDE
722     {
723         if (m_pointsToFoo)
724             visitor->mark(static_cast<Foo*>(m_bar));
725         else
726             visitor->mark(m_bar);
727     }
728 
729 private:
Foo(Bar * bar)730     Foo(Bar* bar)
731         : Bar()
732         , m_bar(bar)
733         , m_pointsToFoo(false)
734     {
735     }
736 
Foo(Foo * foo)737     Foo(Foo* foo)
738         : Bar()
739         , m_bar(foo)
740         , m_pointsToFoo(true)
741     {
742     }
743 
744     Bar* m_bar;
745     bool m_pointsToFoo;
746 };
747 
748 class Bars : public Bar {
749 public:
create()750     static Bars* create()
751     {
752         return new Bars();
753     }
754 
trace(Visitor * visitor)755     virtual void trace(Visitor* visitor) OVERRIDE
756     {
757         for (unsigned i = 0; i < m_width; i++)
758             visitor->trace(m_bars[i]);
759     }
760 
getWidth() const761     unsigned getWidth() const
762     {
763         return m_width;
764     }
765 
766     static const unsigned width = 7500;
767 private:
Bars()768     Bars() : m_width(0)
769     {
770         for (unsigned i = 0; i < width; i++) {
771             m_bars[i] = Bar::create();
772             m_width++;
773         }
774     }
775 
776     unsigned m_width;
777     Member<Bar> m_bars[width];
778 };
779 
780 class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
781 public:
create()782     static ConstructorAllocation* create() { return new ConstructorAllocation(); }
783 
trace(Visitor * visitor)784     void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
785 
786 private:
ConstructorAllocation()787     ConstructorAllocation()
788     {
789         m_intWrapper = IntWrapper::create(42);
790     }
791 
792     Member<IntWrapper> m_intWrapper;
793 };
794 
795 class LargeObject : public GarbageCollectedFinalized<LargeObject> {
796 public:
~LargeObject()797     ~LargeObject()
798     {
799         s_destructorCalls++;
800     }
create()801     static LargeObject* create() { return new LargeObject(); }
get(size_t i)802     char get(size_t i) { return m_data[i]; }
set(size_t i,char c)803     void set(size_t i, char c) { m_data[i] = c; }
length()804     size_t length() { return s_length; }
trace(Visitor * visitor)805     void trace(Visitor* visitor)
806     {
807         visitor->trace(m_intWrapper);
808     }
809     static int s_destructorCalls;
810 
811 private:
812     static const size_t s_length = 1024*1024;
LargeObject()813     LargeObject()
814     {
815         m_intWrapper = IntWrapper::create(23);
816     }
817     Member<IntWrapper> m_intWrapper;
818     char m_data[s_length];
819 };
820 
821 int LargeObject::s_destructorCalls = 0;
822 
823 class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
824 public:
create()825     static PassRefPtr<RefCountedAndGarbageCollected> create()
826     {
827         return adoptRef(new RefCountedAndGarbageCollected());
828     }
829 
~RefCountedAndGarbageCollected()830     ~RefCountedAndGarbageCollected()
831     {
832         ++s_destructorCalls;
833     }
834 
835     // These are here with their default implementations so you can break in
836     // them in the debugger.
ref()837     void ref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::ref(); }
deref()838     void deref() { RefCountedGarbageCollected<RefCountedAndGarbageCollected>::deref(); }
839 
trace(Visitor *)840     void trace(Visitor*) { }
841 
842     static int s_destructorCalls;
843 
844 private:
RefCountedAndGarbageCollected()845     RefCountedAndGarbageCollected()
846     {
847     }
848 };
849 
850 int RefCountedAndGarbageCollected::s_destructorCalls = 0;
851 
852 class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
853 public:
create()854     static RefCountedAndGarbageCollected2* create()
855     {
856         return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
857     }
858 
~RefCountedAndGarbageCollected2()859     ~RefCountedAndGarbageCollected2()
860     {
861         ++s_destructorCalls;
862     }
863 
trace(Visitor *)864     void trace(Visitor*) { }
865 
866     static int s_destructorCalls;
867 
868 private:
RefCountedAndGarbageCollected2()869     RefCountedAndGarbageCollected2()
870     {
871     }
872 };
873 
874 int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
875 
876 #define DEFINE_VISITOR_METHODS(Type)                                       \
877     virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
878     {                                                                      \
879         mark(object);                                                      \
880     }                                                                      \
881 
882 class RefCountedGarbageCollectedVisitor : public CountingVisitor {
883 public:
RefCountedGarbageCollectedVisitor(int expected,void ** objects)884     RefCountedGarbageCollectedVisitor(int expected, void** objects)
885         : m_count(0)
886         , m_expectedCount(expected)
887         , m_expectedObjects(objects)
888     {
889     }
890 
mark(const void * ptr)891     void mark(const void* ptr) { markNoTrace(ptr); }
892 
markNoTrace(const void * ptr)893     virtual void markNoTrace(const void* ptr)
894     {
895         if (!ptr)
896             return;
897         if (m_count < m_expectedCount)
898             EXPECT_TRUE(expectedObject(ptr));
899         else
900             EXPECT_FALSE(expectedObject(ptr));
901         m_count++;
902     }
903 
mark(const void * ptr,TraceCallback)904     virtual void mark(const void* ptr, TraceCallback) OVERRIDE
905     {
906         mark(ptr);
907     }
908 
mark(HeapObjectHeader * header,TraceCallback callback)909     virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
910     {
911         mark(header->payload());
912     }
913 
mark(FinalizedHeapObjectHeader * header,TraceCallback callback)914     virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
915     {
916         mark(header->payload());
917     }
918 
validate()919     bool validate() { return m_count >= m_expectedCount; }
reset()920     void reset() { m_count = 0; }
921 
922     FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
923 
924 private:
expectedObject(const void * ptr)925     bool expectedObject(const void* ptr)
926     {
927         for (int i = 0; i < m_expectedCount; i++) {
928             if (m_expectedObjects[i] == ptr)
929                 return true;
930         }
931         return false;
932     }
933 
934     int m_count;
935     int m_expectedCount;
936     void** m_expectedObjects;
937 };
938 
939 #undef DEFINE_VISITOR_METHODS
940 
941 class Weak : public Bar {
942 public:
create(Bar * strong,Bar * weak)943     static Weak* create(Bar* strong, Bar* weak)
944     {
945         return new Weak(strong, weak);
946     }
947 
trace(Visitor * visitor)948     virtual void trace(Visitor* visitor) OVERRIDE
949     {
950         visitor->trace(m_strongBar);
951         visitor->registerWeakMembers(this, zapWeakMembers);
952     }
953 
zapWeakMembers(Visitor * visitor,void * self)954     static void zapWeakMembers(Visitor* visitor, void* self)
955     {
956         reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
957     }
958 
strongIsThere()959     bool strongIsThere() { return !!m_strongBar; }
weakIsThere()960     bool weakIsThere() { return !!m_weakBar; }
961 
962 private:
Weak(Bar * strongBar,Bar * weakBar)963     Weak(Bar* strongBar, Bar* weakBar)
964         : Bar()
965         , m_strongBar(strongBar)
966         , m_weakBar(weakBar)
967     {
968     }
969 
zapWeakMembers(Visitor * visitor)970     void zapWeakMembers(Visitor* visitor)
971     {
972         if (!visitor->isAlive(m_weakBar))
973             m_weakBar = 0;
974     }
975 
976     Member<Bar> m_strongBar;
977     Bar* m_weakBar;
978 };
979 
980 class WithWeakMember : public Bar {
981 public:
create(Bar * strong,Bar * weak)982     static WithWeakMember* create(Bar* strong, Bar* weak)
983     {
984         return new WithWeakMember(strong, weak);
985     }
986 
trace(Visitor * visitor)987     virtual void trace(Visitor* visitor) OVERRIDE
988     {
989         visitor->trace(m_strongBar);
990         visitor->trace(m_weakBar);
991     }
992 
strongIsThere()993     bool strongIsThere() { return !!m_strongBar; }
weakIsThere()994     bool weakIsThere() { return !!m_weakBar; }
995 
996 private:
WithWeakMember(Bar * strongBar,Bar * weakBar)997     WithWeakMember(Bar* strongBar, Bar* weakBar)
998         : Bar()
999         , m_strongBar(strongBar)
1000         , m_weakBar(weakBar)
1001     {
1002     }
1003 
1004     Member<Bar> m_strongBar;
1005     WeakMember<Bar> m_weakBar;
1006 };
1007 
1008 class Observable : public GarbageCollectedFinalized<Observable> {
1009 public:
create(Bar * bar)1010     static Observable* create(Bar* bar) { return new Observable(bar);  }
~Observable()1011     ~Observable() { m_wasDestructed = true; }
trace(Visitor * visitor)1012     void trace(Visitor* visitor) { visitor->trace(m_bar); }
1013 
1014     // willFinalize is called by FinalizationObserver. willFinalize can touch
1015     // other on-heap objects.
willFinalize()1016     void willFinalize()
1017     {
1018         EXPECT_FALSE(m_wasDestructed);
1019         EXPECT_FALSE(m_bar->hasBeenFinalized());
1020     }
1021 
1022 private:
Observable(Bar * bar)1023     explicit Observable(Bar* bar)
1024         : m_bar(bar)
1025         , m_wasDestructed(false)
1026     {
1027     }
1028 
1029     Member<Bar> m_bar;
1030     bool m_wasDestructed;
1031 };
1032 
1033 template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
1034 public:
create(T * data)1035     static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
didCallWillFinalize() const1036     bool didCallWillFinalize() const { return m_didCallWillFinalize; }
1037 
trace(Visitor * visitor)1038     void trace(Visitor* visitor)
1039     {
1040         visitor->registerWeakMembers(this, zapWeakMembers);
1041     }
1042 
1043 private:
FinalizationObserver(T * data)1044     FinalizationObserver(T* data)
1045         : m_data(data)
1046         , m_didCallWillFinalize(false)
1047     {
1048     }
1049 
zapWeakMembers(Visitor * visitor,void * self)1050     static void zapWeakMembers(Visitor* visitor, void* self)
1051     {
1052         FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
1053         if (o->m_data && !visitor->isAlive(o->m_data)) {
1054             o->m_data->willFinalize();
1055             o->m_data = nullptr;
1056             o->m_didCallWillFinalize = true;
1057         }
1058     }
1059 
1060     WeakMember<T> m_data;
1061     bool m_didCallWillFinalize;
1062 };
1063 
1064 class FinalizationObserverWithHashMap {
1065 public:
1066     typedef HeapHashMap<WeakMember<Observable>, OwnPtr<FinalizationObserverWithHashMap> > ObserverMap;
1067 
FinalizationObserverWithHashMap(Observable & target)1068     explicit FinalizationObserverWithHashMap(Observable& target) : m_target(target) { }
~FinalizationObserverWithHashMap()1069     ~FinalizationObserverWithHashMap()
1070     {
1071         m_target.willFinalize();
1072         s_didCallWillFinalize = true;
1073     }
1074 
observe(Observable & target)1075     static ObserverMap& observe(Observable& target)
1076     {
1077         ObserverMap& map = observers();
1078         ObserverMap::AddResult result = map.add(&target, nullptr);
1079         if (result.isNewEntry)
1080             result.storedValue->value = adoptPtr(new FinalizationObserverWithHashMap(target));
1081         else
1082             ASSERT(result.storedValue->value);
1083         return map;
1084     }
1085 
1086     static bool s_didCallWillFinalize;
1087 
1088 private:
observers()1089     static ObserverMap& observers()
1090     {
1091         DEFINE_STATIC_LOCAL(Persistent<ObserverMap>, observerMap, ());
1092         if (!observerMap)
1093             observerMap = new ObserverMap();
1094         return *observerMap;
1095     }
1096 
1097     Observable& m_target;
1098 };
1099 
1100 bool FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
1101 
1102 class SuperClass;
1103 
1104 class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
1105 public:
create()1106     static PassRefPtrWillBeRawPtr<PointsBack> create()
1107     {
1108         return adoptRefWillBeNoop(new PointsBack());
1109     }
1110 
~PointsBack()1111     ~PointsBack()
1112     {
1113         --s_aliveCount;
1114     }
1115 
setBackPointer(SuperClass * backPointer)1116     void setBackPointer(SuperClass* backPointer)
1117     {
1118         m_backPointer = backPointer;
1119     }
1120 
backPointer() const1121     SuperClass* backPointer() const { return m_backPointer; }
1122 
trace(Visitor * visitor)1123     void trace(Visitor* visitor)
1124     {
1125 #if ENABLE_OILPAN
1126         visitor->trace(m_backPointer);
1127 #endif
1128     }
1129 
1130     static int s_aliveCount;
1131 private:
PointsBack()1132     PointsBack() : m_backPointer(nullptr)
1133     {
1134         ++s_aliveCount;
1135     }
1136 
1137     RawPtrWillBeWeakMember<SuperClass> m_backPointer;
1138 };
1139 
1140 int PointsBack::s_aliveCount = 0;
1141 
1142 class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
1143 public:
create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1144     static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1145     {
1146         return adoptRefWillBeNoop(new SuperClass(pointsBack));
1147     }
1148 
~SuperClass()1149     virtual ~SuperClass()
1150     {
1151 #if !ENABLE_OILPAN
1152         m_pointsBack->setBackPointer(0);
1153 #endif
1154         --s_aliveCount;
1155     }
1156 
doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass,PointsBack * pointsBack,int superClassCount)1157     void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
1158     {
1159         RefPtrWillBeRawPtr<SuperClass> target = targetPass;
1160         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1161         EXPECT_EQ(pointsBack, target->pointsBack());
1162         EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
1163     }
1164 
trace(Visitor * visitor)1165     virtual void trace(Visitor* visitor)
1166     {
1167 #if ENABLE_OILPAN
1168         visitor->trace(m_pointsBack);
1169 #endif
1170     }
1171 
pointsBack() const1172     PointsBack* pointsBack() const { return m_pointsBack.get(); }
1173 
1174     static int s_aliveCount;
1175 protected:
SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1176     explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1177         : m_pointsBack(pointsBack)
1178     {
1179         m_pointsBack->setBackPointer(this);
1180         ++s_aliveCount;
1181     }
1182 
1183 private:
1184     RefPtrWillBeMember<PointsBack> m_pointsBack;
1185 };
1186 
1187 int SuperClass::s_aliveCount = 0;
1188 class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
1189 public:
SubData()1190     SubData() { ++s_aliveCount; }
~SubData()1191     ~SubData() { --s_aliveCount; }
1192 
trace(Visitor *)1193     void trace(Visitor*) { }
1194 
1195     static int s_aliveCount;
1196 };
1197 
1198 int SubData::s_aliveCount = 0;
1199 
1200 class SubClass : public SuperClass {
1201 public:
create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1202     static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1203     {
1204         return adoptRefWillBeNoop(new SubClass(pointsBack));
1205     }
1206 
~SubClass()1207     virtual ~SubClass()
1208     {
1209         --s_aliveCount;
1210     }
1211 
trace(Visitor * visitor)1212     virtual void trace(Visitor* visitor)
1213     {
1214 #if ENABLE_OILPAN
1215         SuperClass::trace(visitor);
1216         visitor->trace(m_data);
1217 #endif
1218     }
1219 
1220     static int s_aliveCount;
1221 private:
SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)1222     explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1223         : SuperClass(pointsBack)
1224         , m_data(adoptPtrWillBeNoop(new SubData()))
1225     {
1226         ++s_aliveCount;
1227     }
1228 
1229 private:
1230     OwnPtrWillBeMember<SubData> m_data;
1231 };
1232 
1233 int SubClass::s_aliveCount = 0;
1234 
1235 class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
1236 public:
create()1237     static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1238     {
1239         return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
1240     }
1241 
~TransitionRefCounted()1242     ~TransitionRefCounted()
1243     {
1244         --s_aliveCount;
1245     }
1246 
trace(Visitor * visitor)1247     void trace(Visitor* visitor) { }
1248 
1249     static int s_aliveCount;
1250 
1251 private:
TransitionRefCounted()1252     TransitionRefCounted()
1253     {
1254         ++s_aliveCount;
1255     }
1256 };
1257 
1258 int TransitionRefCounted::s_aliveCount = 0;
1259 
1260 class Mixin : public GarbageCollectedMixin {
1261 public:
trace(Visitor * visitor)1262     virtual void trace(Visitor* visitor) { }
1263 
getPayload(int i)1264     virtual char getPayload(int i) { return m_padding[i]; }
1265 
1266 protected:
1267     int m_padding[8];
1268 };
1269 
1270 class UseMixin : public SimpleObject, public Mixin {
1271     USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1272 public:
create()1273     static UseMixin* create()
1274     {
1275         return new UseMixin();
1276     }
1277 
1278     static int s_traceCount;
trace(Visitor * visitor)1279     virtual void trace(Visitor* visitor)
1280     {
1281         SimpleObject::trace(visitor);
1282         Mixin::trace(visitor);
1283         ++s_traceCount;
1284     }
1285 
1286 private:
UseMixin()1287     UseMixin()
1288     {
1289         s_traceCount = 0;
1290     }
1291 };
1292 
1293 int UseMixin::s_traceCount = 0;
1294 
1295 class VectorObject {
1296     ALLOW_ONLY_INLINE_ALLOCATION();
1297 public:
VectorObject()1298     VectorObject()
1299     {
1300         m_value = SimpleFinalizedObject::create();
1301     }
1302 
trace(Visitor * visitor)1303     void trace(Visitor* visitor)
1304     {
1305         visitor->trace(m_value);
1306     }
1307 
1308 private:
1309     Member<SimpleFinalizedObject> m_value;
1310 };
1311 
1312 class VectorObjectInheritedTrace : public VectorObject { };
1313 
1314 class VectorObjectNoTrace {
1315     ALLOW_ONLY_INLINE_ALLOCATION();
1316 public:
VectorObjectNoTrace()1317     VectorObjectNoTrace()
1318     {
1319         m_value = SimpleFinalizedObject::create();
1320     }
1321 
1322 private:
1323     Member<SimpleFinalizedObject> m_value;
1324 };
1325 
1326 class TerminatedArrayItem {
1327     ALLOW_ONLY_INLINE_ALLOCATION();
1328 public:
TerminatedArrayItem(IntWrapper * payload)1329     TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1330 
trace(Visitor * visitor)1331     void trace(Visitor* visitor) { visitor->trace(m_payload); }
1332 
isLastInArray() const1333     bool isLastInArray() const { return m_isLast; }
setLastInArray(bool value)1334     void setLastInArray(bool value) { m_isLast = value; }
1335 
payload() const1336     IntWrapper* payload() const { return m_payload; }
1337 
1338 private:
1339     Member<IntWrapper> m_payload;
1340     bool m_isLast;
1341 };
1342 
1343 } // namespace blink
1344 
1345 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObject);
1346 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectInheritedTrace);
1347 WTF_ALLOW_MOVE_INIT_AND_COMPARE_WITH_MEM_FUNCTIONS(blink::VectorObjectNoTrace);
1348 
1349 namespace blink {
1350 
1351 class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1352 public:
~OneKiloByteObject()1353     ~OneKiloByteObject() { s_destructorCalls++; }
data()1354     char* data() { return m_data; }
trace(Visitor * visitor)1355     void trace(Visitor* visitor) { }
1356     static int s_destructorCalls;
1357 
1358 private:
1359     static const size_t s_length = 1024;
1360     char m_data[s_length];
1361 };
1362 
1363 int OneKiloByteObject::s_destructorCalls = 0;
1364 
1365 class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1366 public:
create(size_t size)1367     static DynamicallySizedObject* create(size_t size)
1368     {
1369         void* slot = Heap::allocate<DynamicallySizedObject>(size);
1370         return new (slot) DynamicallySizedObject();
1371     }
1372 
operator new(std::size_t,void * location)1373     void* operator new(std::size_t, void* location)
1374     {
1375         return location;
1376     }
1377 
get(int i)1378     uint8_t get(int i)
1379     {
1380         return *(reinterpret_cast<uint8_t*>(this) + i);
1381     }
1382 
trace(Visitor *)1383     void trace(Visitor*) { }
1384 
1385 private:
DynamicallySizedObject()1386     DynamicallySizedObject() { }
1387 };
1388 
1389 class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1390 public:
FinalizationAllocator(Persistent<IntWrapper> * wrapper)1391     FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1392         : m_wrapper(wrapper)
1393     {
1394     }
1395 
~FinalizationAllocator()1396     ~FinalizationAllocator()
1397     {
1398         for (int i = 0; i < 10; ++i)
1399             *m_wrapper = IntWrapper::create(42);
1400         for (int i = 0; i < 512; ++i)
1401             new OneKiloByteObject();
1402     }
1403 
trace(Visitor *)1404     void trace(Visitor*) { }
1405 
1406 private:
1407     Persistent<IntWrapper>* m_wrapper;
1408 };
1409 
TEST(HeapTest,Transition)1410 TEST(HeapTest, Transition)
1411 {
1412     {
1413         RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1414         EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1415         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1416         EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1417     }
1418     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1419     EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1420 
1421     RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1422     RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1423     RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1424     RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1425     EXPECT_EQ(2, PointsBack::s_aliveCount);
1426     EXPECT_EQ(2, SuperClass::s_aliveCount);
1427     EXPECT_EQ(1, SubClass::s_aliveCount);
1428     EXPECT_EQ(1, SubData::s_aliveCount);
1429 
1430     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1431     EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1432     EXPECT_EQ(2, PointsBack::s_aliveCount);
1433     EXPECT_EQ(2, SuperClass::s_aliveCount);
1434     EXPECT_EQ(1, SubClass::s_aliveCount);
1435     EXPECT_EQ(1, SubData::s_aliveCount);
1436 
1437     superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1438     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1439     EXPECT_EQ(2, PointsBack::s_aliveCount);
1440     EXPECT_EQ(1, SuperClass::s_aliveCount);
1441     EXPECT_EQ(1, SubClass::s_aliveCount);
1442     EXPECT_EQ(1, SubData::s_aliveCount);
1443     EXPECT_EQ(0, pointsBack1->backPointer());
1444 
1445     pointsBack1.release();
1446     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1447     EXPECT_EQ(1, PointsBack::s_aliveCount);
1448     EXPECT_EQ(1, SuperClass::s_aliveCount);
1449     EXPECT_EQ(1, SubClass::s_aliveCount);
1450     EXPECT_EQ(1, SubData::s_aliveCount);
1451 
1452     subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1453     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1454     EXPECT_EQ(1, PointsBack::s_aliveCount);
1455     EXPECT_EQ(0, SuperClass::s_aliveCount);
1456     EXPECT_EQ(0, SubClass::s_aliveCount);
1457     EXPECT_EQ(0, SubData::s_aliveCount);
1458     EXPECT_EQ(0, pointsBack2->backPointer());
1459 
1460     pointsBack2.release();
1461     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1462     EXPECT_EQ(0, PointsBack::s_aliveCount);
1463     EXPECT_EQ(0, SuperClass::s_aliveCount);
1464     EXPECT_EQ(0, SubClass::s_aliveCount);
1465     EXPECT_EQ(0, SubData::s_aliveCount);
1466 
1467     EXPECT_TRUE(superClass == subClass);
1468 }
1469 
TEST(HeapTest,Threading)1470 TEST(HeapTest, Threading)
1471 {
1472     ThreadedHeapTester::test();
1473 }
1474 
TEST(HeapTest,ThreadedWeakness)1475 TEST(HeapTest, ThreadedWeakness)
1476 {
1477     ThreadedWeaknessTester::test();
1478 }
1479 
TEST(HeapTest,BasicFunctionality)1480 TEST(HeapTest, BasicFunctionality)
1481 {
1482     HeapStats heapStats;
1483     clearOutOldGarbage(&heapStats);
1484     {
1485         size_t slack = 0;
1486 
1487         // When the test starts there may already have been leaked some memory
1488         // on the heap, so we establish a base line.
1489         size_t baseLevel = heapStats.totalObjectSpace();
1490         bool testPagesAllocated = !baseLevel;
1491         if (testPagesAllocated)
1492             EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1493 
1494         // This allocates objects on the general heap which should add a page of memory.
1495         DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
1496         slack += 4;
1497         memset(alloc32, 40, 32);
1498         DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
1499         slack += 4;
1500         memset(alloc64, 27, 64);
1501 
1502         size_t total = 96;
1503 
1504         getHeapStats(&heapStats);
1505         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1506         if (testPagesAllocated)
1507             EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1508 
1509         CheckWithSlack(alloc32 + 32 + sizeof(FinalizedHeapObjectHeader), alloc64, slack);
1510 
1511         EXPECT_EQ(alloc32->get(0), 40);
1512         EXPECT_EQ(alloc32->get(31), 40);
1513         EXPECT_EQ(alloc64->get(0), 27);
1514         EXPECT_EQ(alloc64->get(63), 27);
1515 
1516         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1517 
1518         EXPECT_EQ(alloc32->get(0), 40);
1519         EXPECT_EQ(alloc32->get(31), 40);
1520         EXPECT_EQ(alloc64->get(0), 27);
1521         EXPECT_EQ(alloc64->get(63), 27);
1522     }
1523 
1524     clearOutOldGarbage(&heapStats);
1525     size_t total = 0;
1526     size_t slack = 0;
1527     size_t baseLevel = heapStats.totalObjectSpace();
1528     bool testPagesAllocated = !baseLevel;
1529     if (testPagesAllocated)
1530         EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1531 
1532     size_t big = 1008;
1533     Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
1534     total += big;
1535     slack += 4;
1536 
1537     size_t persistentCount = 0;
1538     const size_t numPersistents = 100000;
1539     Persistent<DynamicallySizedObject>* persistents[numPersistents];
1540 
1541     for (int i = 0; i < 1000; i++) {
1542         size_t size = 128 + i * 8;
1543         total += size;
1544         persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
1545         slack += 4;
1546         getHeapStats(&heapStats);
1547         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1548         if (testPagesAllocated)
1549             EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1550     }
1551 
1552     {
1553         DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
1554         slack += 4;
1555         memset(alloc32b, 40, 32);
1556         DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
1557         slack += 4;
1558         memset(alloc64b, 27, 64);
1559         EXPECT_TRUE(alloc32b != alloc64b);
1560 
1561         total += 96;
1562         getHeapStats(&heapStats);
1563         CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1564         if (testPagesAllocated)
1565             EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1566     }
1567 
1568     clearOutOldGarbage(&heapStats);
1569     total -= 96;
1570     slack -= 8;
1571     if (testPagesAllocated)
1572         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1573 
1574     DynamicallySizedObject* bigAreaRaw = bigArea;
1575     // Clear the persistent, so that the big area will be garbage collected.
1576     bigArea.release();
1577     clearOutOldGarbage(&heapStats);
1578 
1579     total -= big;
1580     slack -= 4;
1581     getHeapStats(&heapStats);
1582     CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1583     if (testPagesAllocated)
1584         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1585 
1586     // Endless loop unless we eventually get the memory back that we just freed.
1587     while (true) {
1588         Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
1589         slack += 4;
1590         persistents[persistentCount++] = alloc;
1591         EXPECT_LT(persistentCount, numPersistents);
1592         total += big / 2;
1593         if (bigAreaRaw == alloc->get())
1594             break;
1595     }
1596 
1597     getHeapStats(&heapStats);
1598     CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1599     if (testPagesAllocated)
1600         EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1601 
1602     for (size_t i = 0; i < persistentCount; i++) {
1603         delete persistents[i];
1604         persistents[i] = 0;
1605     }
1606 
1607     uint8_t* address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(0, 100));
1608     for (int i = 0; i < 100; i++)
1609         address[i] = i;
1610     address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 100000));
1611     for (int i = 0; i < 100; i++)
1612         EXPECT_EQ(address[i], i);
1613     address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject>(address, 50));
1614     for (int i = 0; i < 50; i++)
1615         EXPECT_EQ(address[i], i);
1616     // This should be equivalent to free(address).
1617     EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(address, 0)), 0ul);
1618     // This should be equivalent to malloc(0).
1619     EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<DynamicallySizedObject>(0, 0)), 0ul);
1620 }
1621 
TEST(HeapTest,SimpleAllocation)1622 TEST(HeapTest, SimpleAllocation)
1623 {
1624     HeapStats initialHeapStats;
1625     clearOutOldGarbage(&initialHeapStats);
1626     EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1627 
1628     // Allocate an object in the heap.
1629     HeapAllocatedArray* array = new HeapAllocatedArray();
1630     HeapStats statsAfterAllocation;
1631     getHeapStats(&statsAfterAllocation);
1632     EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1633 
1634     // Sanity check of the contents in the heap.
1635     EXPECT_EQ(0, array->at(0));
1636     EXPECT_EQ(42, array->at(42));
1637     EXPECT_EQ(0, array->at(128));
1638     EXPECT_EQ(999 % 128, array->at(999));
1639 }
1640 
TEST(HeapTest,SimplePersistent)1641 TEST(HeapTest, SimplePersistent)
1642 {
1643     Persistent<TraceCounter> traceCounter = TraceCounter::create();
1644     EXPECT_EQ(0, traceCounter->traceCount());
1645 
1646     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1647     EXPECT_EQ(1, traceCounter->traceCount());
1648 
1649     Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1650     EXPECT_EQ(0, classWithMember->traceCount());
1651 
1652     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1653     EXPECT_EQ(1, classWithMember->traceCount());
1654     EXPECT_EQ(2, traceCounter->traceCount());
1655 }
1656 
TEST(HeapTest,SimpleFinalization)1657 TEST(HeapTest, SimpleFinalization)
1658 {
1659     {
1660         Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1661         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1662         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1663         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1664     }
1665 
1666     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1667     EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1668 }
1669 
TEST(HeapTest,Finalization)1670 TEST(HeapTest, Finalization)
1671 {
1672     {
1673         HeapTestSubClass* t1 = HeapTestSubClass::create();
1674         HeapTestSubClass* t2 = HeapTestSubClass::create();
1675         HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1676         // FIXME(oilpan): Ignore unused variables.
1677         (void)t1;
1678         (void)t2;
1679         (void)t3;
1680     }
1681     // Nothing is marked so the GC should free everything and call
1682     // the finalizer on all three objects.
1683     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1684     EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1685     EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1686     // Destructors not called again when GCing again.
1687     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1688     EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1689     EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1690 }
1691 
TEST(HeapTest,TypedHeapSanity)1692 TEST(HeapTest, TypedHeapSanity)
1693 {
1694     // We use TraceCounter for allocating an object on the general heap.
1695     Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1696     Persistent<Node> typedHeapObject = Node::create(0);
1697     EXPECT_NE(pageHeaderFromObject(generalHeapObject.get()),
1698         pageHeaderFromObject(typedHeapObject.get()));
1699 }
1700 
TEST(HeapTest,NoAllocation)1701 TEST(HeapTest, NoAllocation)
1702 {
1703     EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1704     {
1705         // Disallow allocation
1706         NoAllocationScope<AnyThread> noAllocationScope;
1707         EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1708     }
1709     EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1710 }
1711 
TEST(HeapTest,Members)1712 TEST(HeapTest, Members)
1713 {
1714     Bar::s_live = 0;
1715     {
1716         Persistent<Baz> h1;
1717         Persistent<Baz> h2;
1718         {
1719             h1 = Baz::create(Bar::create());
1720             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1721             EXPECT_EQ(1u, Bar::s_live);
1722             h2 = Baz::create(Bar::create());
1723             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1724             EXPECT_EQ(2u, Bar::s_live);
1725         }
1726         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1727         EXPECT_EQ(2u, Bar::s_live);
1728         h1->clear();
1729         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1730         EXPECT_EQ(1u, Bar::s_live);
1731     }
1732     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1733     EXPECT_EQ(0u, Bar::s_live);
1734 }
1735 
TEST(HeapTest,MarkTest)1736 TEST(HeapTest, MarkTest)
1737 {
1738     {
1739         Bar::s_live = 0;
1740         Persistent<Bar> bar = Bar::create();
1741         EXPECT_TRUE(ThreadState::current()->contains(bar));
1742         EXPECT_EQ(1u, Bar::s_live);
1743         {
1744             Foo* foo = Foo::create(bar);
1745             EXPECT_TRUE(ThreadState::current()->contains(foo));
1746             EXPECT_EQ(2u, Bar::s_live);
1747             EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1748             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1749             EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1750             EXPECT_EQ(2u, Bar::s_live);
1751         }
1752         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1753         EXPECT_EQ(1u, Bar::s_live);
1754     }
1755     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1756     EXPECT_EQ(0u, Bar::s_live);
1757 }
1758 
TEST(HeapTest,DeepTest)1759 TEST(HeapTest, DeepTest)
1760 {
1761     const unsigned depth = 100000;
1762     Bar::s_live = 0;
1763     {
1764         Bar* bar = Bar::create();
1765         EXPECT_TRUE(ThreadState::current()->contains(bar));
1766         Foo* foo = Foo::create(bar);
1767         EXPECT_TRUE(ThreadState::current()->contains(foo));
1768         EXPECT_EQ(2u, Bar::s_live);
1769         for (unsigned i = 0; i < depth; i++) {
1770             Foo* foo2 = Foo::create(foo);
1771             foo = foo2;
1772             EXPECT_TRUE(ThreadState::current()->contains(foo));
1773         }
1774         EXPECT_EQ(depth + 2, Bar::s_live);
1775         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1776         EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1777         EXPECT_EQ(depth + 2, Bar::s_live);
1778     }
1779     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1780     EXPECT_EQ(0u, Bar::s_live);
1781 }
1782 
TEST(HeapTest,WideTest)1783 TEST(HeapTest, WideTest)
1784 {
1785     Bar::s_live = 0;
1786     {
1787         Bars* bars = Bars::create();
1788         unsigned width = Bars::width;
1789         EXPECT_EQ(width + 1, Bar::s_live);
1790         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1791         EXPECT_EQ(width + 1, Bar::s_live);
1792         // Use bars here to make sure that it will be on the stack
1793         // for the conservative stack scan to find.
1794         EXPECT_EQ(width, bars->getWidth());
1795     }
1796     EXPECT_EQ(Bars::width + 1, Bar::s_live);
1797     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1798     EXPECT_EQ(0u, Bar::s_live);
1799 }
1800 
TEST(HeapTest,HashMapOfMembers)1801 TEST(HeapTest, HashMapOfMembers)
1802 {
1803     HeapStats initialHeapSize;
1804     IntWrapper::s_destructorCalls = 0;
1805 
1806     clearOutOldGarbage(&initialHeapSize);
1807     {
1808         typedef HeapHashMap<
1809             Member<IntWrapper>,
1810             Member<IntWrapper>,
1811             DefaultHash<Member<IntWrapper> >::Hash,
1812             HashTraits<Member<IntWrapper> >,
1813             HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
1814 
1815         Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
1816 
1817         map->clear();
1818         HeapStats afterSetWasCreated;
1819         getHeapStats(&afterSetWasCreated);
1820         EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1821 
1822         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1823         HeapStats afterGC;
1824         getHeapStats(&afterGC);
1825         EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1826 
1827         // If the additions below cause garbage collections, these
1828         // pointers should be found by conservative stack scanning.
1829         IntWrapper* one(IntWrapper::create(1));
1830         IntWrapper* anotherOne(IntWrapper::create(1));
1831 
1832         map->add(one, one);
1833 
1834         HeapStats afterOneAdd;
1835         getHeapStats(&afterOneAdd);
1836         EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1837 
1838         HeapObjectIdentityMap::iterator it(map->begin());
1839         HeapObjectIdentityMap::iterator it2(map->begin());
1840         ++it;
1841         ++it2;
1842 
1843         map->add(anotherOne, one);
1844 
1845         // The addition above can cause an allocation of a new
1846         // backing store. We therefore garbage collect before
1847         // taking the heap stats in order to get rid of the old
1848         // backing store. We make sure to not use conservative
1849         // stack scanning as that could find a pointer to the
1850         // old backing.
1851         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1852         HeapStats afterAddAndGC;
1853         getHeapStats(&afterAddAndGC);
1854         EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1855 
1856         EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1857 
1858         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1859         EXPECT_TRUE(map->contains(one));
1860         EXPECT_TRUE(map->contains(anotherOne));
1861 
1862         IntWrapper* gotten(map->get(one));
1863         EXPECT_EQ(gotten->value(), one->value());
1864         EXPECT_EQ(gotten, one);
1865 
1866         HeapStats afterGC2;
1867         getHeapStats(&afterGC2);
1868         EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1869 
1870         IntWrapper* dozen = 0;
1871 
1872         for (int i = 1; i < 1000; i++) { // 999 iterations.
1873             IntWrapper* iWrapper(IntWrapper::create(i));
1874             IntWrapper* iSquared(IntWrapper::create(i * i));
1875             map->add(iWrapper, iSquared);
1876             if (i == 12)
1877                 dozen = iWrapper;
1878         }
1879         HeapStats afterAdding1000;
1880         getHeapStats(&afterAdding1000);
1881         EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1882 
1883         IntWrapper* gross(map->get(dozen));
1884         EXPECT_EQ(gross->value(), 144);
1885 
1886         // This should clear out any junk backings created by all the adds.
1887         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1888         HeapStats afterGC3;
1889         getHeapStats(&afterGC3);
1890         EXPECT_TRUE(afterGC3.totalObjectSpace() <= afterAdding1000.totalObjectSpace());
1891     }
1892 
1893     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1894     // The objects 'one', anotherOne, and the 999 other pairs.
1895     EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1896     HeapStats afterGC4;
1897     getHeapStats(&afterGC4);
1898     EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1899 }
1900 
TEST(HeapTest,NestedAllocation)1901 TEST(HeapTest, NestedAllocation)
1902 {
1903     HeapStats initialHeapSize;
1904     clearOutOldGarbage(&initialHeapSize);
1905     {
1906         Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1907     }
1908     HeapStats afterFree;
1909     clearOutOldGarbage(&afterFree);
1910     EXPECT_TRUE(initialHeapSize == afterFree);
1911 }
1912 
TEST(HeapTest,LargeObjects)1913 TEST(HeapTest, LargeObjects)
1914 {
1915     HeapStats initialHeapSize;
1916     clearOutOldGarbage(&initialHeapSize);
1917     IntWrapper::s_destructorCalls = 0;
1918     LargeObject::s_destructorCalls = 0;
1919     {
1920         int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1921         Persistent<LargeObject> object = LargeObject::create();
1922         EXPECT_TRUE(ThreadState::current()->contains(object));
1923         EXPECT_TRUE(ThreadState::current()->contains(reinterpret_cast<char*>(object.get()) + sizeof(LargeObject) - 1));
1924 #if ENABLE(GC_PROFILE_MARKING)
1925         const GCInfo* info = ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()));
1926         EXPECT_NE(reinterpret_cast<const GCInfo*>(0), info);
1927         EXPECT_EQ(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject) - 1));
1928         EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) + sizeof(LargeObject)));
1929         EXPECT_NE(info, ThreadState::current()->findGCInfo(reinterpret_cast<Address>(object.get()) - 1));
1930 #endif
1931         HeapStats afterAllocation;
1932         clearOutOldGarbage(&afterAllocation);
1933         {
1934             object->set(0, 'a');
1935             EXPECT_EQ('a', object->get(0));
1936             object->set(object->length() - 1, 'b');
1937             EXPECT_EQ('b', object->get(object->length() - 1));
1938             size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1939             size_t actualObjectSpace =
1940                 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1941             CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1942             // There is probably space for the IntWrapper in a heap page without
1943             // allocating extra pages. However, the IntWrapper allocation might cause
1944             // the addition of a heap page.
1945             size_t largeObjectAllocationSize =
1946                 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1947             size_t allocatedSpaceLowerBound =
1948                 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1949             size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1950             EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1951             EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1952             EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1953             EXPECT_EQ(0, LargeObject::s_destructorCalls);
1954             for (int i = 0; i < 10; i++)
1955                 object = LargeObject::create();
1956         }
1957         HeapStats oneLargeObject;
1958         clearOutOldGarbage(&oneLargeObject);
1959         EXPECT_TRUE(oneLargeObject == afterAllocation);
1960         EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1961         EXPECT_EQ(10, LargeObject::s_destructorCalls);
1962     }
1963     HeapStats backToInitial;
1964     clearOutOldGarbage(&backToInitial);
1965     EXPECT_TRUE(initialHeapSize == backToInitial);
1966     EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1967     EXPECT_EQ(11, LargeObject::s_destructorCalls);
1968     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1969 }
1970 
1971 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1972 typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1973 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1974 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1975 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1976 typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1977 
1978 class Container : public GarbageCollected<Container> {
1979 public:
create()1980     static Container* create() { return new Container(); }
1981     HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1982     HeapHashSet<Member<IntWrapper> > set;
1983     HeapHashSet<Member<IntWrapper> > set2;
1984     HeapHashCountedSet<Member<IntWrapper> > set3;
1985     HeapVector<Member<IntWrapper>, 2> vector;
1986     HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1987     HeapVector<PairUnwrappedWrapped, 2> vectorUW;
1988     HeapDeque<Member<IntWrapper>, 0> deque;
1989     HeapDeque<PairWrappedUnwrapped, 0> dequeWU;
1990     HeapDeque<PairUnwrappedWrapped, 0> dequeUW;
trace(Visitor * visitor)1991     void trace(Visitor* visitor)
1992     {
1993         visitor->trace(map);
1994         visitor->trace(set);
1995         visitor->trace(set2);
1996         visitor->trace(set3);
1997         visitor->trace(vector);
1998         visitor->trace(vectorWU);
1999         visitor->trace(vectorUW);
2000         visitor->trace(deque);
2001         visitor->trace(dequeWU);
2002         visitor->trace(dequeUW);
2003     }
2004 };
2005 
2006 struct ShouldBeTraced {
ShouldBeTracedblink::ShouldBeTraced2007     explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
traceblink::ShouldBeTraced2008     void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
2009     Member<IntWrapper> m_wrapper;
2010 };
2011 
2012 class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
2013 public:
create()2014     static OffHeapContainer* create() { return new OffHeapContainer(); }
2015 
2016     static const int iterations = 300;
2017     static const int deadWrappers = 1200;
2018 
OffHeapContainer()2019     OffHeapContainer()
2020     {
2021         for (int i = 0; i < iterations; i++) {
2022             m_deque1.append(ShouldBeTraced(IntWrapper::create(i)));
2023             m_vector1.append(ShouldBeTraced(IntWrapper::create(i)));
2024             m_deque2.append(IntWrapper::create(i));
2025             m_vector2.append(IntWrapper::create(i));
2026         }
2027 
2028         Deque<ShouldBeTraced>::iterator d1Iterator(m_deque1.begin());
2029         Vector<ShouldBeTraced>::iterator v1Iterator(m_vector1.begin());
2030         Deque<Member<IntWrapper> >::iterator d2Iterator(m_deque2.begin());
2031         Vector<Member<IntWrapper> >::iterator v2Iterator(m_vector2.begin());
2032 
2033         for (int i = 0; i < iterations; i++) {
2034             EXPECT_EQ(i, m_vector1[i].m_wrapper->value());
2035             EXPECT_EQ(i, m_vector2[i]->value());
2036             EXPECT_EQ(i, d1Iterator->m_wrapper->value());
2037             EXPECT_EQ(i, v1Iterator->m_wrapper->value());
2038             EXPECT_EQ(i, d2Iterator->get()->value());
2039             EXPECT_EQ(i, v2Iterator->get()->value());
2040             ++d1Iterator;
2041             ++v1Iterator;
2042             ++d2Iterator;
2043             ++v2Iterator;
2044         }
2045         EXPECT_EQ(d1Iterator, m_deque1.end());
2046         EXPECT_EQ(v1Iterator, m_vector1.end());
2047         EXPECT_EQ(d2Iterator, m_deque2.end());
2048         EXPECT_EQ(v2Iterator, m_vector2.end());
2049     }
2050 
trace(Visitor * visitor)2051     void trace(Visitor* visitor)
2052     {
2053         visitor->trace(m_deque1);
2054         visitor->trace(m_vector1);
2055         visitor->trace(m_deque2);
2056         visitor->trace(m_vector2);
2057     }
2058 
2059     Deque<ShouldBeTraced> m_deque1;
2060     Vector<ShouldBeTraced> m_vector1;
2061     Deque<Member<IntWrapper> > m_deque2;
2062     Vector<Member<IntWrapper> > m_vector2;
2063 };
2064 
2065 const int OffHeapContainer::iterations;
2066 const int OffHeapContainer::deadWrappers;
2067 
2068 // These class definitions test compile-time asserts with transition
2069 // types. They are therefore unused in test code and just need to
2070 // compile. This is intentional; do not delete the A and B classes below.
2071 class A : public WillBeGarbageCollectedMixin {
2072 };
2073 
2074 class B : public NoBaseWillBeGarbageCollected<B>, public A {
2075     WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
2076 public:
trace(Visitor *)2077     void trace(Visitor*) { }
2078 };
2079 
TEST(HeapTest,HeapVectorFilledWithValue)2080 TEST(HeapTest, HeapVectorFilledWithValue)
2081 {
2082     IntWrapper* val = IntWrapper::create(1);
2083     HeapVector<Member<IntWrapper> > vector(10, val);
2084     EXPECT_EQ(10u, vector.size());
2085     for (size_t i = 0; i < vector.size(); i++)
2086         EXPECT_EQ(val, vector[i]);
2087 }
2088 
TEST(HeapTest,HeapVectorWithInlineCapacity)2089 TEST(HeapTest, HeapVectorWithInlineCapacity)
2090 {
2091     IntWrapper* one = IntWrapper::create(1);
2092     IntWrapper* two = IntWrapper::create(2);
2093     IntWrapper* three = IntWrapper::create(3);
2094     IntWrapper* four = IntWrapper::create(4);
2095     IntWrapper* five = IntWrapper::create(5);
2096     IntWrapper* six = IntWrapper::create(6);
2097     {
2098         HeapVector<Member<IntWrapper>, 2> vector;
2099         vector.append(one);
2100         vector.append(two);
2101         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2102         EXPECT_TRUE(vector.contains(one));
2103         EXPECT_TRUE(vector.contains(two));
2104 
2105         vector.append(three);
2106         vector.append(four);
2107         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2108         EXPECT_TRUE(vector.contains(one));
2109         EXPECT_TRUE(vector.contains(two));
2110         EXPECT_TRUE(vector.contains(three));
2111         EXPECT_TRUE(vector.contains(four));
2112 
2113         vector.shrink(1);
2114         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2115         EXPECT_TRUE(vector.contains(one));
2116         EXPECT_FALSE(vector.contains(two));
2117         EXPECT_FALSE(vector.contains(three));
2118         EXPECT_FALSE(vector.contains(four));
2119     }
2120     {
2121         HeapVector<Member<IntWrapper>, 2> vector1;
2122         HeapVector<Member<IntWrapper>, 2> vector2;
2123 
2124         vector1.append(one);
2125         vector2.append(two);
2126         vector1.swap(vector2);
2127         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2128         EXPECT_TRUE(vector1.contains(two));
2129         EXPECT_TRUE(vector2.contains(one));
2130     }
2131     {
2132         HeapVector<Member<IntWrapper>, 2> vector1;
2133         HeapVector<Member<IntWrapper>, 2> vector2;
2134 
2135         vector1.append(one);
2136         vector1.append(two);
2137         vector2.append(three);
2138         vector2.append(four);
2139         vector2.append(five);
2140         vector2.append(six);
2141         vector1.swap(vector2);
2142         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2143         EXPECT_TRUE(vector1.contains(three));
2144         EXPECT_TRUE(vector1.contains(four));
2145         EXPECT_TRUE(vector1.contains(five));
2146         EXPECT_TRUE(vector1.contains(six));
2147         EXPECT_TRUE(vector2.contains(one));
2148         EXPECT_TRUE(vector2.contains(two));
2149     }
2150 }
2151 
2152 template<typename T, size_t inlineCapacity, typename U>
dequeContains(HeapDeque<T,inlineCapacity> & deque,U u)2153 bool dequeContains(HeapDeque<T, inlineCapacity>& deque, U u)
2154 {
2155     typedef typename HeapDeque<T, inlineCapacity>::iterator iterator;
2156     for (iterator it = deque.begin(); it != deque.end(); ++it) {
2157         if (*it == u)
2158             return true;
2159     }
2160     return false;
2161 }
2162 
TEST(HeapTest,HeapCollectionTypes)2163 TEST(HeapTest, HeapCollectionTypes)
2164 {
2165     HeapStats initialHeapSize;
2166     IntWrapper::s_destructorCalls = 0;
2167 
2168     typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
2169     typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
2170     typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
2171 
2172     typedef HeapHashSet<Member<IntWrapper> > MemberSet;
2173     typedef HeapHashCountedSet<Member<IntWrapper> > MemberCountedSet;
2174 
2175     typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
2176     typedef HeapDeque<Member<IntWrapper>, 0> MemberDeque;
2177 
2178     typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
2179     typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
2180     typedef HeapDeque<PairWrappedUnwrapped, 0> DequeWU;
2181     typedef HeapDeque<PairUnwrappedWrapped, 0> DequeUW;
2182 
2183     Persistent<MemberMember> memberMember = new MemberMember();
2184     Persistent<MemberMember> memberMember2 = new MemberMember();
2185     Persistent<MemberMember> memberMember3 = new MemberMember();
2186     Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
2187     Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
2188     Persistent<MemberSet> set = new MemberSet();
2189     Persistent<MemberSet> set2 = new MemberSet();
2190     Persistent<MemberCountedSet> set3 = new MemberCountedSet();
2191     Persistent<MemberVector> vector = new MemberVector();
2192     Persistent<MemberVector> vector2 = new MemberVector();
2193     Persistent<VectorWU> vectorWU = new VectorWU();
2194     Persistent<VectorWU> vectorWU2 = new VectorWU();
2195     Persistent<VectorUW> vectorUW = new VectorUW();
2196     Persistent<VectorUW> vectorUW2 = new VectorUW();
2197     Persistent<MemberDeque> deque = new MemberDeque();
2198     Persistent<MemberDeque> deque2 = new MemberDeque();
2199     Persistent<DequeWU> dequeWU = new DequeWU();
2200     Persistent<DequeWU> dequeWU2 = new DequeWU();
2201     Persistent<DequeUW> dequeUW = new DequeUW();
2202     Persistent<DequeUW> dequeUW2 = new DequeUW();
2203     Persistent<Container> container = Container::create();
2204 
2205     clearOutOldGarbage(&initialHeapSize);
2206     {
2207         Persistent<IntWrapper> one(IntWrapper::create(1));
2208         Persistent<IntWrapper> two(IntWrapper::create(2));
2209         Persistent<IntWrapper> oneB(IntWrapper::create(1));
2210         Persistent<IntWrapper> twoB(IntWrapper::create(2));
2211         Persistent<IntWrapper> oneC(IntWrapper::create(1));
2212         Persistent<IntWrapper> oneD(IntWrapper::create(1));
2213         Persistent<IntWrapper> oneE(IntWrapper::create(1));
2214         Persistent<IntWrapper> oneF(IntWrapper::create(1));
2215         {
2216             IntWrapper* threeB(IntWrapper::create(3));
2217             IntWrapper* threeC(IntWrapper::create(3));
2218             IntWrapper* threeD(IntWrapper::create(3));
2219             IntWrapper* threeE(IntWrapper::create(3));
2220             IntWrapper* threeF(IntWrapper::create(3));
2221             IntWrapper* three(IntWrapper::create(3));
2222             IntWrapper* fourB(IntWrapper::create(4));
2223             IntWrapper* fourC(IntWrapper::create(4));
2224             IntWrapper* fourD(IntWrapper::create(4));
2225             IntWrapper* fourE(IntWrapper::create(4));
2226             IntWrapper* fourF(IntWrapper::create(4));
2227             IntWrapper* four(IntWrapper::create(4));
2228             IntWrapper* fiveC(IntWrapper::create(5));
2229             IntWrapper* fiveD(IntWrapper::create(5));
2230             IntWrapper* fiveE(IntWrapper::create(5));
2231             IntWrapper* fiveF(IntWrapper::create(5));
2232 
2233             // Member Collections.
2234             memberMember2->add(one, two);
2235             memberMember2->add(two, three);
2236             memberMember2->add(three, four);
2237             memberMember2->add(four, one);
2238             primitiveMember->add(1, two);
2239             primitiveMember->add(2, three);
2240             primitiveMember->add(3, four);
2241             primitiveMember->add(4, one);
2242             memberPrimitive->add(one, 2);
2243             memberPrimitive->add(two, 3);
2244             memberPrimitive->add(three, 4);
2245             memberPrimitive->add(four, 1);
2246             set2->add(one);
2247             set2->add(two);
2248             set2->add(three);
2249             set2->add(four);
2250             set->add(oneB);
2251             set3->add(oneB);
2252             set3->add(oneB);
2253             vector->append(oneB);
2254             deque->append(oneB);
2255             vector2->append(threeB);
2256             vector2->append(fourB);
2257             deque2->append(threeE);
2258             deque2->append(fourE);
2259             vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2260             dequeWU->append(PairWrappedUnwrapped(&*oneE, 42));
2261             vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2262             vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2263             vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2264             dequeWU2->append(PairWrappedUnwrapped(&*threeE, 43));
2265             dequeWU2->append(PairWrappedUnwrapped(&*fourE, 44));
2266             dequeWU2->append(PairWrappedUnwrapped(&*fiveE, 45));
2267             vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2268             vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2269             vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2270             vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
2271             dequeUW->append(PairUnwrappedWrapped(1, &*oneF));
2272             dequeUW2->append(PairUnwrappedWrapped(103, &*threeF));
2273             dequeUW2->append(PairUnwrappedWrapped(104, &*fourF));
2274             dequeUW2->append(PairUnwrappedWrapped(105, &*fiveF));
2275 
2276             EXPECT_TRUE(dequeContains(*deque, oneB));
2277 
2278             // Collect garbage. This should change nothing since we are keeping
2279             // alive the IntWrapper objects with on-stack pointers.
2280             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2281 
2282             EXPECT_TRUE(dequeContains(*deque, oneB));
2283 
2284             EXPECT_EQ(0u, memberMember->size());
2285             EXPECT_EQ(4u, memberMember2->size());
2286             EXPECT_EQ(4u, primitiveMember->size());
2287             EXPECT_EQ(4u, memberPrimitive->size());
2288             EXPECT_EQ(1u, set->size());
2289             EXPECT_EQ(4u, set2->size());
2290             EXPECT_EQ(1u, set3->size());
2291             EXPECT_EQ(1u, vector->size());
2292             EXPECT_EQ(2u, vector2->size());
2293             EXPECT_EQ(1u, vectorWU->size());
2294             EXPECT_EQ(3u, vectorWU2->size());
2295             EXPECT_EQ(1u, vectorUW->size());
2296             EXPECT_EQ(3u, vectorUW2->size());
2297             EXPECT_EQ(1u, deque->size());
2298             EXPECT_EQ(2u, deque2->size());
2299             EXPECT_EQ(1u, dequeWU->size());
2300             EXPECT_EQ(3u, dequeWU2->size());
2301             EXPECT_EQ(1u, dequeUW->size());
2302             EXPECT_EQ(3u, dequeUW2->size());
2303 
2304             MemberVector& cvec = container->vector;
2305             cvec.swap(*vector.get());
2306             vector2->swap(cvec);
2307             vector->swap(cvec);
2308 
2309             VectorWU& cvecWU = container->vectorWU;
2310             cvecWU.swap(*vectorWU.get());
2311             vectorWU2->swap(cvecWU);
2312             vectorWU->swap(cvecWU);
2313 
2314             VectorUW& cvecUW = container->vectorUW;
2315             cvecUW.swap(*vectorUW.get());
2316             vectorUW2->swap(cvecUW);
2317             vectorUW->swap(cvecUW);
2318 
2319             MemberDeque& cDeque = container->deque;
2320             cDeque.swap(*deque.get());
2321             deque2->swap(cDeque);
2322             deque->swap(cDeque);
2323 
2324             DequeWU& cDequeWU = container->dequeWU;
2325             cDequeWU.swap(*dequeWU.get());
2326             dequeWU2->swap(cDequeWU);
2327             dequeWU->swap(cDequeWU);
2328 
2329             DequeUW& cDequeUW = container->dequeUW;
2330             cDequeUW.swap(*dequeUW.get());
2331             dequeUW2->swap(cDequeUW);
2332             dequeUW->swap(cDequeUW);
2333 
2334             // Swap set and set2 in a roundabout way.
2335             MemberSet& cset1 = container->set;
2336             MemberSet& cset2 = container->set2;
2337             set->swap(cset1);
2338             set2->swap(cset2);
2339             set->swap(cset2);
2340             cset1.swap(cset2);
2341             cset2.swap(set2);
2342 
2343             MemberCountedSet& cCountedSet = container->set3;
2344             set3->swap(cCountedSet);
2345             EXPECT_EQ(0u, set3->size());
2346             set3->swap(cCountedSet);
2347 
2348             // Triple swap.
2349             container->map.swap(memberMember2);
2350             MemberMember& containedMap = container->map;
2351             memberMember3->swap(containedMap);
2352             memberMember3->swap(memberMember);
2353 
2354             EXPECT_TRUE(memberMember->get(one) == two);
2355             EXPECT_TRUE(memberMember->get(two) == three);
2356             EXPECT_TRUE(memberMember->get(three) == four);
2357             EXPECT_TRUE(memberMember->get(four) == one);
2358             EXPECT_TRUE(primitiveMember->get(1) == two);
2359             EXPECT_TRUE(primitiveMember->get(2) == three);
2360             EXPECT_TRUE(primitiveMember->get(3) == four);
2361             EXPECT_TRUE(primitiveMember->get(4) == one);
2362             EXPECT_EQ(1, memberPrimitive->get(four));
2363             EXPECT_EQ(2, memberPrimitive->get(one));
2364             EXPECT_EQ(3, memberPrimitive->get(two));
2365             EXPECT_EQ(4, memberPrimitive->get(three));
2366             EXPECT_TRUE(set->contains(one));
2367             EXPECT_TRUE(set->contains(two));
2368             EXPECT_TRUE(set->contains(three));
2369             EXPECT_TRUE(set->contains(four));
2370             EXPECT_TRUE(set2->contains(oneB));
2371             EXPECT_TRUE(set3->contains(oneB));
2372             EXPECT_TRUE(vector->contains(threeB));
2373             EXPECT_TRUE(vector->contains(fourB));
2374             EXPECT_TRUE(dequeContains(*deque, threeE));
2375             EXPECT_TRUE(dequeContains(*deque, fourE));
2376             EXPECT_TRUE(vector2->contains(oneB));
2377             EXPECT_FALSE(vector2->contains(threeB));
2378             EXPECT_TRUE(dequeContains(*deque2, oneB));
2379             EXPECT_FALSE(dequeContains(*deque2, threeE));
2380             EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2381             EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2382             EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2383             EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2384             EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2385             EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2386             EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2387             EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2388             EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2389             EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
2390             EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*threeE, 43)));
2391             EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fourE, 44)));
2392             EXPECT_TRUE(dequeContains(*dequeWU, PairWrappedUnwrapped(&*fiveE, 45)));
2393             EXPECT_TRUE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*oneE, 42)));
2394             EXPECT_FALSE(dequeContains(*dequeWU2, PairWrappedUnwrapped(&*threeE, 43)));
2395             EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(103, &*threeF)));
2396             EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(104, &*fourF)));
2397             EXPECT_TRUE(dequeContains(*dequeUW, PairUnwrappedWrapped(105, &*fiveF)));
2398             EXPECT_TRUE(dequeContains(*dequeUW2, PairUnwrappedWrapped(1, &*oneF)));
2399             EXPECT_FALSE(dequeContains(*dequeUW2, PairUnwrappedWrapped(103, &*threeF)));
2400         }
2401 
2402         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2403 
2404         EXPECT_EQ(4u, memberMember->size());
2405         EXPECT_EQ(0u, memberMember2->size());
2406         EXPECT_EQ(4u, primitiveMember->size());
2407         EXPECT_EQ(4u, memberPrimitive->size());
2408         EXPECT_EQ(4u, set->size());
2409         EXPECT_EQ(1u, set2->size());
2410         EXPECT_EQ(1u, set3->size());
2411         EXPECT_EQ(2u, vector->size());
2412         EXPECT_EQ(1u, vector2->size());
2413         EXPECT_EQ(3u, vectorUW->size());
2414         EXPECT_EQ(1u, vector2->size());
2415         EXPECT_EQ(2u, deque->size());
2416         EXPECT_EQ(1u, deque2->size());
2417         EXPECT_EQ(3u, dequeUW->size());
2418         EXPECT_EQ(1u, deque2->size());
2419 
2420         EXPECT_TRUE(memberMember->get(one) == two);
2421         EXPECT_TRUE(primitiveMember->get(1) == two);
2422         EXPECT_TRUE(primitiveMember->get(4) == one);
2423         EXPECT_EQ(2, memberPrimitive->get(one));
2424         EXPECT_EQ(3, memberPrimitive->get(two));
2425         EXPECT_TRUE(set->contains(one));
2426         EXPECT_TRUE(set->contains(two));
2427         EXPECT_FALSE(set->contains(oneB));
2428         EXPECT_TRUE(set2->contains(oneB));
2429         EXPECT_TRUE(set3->contains(oneB));
2430         EXPECT_EQ(2u, set3->find(oneB)->value);
2431         EXPECT_EQ(3, vector->at(0)->value());
2432         EXPECT_EQ(4, vector->at(1)->value());
2433         EXPECT_EQ(3, deque->begin()->get()->value());
2434     }
2435 
2436     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2437     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2438 
2439     EXPECT_EQ(4u, memberMember->size());
2440     EXPECT_EQ(4u, primitiveMember->size());
2441     EXPECT_EQ(4u, memberPrimitive->size());
2442     EXPECT_EQ(4u, set->size());
2443     EXPECT_EQ(1u, set2->size());
2444     EXPECT_EQ(2u, vector->size());
2445     EXPECT_EQ(1u, vector2->size());
2446     EXPECT_EQ(3u, vectorWU->size());
2447     EXPECT_EQ(1u, vectorWU2->size());
2448     EXPECT_EQ(3u, vectorUW->size());
2449     EXPECT_EQ(1u, vectorUW2->size());
2450     EXPECT_EQ(2u, deque->size());
2451     EXPECT_EQ(1u, deque2->size());
2452     EXPECT_EQ(3u, dequeWU->size());
2453     EXPECT_EQ(1u, dequeWU2->size());
2454     EXPECT_EQ(3u, dequeUW->size());
2455     EXPECT_EQ(1u, dequeUW2->size());
2456 }
2457 
2458 template<typename T>
MapIteratorCheck(T & it,const T & end,int expected)2459 void MapIteratorCheck(T& it, const T& end, int expected)
2460 {
2461     int found = 0;
2462     while (it != end) {
2463         found++;
2464         int key = it->key->value();
2465         int value = it->value->value();
2466         EXPECT_TRUE(key >= 0 && key < 1100);
2467         EXPECT_TRUE(value >= 0 && value < 1100);
2468         ++it;
2469     }
2470     EXPECT_EQ(expected, found);
2471 }
2472 
2473 template<typename T>
SetIteratorCheck(T & it,const T & end,int expected)2474 void SetIteratorCheck(T& it, const T& end, int expected)
2475 {
2476     int found = 0;
2477     while (it != end) {
2478         found++;
2479         int value = (*it)->value();
2480         EXPECT_TRUE(value >= 0 && value < 1100);
2481         ++it;
2482     }
2483     EXPECT_EQ(expected, found);
2484 }
2485 
TEST(HeapTest,HeapWeakCollectionSimple)2486 TEST(HeapTest, HeapWeakCollectionSimple)
2487 {
2488     HeapStats initialHeapStats;
2489     clearOutOldGarbage(&initialHeapStats);
2490     IntWrapper::s_destructorCalls = 0;
2491 
2492     PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2493 
2494     typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2495     typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2496     typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2497     typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2498     typedef HeapHashCountedSet<WeakMember<IntWrapper> > WeakCountedSet;
2499 
2500     Persistent<WeakStrong> weakStrong = new WeakStrong();
2501     Persistent<StrongWeak> strongWeak = new StrongWeak();
2502     Persistent<WeakWeak> weakWeak = new WeakWeak();
2503     Persistent<WeakSet> weakSet = new WeakSet();
2504     Persistent<WeakCountedSet> weakCountedSet = new WeakCountedSet();
2505 
2506     Persistent<IntWrapper> two = IntWrapper::create(2);
2507 
2508     keepNumbersAlive.append(IntWrapper::create(103));
2509     keepNumbersAlive.append(IntWrapper::create(10));
2510 
2511     {
2512         weakStrong->add(IntWrapper::create(1), two);
2513         strongWeak->add(two, IntWrapper::create(1));
2514         weakWeak->add(two, IntWrapper::create(42));
2515         weakWeak->add(IntWrapper::create(42), two);
2516         weakSet->add(IntWrapper::create(0));
2517         weakSet->add(two);
2518         weakSet->add(keepNumbersAlive[0]);
2519         weakSet->add(keepNumbersAlive[1]);
2520         weakCountedSet->add(IntWrapper::create(0));
2521         weakCountedSet->add(two);
2522         weakCountedSet->add(two);
2523         weakCountedSet->add(two);
2524         weakCountedSet->add(keepNumbersAlive[0]);
2525         weakCountedSet->add(keepNumbersAlive[1]);
2526         EXPECT_EQ(1u, weakStrong->size());
2527         EXPECT_EQ(1u, strongWeak->size());
2528         EXPECT_EQ(2u, weakWeak->size());
2529         EXPECT_EQ(4u, weakSet->size());
2530         EXPECT_EQ(4u, weakCountedSet->size());
2531         EXPECT_EQ(3u, weakCountedSet->find(two)->value);
2532         weakCountedSet->remove(two);
2533         EXPECT_EQ(2u, weakCountedSet->find(two)->value);
2534     }
2535 
2536     keepNumbersAlive[0] = nullptr;
2537 
2538     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2539 
2540     EXPECT_EQ(0u, weakStrong->size());
2541     EXPECT_EQ(0u, strongWeak->size());
2542     EXPECT_EQ(0u, weakWeak->size());
2543     EXPECT_EQ(2u, weakSet->size());
2544     EXPECT_EQ(2u, weakCountedSet->size());
2545 }
2546 
2547 template<typename Set>
orderedSetHelper(bool strong)2548 void orderedSetHelper(bool strong)
2549 {
2550     HeapStats initialHeapStats;
2551     clearOutOldGarbage(&initialHeapStats);
2552     IntWrapper::s_destructorCalls = 0;
2553 
2554     PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2555 
2556     Persistent<Set> set1 = new Set();
2557     Persistent<Set> set2 = new Set();
2558 
2559     const Set& constSet = *set1.get();
2560 
2561     keepNumbersAlive.append(IntWrapper::create(2));
2562     keepNumbersAlive.append(IntWrapper::create(103));
2563     keepNumbersAlive.append(IntWrapper::create(10));
2564 
2565     set1->add(IntWrapper::create(0));
2566     set1->add(keepNumbersAlive[0]);
2567     set1->add(keepNumbersAlive[1]);
2568     set1->add(keepNumbersAlive[2]);
2569 
2570     set2->clear();
2571     set2->add(IntWrapper::create(42));
2572     set2->clear();
2573 
2574     EXPECT_EQ(4u, set1->size());
2575     typename Set::iterator it(set1->begin());
2576     typename Set::reverse_iterator reverse(set1->rbegin());
2577     typename Set::const_iterator cit(constSet.begin());
2578     typename Set::const_reverse_iterator creverse(constSet.rbegin());
2579 
2580     EXPECT_EQ(0, (*it)->value());
2581     EXPECT_EQ(0, (*cit)->value());
2582     ++it;
2583     ++cit;
2584     EXPECT_EQ(2, (*it)->value());
2585     EXPECT_EQ(2, (*cit)->value());
2586     --it;
2587     --cit;
2588     EXPECT_EQ(0, (*it)->value());
2589     EXPECT_EQ(0, (*cit)->value());
2590     ++it;
2591     ++cit;
2592     ++it;
2593     ++cit;
2594     EXPECT_EQ(103, (*it)->value());
2595     EXPECT_EQ(103, (*cit)->value());
2596     ++it;
2597     ++cit;
2598     EXPECT_EQ(10, (*it)->value());
2599     EXPECT_EQ(10, (*cit)->value());
2600     ++it;
2601     ++cit;
2602 
2603     EXPECT_EQ(10, (*reverse)->value());
2604     EXPECT_EQ(10, (*creverse)->value());
2605     ++reverse;
2606     ++creverse;
2607     EXPECT_EQ(103, (*reverse)->value());
2608     EXPECT_EQ(103, (*creverse)->value());
2609     --reverse;
2610     --creverse;
2611     EXPECT_EQ(10, (*reverse)->value());
2612     EXPECT_EQ(10, (*creverse)->value());
2613     ++reverse;
2614     ++creverse;
2615     ++reverse;
2616     ++creverse;
2617     EXPECT_EQ(2, (*reverse)->value());
2618     EXPECT_EQ(2, (*creverse)->value());
2619     ++reverse;
2620     ++creverse;
2621     EXPECT_EQ(0, (*reverse)->value());
2622     EXPECT_EQ(0, (*creverse)->value());
2623     ++reverse;
2624     ++creverse;
2625 
2626     EXPECT_EQ(set1->end(), it);
2627     EXPECT_EQ(constSet.end(), cit);
2628     EXPECT_EQ(set1->rend(), reverse);
2629     EXPECT_EQ(constSet.rend(), creverse);
2630 
2631     typename Set::iterator iX(set2->begin());
2632     EXPECT_EQ(set2->end(), iX);
2633 
2634     if (strong)
2635         set1->remove(keepNumbersAlive[0]);
2636 
2637     keepNumbersAlive[0] = nullptr;
2638 
2639     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2640 
2641     EXPECT_EQ(2u + (strong ? 1u : 0u), set1->size());
2642 
2643     EXPECT_EQ(2 + (strong ? 0 : 1), IntWrapper::s_destructorCalls);
2644 
2645     typename Set::iterator i2(set1->begin());
2646     if (strong) {
2647         EXPECT_EQ(0, (*i2)->value());
2648         ++i2;
2649         EXPECT_NE(set1->end(), i2);
2650     }
2651     EXPECT_EQ(103, (*i2)->value());
2652     ++i2;
2653     EXPECT_NE(set1->end(), i2);
2654     EXPECT_EQ(10, (*i2)->value());
2655     ++i2;
2656     EXPECT_EQ(set1->end(), i2);
2657 }
2658 
TEST(HeapTest,HeapWeakLinkedHashSet)2659 TEST(HeapTest, HeapWeakLinkedHashSet)
2660 {
2661     orderedSetHelper<HeapLinkedHashSet<Member<IntWrapper> > >(true);
2662     orderedSetHelper<HeapLinkedHashSet<WeakMember<IntWrapper> > >(false);
2663     orderedSetHelper<HeapListHashSet<Member<IntWrapper> > >(true);
2664 }
2665 
2666 class ThingWithDestructor {
2667 public:
ThingWithDestructor()2668     ThingWithDestructor()
2669         : m_x(emptyValue)
2670     {
2671         s_liveThingsWithDestructor++;
2672     }
2673 
ThingWithDestructor(int x)2674     ThingWithDestructor(int x)
2675         : m_x(x)
2676     {
2677         s_liveThingsWithDestructor++;
2678     }
2679 
ThingWithDestructor(const ThingWithDestructor & other)2680     ThingWithDestructor(const ThingWithDestructor&other)
2681     {
2682         *this = other;
2683         s_liveThingsWithDestructor++;
2684     }
2685 
~ThingWithDestructor()2686     ~ThingWithDestructor()
2687     {
2688         s_liveThingsWithDestructor--;
2689     }
2690 
value()2691     int value() { return m_x; }
2692 
2693     static int s_liveThingsWithDestructor;
2694 
hash()2695     unsigned hash() { return IntHash<int>::hash(m_x); }
2696 
2697 private:
2698     static const int emptyValue = 0;
2699     int m_x;
2700 };
2701 
2702 int ThingWithDestructor::s_liveThingsWithDestructor;
2703 
2704 struct ThingWithDestructorTraits : public HashTraits<ThingWithDestructor> {
2705     static const bool needsDestruction = true;
2706 };
2707 
heapMapDestructorHelper(bool clearMaps)2708 static void heapMapDestructorHelper(bool clearMaps)
2709 {
2710     HeapStats initialHeapStats;
2711     clearOutOldGarbage(&initialHeapStats);
2712     ThingWithDestructor::s_liveThingsWithDestructor = 0;
2713 
2714     typedef HeapHashMap<WeakMember<IntWrapper>, RefPtr<RefCountedAndGarbageCollected> > RefMap;
2715 
2716     typedef HeapHashMap<
2717         WeakMember<IntWrapper>,
2718         ThingWithDestructor,
2719         DefaultHash<WeakMember<IntWrapper> >::Hash,
2720         HashTraits<WeakMember<IntWrapper> >,
2721         ThingWithDestructorTraits> Map;
2722 
2723     Persistent<Map> map(new Map());
2724     Persistent<RefMap> refMap(new RefMap());
2725 
2726     Persistent<IntWrapper> luck(IntWrapper::create(103));
2727 
2728     int baseLine, refBaseLine;
2729 
2730     {
2731         Map stackMap;
2732         RefMap stackRefMap;
2733 
2734         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2735         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2736 
2737         stackMap.add(IntWrapper::create(42), ThingWithDestructor(1729));
2738         stackMap.add(luck, ThingWithDestructor(8128));
2739         stackRefMap.add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2740         stackRefMap.add(luck, RefCountedAndGarbageCollected::create());
2741 
2742         baseLine = ThingWithDestructor::s_liveThingsWithDestructor;
2743         refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2744 
2745         // Although the heap maps are on-stack, we can't expect prompt
2746         // finalization of the elements, so when they go out of scope here we
2747         // will not necessarily have called the relevant destructors.
2748     }
2749 
2750     // The RefCountedAndGarbageCollected things need an extra GC to discover
2751     // that they are no longer ref counted.
2752     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2753     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2754     EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2755     EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2756 
2757     // Now use maps kept alive with persistents. Here we don't expect any
2758     // destructors to be called before there have been GCs.
2759 
2760     map->add(IntWrapper::create(42), ThingWithDestructor(1729));
2761     map->add(luck, ThingWithDestructor(8128));
2762     refMap->add(IntWrapper::create(42), RefCountedAndGarbageCollected::create());
2763     refMap->add(luck, RefCountedAndGarbageCollected::create());
2764 
2765     baseLine  =  ThingWithDestructor::s_liveThingsWithDestructor;
2766     refBaseLine = RefCountedAndGarbageCollected::s_destructorCalls;
2767 
2768     luck.clear();
2769     if (clearMaps) {
2770         map->clear(); // Clear map.
2771         refMap->clear(); // Clear map.
2772     } else {
2773         map.clear(); // Clear Persistent handle, not map.
2774         refMap.clear(); // Clear Persistent handle, not map.
2775         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2776         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2777     }
2778 
2779     EXPECT_EQ(baseLine - 2, ThingWithDestructor::s_liveThingsWithDestructor);
2780 
2781     // Need a GC to make sure that the RefCountedAndGarbageCollected thing
2782     // noticies it's been decremented to zero.
2783     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2784     EXPECT_EQ(refBaseLine + 2, RefCountedAndGarbageCollected::s_destructorCalls);
2785 }
2786 
TEST(HeapTest,HeapMapDestructor)2787 TEST(HeapTest, HeapMapDestructor)
2788 {
2789     heapMapDestructorHelper(true);
2790     heapMapDestructorHelper(false);
2791 }
2792 
2793 typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2794 typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2795 typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2796 typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2797 typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongLinkedSet;
2798 typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedLinkedSet;
2799 typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakLinkedSet;
2800 typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakLinkedSet;
2801 typedef HeapHashCountedSet<PairWeakStrong> WeakStrongCountedSet;
2802 typedef HeapHashCountedSet<PairWeakUnwrapped> WeakUnwrappedCountedSet;
2803 typedef HeapHashCountedSet<PairStrongWeak> StrongWeakCountedSet;
2804 typedef HeapHashCountedSet<PairUnwrappedWeak> UnwrappedWeakCountedSet;
2805 
2806 template<typename T>
iteratorExtractor(WTF::KeyValuePair<T,unsigned> & pair)2807 T& iteratorExtractor(WTF::KeyValuePair<T, unsigned>& pair)
2808 {
2809     return pair.key;
2810 }
2811 
2812 template<typename T>
iteratorExtractor(T & notAPair)2813 T& iteratorExtractor(T& notAPair)
2814 {
2815     return notAPair;
2816 }
2817 
2818 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)2819 void checkPairSets(
2820     Persistent<WSSet>& weakStrong,
2821     Persistent<SWSet>& strongWeak,
2822     Persistent<WUSet>& weakUnwrapped,
2823     Persistent<UWSet>& unwrappedWeak,
2824     bool ones,
2825     Persistent<IntWrapper>& two)
2826 {
2827     typename WSSet::iterator itWS = weakStrong->begin();
2828     typename SWSet::iterator itSW = strongWeak->begin();
2829     typename WUSet::iterator itWU = weakUnwrapped->begin();
2830     typename UWSet::iterator itUW = unwrappedWeak->begin();
2831 
2832     EXPECT_EQ(2u, weakStrong->size());
2833     EXPECT_EQ(2u, strongWeak->size());
2834     EXPECT_EQ(2u, weakUnwrapped->size());
2835     EXPECT_EQ(2u, unwrappedWeak->size());
2836 
2837     PairWeakStrong p = iteratorExtractor(*itWS);
2838     PairStrongWeak p2 = iteratorExtractor(*itSW);
2839     PairWeakUnwrapped p3 = iteratorExtractor(*itWU);
2840     PairUnwrappedWeak p4 = iteratorExtractor(*itUW);
2841     if (p.first == two && p.second == two)
2842         ++itWS;
2843     if (p2.first == two && p2.second == two)
2844         ++itSW;
2845     if (p3.first == two && p3.second == 2)
2846         ++itWU;
2847     if (p4.first == 2 && p4.second == two)
2848         ++itUW;
2849     p = iteratorExtractor(*itWS);
2850     p2 = iteratorExtractor(*itSW);
2851     p3 = iteratorExtractor(*itWU);
2852     p4 = iteratorExtractor(*itUW);
2853     IntWrapper* nullWrapper = 0;
2854     if (ones) {
2855         EXPECT_EQ(p.first->value(), 1);
2856         EXPECT_EQ(p2.second->value(), 1);
2857         EXPECT_EQ(p3.first->value(), 1);
2858         EXPECT_EQ(p4.second->value(), 1);
2859     } else {
2860         EXPECT_EQ(p.first, nullWrapper);
2861         EXPECT_EQ(p2.second, nullWrapper);
2862         EXPECT_EQ(p3.first, nullWrapper);
2863         EXPECT_EQ(p4.second, nullWrapper);
2864     }
2865 
2866     EXPECT_EQ(p.second->value(), 2);
2867     EXPECT_EQ(p2.first->value(), 2);
2868     EXPECT_EQ(p3.second, 2);
2869     EXPECT_EQ(p4.first, 2);
2870 
2871     EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2872     EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2873     EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2874     EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2875 }
2876 
2877 template<typename WSSet, typename SWSet, typename WUSet, typename UWSet>
weakPairsHelper()2878 void weakPairsHelper()
2879 {
2880     IntWrapper::s_destructorCalls = 0;
2881 
2882     PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2883 
2884     Persistent<WSSet> weakStrong = new WSSet();
2885     Persistent<SWSet> strongWeak = new SWSet();
2886     Persistent<WUSet> weakUnwrapped = new WUSet();
2887     Persistent<UWSet> unwrappedWeak = new UWSet();
2888 
2889     Persistent<IntWrapper> two = IntWrapper::create(2);
2890 
2891     weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2892     weakStrong->add(PairWeakStrong(&*two, &*two));
2893     strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2894     strongWeak->add(PairStrongWeak(&*two, &*two));
2895     weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2896     weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2897     unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2898     unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2899 
2900     checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2901 
2902     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2903     checkPairSets<WSSet, SWSet, WUSet, UWSet>(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2904 }
2905 
TEST(HeapTest,HeapWeakPairs)2906 TEST(HeapTest, HeapWeakPairs)
2907 {
2908     {
2909         typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2910         typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2911         typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2912         typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2913         weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2914     }
2915 
2916     {
2917         typedef HeapListHashSet<PairWeakStrong> WeakStrongSet;
2918         typedef HeapListHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2919         typedef HeapListHashSet<PairStrongWeak> StrongWeakSet;
2920         typedef HeapListHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2921         weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2922     }
2923 
2924     {
2925         typedef HeapLinkedHashSet<PairWeakStrong> WeakStrongSet;
2926         typedef HeapLinkedHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2927         typedef HeapLinkedHashSet<PairStrongWeak> StrongWeakSet;
2928         typedef HeapLinkedHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2929         weakPairsHelper<WeakStrongSet, StrongWeakSet, WeakUnwrappedSet, UnwrappedWeakSet>();
2930     }
2931 }
2932 
TEST(HeapTest,HeapWeakCollectionTypes)2933 TEST(HeapTest, HeapWeakCollectionTypes)
2934 {
2935     HeapStats initialHeapSize;
2936     IntWrapper::s_destructorCalls = 0;
2937 
2938     typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2939     typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2940     typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2941     typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2942     typedef HeapLinkedHashSet<WeakMember<IntWrapper> > WeakOrderedSet;
2943 
2944     clearOutOldGarbage(&initialHeapSize);
2945 
2946     const int weakStrongIndex = 0;
2947     const int strongWeakIndex = 1;
2948     const int weakWeakIndex = 2;
2949     const int numberOfMapIndices = 3;
2950     const int weakSetIndex = 3;
2951     const int weakOrderedSetIndex = 4;
2952     const int numberOfCollections = 5;
2953 
2954     for (int testRun = 0; testRun < 4; testRun++) {
2955         for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2956             bool deleteAfterwards = (testRun == 1);
2957             bool addAfterwards = (testRun == 2);
2958             bool testThatIteratorsMakeStrong = (testRun == 3);
2959 
2960             // The test doesn't work for strongWeak with deleting because we lost
2961             // the key from the keepNumbersAlive array, so we can't do the lookup.
2962             if (deleteAfterwards && collectionNumber == strongWeakIndex)
2963                 continue;
2964 
2965             unsigned added = addAfterwards ? 100 : 0;
2966 
2967             Persistent<WeakStrong> weakStrong = new WeakStrong();
2968             Persistent<StrongWeak> strongWeak = new StrongWeak();
2969             Persistent<WeakWeak> weakWeak = new WeakWeak();
2970 
2971             Persistent<WeakSet> weakSet = new WeakSet();
2972             Persistent<WeakOrderedSet> weakOrderedSet = new WeakOrderedSet();
2973 
2974             PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2975             for (int i = 0; i < 128; i += 2) {
2976                 IntWrapper* wrapped = IntWrapper::create(i);
2977                 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
2978                 keepNumbersAlive.append(wrapped);
2979                 keepNumbersAlive.append(wrapped2);
2980                 weakStrong->add(wrapped, wrapped2);
2981                 strongWeak->add(wrapped2, wrapped);
2982                 weakWeak->add(wrapped, wrapped2);
2983                 weakSet->add(wrapped);
2984                 weakOrderedSet->add(wrapped);
2985             }
2986 
2987             EXPECT_EQ(64u, weakStrong->size());
2988             EXPECT_EQ(64u, strongWeak->size());
2989             EXPECT_EQ(64u, weakWeak->size());
2990             EXPECT_EQ(64u, weakSet->size());
2991             EXPECT_EQ(64u, weakOrderedSet->size());
2992 
2993             // Collect garbage. This should change nothing since we are keeping
2994             // alive the IntWrapper objects.
2995             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2996 
2997             EXPECT_EQ(64u, weakStrong->size());
2998             EXPECT_EQ(64u, strongWeak->size());
2999             EXPECT_EQ(64u, weakWeak->size());
3000             EXPECT_EQ(64u, weakSet->size());
3001             EXPECT_EQ(64u, weakOrderedSet->size());
3002 
3003             for (int i = 0; i < 128; i += 2) {
3004                 IntWrapper* wrapped = keepNumbersAlive[i];
3005                 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
3006                 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
3007                 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
3008                 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
3009                 EXPECT_TRUE(weakSet->contains(wrapped));
3010                 EXPECT_TRUE(weakOrderedSet->contains(wrapped));
3011             }
3012 
3013             for (int i = 0; i < 128; i += 3)
3014                 keepNumbersAlive[i] = nullptr;
3015 
3016             if (collectionNumber != weakStrongIndex)
3017                 weakStrong->clear();
3018             if (collectionNumber != strongWeakIndex)
3019                 strongWeak->clear();
3020             if (collectionNumber != weakWeakIndex)
3021                 weakWeak->clear();
3022             if (collectionNumber != weakSetIndex)
3023                 weakSet->clear();
3024             if (collectionNumber != weakOrderedSetIndex)
3025                 weakOrderedSet->clear();
3026 
3027             if (testThatIteratorsMakeStrong) {
3028                 WeakStrong::iterator it1 = weakStrong->begin();
3029                 StrongWeak::iterator it2 = strongWeak->begin();
3030                 WeakWeak::iterator it3 = weakWeak->begin();
3031                 WeakSet::iterator it4 = weakSet->begin();
3032                 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3033                 // Collect garbage. This should change nothing since the
3034                 // iterators make the collections strong.
3035                 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3036                 if (collectionNumber == weakStrongIndex) {
3037                     EXPECT_EQ(64u, weakStrong->size());
3038                     MapIteratorCheck(it1, weakStrong->end(), 64);
3039                 } else if (collectionNumber == strongWeakIndex) {
3040                     EXPECT_EQ(64u, strongWeak->size());
3041                     MapIteratorCheck(it2, strongWeak->end(), 64);
3042                 } else if (collectionNumber == weakWeakIndex) {
3043                     EXPECT_EQ(64u, weakWeak->size());
3044                     MapIteratorCheck(it3, weakWeak->end(), 64);
3045                 } else if (collectionNumber == weakSetIndex) {
3046                     EXPECT_EQ(64u, weakSet->size());
3047                     SetIteratorCheck(it4, weakSet->end(), 64);
3048                 } else if (collectionNumber == weakOrderedSetIndex) {
3049                     EXPECT_EQ(64u, weakOrderedSet->size());
3050                     SetIteratorCheck(it5, weakOrderedSet->end(), 64);
3051                 }
3052             } else {
3053                 // Collect garbage. This causes weak processing to remove
3054                 // things from the collections.
3055                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3056                 unsigned count = 0;
3057                 for (int i = 0; i < 128; i += 2) {
3058                     bool firstAlive = keepNumbersAlive[i];
3059                     bool secondAlive = keepNumbersAlive[i + 1];
3060                     if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
3061                         secondAlive = true;
3062                     if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
3063                         if (collectionNumber == weakStrongIndex) {
3064                             if (deleteAfterwards)
3065                                 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
3066                         } else if (collectionNumber == strongWeakIndex) {
3067                             if (deleteAfterwards)
3068                                 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
3069                         } else if (collectionNumber == weakWeakIndex) {
3070                             if (deleteAfterwards)
3071                                 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
3072                         }
3073                         if (!deleteAfterwards)
3074                             count++;
3075                     } else if (collectionNumber == weakSetIndex && firstAlive) {
3076                         ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
3077                         if (deleteAfterwards)
3078                             weakSet->remove(keepNumbersAlive[i]);
3079                         else
3080                             count++;
3081                     } else if (collectionNumber == weakOrderedSetIndex && firstAlive) {
3082                         ASSERT_TRUE(weakOrderedSet->contains(keepNumbersAlive[i]));
3083                         if (deleteAfterwards)
3084                             weakOrderedSet->remove(keepNumbersAlive[i]);
3085                         else
3086                             count++;
3087                     }
3088                 }
3089                 if (addAfterwards) {
3090                     for (int i = 1000; i < 1100; i++) {
3091                         IntWrapper* wrapped = IntWrapper::create(i);
3092                         keepNumbersAlive.append(wrapped);
3093                         weakStrong->add(wrapped, wrapped);
3094                         strongWeak->add(wrapped, wrapped);
3095                         weakWeak->add(wrapped, wrapped);
3096                         weakSet->add(wrapped);
3097                         weakOrderedSet->add(wrapped);
3098                     }
3099                 }
3100                 if (collectionNumber == weakStrongIndex)
3101                     EXPECT_EQ(count + added, weakStrong->size());
3102                 else if (collectionNumber == strongWeakIndex)
3103                     EXPECT_EQ(count + added, strongWeak->size());
3104                 else if (collectionNumber == weakWeakIndex)
3105                     EXPECT_EQ(count + added, weakWeak->size());
3106                 else if (collectionNumber == weakSetIndex)
3107                     EXPECT_EQ(count + added, weakSet->size());
3108                 else if (collectionNumber == weakOrderedSetIndex)
3109                     EXPECT_EQ(count + added, weakOrderedSet->size());
3110                 WeakStrong::iterator it1 = weakStrong->begin();
3111                 StrongWeak::iterator it2 = strongWeak->begin();
3112                 WeakWeak::iterator it3 = weakWeak->begin();
3113                 WeakSet::iterator it4 = weakSet->begin();
3114                 WeakOrderedSet::iterator it5 = weakOrderedSet->begin();
3115                 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
3116                 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
3117                 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
3118                 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
3119                 SetIteratorCheck(it5, weakOrderedSet->end(), (collectionNumber == weakOrderedSetIndex ? count : 0) + added);
3120             }
3121             for (unsigned i = 0; i < 128 + added; i++)
3122                 keepNumbersAlive[i] = nullptr;
3123             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3124             EXPECT_EQ(0u, weakStrong->size());
3125             EXPECT_EQ(0u, strongWeak->size());
3126             EXPECT_EQ(0u, weakWeak->size());
3127             EXPECT_EQ(0u, weakSet->size());
3128             EXPECT_EQ(0u, weakOrderedSet->size());
3129         }
3130     }
3131 }
3132 
TEST(HeapTest,RefCountedGarbageCollected)3133 TEST(HeapTest, RefCountedGarbageCollected)
3134 {
3135     RefCountedAndGarbageCollected::s_destructorCalls = 0;
3136     {
3137         RefPtr<RefCountedAndGarbageCollected> refPtr3;
3138         {
3139             Persistent<RefCountedAndGarbageCollected> persistent;
3140             {
3141                 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
3142                 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
3143                 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3144                 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3145                 persistent = refPtr1.get();
3146             }
3147             // Reference count is zero for both objects but one of
3148             // them is kept alive by a persistent handle.
3149             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3150             EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3151             refPtr3 = persistent.get();
3152         }
3153         // The persistent handle is gone but the ref count has been
3154         // increased to 1.
3155         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3156         EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3157     }
3158     // Both persistent handle is gone and ref count is zero so the
3159     // object can be collected.
3160     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3161     EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
3162 }
3163 
TEST(HeapTest,RefCountedGarbageCollectedWithStackPointers)3164 TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
3165 {
3166     RefCountedAndGarbageCollected::s_destructorCalls = 0;
3167     RefCountedAndGarbageCollected2::s_destructorCalls = 0;
3168     {
3169         RefCountedAndGarbageCollected* pointer1 = 0;
3170         RefCountedAndGarbageCollected2* pointer2 = 0;
3171         {
3172             RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
3173             RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
3174             pointer1 = object1.get();
3175             pointer2 = object2.get();
3176             void* objects[2] = { object1.get(), object2.get() };
3177             RefCountedGarbageCollectedVisitor visitor(2, objects);
3178             ThreadState::current()->visitPersistents(&visitor);
3179             EXPECT_TRUE(visitor.validate());
3180 
3181             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3182             EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3183             EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3184         }
3185         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3186         EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3187         EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3188 
3189         // At this point, the reference counts of object1 and object2 are 0.
3190         // Only pointer1 and pointer2 keep references to object1 and object2.
3191         void* objects[] = { 0 };
3192         RefCountedGarbageCollectedVisitor visitor(0, objects);
3193         ThreadState::current()->visitPersistents(&visitor);
3194         EXPECT_TRUE(visitor.validate());
3195 
3196         {
3197             RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
3198             RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
3199             void* objects[2] = { object1.get(), object2.get() };
3200             RefCountedGarbageCollectedVisitor visitor(2, objects);
3201             ThreadState::current()->visitPersistents(&visitor);
3202             EXPECT_TRUE(visitor.validate());
3203 
3204             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3205             EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3206             EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3207         }
3208 
3209         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3210         EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
3211         EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
3212     }
3213 
3214     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3215     EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
3216     EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
3217 }
3218 
TEST(HeapTest,WeakMembers)3219 TEST(HeapTest, WeakMembers)
3220 {
3221     Bar::s_live = 0;
3222     {
3223         Persistent<Bar> h1 = Bar::create();
3224         Persistent<Weak> h4;
3225         Persistent<WithWeakMember> h5;
3226         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3227         ASSERT_EQ(1u, Bar::s_live); // h1 is live.
3228         {
3229             Bar* h2 = Bar::create();
3230             Bar* h3 = Bar::create();
3231             h4 = Weak::create(h2, h3);
3232             h5 = WithWeakMember::create(h2, h3);
3233             Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3234             EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
3235             EXPECT_TRUE(h4->strongIsThere());
3236             EXPECT_TRUE(h4->weakIsThere());
3237             EXPECT_TRUE(h5->strongIsThere());
3238             EXPECT_TRUE(h5->weakIsThere());
3239         }
3240         // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
3241         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3242         EXPECT_EQ(4u, Bar::s_live);
3243         EXPECT_TRUE(h4->strongIsThere());
3244         EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
3245         EXPECT_TRUE(h5->strongIsThere());
3246         EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
3247         h1.release(); // Zero out h1.
3248         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3249         EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
3250         EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
3251         EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
3252     }
3253     // h4 and h5 have gone out of scope now and they were keeping h2 alive.
3254     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3255     EXPECT_EQ(0u, Bar::s_live); // All gone.
3256 }
3257 
TEST(HeapTest,FinalizationObserver)3258 TEST(HeapTest, FinalizationObserver)
3259 {
3260     Persistent<FinalizationObserver<Observable> > o;
3261     {
3262         Observable* foo = Observable::create(Bar::create());
3263         // |o| observes |foo|.
3264         o = FinalizationObserver<Observable>::create(foo);
3265     }
3266     // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
3267     // and its member will be collected.
3268     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3269     EXPECT_EQ(0u, Bar::s_live);
3270     EXPECT_TRUE(o->didCallWillFinalize());
3271 
3272     FinalizationObserverWithHashMap::s_didCallWillFinalize = false;
3273     Observable* foo = Observable::create(Bar::create());
3274     FinalizationObserverWithHashMap::ObserverMap& map = FinalizationObserverWithHashMap::observe(*foo);
3275     EXPECT_EQ(1u, map.size());
3276     foo = 0;
3277     // FinalizationObserverWithHashMap doesn't have a strong reference to
3278     // |foo|. So |foo| and its member will be collected.
3279     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3280     EXPECT_EQ(0u, Bar::s_live);
3281     EXPECT_EQ(0u, map.size());
3282     EXPECT_TRUE(FinalizationObserverWithHashMap::s_didCallWillFinalize);
3283 }
3284 
TEST(HeapTest,Comparisons)3285 TEST(HeapTest, Comparisons)
3286 {
3287     Persistent<Bar> barPersistent = Bar::create();
3288     Persistent<Foo> fooPersistent = Foo::create(barPersistent);
3289     EXPECT_TRUE(barPersistent != fooPersistent);
3290     barPersistent = fooPersistent;
3291     EXPECT_TRUE(barPersistent == fooPersistent);
3292 }
3293 
TEST(HeapTest,CheckAndMarkPointer)3294 TEST(HeapTest, CheckAndMarkPointer)
3295 {
3296     HeapStats initialHeapStats;
3297     clearOutOldGarbage(&initialHeapStats);
3298 
3299     Vector<Address> objectAddresses;
3300     Vector<Address> endAddresses;
3301     Address largeObjectAddress;
3302     Address largeObjectEndAddress;
3303     CountingVisitor visitor;
3304     for (int i = 0; i < 10; i++) {
3305         SimpleObject* object = SimpleObject::create();
3306         Address objectAddress = reinterpret_cast<Address>(object);
3307         objectAddresses.append(objectAddress);
3308         endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
3309     }
3310     LargeObject* largeObject = LargeObject::create();
3311     largeObjectAddress = reinterpret_cast<Address>(largeObject);
3312     largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
3313 
3314     // This is a low-level test where we call checkAndMarkPointer. This method
3315     // causes the object start bitmap to be computed which requires the heap
3316     // to be in a consistent state (e.g. the free allocation area must be put
3317     // into a free list header). However when we call makeConsistentForSweeping it
3318     // also clears out the freelists so we have to rebuild those before trying
3319     // to allocate anything again. We do this by forcing a GC after doing the
3320     // checkAndMarkPointer tests.
3321     {
3322         TestGCScope scope(ThreadState::HeapPointersOnStack);
3323         EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads.
3324         Heap::makeConsistentForSweeping();
3325         for (size_t i = 0; i < objectAddresses.size(); i++) {
3326             EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
3327             EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
3328         }
3329         EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
3330         visitor.reset();
3331         EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
3332         EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
3333         EXPECT_EQ(2ul, visitor.count());
3334         visitor.reset();
3335     }
3336     // This forces a GC without stack scanning which results in the objects
3337     // being collected. This will also rebuild the above mentioned freelists,
3338     // however we don't rely on that below since we don't have any allocations.
3339     clearOutOldGarbage(&initialHeapStats);
3340     {
3341         TestGCScope scope(ThreadState::HeapPointersOnStack);
3342         EXPECT_TRUE(scope.allThreadsParked());
3343         Heap::makeConsistentForSweeping();
3344         for (size_t i = 0; i < objectAddresses.size(); i++) {
3345             // We would like to assert that checkAndMarkPointer returned false
3346             // here because the pointers no longer point into a valid object
3347             // (it's been freed by the GCs. But checkAndMarkPointer will return
3348             // true for any pointer that points into a heap page, regardless of
3349             // whether it points at a valid object (this ensures the
3350             // correctness of the page-based on-heap address caches), so we
3351             // can't make that assert.
3352             Heap::checkAndMarkPointer(&visitor, objectAddresses[i]);
3353             Heap::checkAndMarkPointer(&visitor, endAddresses[i]);
3354         }
3355         EXPECT_EQ(0ul, visitor.count());
3356         Heap::checkAndMarkPointer(&visitor, largeObjectAddress);
3357         Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress);
3358         EXPECT_EQ(0ul, visitor.count());
3359     }
3360     // This round of GC is important to make sure that the object start
3361     // bitmap are cleared out and that the free lists are rebuild.
3362     clearOutOldGarbage(&initialHeapStats);
3363 }
3364 
TEST(HeapTest,VisitOffHeapCollections)3365 TEST(HeapTest, VisitOffHeapCollections)
3366 {
3367     HeapStats initialHeapStats;
3368     clearOutOldGarbage(&initialHeapStats);
3369     IntWrapper::s_destructorCalls = 0;
3370     Persistent<OffHeapContainer> container = OffHeapContainer::create();
3371     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3372     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3373     container = nullptr;
3374     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3375     EXPECT_EQ(OffHeapContainer::deadWrappers, IntWrapper::s_destructorCalls);
3376 }
3377 
TEST(HeapTest,PersistentHeapCollectionTypes)3378 TEST(HeapTest, PersistentHeapCollectionTypes)
3379 {
3380     HeapStats initialHeapSize;
3381     IntWrapper::s_destructorCalls = 0;
3382 
3383     typedef HeapVector<Member<IntWrapper> > Vec;
3384     typedef PersistentHeapVector<Member<IntWrapper> > PVec;
3385     typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
3386     typedef PersistentHeapListHashSet<Member<IntWrapper> > PListSet;
3387     typedef PersistentHeapLinkedHashSet<Member<IntWrapper> > PLinkedSet;
3388     typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
3389     typedef PersistentHeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakPMap;
3390     typedef PersistentHeapDeque<Member<IntWrapper> > PDeque;
3391 
3392     clearOutOldGarbage(&initialHeapSize);
3393     {
3394         PVec pVec;
3395         PDeque pDeque;
3396         PSet pSet;
3397         PListSet pListSet;
3398         PLinkedSet pLinkedSet;
3399         PMap pMap;
3400         WeakPMap wpMap;
3401 
3402         IntWrapper* one(IntWrapper::create(1));
3403         IntWrapper* two(IntWrapper::create(2));
3404         IntWrapper* three(IntWrapper::create(3));
3405         IntWrapper* four(IntWrapper::create(4));
3406         IntWrapper* five(IntWrapper::create(5));
3407         IntWrapper* six(IntWrapper::create(6));
3408         IntWrapper* seven(IntWrapper::create(7));
3409         IntWrapper* eight(IntWrapper::create(8));
3410         IntWrapper* nine(IntWrapper::create(9));
3411         Persistent<IntWrapper> ten(IntWrapper::create(10));
3412         IntWrapper* eleven(IntWrapper::create(11));
3413 
3414         pVec.append(one);
3415         pVec.append(two);
3416 
3417         pDeque.append(seven);
3418         pDeque.append(two);
3419 
3420         Vec* vec = new Vec();
3421         vec->swap(pVec);
3422 
3423         pVec.append(two);
3424         pVec.append(three);
3425 
3426         pSet.add(four);
3427         pListSet.add(eight);
3428         pLinkedSet.add(nine);
3429         pMap.add(five, six);
3430         wpMap.add(ten, eleven);
3431 
3432         // Collect |vec| and |one|.
3433         vec = 0;
3434         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3435         EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3436 
3437         EXPECT_EQ(2u, pVec.size());
3438         EXPECT_EQ(two, pVec.at(0));
3439         EXPECT_EQ(three, pVec.at(1));
3440 
3441         EXPECT_EQ(2u, pDeque.size());
3442         EXPECT_EQ(seven, pDeque.first());
3443         EXPECT_EQ(seven, pDeque.takeFirst());
3444         EXPECT_EQ(two, pDeque.first());
3445 
3446         EXPECT_EQ(1u, pDeque.size());
3447 
3448         EXPECT_EQ(1u, pSet.size());
3449         EXPECT_TRUE(pSet.contains(four));
3450 
3451         EXPECT_EQ(1u, pListSet.size());
3452         EXPECT_TRUE(pListSet.contains(eight));
3453 
3454         EXPECT_EQ(1u, pLinkedSet.size());
3455         EXPECT_TRUE(pLinkedSet.contains(nine));
3456 
3457         EXPECT_EQ(1u, pMap.size());
3458         EXPECT_EQ(six, pMap.get(five));
3459 
3460         EXPECT_EQ(1u, wpMap.size());
3461         EXPECT_EQ(eleven, wpMap.get(ten));
3462         ten.clear();
3463         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3464         EXPECT_EQ(0u, wpMap.size());
3465     }
3466 
3467     // Collect previous roots.
3468     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3469     EXPECT_EQ(11, IntWrapper::s_destructorCalls);
3470 }
3471 
TEST(HeapTest,CollectionNesting)3472 TEST(HeapTest, CollectionNesting)
3473 {
3474     HeapStats initialStats;
3475     clearOutOldGarbage(&initialStats);
3476     int* key = &IntWrapper::s_destructorCalls;
3477     IntWrapper::s_destructorCalls = 0;
3478     typedef HeapVector<Member<IntWrapper> > IntVector;
3479     typedef HeapDeque<Member<IntWrapper> > IntDeque;
3480     HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
3481     HeapHashMap<void*, IntDeque>* map2 = new HeapHashMap<void*, IntDeque>();
3482 
3483     map->add(key, IntVector());
3484     map2->add(key, IntDeque());
3485 
3486     HeapHashMap<void*, IntVector>::iterator it = map->find(key);
3487     EXPECT_EQ(0u, map->get(key).size());
3488 
3489     HeapHashMap<void*, IntDeque>::iterator it2 = map2->find(key);
3490     EXPECT_EQ(0u, map2->get(key).size());
3491 
3492     it->value.append(IntWrapper::create(42));
3493     EXPECT_EQ(1u, map->get(key).size());
3494 
3495     it2->value.append(IntWrapper::create(42));
3496     EXPECT_EQ(1u, map2->get(key).size());
3497 
3498     Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
3499     Persistent<HeapHashMap<void*, IntDeque> > keepAlive2(map2);
3500 
3501     for (int i = 0; i < 100; i++) {
3502         map->add(key + 1 + i, IntVector());
3503         map2->add(key + 1 + i, IntDeque());
3504     }
3505 
3506     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3507 
3508     EXPECT_EQ(1u, map->get(key).size());
3509     EXPECT_EQ(1u, map2->get(key).size());
3510     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3511 
3512     keepAlive = nullptr;
3513     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3514     EXPECT_EQ(1, IntWrapper::s_destructorCalls);
3515 }
3516 
TEST(HeapTest,GarbageCollectedMixin)3517 TEST(HeapTest, GarbageCollectedMixin)
3518 {
3519     HeapStats initialHeapStats;
3520     clearOutOldGarbage(&initialHeapStats);
3521 
3522     Persistent<UseMixin> usemixin = UseMixin::create();
3523     EXPECT_EQ(0, UseMixin::s_traceCount);
3524     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3525     EXPECT_EQ(1, UseMixin::s_traceCount);
3526 
3527     Persistent<Mixin> mixin = usemixin;
3528     usemixin = nullptr;
3529     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3530     EXPECT_EQ(2, UseMixin::s_traceCount);
3531 
3532     PersistentHeapHashSet<WeakMember<Mixin> > weakMap;
3533     weakMap.add(UseMixin::create());
3534     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3535     EXPECT_EQ(0u, weakMap.size());
3536 }
3537 
TEST(HeapTest,CollectionNesting2)3538 TEST(HeapTest, CollectionNesting2)
3539 {
3540     HeapStats initialStats;
3541     clearOutOldGarbage(&initialStats);
3542     void* key = &IntWrapper::s_destructorCalls;
3543     IntWrapper::s_destructorCalls = 0;
3544     typedef HeapHashSet<Member<IntWrapper> > IntSet;
3545     HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
3546 
3547     map->add(key, IntSet());
3548 
3549     HeapHashMap<void*, IntSet>::iterator it = map->find(key);
3550     EXPECT_EQ(0u, map->get(key).size());
3551 
3552     it->value.add(IntWrapper::create(42));
3553     EXPECT_EQ(1u, map->get(key).size());
3554 
3555     Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
3556     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3557     EXPECT_EQ(1u, map->get(key).size());
3558     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3559 }
3560 
TEST(HeapTest,CollectionNesting3)3561 TEST(HeapTest, CollectionNesting3)
3562 {
3563     HeapStats initialStats;
3564     clearOutOldGarbage(&initialStats);
3565     IntWrapper::s_destructorCalls = 0;
3566     typedef HeapVector<Member<IntWrapper> > IntVector;
3567     typedef HeapDeque<Member<IntWrapper> > IntDeque;
3568     HeapVector<IntVector>* vector = new HeapVector<IntVector>();
3569     HeapDeque<IntDeque>* deque = new HeapDeque<IntDeque>();
3570 
3571     vector->append(IntVector());
3572     deque->append(IntDeque());
3573 
3574     HeapVector<IntVector>::iterator it = vector->begin();
3575     HeapDeque<IntDeque>::iterator it2 = deque->begin();
3576     EXPECT_EQ(0u, it->size());
3577     EXPECT_EQ(0u, it2->size());
3578 
3579     it->append(IntWrapper::create(42));
3580     it2->append(IntWrapper::create(42));
3581     EXPECT_EQ(1u, it->size());
3582     EXPECT_EQ(1u, it2->size());
3583 
3584     Persistent<HeapVector<IntVector> > keepAlive(vector);
3585     Persistent<HeapDeque<IntDeque> > keepAlive2(deque);
3586     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3587     EXPECT_EQ(1u, it->size());
3588     EXPECT_EQ(1u, it2->size());
3589     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3590 }
3591 
TEST(HeapTest,EmbeddedInVector)3592 TEST(HeapTest, EmbeddedInVector)
3593 {
3594     HeapStats initialStats;
3595     clearOutOldGarbage(&initialStats);
3596     SimpleFinalizedObject::s_destructorCalls = 0;
3597     {
3598         PersistentHeapVector<VectorObject, 2> inlineVector;
3599         PersistentHeapVector<VectorObject> outlineVector;
3600         VectorObject i1, i2;
3601         inlineVector.append(i1);
3602         inlineVector.append(i2);
3603 
3604         VectorObject o1, o2;
3605         outlineVector.append(o1);
3606         outlineVector.append(o2);
3607 
3608         PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
3609         VectorObjectInheritedTrace it1, it2;
3610         vectorInheritedTrace.append(it1);
3611         vectorInheritedTrace.append(it2);
3612 
3613         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3614         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3615 
3616         // Since VectorObjectNoTrace has no trace method it will
3617         // not be traced and hence be collected when doing GC.
3618         // We trace items in a collection braced on the item's
3619         // having a trace method. This is determined via the
3620         // NeedsTracing trait in wtf/TypeTraits.h.
3621         PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
3622         VectorObjectNoTrace n1, n2;
3623         vectorNoTrace.append(n1);
3624         vectorNoTrace.append(n2);
3625         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3626         EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3627     }
3628     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3629     EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3630 }
3631 
TEST(HeapTest,EmbeddedInDeque)3632 TEST(HeapTest, EmbeddedInDeque)
3633 {
3634     HeapStats initialStats;
3635     clearOutOldGarbage(&initialStats);
3636     SimpleFinalizedObject::s_destructorCalls = 0;
3637     {
3638         PersistentHeapDeque<VectorObject, 2> inlineDeque;
3639         PersistentHeapDeque<VectorObject> outlineDeque;
3640         VectorObject i1, i2;
3641         inlineDeque.append(i1);
3642         inlineDeque.append(i2);
3643 
3644         VectorObject o1, o2;
3645         outlineDeque.append(o1);
3646         outlineDeque.append(o2);
3647 
3648         PersistentHeapDeque<VectorObjectInheritedTrace> dequeInheritedTrace;
3649         VectorObjectInheritedTrace it1, it2;
3650         dequeInheritedTrace.append(it1);
3651         dequeInheritedTrace.append(it2);
3652 
3653         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3654         EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
3655 
3656         // Since VectorObjectNoTrace has no trace method it will
3657         // not be traced and hence be collected when doing GC.
3658         // We trace items in a collection braced on the item's
3659         // having a trace method. This is determined via the
3660         // NeedsTracing trait in wtf/TypeTraits.h.
3661         PersistentHeapDeque<VectorObjectNoTrace> dequeNoTrace;
3662         VectorObjectNoTrace n1, n2;
3663         dequeNoTrace.append(n1);
3664         dequeNoTrace.append(n2);
3665         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3666         EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
3667     }
3668     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3669     EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
3670 }
3671 
3672 template<typename Set>
rawPtrInHashHelper()3673 void rawPtrInHashHelper()
3674 {
3675     Set set;
3676     set.add(new int(42));
3677     set.add(new int(42));
3678     EXPECT_EQ(2u, set.size());
3679     for (typename Set::iterator it = set.begin(); it != set.end(); ++it) {
3680         EXPECT_EQ(42, **it);
3681         delete *it;
3682     }
3683 }
3684 
TEST(HeapTest,RawPtrInHash)3685 TEST(HeapTest, RawPtrInHash)
3686 {
3687     rawPtrInHashHelper<HashSet<RawPtr<int> > >();
3688     rawPtrInHashHelper<ListHashSet<RawPtr<int> > >();
3689     rawPtrInHashHelper<LinkedHashSet<RawPtr<int> > >();
3690 }
3691 
TEST(HeapTest,HeapTerminatedArray)3692 TEST(HeapTest, HeapTerminatedArray)
3693 {
3694     HeapStats initialHeapSize;
3695     clearOutOldGarbage(&initialHeapSize);
3696     IntWrapper::s_destructorCalls = 0;
3697 
3698     HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
3699 
3700     const size_t prefixSize = 4;
3701     const size_t suffixSize = 4;
3702 
3703     {
3704         HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3705         builder.grow(prefixSize);
3706         for (size_t i = 0; i < prefixSize; i++)
3707             builder.append(TerminatedArrayItem(IntWrapper::create(i)));
3708         arr = builder.release();
3709     }
3710 
3711     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3712     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3713     EXPECT_EQ(prefixSize, arr->size());
3714     for (size_t i = 0; i < prefixSize; i++)
3715         EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3716 
3717     {
3718         HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
3719         builder.grow(suffixSize);
3720         for (size_t i = 0; i < suffixSize; i++)
3721             builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
3722         arr = builder.release();
3723     }
3724 
3725     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3726     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3727     EXPECT_EQ(prefixSize + suffixSize, arr->size());
3728     for (size_t i = 0; i < prefixSize + suffixSize; i++)
3729         EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3730 
3731     {
3732         Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
3733         arr = 0;
3734         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3735         arr = persistentArr.get();
3736         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3737         EXPECT_EQ(prefixSize + suffixSize, arr->size());
3738         for (size_t i = 0; i < prefixSize + suffixSize; i++)
3739             EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
3740     }
3741 
3742     arr = 0;
3743     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3744     EXPECT_EQ(8, IntWrapper::s_destructorCalls);
3745 }
3746 
TEST(HeapTest,HeapLinkedStack)3747 TEST(HeapTest, HeapLinkedStack)
3748 {
3749     HeapStats initialHeapSize;
3750     clearOutOldGarbage(&initialHeapSize);
3751     IntWrapper::s_destructorCalls = 0;
3752 
3753     HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
3754 
3755     const size_t stackSize = 10;
3756 
3757     for (size_t i = 0; i < stackSize; i++)
3758         stack->push(TerminatedArrayItem(IntWrapper::create(i)));
3759 
3760     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3761     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3762     EXPECT_EQ(stackSize, stack->size());
3763     while (!stack->isEmpty()) {
3764         EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
3765         stack->pop();
3766     }
3767 
3768     Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
3769 
3770     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3771     EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
3772     EXPECT_EQ(0u, pStack->size());
3773 }
3774 
TEST(HeapTest,AllocationDuringFinalization)3775 TEST(HeapTest, AllocationDuringFinalization)
3776 {
3777     HeapStats initialHeapSize;
3778     clearOutOldGarbage(&initialHeapSize);
3779     IntWrapper::s_destructorCalls = 0;
3780     OneKiloByteObject::s_destructorCalls = 0;
3781 
3782     Persistent<IntWrapper> wrapper;
3783     new FinalizationAllocator(&wrapper);
3784 
3785     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3786     EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3787     // Check that the wrapper allocated during finalization is not
3788     // swept away and zapped later in the same sweeping phase.
3789     EXPECT_EQ(42, wrapper->value());
3790 
3791     wrapper.clear();
3792     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3793     EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3794     EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3795 }
3796 
3797 class SimpleClassWithDestructor {
3798 public:
SimpleClassWithDestructor()3799     SimpleClassWithDestructor() { }
~SimpleClassWithDestructor()3800     ~SimpleClassWithDestructor()
3801     {
3802         s_wasDestructed = true;
3803     }
3804     static bool s_wasDestructed;
3805 };
3806 
3807 bool SimpleClassWithDestructor::s_wasDestructed;
3808 
3809 class RefCountedWithDestructor : public RefCounted<RefCountedWithDestructor> {
3810 public:
RefCountedWithDestructor()3811     RefCountedWithDestructor() { }
~RefCountedWithDestructor()3812     ~RefCountedWithDestructor()
3813     {
3814         s_wasDestructed = true;
3815     }
3816     static bool s_wasDestructed;
3817 };
3818 
3819 bool RefCountedWithDestructor::s_wasDestructed;
3820 
3821 template<typename Set>
destructorsCalledOnGC(bool addLots)3822 void destructorsCalledOnGC(bool addLots)
3823 {
3824     RefCountedWithDestructor::s_wasDestructed = false;
3825     {
3826         Set set;
3827         RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3828         set.add(adoptRef(hasDestructor));
3829         EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3830 
3831         if (addLots) {
3832             for (int i = 0; i < 1000; i++) {
3833                 set.add(adoptRef(new RefCountedWithDestructor()));
3834             }
3835         }
3836 
3837         EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3838         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
3839         EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3840     }
3841     // The destructors of the sets don't call the destructors of the elements
3842     // in the heap sets. You have to actually remove the elments, call clear()
3843     // or have a GC to get the destructors called.
3844     EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3845     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3846     EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3847 }
3848 
3849 template<typename Set>
destructorsCalledOnClear(bool addLots)3850 void destructorsCalledOnClear(bool addLots)
3851 {
3852     RefCountedWithDestructor::s_wasDestructed = false;
3853     Set set;
3854     RefCountedWithDestructor* hasDestructor = new RefCountedWithDestructor();
3855     set.add(adoptRef(hasDestructor));
3856     EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3857 
3858     if (addLots) {
3859         for (int i = 0; i < 1000; i++) {
3860             set.add(adoptRef(new RefCountedWithDestructor()));
3861         }
3862     }
3863 
3864     EXPECT_FALSE(RefCountedWithDestructor::s_wasDestructed);
3865     set.clear();
3866     EXPECT_TRUE(RefCountedWithDestructor::s_wasDestructed);
3867 }
3868 
TEST(HeapTest,DestructorsCalled)3869 TEST(HeapTest, DestructorsCalled)
3870 {
3871     HeapHashMap<SimpleClassWithDestructor*, OwnPtr<SimpleClassWithDestructor> > map;
3872     SimpleClassWithDestructor* hasDestructor = new SimpleClassWithDestructor();
3873     map.add(hasDestructor, adoptPtr(hasDestructor));
3874     SimpleClassWithDestructor::s_wasDestructed = false;
3875     map.clear();
3876     EXPECT_TRUE(SimpleClassWithDestructor::s_wasDestructed);
3877 
3878     destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3879     destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3880     destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3881     destructorsCalledOnClear<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3882     destructorsCalledOnClear<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3883     destructorsCalledOnClear<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3884 
3885     destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3886     destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3887     destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(false);
3888     destructorsCalledOnGC<HeapHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3889     destructorsCalledOnGC<HeapListHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3890     destructorsCalledOnGC<HeapLinkedHashSet<RefPtr<RefCountedWithDestructor> > >(true);
3891 }
3892 
3893 class MixinA : public GarbageCollectedMixin {
3894 public:
MixinA()3895     MixinA() : m_obj(IntWrapper::create(100)) { }
trace(Visitor * visitor)3896     virtual void trace(Visitor* visitor)
3897     {
3898         visitor->trace(m_obj);
3899     }
3900     Member<IntWrapper> m_obj;
3901 };
3902 
3903 class MixinB : public GarbageCollectedMixin {
3904 public:
MixinB()3905     MixinB() : m_obj(IntWrapper::create(101)) { }
trace(Visitor * visitor)3906     virtual void trace(Visitor* visitor)
3907     {
3908         visitor->trace(m_obj);
3909     }
3910     Member<IntWrapper> m_obj;
3911 };
3912 
3913 class MultipleMixins : public GarbageCollected<MultipleMixins>, public MixinA, public MixinB {
3914     USING_GARBAGE_COLLECTED_MIXIN(MultipleMixins);
3915 public:
MultipleMixins()3916     MultipleMixins() : m_obj(IntWrapper::create(102)) { }
trace(Visitor * visitor)3917     virtual void trace(Visitor* visitor)
3918     {
3919         visitor->trace(m_obj);
3920         MixinA::trace(visitor);
3921         MixinB::trace(visitor);
3922     }
3923     Member<IntWrapper> m_obj;
3924 };
3925 
3926 static const bool s_isMixinTrue = IsGarbageCollectedMixin<MultipleMixins>::value;
3927 static const bool s_isMixinFalse = IsGarbageCollectedMixin<IntWrapper>::value;
3928 
TEST(HeapTest,MultipleMixins)3929 TEST(HeapTest, MultipleMixins)
3930 {
3931     EXPECT_TRUE(s_isMixinTrue);
3932     EXPECT_FALSE(s_isMixinFalse);
3933 
3934     HeapStats initialHeapSize;
3935     clearOutOldGarbage(&initialHeapSize);
3936     IntWrapper::s_destructorCalls = 0;
3937     MultipleMixins* obj = new MultipleMixins();
3938     {
3939         Persistent<MixinA> a = obj;
3940         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3941         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3942     }
3943     {
3944         Persistent<MixinB> b = obj;
3945         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3946         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3947     }
3948     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3949     EXPECT_EQ(3, IntWrapper::s_destructorCalls);
3950 }
3951 
3952 class GCParkingThreadTester {
3953 public:
test()3954     static void test()
3955     {
3956         OwnPtr<WebThread> sleepingThread = adoptPtr(Platform::current()->createThread("SleepingThread"));
3957         sleepingThread->postTask(new Task(WTF::bind(sleeperMainFunc)));
3958 
3959         // Wait for the sleeper to run.
3960         while (!s_sleeperRunning) {
3961             Platform::current()->yieldCurrentThread();
3962         }
3963 
3964         {
3965             // Expect the first attempt to park the sleeping thread to fail
3966             TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3967             EXPECT_FALSE(scope.allThreadsParked());
3968         }
3969 
3970         s_sleeperDone = true;
3971 
3972         // Wait for the sleeper to finish.
3973         while (s_sleeperRunning) {
3974             // We enter the safepoint here since the sleeper thread will detach
3975             // causing it to GC.
3976             ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
3977             Platform::current()->yieldCurrentThread();
3978         }
3979 
3980         {
3981             // Since the sleeper thread has detached this is the only thread.
3982             TestGCScope scope(ThreadState::NoHeapPointersOnStack);
3983             EXPECT_TRUE(scope.allThreadsParked());
3984         }
3985     }
3986 
3987 private:
sleeperMainFunc()3988     static void sleeperMainFunc()
3989     {
3990         ThreadState::attach();
3991         s_sleeperRunning = true;
3992 
3993         // Simulate a long running op that is not entering a safepoint.
3994         while (!s_sleeperDone) {
3995             Platform::current()->yieldCurrentThread();
3996         }
3997 
3998         ThreadState::detach();
3999         s_sleeperRunning = false;
4000     }
4001 
4002     static volatile bool s_sleeperRunning;
4003     static volatile bool s_sleeperDone;
4004 };
4005 
4006 volatile bool GCParkingThreadTester::s_sleeperRunning = false;
4007 volatile bool GCParkingThreadTester::s_sleeperDone = false;
4008 
TEST(HeapTest,GCParkingTimeout)4009 TEST(HeapTest, GCParkingTimeout)
4010 {
4011     GCParkingThreadTester::test();
4012 }
4013 
TEST(HeapTest,NeedsAdjustAndMark)4014 TEST(HeapTest, NeedsAdjustAndMark)
4015 {
4016     // class Mixin : public GarbageCollectedMixin {};
4017     EXPECT_TRUE(NeedsAdjustAndMark<Mixin>::value);
4018     EXPECT_TRUE(NeedsAdjustAndMark<const Mixin>::value);
4019 
4020     // class SimpleObject : public GarbageCollected<SimpleObject> {};
4021     EXPECT_FALSE(NeedsAdjustAndMark<SimpleObject>::value);
4022     EXPECT_FALSE(NeedsAdjustAndMark<const SimpleObject>::value);
4023 
4024     // class UseMixin : public SimpleObject, public Mixin {};
4025     EXPECT_FALSE(NeedsAdjustAndMark<UseMixin>::value);
4026     EXPECT_FALSE(NeedsAdjustAndMark<const UseMixin>::value);
4027 }
4028 
4029 template<typename Set>
setWithCustomWeaknessHandling()4030 void setWithCustomWeaknessHandling()
4031 {
4032     typedef typename Set::iterator Iterator;
4033     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4034     Persistent<Set> set1(new Set());
4035     {
4036         Set set2;
4037         Set* set3 = new Set();
4038         set2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4039         set3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4040         set1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4041         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4042         // The first set is pointed to from a persistent, so it's referenced, but
4043         // the weak processing may have taken place.
4044         if (set1->size()) {
4045             Iterator i1 = set1->begin();
4046             EXPECT_EQ(4, i1->first->value());
4047             EXPECT_EQ(5, i1->second->value());
4048         }
4049         // The second set is on-stack, so its backing store must be referenced from
4050         // the stack. That makes the weak references strong.
4051         Iterator i2 = set2.begin();
4052         EXPECT_EQ(0, i2->first->value());
4053         EXPECT_EQ(1, i2->second->value());
4054         // The third set is pointed to from the stack, so it's referenced, but the
4055         // weak processing may have taken place.
4056         if (set3->size()) {
4057             Iterator i3 = set3->begin();
4058             EXPECT_EQ(2, i3->first->value());
4059             EXPECT_EQ(3, i3->second->value());
4060         }
4061     }
4062     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4063     EXPECT_EQ(0u, set1->size());
4064     set1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt));
4065     set1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4066     set1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4067     set1->add(PairWithWeakHandling(livingInt, livingInt));
4068     set1->add(PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4069     EXPECT_EQ(4u, set1->size());
4070     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4071     EXPECT_EQ(2u, set1->size());
4072     Iterator i1 = set1->begin();
4073     EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4074     EXPECT_EQ(livingInt, i1->second);
4075     ++i1;
4076     EXPECT_TRUE(i1->first->value() == 103 || i1->first == livingInt);
4077     EXPECT_EQ(livingInt, i1->second);
4078 }
4079 
TEST(HeapTest,SetWithCustomWeaknessHandling)4080 TEST(HeapTest, SetWithCustomWeaknessHandling)
4081 {
4082     setWithCustomWeaknessHandling<HeapHashSet<PairWithWeakHandling> >();
4083     setWithCustomWeaknessHandling<HeapLinkedHashSet<PairWithWeakHandling> >();
4084 }
4085 
TEST(HeapTest,MapWithCustomWeaknessHandling)4086 TEST(HeapTest, MapWithCustomWeaknessHandling)
4087 {
4088     typedef HeapHashMap<PairWithWeakHandling, RefPtr<OffHeapInt> > Map;
4089     typedef Map::iterator Iterator;
4090     HeapStats initialHeapSize;
4091     clearOutOldGarbage(&initialHeapSize);
4092     OffHeapInt::s_destructorCalls = 0;
4093 
4094     Persistent<Map> map1(new Map());
4095     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4096     {
4097         Map map2;
4098         Map* map3 = new Map();
4099         map2.add(PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)), OffHeapInt::create(1001));
4100         map3->add(PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)), OffHeapInt::create(1002));
4101         map1->add(PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)), OffHeapInt::create(1003));
4102         EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4103 
4104         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4105         // The first map2 is pointed to from a persistent, so it's referenced, but
4106         // the weak processing may have taken place.
4107         if (map1->size()) {
4108             Iterator i1 = map1->begin();
4109             EXPECT_EQ(4, i1->key.first->value());
4110             EXPECT_EQ(5, i1->key.second->value());
4111             EXPECT_EQ(1003, i1->value->value());
4112         }
4113         // The second map2 is on-stack, so its backing store must be referenced from
4114         // the stack. That makes the weak references strong.
4115         Iterator i2 = map2.begin();
4116         EXPECT_EQ(0, i2->key.first->value());
4117         EXPECT_EQ(1, i2->key.second->value());
4118         EXPECT_EQ(1001, i2->value->value());
4119         // The third map2 is pointed to from the stack, so it's referenced, but the
4120         // weak processing may have taken place.
4121         if (map3->size()) {
4122             Iterator i3 = map3->begin();
4123             EXPECT_EQ(2, i3->key.first->value());
4124             EXPECT_EQ(3, i3->key.second->value());
4125             EXPECT_EQ(1002, i3->value->value());
4126         }
4127     }
4128     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4129 
4130     EXPECT_EQ(0u, map1->size());
4131     EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4132 
4133     OffHeapInt::s_destructorCalls = 0;
4134 
4135     map1->add(PairWithWeakHandling(IntWrapper::create(103), livingInt), OffHeapInt::create(2000));
4136     map1->add(PairWithWeakHandling(livingInt, IntWrapper::create(103)), OffHeapInt::create(2001)); // This one gets zapped at GC time because nothing holds the 103 alive.
4137     map1->add(PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103)), OffHeapInt::create(2002)); // This one gets zapped too.
4138     RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4139     map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt);
4140     map1->add(PairWithWeakHandling(livingInt, livingInt), dupeInt); // This one is identical to the previous and doesn't add anything.
4141     dupeInt.clear();
4142 
4143     EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4144     EXPECT_EQ(4u, map1->size());
4145     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4146     EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4147     EXPECT_EQ(2u, map1->size());
4148     Iterator i1 = map1->begin();
4149     EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4150     EXPECT_EQ(livingInt, i1->key.second);
4151     ++i1;
4152     EXPECT_TRUE(i1->key.first->value() == 103 || i1->key.first == livingInt);
4153     EXPECT_EQ(livingInt, i1->key.second);
4154 }
4155 
TEST(HeapTest,MapWithCustomWeaknessHandling2)4156 TEST(HeapTest, MapWithCustomWeaknessHandling2)
4157 {
4158     typedef HeapHashMap<RefPtr<OffHeapInt>, PairWithWeakHandling> Map;
4159     typedef Map::iterator Iterator;
4160     HeapStats initialHeapSize;
4161     clearOutOldGarbage(&initialHeapSize);
4162     OffHeapInt::s_destructorCalls = 0;
4163 
4164     Persistent<Map> map1(new Map());
4165     Persistent<IntWrapper> livingInt(IntWrapper::create(42));
4166 
4167     {
4168         Map map2;
4169         Map* map3 = new Map();
4170         map2.add(OffHeapInt::create(1001), PairWithWeakHandling(IntWrapper::create(0), IntWrapper::create(1)));
4171         map3->add(OffHeapInt::create(1002), PairWithWeakHandling(IntWrapper::create(2), IntWrapper::create(3)));
4172         map1->add(OffHeapInt::create(1003), PairWithWeakHandling(IntWrapper::create(4), IntWrapper::create(5)));
4173         EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4174 
4175         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4176         // The first map2 is pointed to from a persistent, so it's referenced, but
4177         // the weak processing may have taken place.
4178         if (map1->size()) {
4179             Iterator i1 = map1->begin();
4180             EXPECT_EQ(4, i1->value.first->value());
4181             EXPECT_EQ(5, i1->value.second->value());
4182             EXPECT_EQ(1003, i1->key->value());
4183         }
4184         // The second map2 is on-stack, so its backing store must be referenced from
4185         // the stack. That makes the weak references strong.
4186         Iterator i2 = map2.begin();
4187         EXPECT_EQ(0, i2->value.first->value());
4188         EXPECT_EQ(1, i2->value.second->value());
4189         EXPECT_EQ(1001, i2->key->value());
4190         // The third map2 is pointed to from the stack, so it's referenced, but the
4191         // weak processing may have taken place.
4192         if (map3->size()) {
4193             Iterator i3 = map3->begin();
4194             EXPECT_EQ(2, i3->value.first->value());
4195             EXPECT_EQ(3, i3->value.second->value());
4196             EXPECT_EQ(1002, i3->key->value());
4197         }
4198     }
4199     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4200 
4201     EXPECT_EQ(0u, map1->size());
4202     EXPECT_EQ(3, OffHeapInt::s_destructorCalls);
4203 
4204     OffHeapInt::s_destructorCalls = 0;
4205 
4206     map1->add(OffHeapInt::create(2000), PairWithWeakHandling(IntWrapper::create(103), livingInt));
4207     map1->add(OffHeapInt::create(2001), PairWithWeakHandling(livingInt, IntWrapper::create(103))); // This one gets zapped at GC time because nothing holds the 103 alive.
4208     map1->add(OffHeapInt::create(2002), PairWithWeakHandling(IntWrapper::create(103), IntWrapper::create(103))); // This one gets zapped too.
4209     RefPtr<OffHeapInt> dupeInt(OffHeapInt::create(2003));
4210     map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt));
4211     map1->add(dupeInt, PairWithWeakHandling(livingInt, livingInt)); // This one is identical to the previous and doesn't add anything.
4212     dupeInt.clear();
4213 
4214     EXPECT_EQ(0, OffHeapInt::s_destructorCalls);
4215     EXPECT_EQ(4u, map1->size());
4216     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4217     EXPECT_EQ(2, OffHeapInt::s_destructorCalls);
4218     EXPECT_EQ(2u, map1->size());
4219     Iterator i1 = map1->begin();
4220     EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4221     EXPECT_EQ(livingInt, i1->value.second);
4222     ++i1;
4223     EXPECT_TRUE(i1->value.first->value() == 103 || i1->value.first == livingInt);
4224     EXPECT_EQ(livingInt, i1->value.second);
4225 }
4226 
addElementsToWeakMap(HeapHashMap<int,WeakMember<IntWrapper>> * map)4227 static void addElementsToWeakMap(HeapHashMap<int, WeakMember<IntWrapper> >* map)
4228 {
4229     // Key cannot be zero in hashmap.
4230     for (int i = 1; i < 11; i++)
4231         map->add(i, IntWrapper::create(i));
4232 }
4233 
4234 // crbug.com/402426
4235 // If it doesn't assert a concurrent modification to the map, then it's passing.
TEST(HeapTest,RegressNullIsStrongified)4236 TEST(HeapTest, RegressNullIsStrongified)
4237 {
4238     Persistent<HeapHashMap<int, WeakMember<IntWrapper> > > map = new HeapHashMap<int, WeakMember<IntWrapper> >();
4239     addElementsToWeakMap(map);
4240     HeapHashMap<int, WeakMember<IntWrapper> >::AddResult result = map->add(800, nullptr);
4241     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4242     result.storedValue->value = IntWrapper::create(42);
4243 }
4244 
TEST(HeapTest,Bind)4245 TEST(HeapTest, Bind)
4246 {
4247     Closure closure = bind(&Bar::trace, Bar::create(), static_cast<Visitor*>(0));
4248     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4249     // The closure should have a persistent handle to the Bar.
4250     EXPECT_EQ(1u, Bar::s_live);
4251 
4252     Closure closure2 = bind(&Bar::trace, RawPtr<Bar>(Bar::create()), static_cast<Visitor*>(0));
4253     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4254     // The closure should have a persistent handle to the Bar.
4255     EXPECT_EQ(2u, Bar::s_live);
4256     // RawPtr<OffHeapInt> should not make Persistent.
4257     Closure closure3 = bind(&OffHeapInt::voidFunction, RawPtr<OffHeapInt>(OffHeapInt::create(1).get()));
4258 
4259     UseMixin::s_traceCount = 0;
4260     Mixin* mixin = UseMixin::create();
4261     Closure mixinClosure = bind(&Mixin::trace, mixin, static_cast<Visitor*>(0));
4262     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4263     // The closure should have a persistent handle to the mixin.
4264     EXPECT_EQ(1, UseMixin::s_traceCount);
4265 }
4266 
4267 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
4268 
4269 // These special traits will remove a set from a map when the set is empty.
4270 struct EmptyClearingHashSetTraits : HashTraits<WeakSet> {
4271     static const WTF::WeakHandlingFlag weakHandlingFlag = WTF::WeakHandlingInCollections;
traceInCollectionblink::EmptyClearingHashSetTraits4272     static bool traceInCollection(Visitor* visitor, WeakSet& set, WTF::ShouldWeakPointersBeMarkedStrongly strongify)
4273     {
4274         bool liveEntriesFound = false;
4275         WeakSet::iterator end = set.end();
4276         for (WeakSet::iterator it = set.begin(); it != end; ++it) {
4277             if (visitor->isAlive(*it)) {
4278                 liveEntriesFound = true;
4279                 break;
4280             }
4281         }
4282         // If there are live entries in the set then the set cannot be removed
4283         // from the map it is contained in, and we need to mark it (and its
4284         // backing) live. We just trace normally, which will invoke the normal
4285         // weak handling for any entries that are not live.
4286         if (liveEntriesFound)
4287             set.trace(visitor);
4288         return !liveEntriesFound;
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>, EmptyClearingHashSetTraits> 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     EXPECT_EQ(0u, map->size());
4338 }
4339 
TEST(HeapTest,EphemeronsInEphemerons)4340 TEST(HeapTest, EphemeronsInEphemerons)
4341 {
4342     typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > InnerMap;
4343     typedef HeapHashMap<WeakMember<IntWrapper>, InnerMap> OuterMap;
4344 
4345     for (int keepOuterAlive = 0; keepOuterAlive <= 1; keepOuterAlive++) {
4346         for (int keepInnerAlive = 0; keepInnerAlive <=1; keepInnerAlive++) {
4347             Persistent<OuterMap> outer = new OuterMap();
4348             Persistent<IntWrapper> one = IntWrapper::create(1);
4349             Persistent<IntWrapper> two = IntWrapper::create(2);
4350             outer->add(one, InnerMap());
4351             outer->begin()->value.add(two, IntWrapper::create(3));
4352             EXPECT_EQ(1u, outer->get(one).size());
4353             if (!keepOuterAlive)
4354                 one.clear();
4355             if (!keepInnerAlive)
4356                 two.clear();
4357             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4358             if (keepOuterAlive) {
4359                 const InnerMap& inner = outer->get(one);
4360                 if (keepInnerAlive) {
4361                     EXPECT_EQ(1u, inner.size());
4362                     IntWrapper* three = inner.get(two);
4363                     EXPECT_EQ(3, three->value());
4364                 } else {
4365                     EXPECT_EQ(0u, inner.size());
4366                 }
4367             } else {
4368                 EXPECT_EQ(0u, outer->size());
4369             }
4370             outer->clear();
4371             Persistent<IntWrapper> deep = IntWrapper::create(42);
4372             Persistent<IntWrapper> home = IntWrapper::create(103);
4373             Persistent<IntWrapper> composite = IntWrapper::create(91);
4374             Persistent<HeapVector<Member<IntWrapper> > > keepAlive = new HeapVector<Member<IntWrapper> >();
4375             for (int i = 0; i < 10000; i++) {
4376                 IntWrapper* value = IntWrapper::create(i);
4377                 keepAlive->append(value);
4378                 OuterMap::AddResult newEntry = outer->add(value, InnerMap());
4379                 newEntry.storedValue->value.add(deep, home);
4380                 newEntry.storedValue->value.add(composite, home);
4381             }
4382             composite.clear();
4383             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4384             EXPECT_EQ(10000u, outer->size());
4385             for (int i = 0; i < 10000; i++) {
4386                 IntWrapper* value = keepAlive->at(i);
4387                 EXPECT_EQ(1u, outer->get(value).size()); // Other one was deleted by weak handling.
4388                 if (i & 1)
4389                     keepAlive->at(i) = nullptr;
4390             }
4391             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4392             EXPECT_EQ(5000u, outer->size());
4393         }
4394     }
4395 }
4396 
4397 class EphemeronWrapper : public GarbageCollected<EphemeronWrapper> {
4398 public:
trace(Visitor * visitor)4399     void trace(Visitor* visitor)
4400     {
4401         visitor->trace(m_map);
4402     }
4403 
4404     typedef HeapHashMap<WeakMember<IntWrapper>, Member<EphemeronWrapper> > Map;
map()4405     Map& map() { return m_map; }
4406 
4407 private:
4408     Map m_map;
4409 };
4410 
TEST(HeapTest,EphemeronsPointToEphemerons)4411 TEST(HeapTest, EphemeronsPointToEphemerons)
4412 {
4413     Persistent<IntWrapper> key = IntWrapper::create(42);
4414     Persistent<IntWrapper> key2 = IntWrapper::create(103);
4415 
4416     Persistent<EphemeronWrapper> chain;
4417     for (int i = 0; i < 100; i++) {
4418         EphemeronWrapper* oldHead = chain;
4419         chain = new EphemeronWrapper();
4420         if (i == 50)
4421             chain->map().add(key2, oldHead);
4422         else
4423             chain->map().add(key, oldHead);
4424         chain->map().add(IntWrapper::create(103), new EphemeronWrapper());
4425     }
4426 
4427     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4428 
4429     EphemeronWrapper* wrapper = chain;
4430     for (int i = 0; i< 100; i++) {
4431         EXPECT_EQ(1u, wrapper->map().size());
4432         if (i == 49)
4433             wrapper = wrapper->map().get(key2);
4434         else
4435             wrapper = wrapper->map().get(key);
4436     }
4437     EXPECT_EQ(nullptr, wrapper);
4438 
4439     key2.clear();
4440     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4441 
4442     wrapper = chain;
4443     for (int i = 0; i < 50; i++) {
4444         EXPECT_EQ(i == 49 ? 0u : 1u, wrapper->map().size());
4445         wrapper = wrapper->map().get(key);
4446     }
4447     EXPECT_EQ(nullptr, wrapper);
4448 
4449     key.clear();
4450     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4451     EXPECT_EQ(0u, chain->map().size());
4452 }
4453 
TEST(HeapTest,Ephemeron)4454 TEST(HeapTest, Ephemeron)
4455 {
4456     typedef HeapHashMap<WeakMember<IntWrapper>, PairWithWeakHandling>  WeakPairMap;
4457     typedef HeapHashMap<PairWithWeakHandling, WeakMember<IntWrapper> >  PairWeakMap;
4458     typedef HeapHashSet<WeakMember<IntWrapper> > Set;
4459 
4460     Persistent<WeakPairMap> weakPairMap = new WeakPairMap();
4461     Persistent<WeakPairMap> weakPairMap2 = new WeakPairMap();
4462     Persistent<WeakPairMap> weakPairMap3 = new WeakPairMap();
4463     Persistent<WeakPairMap> weakPairMap4 = new WeakPairMap();
4464 
4465     Persistent<PairWeakMap> pairWeakMap = new PairWeakMap();
4466     Persistent<PairWeakMap> pairWeakMap2 = new PairWeakMap();
4467 
4468     Persistent<Set> set = new Set();
4469 
4470     Persistent<IntWrapper> wp1 = IntWrapper::create(1);
4471     Persistent<IntWrapper> wp2 = IntWrapper::create(2);
4472     Persistent<IntWrapper> pw1 = IntWrapper::create(3);
4473     Persistent<IntWrapper> pw2 = IntWrapper::create(4);
4474 
4475     weakPairMap->add(wp1, PairWithWeakHandling(wp1, wp1));
4476     weakPairMap->add(wp2, PairWithWeakHandling(wp1, wp1));
4477     weakPairMap2->add(wp1, PairWithWeakHandling(wp1, wp2));
4478     weakPairMap2->add(wp2, PairWithWeakHandling(wp1, wp2));
4479     // The map from wp1 to (wp2, wp1) would mark wp2 live, so we skip that.
4480     weakPairMap3->add(wp2, PairWithWeakHandling(wp2, wp1));
4481     weakPairMap4->add(wp1, PairWithWeakHandling(wp2, wp2));
4482     weakPairMap4->add(wp2, PairWithWeakHandling(wp2, wp2));
4483 
4484     pairWeakMap->add(PairWithWeakHandling(pw1, pw1), pw1);
4485     pairWeakMap->add(PairWithWeakHandling(pw1, pw2), pw1);
4486     // The map from (pw2, pw1) to pw1 would make pw2 live, so we skip that.
4487     pairWeakMap->add(PairWithWeakHandling(pw2, pw2), pw1);
4488     pairWeakMap2->add(PairWithWeakHandling(pw1, pw1), pw2);
4489     pairWeakMap2->add(PairWithWeakHandling(pw1, pw2), pw2);
4490     pairWeakMap2->add(PairWithWeakHandling(pw2, pw1), pw2);
4491     pairWeakMap2->add(PairWithWeakHandling(pw2, pw2), pw2);
4492 
4493 
4494     set->add(wp1);
4495     set->add(wp2);
4496     set->add(pw1);
4497     set->add(pw2);
4498 
4499     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4500 
4501     EXPECT_EQ(2u, weakPairMap->size());
4502     EXPECT_EQ(2u, weakPairMap2->size());
4503     EXPECT_EQ(1u, weakPairMap3->size());
4504     EXPECT_EQ(2u, weakPairMap4->size());
4505 
4506     EXPECT_EQ(3u, pairWeakMap->size());
4507     EXPECT_EQ(4u, pairWeakMap2->size());
4508 
4509     EXPECT_EQ(4u, set->size());
4510 
4511     wp2.clear(); // Kills all entries in the weakPairMaps except the first.
4512     pw2.clear(); // Kills all entries in the pairWeakMaps except the first.
4513 
4514     for (int i = 0; i < 2; i++) {
4515         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4516 
4517         EXPECT_EQ(1u, weakPairMap->size());
4518         EXPECT_EQ(0u, weakPairMap2->size());
4519         EXPECT_EQ(0u, weakPairMap3->size());
4520         EXPECT_EQ(0u, weakPairMap4->size());
4521 
4522         EXPECT_EQ(1u, pairWeakMap->size());
4523         EXPECT_EQ(0u, pairWeakMap2->size());
4524 
4525         EXPECT_EQ(2u, set->size()); // wp1 and pw1.
4526     }
4527 
4528     wp1.clear();
4529     pw1.clear();
4530 
4531     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4532 
4533     EXPECT_EQ(0u, weakPairMap->size());
4534     EXPECT_EQ(0u, pairWeakMap->size());
4535     EXPECT_EQ(0u, set->size());
4536 }
4537 
4538 class Link1 : public GarbageCollected<Link1> {
4539 public:
Link1(IntWrapper * link)4540     Link1(IntWrapper* link) : m_link(link) { }
4541 
trace(Visitor * visitor)4542     void trace(Visitor* visitor)
4543     {
4544         visitor->trace(m_link);
4545     }
4546 
link()4547     IntWrapper* link() { return m_link; }
4548 
4549 private:
4550     Member<IntWrapper> m_link;
4551 };
4552 
TEST(HeapTest,IndirectStrongToWeak)4553 TEST(HeapTest, IndirectStrongToWeak)
4554 {
4555     typedef HeapHashMap<WeakMember<IntWrapper>, Member<Link1> > Map;
4556     Persistent<Map> map = new Map();
4557     Persistent<IntWrapper> deadObject = IntWrapper::create(100); // Named for "Drowning by Numbers" (1988).
4558     Persistent<IntWrapper> lifeObject = IntWrapper::create(42);
4559     map->add(deadObject, new Link1(deadObject));
4560     map->add(lifeObject, new Link1(lifeObject));
4561     EXPECT_EQ(2u, map->size());
4562     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4563     EXPECT_EQ(2u, map->size());
4564     EXPECT_EQ(deadObject, map->get(deadObject)->link());
4565     EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4566     deadObject.clear(); // Now it can live up to its name.
4567     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4568     EXPECT_EQ(1u, map->size());
4569     EXPECT_EQ(lifeObject, map->get(lifeObject)->link());
4570     lifeObject.clear(); // Despite its name.
4571     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4572     EXPECT_EQ(0u, map->size());
4573 }
4574 
mainThreadMutex()4575 static Mutex& mainThreadMutex()
4576 {
4577     AtomicallyInitializedStatic(Mutex&, mainMutex = *new Mutex);
4578     return mainMutex;
4579 }
4580 
mainThreadCondition()4581 static ThreadCondition& mainThreadCondition()
4582 {
4583     AtomicallyInitializedStatic(ThreadCondition&, mainCondition = *new ThreadCondition);
4584     return mainCondition;
4585 }
4586 
parkMainThread()4587 static void parkMainThread()
4588 {
4589     mainThreadCondition().wait(mainThreadMutex());
4590 }
4591 
wakeMainThread()4592 static void wakeMainThread()
4593 {
4594     MutexLocker locker(mainThreadMutex());
4595     mainThreadCondition().signal();
4596 }
4597 
workerThreadMutex()4598 static Mutex& workerThreadMutex()
4599 {
4600     AtomicallyInitializedStatic(Mutex&, workerMutex = *new Mutex);
4601     return workerMutex;
4602 }
4603 
workerThreadCondition()4604 static ThreadCondition& workerThreadCondition()
4605 {
4606     AtomicallyInitializedStatic(ThreadCondition&, workerCondition = *new ThreadCondition);
4607     return workerCondition;
4608 }
4609 
parkWorkerThread()4610 static void parkWorkerThread()
4611 {
4612     workerThreadCondition().wait(workerThreadMutex());
4613 }
4614 
wakeWorkerThread()4615 static void wakeWorkerThread()
4616 {
4617     MutexLocker locker(workerThreadMutex());
4618     workerThreadCondition().signal();
4619 }
4620 
4621 class CrossThreadObject : public GarbageCollectedFinalized<CrossThreadObject> {
4622 public:
create(IntWrapper * workerObjectPointer)4623     static CrossThreadObject* create(IntWrapper* workerObjectPointer)
4624     {
4625         return new CrossThreadObject(workerObjectPointer);
4626     }
4627 
~CrossThreadObject()4628     virtual ~CrossThreadObject()
4629     {
4630         ++s_destructorCalls;
4631     }
4632 
4633     static int s_destructorCalls;
trace(Visitor * visitor)4634     void trace(Visitor* visitor) { visitor->trace(m_workerObject); }
4635 
4636 private:
CrossThreadObject(IntWrapper * workerObjectPointer)4637     CrossThreadObject(IntWrapper* workerObjectPointer) : m_workerObject(workerObjectPointer) { }
4638 
4639 private:
4640     Member<IntWrapper> m_workerObject;
4641 };
4642 
4643 int CrossThreadObject::s_destructorCalls = 0;
4644 
4645 class CrossThreadPointerTester {
4646 public:
test()4647     static void test()
4648     {
4649         CrossThreadObject::s_destructorCalls = 0;
4650         IntWrapper::s_destructorCalls = 0;
4651 
4652         MutexLocker locker(mainThreadMutex());
4653         OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4654         workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4655 
4656         parkMainThread();
4657 
4658         uintptr_t stackPtrValue = 0;
4659         {
4660             // Create an object with a pointer to the other heap's IntWrapper.
4661             Persistent<CrossThreadObject> cto = CrossThreadObject::create(const_cast<IntWrapper*>(s_workerObjectPointer));
4662             s_workerObjectPointer = 0;
4663 
4664             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4665 
4666             // Nothing should have been collected/destructed.
4667             EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4668             EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4669 
4670             // Put cto into a stack value. This is used to check that a conservative
4671             // GC succeeds even though we are tracing the other thread heap after
4672             // shutting it down.
4673             stackPtrValue = reinterpret_cast<uintptr_t>(cto.get());
4674         }
4675         // At this point it is "programatically" okay to shut down the worker thread
4676         // since the cto object should be dead. However out stackPtrValue will cause a
4677         // trace of the object when doing a conservative GC.
4678         // The worker thread's thread local GC's should just add the worker thread's
4679         // pages to the heap after finalizing IntWrapper.
4680         wakeWorkerThread();
4681 
4682         // Wait for the worker to shutdown.
4683         parkMainThread();
4684 
4685         // After the worker thread has detached it should have finalized the
4686         // IntWrapper object on its heaps. Since there has been no global GC
4687         // the cto object should not have been finalized.
4688         EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4689         EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4690 
4691         // Now do a conservative GC. The stackPtrValue should keep cto alive
4692         // and will also cause the orphaned page of the other thread to be
4693         // traced. At this point cto should still not be finalized.
4694         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4695         EXPECT_EQ(0, CrossThreadObject::s_destructorCalls);
4696         EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4697 
4698         // This release assert is here to ensure the stackValuePtr is not
4699         // optimized away before doing the above conservative GC. If the
4700         // EXPECT_EQ(0, CrossThreadObject::s_destructorCalls) call above
4701         // starts failing it means we have to find a better way to ensure
4702         // the stackPtrValue is not optimized away.
4703         RELEASE_ASSERT(stackPtrValue);
4704 
4705         // Do a GC with no pointers on the stack to see the cto being collected.
4706         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4707         EXPECT_EQ(1, CrossThreadObject::s_destructorCalls);
4708         EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4709     }
4710 
4711 private:
workerThreadMain()4712     static void workerThreadMain()
4713     {
4714         MutexLocker locker(workerThreadMutex());
4715         ThreadState::attach();
4716 
4717         {
4718             // Create a worker object that is only kept alive by a cross thread
4719             // pointer (from CrossThreadObject).
4720             IntWrapper* workerObject = IntWrapper::create(42);
4721             s_workerObjectPointer = workerObject;
4722         }
4723 
4724         // Wake up the main thread which is waiting for the worker to do its
4725         // allocation and passing the pointer.
4726         wakeMainThread();
4727 
4728         // Wait for main thread to signal the worker to shutdown.
4729         {
4730             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4731             parkWorkerThread();
4732         }
4733 
4734         ThreadState::detach();
4735 
4736         // Tell the main thread the worker has done its shutdown.
4737         wakeMainThread();
4738     }
4739 
4740     static volatile IntWrapper* s_workerObjectPointer;
4741 };
4742 
4743 volatile IntWrapper* CrossThreadPointerTester::s_workerObjectPointer = 0;
4744 
TEST(HeapTest,CrossThreadPointerToOrphanedPage)4745 TEST(HeapTest, CrossThreadPointerToOrphanedPage)
4746 {
4747     CrossThreadPointerTester::test();
4748 }
4749 
4750 class DeadBitTester {
4751 public:
test()4752     static void test()
4753     {
4754         IntWrapper::s_destructorCalls = 0;
4755 
4756         MutexLocker locker(mainThreadMutex());
4757         OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4758         workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4759 
4760         // Wait for the worker thread to have done its initialization,
4761         // IE. the worker allocates an object and then throw aways any
4762         // pointers to it.
4763         parkMainThread();
4764 
4765         // Now do a GC. This will not find the worker threads object since it
4766         // is not referred from any of the threads. Even a conservative
4767         // GC will not find it.
4768         // Also at this point the worker is waiting for the main thread
4769         // to be parked and will not do any sweep of its heap.
4770         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4771 
4772         // Since the worker thread is not sweeping the worker object should
4773         // not have been finalized.
4774         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4775 
4776         // Put the worker thread's object address on the stack and do a
4777         // conservative GC. This should find the worker object, but since
4778         // it was dead in the previous GC it should not be traced in this
4779         // GC.
4780         uintptr_t stackPtrValue = s_workerObjectPointer;
4781         s_workerObjectPointer = 0;
4782         ASSERT_UNUSED(stackPtrValue, stackPtrValue);
4783         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4784 
4785         // Since the worker thread is not sweeping the worker object should
4786         // not have been finalized.
4787         EXPECT_EQ(0, IntWrapper::s_destructorCalls);
4788 
4789         // Wake up the worker thread so it can continue with its sweeping.
4790         // This should finalized the worker object which we test below.
4791         // The worker thread will go back to sleep once sweeping to ensure
4792         // we don't have thread local GCs until after validating the destructor
4793         // was called.
4794         wakeWorkerThread();
4795 
4796         // Wait for the worker thread to sweep its heaps before checking.
4797         parkMainThread();
4798         EXPECT_EQ(1, IntWrapper::s_destructorCalls);
4799 
4800         // Wake up the worker to allow it thread to continue with thread
4801         // shutdown.
4802         wakeWorkerThread();
4803     }
4804 
4805 private:
4806 
workerThreadMain()4807     static void workerThreadMain()
4808     {
4809         MutexLocker locker(workerThreadMutex());
4810 
4811         ThreadState::attach();
4812 
4813         {
4814             // Create a worker object that is not kept alive except the
4815             // main thread will keep it as an integer value on its stack.
4816             IntWrapper* workerObject = IntWrapper::create(42);
4817             s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject);
4818         }
4819 
4820         // Signal the main thread that the worker is done with its allocation.
4821         wakeMainThread();
4822 
4823         {
4824             // Wait for the main thread to do two GCs without sweeping this thread
4825             // heap. The worker waits within a safepoint, but there is no sweeping
4826             // until leaving the safepoint scope.
4827             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4828             parkWorkerThread();
4829         }
4830 
4831         // Wake up the main thread when done sweeping.
4832         wakeMainThread();
4833 
4834         // Wait with detach until the main thread says so. This is not strictly
4835         // necessary, but it means the worker thread will not do its thread local
4836         // GCs just yet, making it easier to reason about that no new GC has occurred
4837         // and the above sweep was the one finalizing the worker object.
4838         parkWorkerThread();
4839 
4840         ThreadState::detach();
4841     }
4842 
4843     static volatile uintptr_t s_workerObjectPointer;
4844 };
4845 
4846 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0;
4847 
TEST(HeapTest,ObjectDeadBit)4848 TEST(HeapTest, ObjectDeadBit)
4849 {
4850     DeadBitTester::test();
4851 }
4852 
4853 class ThreadedStrongificationTester {
4854 public:
test()4855     static void test()
4856     {
4857         IntWrapper::s_destructorCalls = 0;
4858 
4859         MutexLocker locker(mainThreadMutex());
4860         OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
4861         workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
4862 
4863         // Wait for the worker thread initialization. The worker
4864         // allocates a weak collection where both collection and
4865         // contents are kept alive via persistent pointers.
4866         parkMainThread();
4867 
4868         // Perform two garbage collections where the worker thread does
4869         // not wake up in between. This will cause us to remove marks
4870         // and mark unmarked objects dead. The collection on the worker
4871         // heap is found through the persistent and the backing should
4872         // be marked.
4873         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4874         Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4875 
4876         // Wake up the worker thread so it can continue. It will sweep
4877         // and perform another GC where the backing store of its
4878         // collection should be strongified.
4879         wakeWorkerThread();
4880 
4881         // Wait for the worker thread to sweep its heaps before checking.
4882         {
4883             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4884             parkMainThread();
4885         }
4886     }
4887 
4888 private:
4889 
allocateCollection()4890     static HeapHashSet<WeakMember<IntWrapper> >* allocateCollection()
4891     {
4892         // Create a weak collection that is kept alive by a persistent
4893         // and keep the contents alive with a persistents as
4894         // well.
4895         Persistent<IntWrapper> wrapper1 = IntWrapper::create(32);
4896         Persistent<IntWrapper> wrapper2 = IntWrapper::create(32);
4897         Persistent<IntWrapper> wrapper3 = IntWrapper::create(32);
4898         Persistent<IntWrapper> wrapper4 = IntWrapper::create(32);
4899         Persistent<IntWrapper> wrapper5 = IntWrapper::create(32);
4900         Persistent<IntWrapper> wrapper6 = IntWrapper::create(32);
4901         Persistent<HeapHashSet<WeakMember<IntWrapper> > > weakCollection = new HeapHashSet<WeakMember<IntWrapper> >;
4902         weakCollection->add(wrapper1);
4903         weakCollection->add(wrapper2);
4904         weakCollection->add(wrapper3);
4905         weakCollection->add(wrapper4);
4906         weakCollection->add(wrapper5);
4907         weakCollection->add(wrapper6);
4908 
4909         // Signal the main thread that the worker is done with its allocation.
4910         wakeMainThread();
4911 
4912         {
4913             // Wait for the main thread to do two GCs without sweeping
4914             // this thread heap. The worker waits within a safepoint,
4915             // but there is no sweeping until leaving the safepoint
4916             // scope. If the weak collection backing is marked dead
4917             // because of this we will not get strongification in the
4918             // GC we force when we continue.
4919             ThreadState::SafePointScope scope(ThreadState::NoHeapPointersOnStack);
4920             parkWorkerThread();
4921         }
4922 
4923         return weakCollection;
4924     }
4925 
workerThreadMain()4926     static void workerThreadMain()
4927     {
4928         MutexLocker locker(workerThreadMutex());
4929 
4930         ThreadState::attach();
4931 
4932         {
4933             Persistent<HeapHashSet<WeakMember<IntWrapper> > > collection = allocateCollection();
4934             {
4935                 // Prevent weak processing with an iterator and GC.
4936                 HeapHashSet<WeakMember<IntWrapper> >::iterator it = collection->begin();
4937                 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4938 
4939                 // The backing should be strongified because of the iterator.
4940                 EXPECT_EQ(6u, collection->size());
4941                 EXPECT_EQ(32, (*it)->value());
4942             }
4943 
4944             // Disregarding the iterator but keeping the collection alive
4945             // with a persistent should lead to weak processing.
4946             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4947             EXPECT_EQ(0u, collection->size());
4948         }
4949 
4950         wakeMainThread();
4951         ThreadState::detach();
4952     }
4953 
4954     static volatile uintptr_t s_workerObjectPointer;
4955 };
4956 
TEST(HeapTest,ThreadedStrongification)4957 TEST(HeapTest, ThreadedStrongification)
4958 {
4959     ThreadedStrongificationTester::test();
4960 }
4961 
allocateAndReturnBool()4962 static bool allocateAndReturnBool()
4963 {
4964     Heap::collectGarbage(ThreadState::HeapPointersOnStack);
4965     return true;
4966 }
4967 
4968 class MixinWithGarbageCollectionInConstructor : public GarbageCollectedMixin {
4969 public:
MixinWithGarbageCollectionInConstructor()4970     MixinWithGarbageCollectionInConstructor() : m_dummy(allocateAndReturnBool())
4971     {
4972     }
4973 private:
4974     bool m_dummy;
4975 };
4976 
4977 class ClassWithGarbageCollectingMixinConstructor
4978     : public GarbageCollected<ClassWithGarbageCollectingMixinConstructor>
4979     , public MixinWithGarbageCollectionInConstructor {
4980     USING_GARBAGE_COLLECTED_MIXIN(ClassWithGarbageCollectingMixinConstructor);
4981 public:
ClassWithGarbageCollectingMixinConstructor()4982     ClassWithGarbageCollectingMixinConstructor() : m_wrapper(IntWrapper::create(32))
4983     {
4984     }
4985 
trace(Visitor * visitor)4986     virtual void trace(Visitor* visitor)
4987     {
4988         visitor->trace(m_wrapper);
4989     }
4990 
verify()4991     void verify()
4992     {
4993         EXPECT_EQ(32, m_wrapper->value());
4994     }
4995 
4996 private:
4997     Member<IntWrapper> m_wrapper;
4998 };
4999 
5000 // Regression test for out of bounds call through vtable.
5001 // Passes if it doesn't crash.
TEST(HeapTest,GarbageCollectionDuringMixinConstruction)5002 TEST(HeapTest, GarbageCollectionDuringMixinConstruction)
5003 {
5004     ClassWithGarbageCollectingMixinConstructor* a =
5005         new ClassWithGarbageCollectingMixinConstructor();
5006     a->verify();
5007 }
5008 
recursiveMutex()5009 static RecursiveMutex& recursiveMutex()
5010 {
5011     AtomicallyInitializedStatic(RecursiveMutex&, recursiveMutex = *new RecursiveMutex);
5012     return recursiveMutex;
5013 }
5014 
5015 class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLockingObject> {
5016 public:
create()5017     static DestructorLockingObject* create()
5018     {
5019         return new DestructorLockingObject();
5020     }
5021 
~DestructorLockingObject()5022     virtual ~DestructorLockingObject()
5023     {
5024         SafePointAwareMutexLocker lock(recursiveMutex());
5025         ++s_destructorCalls;
5026     }
5027 
5028     static int s_destructorCalls;
trace(Visitor * visitor)5029     void trace(Visitor* visitor) { }
5030 
5031 private:
DestructorLockingObject()5032     DestructorLockingObject() { }
5033 };
5034 
5035 int DestructorLockingObject::s_destructorCalls = 0;
5036 
5037 class RecursiveLockingTester {
5038 public:
test()5039     static void test()
5040     {
5041         DestructorLockingObject::s_destructorCalls = 0;
5042 
5043         MutexLocker locker(mainThreadMutex());
5044         OwnPtr<WebThread> workerThread = adoptPtr(Platform::current()->createThread("Test Worker Thread"));
5045         workerThread->postTask(new Task(WTF::bind(workerThreadMain)));
5046 
5047         // Park the main thread until the worker thread has initialized.
5048         parkMainThread();
5049 
5050         {
5051             SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
5052 
5053             // Let the worker try to acquire the above mutex. It won't get it
5054             // until the main thread has done its GC.
5055             wakeWorkerThread();
5056 
5057             Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5058 
5059             // The worker thread should not have swept yet since it is waiting
5060             // to get the global mutex.
5061             EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
5062         }
5063         // At this point the main thread releases the global lock and the worker
5064         // can acquire it and do its sweep of its heaps. Just wait for the worker
5065         // to complete its sweep and check the result.
5066         parkMainThread();
5067         EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
5068     }
5069 
5070 private:
workerThreadMain()5071     static void workerThreadMain()
5072     {
5073         MutexLocker locker(workerThreadMutex());
5074         ThreadState::attach();
5075 
5076         DestructorLockingObject* dlo = DestructorLockingObject::create();
5077         ASSERT_UNUSED(dlo, dlo);
5078 
5079         // Wake up the main thread which is waiting for the worker to do its
5080         // allocation.
5081         wakeMainThread();
5082 
5083         // Wait for the main thread to get the global lock to ensure it has
5084         // it before the worker tries to acquire it. We want the worker to
5085         // block in the SafePointAwareMutexLocker until the main thread
5086         // has done a GC. The GC will not mark the "dlo" object since the worker
5087         // is entering the safepoint with NoHeapPointersOnStack. When the worker
5088         // subsequently gets the global lock and leaves the safepoint it will
5089         // sweep its heap and finalize "dlo". The destructor of "dlo" will try
5090         // to acquire the same global lock that the thread just got and deadlock
5091         // unless the global lock is recursive.
5092         parkWorkerThread();
5093         SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState::NoHeapPointersOnStack);
5094 
5095         // We won't get here unless the lock is recursive since the sweep done
5096         // in the constructor of SafePointAwareMutexLocker after
5097         // getting the lock will not complete given the "dlo" destructor is
5098         // waiting to get the same lock.
5099         // Tell the main thread the worker has done its sweep.
5100         wakeMainThread();
5101 
5102         ThreadState::detach();
5103     }
5104 
5105     static volatile IntWrapper* s_workerObjectPointer;
5106 };
5107 
TEST(HeapTest,RecursiveMutex)5108 TEST(HeapTest, RecursiveMutex)
5109 {
5110     RecursiveLockingTester::test();
5111 }
5112 
5113 template<typename T>
5114 class TraceIfNeededTester : public GarbageCollectedFinalized<TraceIfNeededTester<T> > {
5115 public:
create()5116     static TraceIfNeededTester<T>* create() { return new TraceIfNeededTester<T>(); }
create(const T & obj)5117     static TraceIfNeededTester<T>* create(const T& obj) { return new TraceIfNeededTester<T>(obj); }
trace(Visitor * visitor)5118     void trace(Visitor* visitor) { TraceIfNeeded<T>::trace(visitor, &m_obj); }
obj()5119     T& obj() { return m_obj; }
~TraceIfNeededTester()5120     ~TraceIfNeededTester() { }
5121 private:
TraceIfNeededTester()5122     TraceIfNeededTester() { }
TraceIfNeededTester(const T & obj)5123     explicit TraceIfNeededTester(const T& obj) : m_obj(obj) { }
5124     T m_obj;
5125 };
5126 
5127 class PartObject {
5128     DISALLOW_ALLOCATION();
5129 public:
PartObject()5130     PartObject() : m_obj(SimpleObject::create()) { }
trace(Visitor * visitor)5131     void trace(Visitor* visitor) { visitor->trace(m_obj); }
5132 private:
5133     Member<SimpleObject> m_obj;
5134 };
5135 
TEST(HeapTest,TraceIfNeeded)5136 TEST(HeapTest, TraceIfNeeded)
5137 {
5138     CountingVisitor visitor;
5139 
5140     {
5141         TraceIfNeededTester<RefPtr<OffHeapInt> >* m_offHeap = TraceIfNeededTester<RefPtr<OffHeapInt> >::create(OffHeapInt::create(42));
5142         visitor.reset();
5143         m_offHeap->trace(&visitor);
5144         EXPECT_EQ(0u, visitor.count());
5145     }
5146 
5147     {
5148         TraceIfNeededTester<PartObject>* m_part = TraceIfNeededTester<PartObject>::create();
5149         visitor.reset();
5150         m_part->trace(&visitor);
5151         EXPECT_EQ(1u, visitor.count());
5152     }
5153 
5154     {
5155         TraceIfNeededTester<Member<SimpleObject> >* m_obj = TraceIfNeededTester<Member<SimpleObject> >::create(Member<SimpleObject>(SimpleObject::create()));
5156         visitor.reset();
5157         m_obj->trace(&visitor);
5158         EXPECT_EQ(1u, visitor.count());
5159     }
5160 
5161     {
5162         TraceIfNeededTester<HeapVector<Member<SimpleObject> > >* m_vec = TraceIfNeededTester<HeapVector<Member<SimpleObject> > >::create();
5163         m_vec->obj().append(SimpleObject::create());
5164         visitor.reset();
5165         m_vec->trace(&visitor);
5166         EXPECT_EQ(2u, visitor.count());
5167     }
5168 }
5169 
5170 class AllocatesOnAssignment {
5171 public:
AllocatesOnAssignment(std::nullptr_t)5172     AllocatesOnAssignment(std::nullptr_t)
5173         : m_value(nullptr)
5174     { }
AllocatesOnAssignment(int x)5175     AllocatesOnAssignment(int x)
5176         : m_value(new IntWrapper(x))
5177     { }
AllocatesOnAssignment(IntWrapper * x)5178     AllocatesOnAssignment(IntWrapper* x)
5179         : m_value(x)
5180     { }
5181 
operator =(const AllocatesOnAssignment x)5182     AllocatesOnAssignment& operator=(const AllocatesOnAssignment x)
5183     {
5184         m_value = x.m_value;
5185         return *this;
5186     }
5187 
5188     enum DeletedMarker {
5189         DeletedValue
5190     };
5191 
AllocatesOnAssignment(const AllocatesOnAssignment & other)5192     AllocatesOnAssignment(const AllocatesOnAssignment& other)
5193     {
5194         Heap::collectGarbage(ThreadState::HeapPointersOnStack);
5195         m_value = new IntWrapper(other.m_value->value());
5196     }
5197 
AllocatesOnAssignment(DeletedMarker)5198     AllocatesOnAssignment(DeletedMarker)
5199         : m_value(reinterpret_cast<IntWrapper*>(-1)) { }
5200 
isDeleted() const5201     inline bool isDeleted() const { return m_value == reinterpret_cast<IntWrapper*>(-1); }
5202 
trace(Visitor * visitor)5203     virtual void trace(Visitor* visitor)
5204     {
5205         visitor->trace(m_value);
5206     }
5207 
value()5208     int value() { return m_value->value(); }
5209 
5210 private:
5211     Member<IntWrapper> m_value;
5212 
5213     friend bool operator==(const AllocatesOnAssignment&, const AllocatesOnAssignment&);
5214     friend void swap(AllocatesOnAssignment&, AllocatesOnAssignment&);
5215 };
5216 
operator ==(const AllocatesOnAssignment & a,const AllocatesOnAssignment & b)5217 bool operator==(const AllocatesOnAssignment& a, const AllocatesOnAssignment& b)
5218 {
5219     if (a.m_value)
5220         return b.m_value && a.m_value->value() == b.m_value->value();
5221     return !b.m_value;
5222 }
5223 
swap(AllocatesOnAssignment & a,AllocatesOnAssignment & b)5224 void swap(AllocatesOnAssignment& a, AllocatesOnAssignment& b)
5225 {
5226     std::swap(a.m_value, b.m_value);
5227 }
5228 
5229 struct DegenerateHash {
hashblink::DegenerateHash5230     static unsigned hash(const AllocatesOnAssignment&) { return 0; }
equalblink::DegenerateHash5231     static bool equal(const AllocatesOnAssignment& a, const AllocatesOnAssignment& b) { return !a.isDeleted() && a == b; }
5232     static const bool safeToCompareToEmptyOrDeleted = true;
5233 };
5234 
5235 struct AllocatesOnAssignmentHashTraits : WTF::GenericHashTraits<AllocatesOnAssignment> {
5236     typedef AllocatesOnAssignment T;
5237     typedef std::nullptr_t EmptyValueType;
emptyValueblink::AllocatesOnAssignmentHashTraits5238     static EmptyValueType emptyValue() { return nullptr; }
5239     static const bool emptyValueIsZero = false; // Can't be zero if it has a vtable.
5240     static const bool needsDestruction = false;
constructDeletedValueblink::AllocatesOnAssignmentHashTraits5241     static void constructDeletedValue(T& slot, bool) { slot = T(AllocatesOnAssignment::DeletedValue); }
isDeletedValueblink::AllocatesOnAssignmentHashTraits5242     static bool isDeletedValue(const T& value) { return value.isDeleted(); }
5243 };
5244 
5245 } // namespace blink
5246 
5247 namespace WTF {
5248 
5249 template<> struct DefaultHash<blink::AllocatesOnAssignment> {
5250     typedef blink::DegenerateHash Hash;
5251 };
5252 
5253 template <> struct HashTraits<blink::AllocatesOnAssignment> : blink::AllocatesOnAssignmentHashTraits { };
5254 
5255 } // namespace WTF
5256 
5257 namespace blink {
5258 
TEST(HeapTest,GCInHashMapOperations)5259 TEST(HeapTest, GCInHashMapOperations)
5260 {
5261     typedef HeapHashMap<AllocatesOnAssignment, AllocatesOnAssignment> Map;
5262     Map* map = new Map();
5263     IntWrapper* key = new IntWrapper(42);
5264     map->add(key, AllocatesOnAssignment(103));
5265     map->remove(key);
5266     for (int i = 0; i < 10; i++)
5267         map->add(AllocatesOnAssignment(i), AllocatesOnAssignment(i));
5268     for (Map::iterator it = map->begin(); it != map->end(); ++it)
5269         EXPECT_EQ(it->key.value(), it->value.value());
5270 }
5271 
5272 class PartObjectWithVirtualMethod {
5273 public:
trace(Visitor *)5274     virtual void trace(Visitor*) { }
5275 };
5276 
5277 class ObjectWithVirtualPartObject : public GarbageCollected<ObjectWithVirtualPartObject> {
5278 public:
ObjectWithVirtualPartObject()5279     ObjectWithVirtualPartObject() : m_dummy(allocateAndReturnBool()) { }
trace(Visitor * visitor)5280     void trace(Visitor* visitor) { visitor->trace(m_part); }
5281 private:
5282     bool m_dummy;
5283     PartObjectWithVirtualMethod m_part;
5284 };
5285 
TEST(HeapTest,PartObjectWithVirtualMethod)5286 TEST(HeapTest, PartObjectWithVirtualMethod)
5287 {
5288     ObjectWithVirtualPartObject* object = new ObjectWithVirtualPartObject();
5289     EXPECT_TRUE(object);
5290 }
5291 
5292 class AllocInSuperConstructorArgumentSuper : public GarbageCollectedFinalized<AllocInSuperConstructorArgumentSuper> {
5293 public:
AllocInSuperConstructorArgumentSuper(bool value)5294     AllocInSuperConstructorArgumentSuper(bool value) : m_value(value) { }
trace(Visitor *)5295     virtual void trace(Visitor*) { }
value()5296     bool value() { return m_value; }
5297 private:
5298     bool m_value;
5299 };
5300 
5301 class AllocInSuperConstructorArgument : public AllocInSuperConstructorArgumentSuper {
5302 public:
AllocInSuperConstructorArgument()5303     AllocInSuperConstructorArgument()
5304         : AllocInSuperConstructorArgumentSuper(allocateAndReturnBool())
5305     {
5306     }
5307 };
5308 
5309 // Regression test for crbug.com/404511. Tests conservative marking of
5310 // an object with an uninitialized vtable.
TEST(HeapTest,AllocationInSuperConstructorArgument)5311 TEST(HeapTest, AllocationInSuperConstructorArgument)
5312 {
5313     AllocInSuperConstructorArgument* object = new AllocInSuperConstructorArgument();
5314     EXPECT_TRUE(object);
5315     Heap::collectAllGarbage();
5316 }
5317 
5318 class NonNodeAllocatingNodeInDestructor : public GarbageCollectedFinalized<NonNodeAllocatingNodeInDestructor> {
5319 public:
~NonNodeAllocatingNodeInDestructor()5320     ~NonNodeAllocatingNodeInDestructor()
5321     {
5322         s_node = new Persistent<Node>(Node::create(10));
5323     }
5324 
trace(Visitor *)5325     void trace(Visitor*) { }
5326 
5327     static Persistent<Node>* s_node;
5328 };
5329 
5330 Persistent<Node>* NonNodeAllocatingNodeInDestructor::s_node = 0;
5331 
TEST(HeapTest,NonNodeAllocatingNodeInDestructor)5332 TEST(HeapTest, NonNodeAllocatingNodeInDestructor)
5333 {
5334     new NonNodeAllocatingNodeInDestructor();
5335     Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
5336     EXPECT_EQ(10, (*NonNodeAllocatingNodeInDestructor::s_node)->value());
5337     delete NonNodeAllocatingNodeInDestructor::s_node;
5338     NonNodeAllocatingNodeInDestructor::s_node = 0;
5339 }
5340 
5341 } // namespace blink
5342