blob: 55c02897339210f1bcf493a0f381655c4be1f686 [file] [log] [blame]
Torne (Richard Coles)a854de02013-12-18 16:25:25 +00001/*
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
Torne (Richard Coles)09380292014-02-21 12:17:33 +000033#include "heap/Handle.h"
Torne (Richard Coles)a854de02013-12-18 16:25:25 +000034#include "heap/Heap.h"
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +000035#include "heap/HeapLinkedStack.h"
36#include "heap/HeapTerminatedArrayBuilder.h"
Torne (Richard Coles)09380292014-02-21 12:17:33 +000037#include "heap/ThreadState.h"
38#include "heap/Visitor.h"
Torne (Richard Coles)a854de02013-12-18 16:25:25 +000039
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +000040#include "wtf/HashTraits.h"
41
Torne (Richard Coles)a854de02013-12-18 16:25:25 +000042#include <gtest/gtest.h>
43
Torne (Richard Coles)09380292014-02-21 12:17:33 +000044namespace WebCore {
Torne (Richard Coles)a854de02013-12-18 16:25:25 +000045
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +000046class ThreadMarker {
47public:
48 ThreadMarker() : m_creatingThread(reinterpret_cast<ThreadState*>(0)), m_num(0) { }
49 ThreadMarker(unsigned i) : m_creatingThread(ThreadState::current()), m_num(i) { }
50 ThreadMarker(WTF::HashTableDeletedValueType deleted) : m_creatingThread(reinterpret_cast<ThreadState*>(-1)), m_num(0) { }
51 ~ThreadMarker()
52 {
53 EXPECT_TRUE((m_creatingThread == ThreadState::current())
54 || (m_creatingThread == reinterpret_cast<ThreadState*>(0))
55 || (m_creatingThread == reinterpret_cast<ThreadState*>(-1)));
56 }
57 bool isHashTableDeletedValue() const { return m_creatingThread == reinterpret_cast<ThreadState*>(-1); }
58 bool operator==(const ThreadMarker& other) const { return other.m_creatingThread == m_creatingThread && other.m_num == m_num; }
59 ThreadState* m_creatingThread;
60 unsigned m_num;
61};
62
63struct ThreadMarkerHash {
64 static unsigned hash(const ThreadMarker& key)
65 {
66 return static_cast<unsigned>(reinterpret_cast<uintptr_t>(key.m_creatingThread) + key.m_num);
67 }
68
69 static bool equal(const ThreadMarker& a, const ThreadMarker& b)
70 {
71 return a == b;
72 }
73
74 static const bool safeToCompareToEmptyOrDeleted = false;
75};
76
77}
78
79namespace WTF {
80
81template<typename T> struct DefaultHash;
82template<> struct DefaultHash<WebCore::ThreadMarker> {
83 typedef WebCore::ThreadMarkerHash Hash;
84};
85
86// ThreadMarkerHash is the default hash for ThreadMarker
87template<> struct HashTraits<WebCore::ThreadMarker> : GenericHashTraits<WebCore::ThreadMarker> {
88 static const bool emptyValueIsZero = true;
89 static void constructDeletedValue(WebCore::ThreadMarker& slot) { new (NotNull, &slot) WebCore::ThreadMarker(HashTableDeletedValue); }
90 static bool isDeletedValue(const WebCore::ThreadMarker& slot) { return slot.isHashTableDeletedValue(); }
91};
92
93}
94
95namespace WebCore {
96
Torne (Richard Coles)09380292014-02-21 12:17:33 +000097class TestGCScope {
98public:
99 explicit TestGCScope(ThreadState::StackState state)
100 : m_state(ThreadState::current())
101 , m_safePointScope(state)
102 {
103 m_state->checkThread();
104 ASSERT(!m_state->isInGC());
105 ThreadState::stopThreads();
106 m_state->enterGC();
107 }
Torne (Richard Coles)a854de02013-12-18 16:25:25 +0000108
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000109 ~TestGCScope()
110 {
111 m_state->leaveGC();
112 ASSERT(!m_state->isInGC());
113 ThreadState::resumeThreads();
114 }
115
116private:
117 ThreadState* m_state;
118 ThreadState::SafePointScope m_safePointScope;
119};
120
121static void getHeapStats(HeapStats* stats)
Torne (Richard Coles)a854de02013-12-18 16:25:25 +0000122{
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000123 TestGCScope scope(ThreadState::NoHeapPointersOnStack);
124 Heap::getStats(stats);
Torne (Richard Coles)a854de02013-12-18 16:25:25 +0000125}
126
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000127#define DEFINE_VISITOR_METHODS(Type) \
128 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
129 { \
130 if (object) \
131 m_count++; \
132 } \
133 virtual bool isMarked(const Type*) OVERRIDE { return false; }
134
135class CountingVisitor : public Visitor {
136public:
137 CountingVisitor()
138 : m_count(0)
139 {
140 }
141
142 virtual void mark(const void* object, TraceCallback) OVERRIDE
143 {
144 if (object)
145 m_count++;
146 }
147
148 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
149 {
150 ASSERT(header->payload());
151 m_count++;
152 }
153
154 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
155 {
156 ASSERT(header->payload());
157 m_count++;
158 }
159
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000160 virtual void registerWeakMembers(const void*, const void*, WeakPointerCallback) OVERRIDE { }
161 virtual void registerWeakCell(void**, WeakPointerCallback) OVERRIDE { }
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000162 virtual bool isMarked(const void*) OVERRIDE { return false; }
163
164 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
165
166 size_t count() { return m_count; }
167 void reset() { m_count = 0; }
168
169private:
170 size_t m_count;
171};
172
173class SimpleObject : public GarbageCollected<SimpleObject> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000174public:
175 static SimpleObject* create() { return new SimpleObject(); }
176 void trace(Visitor*) { }
177 char getPayload(int i) { return payload[i]; }
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000178protected:
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000179 SimpleObject() { }
180 char payload[64];
181};
182
183#undef DEFINE_VISITOR_METHODS
184
185class HeapTestSuperClass : public GarbageCollectedFinalized<HeapTestSuperClass> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000186public:
187 static HeapTestSuperClass* create()
188 {
189 return new HeapTestSuperClass();
190 }
191
192 virtual ~HeapTestSuperClass()
193 {
194 ++s_destructorCalls;
195 }
196
197 static int s_destructorCalls;
198 void trace(Visitor*) { }
199
200protected:
201 HeapTestSuperClass() { }
202};
203
204int HeapTestSuperClass::s_destructorCalls = 0;
205
206class HeapTestOtherSuperClass {
207public:
208 int payload;
209};
210
211static const size_t classMagic = 0xABCDDBCA;
212
213class HeapTestSubClass : public HeapTestOtherSuperClass, public HeapTestSuperClass {
214public:
215 static HeapTestSubClass* create()
216 {
217 return new HeapTestSubClass();
218 }
219
220 virtual ~HeapTestSubClass()
221 {
222 EXPECT_EQ(classMagic, m_magic);
223 ++s_destructorCalls;
224 }
225
226 static int s_destructorCalls;
227
228private:
229
230 HeapTestSubClass() : m_magic(classMagic) { }
231
232 const size_t m_magic;
233};
234
235int HeapTestSubClass::s_destructorCalls = 0;
236
237class HeapAllocatedArray : public GarbageCollected<HeapAllocatedArray> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000238public:
239 HeapAllocatedArray()
240 {
241 for (int i = 0; i < s_arraySize; ++i) {
242 m_array[i] = i % 128;
243 }
244 }
245
246 int8_t at(size_t i) { return m_array[i]; }
247 void trace(Visitor*) { }
248private:
249 static const int s_arraySize = 1000;
250 int8_t m_array[s_arraySize];
251};
252
253// Do several GCs to make sure that later GCs don't free up old memory from
254// previously run tests in this process.
255static void clearOutOldGarbage(HeapStats* heapStats)
256{
257 while (true) {
258 getHeapStats(heapStats);
259 size_t used = heapStats->totalObjectSpace();
260 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
261 getHeapStats(heapStats);
262 if (heapStats->totalObjectSpace() >= used)
263 break;
264 }
265}
266
267class IntWrapper : public GarbageCollectedFinalized<IntWrapper> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000268public:
269 static IntWrapper* create(int x)
270 {
271 return new IntWrapper(x);
272 }
273
274 virtual ~IntWrapper()
275 {
276 ++s_destructorCalls;
277 }
278
279 static int s_destructorCalls;
280 static void trace(Visitor*) { }
281
282 int value() const { return m_x; }
283
284 bool operator==(const IntWrapper& other) const { return other.value() == value(); }
285
286 unsigned hash() { return IntHash<int>::hash(m_x); }
287
288protected:
289 IntWrapper(int x) : m_x(x) { }
290
291private:
292 IntWrapper();
293 int m_x;
294};
295
296USED_FROM_MULTIPLE_THREADS(IntWrapper);
297
298int IntWrapper::s_destructorCalls = 0;
299
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000300class ThreadedTesterBase {
301protected:
302 static void test(ThreadedTesterBase* tester)
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000303 {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000304 for (int i = 0; i < numberOfThreads; i++)
305 createThread(&threadFunc, tester, "testing thread");
306 while (tester->m_threadsToFinish) {
307 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
308 yield();
309 }
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000310 delete tester;
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000311 }
312
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000313 virtual void runThread() = 0;
314
315protected:
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000316 static const int numberOfThreads = 10;
317 static const int gcPerThread = 5;
318 static const int numberOfAllocations = 50;
319
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000320 ThreadedTesterBase() : m_gcCount(0), m_threadsToFinish(numberOfThreads)
321 {
322 }
323
324 virtual ~ThreadedTesterBase()
325 {
326 }
327
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000328 inline bool done() const { return m_gcCount >= numberOfThreads * gcPerThread; }
329
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000330 volatile int m_gcCount;
331 volatile int m_threadsToFinish;
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000332
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000333private:
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000334 static void threadFunc(void* data)
335 {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000336 reinterpret_cast<ThreadedTesterBase*>(data)->runThread();
337 }
338};
339
340class ThreadedHeapTester : public ThreadedTesterBase {
341public:
342 static void test()
343 {
344 ThreadedTesterBase::test(new ThreadedHeapTester);
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000345 }
346
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000347protected:
348 virtual void runThread() OVERRIDE
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000349 {
350 ThreadState::attach();
351
352 int gcCount = 0;
353 while (!done()) {
354 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
355 {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000356 Persistent<IntWrapper> wrapper;
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000357
358 typedef Persistent<IntWrapper, GlobalPersistents> GlobalIntWrapperPersistent;
359 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
360
361 for (int i = 0; i < numberOfAllocations; i++) {
362 wrapper = IntWrapper::create(0x0bbac0de);
363 if (!(i % 10)) {
364 globalPersistent = adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(0x0ed0cabb)));
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000365 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000366 }
367 yield();
368 }
369
370 if (gcCount < gcPerThread) {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000371 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000372 gcCount++;
373 atomicIncrement(&m_gcCount);
374 }
375
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000376 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000377 EXPECT_EQ(wrapper->value(), 0x0bbac0de);
378 EXPECT_EQ((*globalPersistent)->value(), 0x0ed0cabb);
379 }
380 yield();
381 }
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000382 ThreadState::detach();
383 atomicDecrement(&m_threadsToFinish);
384 }
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000385};
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000386
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000387class ThreadedWeaknessTester : public ThreadedTesterBase {
388public:
389 static void test()
390 {
391 ThreadedTesterBase::test(new ThreadedWeaknessTester);
392 }
393
394private:
395 virtual void runThread() OVERRIDE
396 {
397 ThreadState::attach();
398
399 int gcCount = 0;
400 while (!done()) {
401 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
402 {
403 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper> > > weakMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper> >;
404 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper> > weakMap2;
405
406 for (int i = 0; i < numberOfAllocations; i++) {
407 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0));
408 weakMap2.add(static_cast<unsigned>(i), IntWrapper::create(0));
409 if (!(i % 10)) {
410 ThreadState::current()->safePoint(ThreadState::NoHeapPointersOnStack);
411 }
412 yield();
413 }
414
415 if (gcCount < gcPerThread) {
416 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
417 gcCount++;
418 atomicIncrement(&m_gcCount);
419 }
420
421 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
422 EXPECT_TRUE(weakMap->isEmpty());
423 EXPECT_TRUE(weakMap2.isEmpty());
424 }
425 yield();
426 }
427 ThreadState::detach();
428 atomicDecrement(&m_threadsToFinish);
429 }
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000430};
431
432// The accounting for memory includes the memory used by rounding up object
433// sizes. This is done in a different way on 32 bit and 64 bit, so we have to
434// have some slack in the tests.
435template<typename T>
436void CheckWithSlack(T expected, T actual, int slack)
437{
438 EXPECT_LE(expected, actual);
439 EXPECT_GE((intptr_t)expected + slack, (intptr_t)actual);
440}
441
442class TraceCounter : public GarbageCollectedFinalized<TraceCounter> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000443public:
444 static TraceCounter* create()
445 {
446 return new TraceCounter();
447 }
448
449 void trace(Visitor*) { m_traceCount++; }
450
451 int traceCount() { return m_traceCount; }
452
453private:
454 TraceCounter()
455 : m_traceCount(0)
456 {
457 }
458
459 int m_traceCount;
460};
461
462class ClassWithMember : public GarbageCollected<ClassWithMember> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000463public:
464 static ClassWithMember* create()
465 {
466 return new ClassWithMember();
467 }
468
469 void trace(Visitor* visitor)
470 {
471 EXPECT_TRUE(visitor->isMarked(this));
472 if (!traceCount())
473 EXPECT_FALSE(visitor->isMarked(m_traceCounter));
474 else
475 EXPECT_TRUE(visitor->isMarked(m_traceCounter));
476
477 visitor->trace(m_traceCounter);
478 }
479
480 int traceCount() { return m_traceCounter->traceCount(); }
481
482private:
483 ClassWithMember()
484 : m_traceCounter(TraceCounter::create())
485 { }
486
487 Member<TraceCounter> m_traceCounter;
488};
489
490class SimpleFinalizedObject : public GarbageCollectedFinalized<SimpleFinalizedObject> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000491public:
492 static SimpleFinalizedObject* create()
493 {
494 return new SimpleFinalizedObject();
495 }
496
497 ~SimpleFinalizedObject()
498 {
499 ++s_destructorCalls;
500 }
501
502 static int s_destructorCalls;
503
504 void trace(Visitor*) { }
505
506private:
507 SimpleFinalizedObject() { }
508};
509
510int SimpleFinalizedObject::s_destructorCalls = 0;
511
512class TestTypedHeapClass : public GarbageCollected<TestTypedHeapClass> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000513public:
514 static TestTypedHeapClass* create()
515 {
516 return new TestTypedHeapClass();
517 }
518
519 void trace(Visitor*) { }
520
521private:
522 TestTypedHeapClass() { }
523};
524
525class Bar : public GarbageCollectedFinalized<Bar> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000526public:
527 static Bar* create()
528 {
529 return new Bar();
530 }
531
532 void finalize()
533 {
534 EXPECT_TRUE(m_magic == magic);
535 m_magic = 0;
536 s_live--;
537 }
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000538 bool hasBeenFinalized() const { return !m_magic; }
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000539
540 virtual void trace(Visitor* visitor) { }
541 static unsigned s_live;
542
543protected:
544 static const int magic = 1337;
545 int m_magic;
546
547 Bar()
548 : m_magic(magic)
549 {
550 s_live++;
551 }
552};
553
554unsigned Bar::s_live = 0;
555
556class Baz : public GarbageCollected<Baz> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000557public:
558 static Baz* create(Bar* bar)
559 {
560 return new Baz(bar);
561 }
562
563 void trace(Visitor* visitor)
564 {
565 visitor->trace(m_bar);
566 }
567
568 void clear() { m_bar.release(); }
569
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000570 // willFinalize is called by FinalizationObserver.
571 void willFinalize()
572 {
573 EXPECT_TRUE(!m_bar->hasBeenFinalized());
574 }
575
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000576private:
577 explicit Baz(Bar* bar)
578 : m_bar(bar)
579 {
580 }
581
582 Member<Bar> m_bar;
583};
584
585class Foo : public Bar {
586public:
587 static Foo* create(Bar* bar)
588 {
589 return new Foo(bar);
590 }
591
592 static Foo* create(Foo* foo)
593 {
594 return new Foo(foo);
595 }
596
597 virtual void trace(Visitor* visitor) OVERRIDE
598 {
599 if (m_pointsToFoo)
600 visitor->mark(static_cast<Foo*>(m_bar));
601 else
602 visitor->mark(m_bar);
603 }
604
605private:
606 Foo(Bar* bar)
607 : Bar()
608 , m_bar(bar)
609 , m_pointsToFoo(false)
610 {
611 }
612
613 Foo(Foo* foo)
614 : Bar()
615 , m_bar(foo)
616 , m_pointsToFoo(true)
617 {
618 }
619
620 Bar* m_bar;
621 bool m_pointsToFoo;
622};
623
624class Bars : public Bar {
625public:
626 static Bars* create()
627 {
628 return new Bars();
629 }
630
631 virtual void trace(Visitor* visitor) OVERRIDE
632 {
633 for (unsigned i = 0; i < m_width; i++)
634 visitor->trace(m_bars[i]);
635 }
636
637 unsigned getWidth() const
638 {
639 return m_width;
640 }
641
642 static const unsigned width = 7500;
643private:
644 Bars() : m_width(0)
645 {
646 for (unsigned i = 0; i < width; i++) {
647 m_bars[i] = Bar::create();
648 m_width++;
649 }
650 }
651
652 unsigned m_width;
653 Member<Bar> m_bars[width];
654};
655
656class ConstructorAllocation : public GarbageCollected<ConstructorAllocation> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000657public:
658 static ConstructorAllocation* create() { return new ConstructorAllocation(); }
659
660 void trace(Visitor* visitor) { visitor->trace(m_intWrapper); }
661
662private:
663 ConstructorAllocation()
664 {
665 m_intWrapper = IntWrapper::create(42);
666 }
667
668 Member<IntWrapper> m_intWrapper;
669};
670
671class LargeObject : public GarbageCollectedFinalized<LargeObject> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000672public:
673 ~LargeObject()
674 {
675 s_destructorCalls++;
676 }
677 static LargeObject* create() { return new LargeObject(); }
678 char get(size_t i) { return m_data[i]; }
679 void set(size_t i, char c) { m_data[i] = c; }
680 size_t length() { return s_length; }
681 void trace(Visitor* visitor)
682 {
683 visitor->trace(m_intWrapper);
684 }
685 static int s_destructorCalls;
686
687private:
688 static const size_t s_length = 1024*1024;
689 LargeObject()
690 {
691 m_intWrapper = IntWrapper::create(23);
692 }
693 Member<IntWrapper> m_intWrapper;
694 char m_data[s_length];
695};
696
697int LargeObject::s_destructorCalls = 0;
698
699class RefCountedAndGarbageCollected : public RefCountedGarbageCollected<RefCountedAndGarbageCollected> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000700public:
701 static PassRefPtr<RefCountedAndGarbageCollected> create()
702 {
703 return adoptRef(new RefCountedAndGarbageCollected());
704 }
705
706 ~RefCountedAndGarbageCollected()
707 {
708 ++s_destructorCalls;
709 }
710
711 void trace(Visitor*) { }
712
713 static int s_destructorCalls;
714
715private:
716 RefCountedAndGarbageCollected()
717 {
718 }
719};
720
721int RefCountedAndGarbageCollected::s_destructorCalls = 0;
722
723class RefCountedAndGarbageCollected2 : public HeapTestOtherSuperClass, public RefCountedGarbageCollected<RefCountedAndGarbageCollected2> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000724public:
725 static RefCountedAndGarbageCollected2* create()
726 {
727 return adoptRefCountedGarbageCollected(new RefCountedAndGarbageCollected2());
728 }
729
730 ~RefCountedAndGarbageCollected2()
731 {
732 ++s_destructorCalls;
733 }
734
735 void trace(Visitor*) { }
736
737 static int s_destructorCalls;
738
739private:
740 RefCountedAndGarbageCollected2()
741 {
742 }
743};
744
745int RefCountedAndGarbageCollected2::s_destructorCalls = 0;
746
747#define DEFINE_VISITOR_METHODS(Type) \
748 virtual void mark(const Type* object, TraceCallback callback) OVERRIDE \
749 { \
750 mark(object); \
751 } \
752
753class RefCountedGarbageCollectedVisitor : public CountingVisitor {
754public:
755 RefCountedGarbageCollectedVisitor(int expected, void** objects)
756 : m_count(0)
757 , m_expectedCount(expected)
758 , m_expectedObjects(objects)
759 {
760 }
761
762 void mark(const void* ptr) { markNoTrace(ptr); }
763
764 virtual void markNoTrace(const void* ptr)
765 {
766 if (!ptr)
767 return;
768 if (m_count < m_expectedCount)
769 EXPECT_TRUE(expectedObject(ptr));
770 else
771 EXPECT_FALSE(expectedObject(ptr));
772 m_count++;
773 }
774
775 virtual void mark(const void* ptr, TraceCallback) OVERRIDE
776 {
777 mark(ptr);
778 }
779
780 virtual void mark(HeapObjectHeader* header, TraceCallback callback) OVERRIDE
781 {
782 mark(header->payload());
783 }
784
785 virtual void mark(FinalizedHeapObjectHeader* header, TraceCallback callback) OVERRIDE
786 {
787 mark(header->payload());
788 }
789
790 bool validate() { return m_count >= m_expectedCount; }
791 void reset() { m_count = 0; }
792
793 FOR_EACH_TYPED_HEAP(DEFINE_VISITOR_METHODS)
794
795private:
796 bool expectedObject(const void* ptr)
797 {
798 for (int i = 0; i < m_expectedCount; i++) {
799 if (m_expectedObjects[i] == ptr)
800 return true;
801 }
802 return false;
803 }
804
805 int m_count;
806 int m_expectedCount;
807 void** m_expectedObjects;
808};
809
810#undef DEFINE_VISITOR_METHODS
811
812class Weak : public Bar {
813public:
814 static Weak* create(Bar* strong, Bar* weak)
815 {
816 return new Weak(strong, weak);
817 }
818
819 virtual void trace(Visitor* visitor) OVERRIDE
820 {
821 visitor->trace(m_strongBar);
822 visitor->registerWeakMembers(this, zapWeakMembers);
823 }
824
825 static void zapWeakMembers(Visitor* visitor, void* self)
826 {
827 reinterpret_cast<Weak*>(self)->zapWeakMembers(visitor);
828 }
829
830 bool strongIsThere() { return !!m_strongBar; }
831 bool weakIsThere() { return !!m_weakBar; }
832
833private:
834 Weak(Bar* strongBar, Bar* weakBar)
835 : Bar()
836 , m_strongBar(strongBar)
837 , m_weakBar(weakBar)
838 {
839 }
840
841 void zapWeakMembers(Visitor* visitor)
842 {
843 if (m_weakBar && !visitor->isAlive(m_weakBar))
844 m_weakBar = 0;
845 }
846
847 Member<Bar> m_strongBar;
848 Bar* m_weakBar;
849};
850
851class WithWeakMember : public Bar {
852public:
853 static WithWeakMember* create(Bar* strong, Bar* weak)
854 {
855 return new WithWeakMember(strong, weak);
856 }
857
858 virtual void trace(Visitor* visitor) OVERRIDE
859 {
860 visitor->trace(m_strongBar);
861 visitor->trace(m_weakBar);
862 }
863
864 bool strongIsThere() { return !!m_strongBar; }
865 bool weakIsThere() { return !!m_weakBar; }
866
867private:
868 WithWeakMember(Bar* strongBar, Bar* weakBar)
869 : Bar()
870 , m_strongBar(strongBar)
871 , m_weakBar(weakBar)
872 {
873 }
874
875 Member<Bar> m_strongBar;
876 WeakMember<Bar> m_weakBar;
877};
878
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000879class Observable : public GarbageCollectedFinalized<Observable> {
880public:
881 static Observable* create(Bar* bar) { return new Observable(bar); }
882 ~Observable() { m_wasDestructed = true; }
883 void trace(Visitor* visitor) { visitor->trace(m_bar); }
884
885 // willFinalize is called by FinalizationObserver. willFinalize can touch
886 // other on-heap objects.
887 void willFinalize()
888 {
889 EXPECT_FALSE(m_wasDestructed);
890 EXPECT_FALSE(m_bar->hasBeenFinalized());
891 }
892
893private:
894 explicit Observable(Bar* bar)
895 : m_bar(bar)
896 , m_wasDestructed(false)
897 {
898 }
899
900 Member<Bar> m_bar;
901 bool m_wasDestructed;
902};
903
904template <typename T> class FinalizationObserver : public GarbageCollected<FinalizationObserver<T> > {
905public:
906 static FinalizationObserver* create(T* data) { return new FinalizationObserver(data); }
907 bool didCallWillFinalize() const { return m_didCallWillFinalize; }
908
909 void trace(Visitor* visitor)
910 {
911 visitor->registerWeakMembers(this, zapWeakMembers);
912 }
913
914private:
915 FinalizationObserver(T* data)
916 : m_data(data)
917 , m_didCallWillFinalize(false)
918 {
919 }
920
921 static void zapWeakMembers(Visitor* visitor, void* self)
922 {
923 FinalizationObserver* o = reinterpret_cast<FinalizationObserver*>(self);
924 if (o->m_data && !visitor->isAlive(o->m_data)) {
925 o->m_data->willFinalize();
926 o->m_data = nullptr;
927 o->m_didCallWillFinalize = true;
928 }
929 }
930
931 WeakMember<T> m_data;
932 bool m_didCallWillFinalize;
933};
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000934
935class SuperClass;
936
937class PointsBack : public RefCountedWillBeGarbageCollectedFinalized<PointsBack> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000938public:
939 static PassRefPtrWillBeRawPtr<PointsBack> create()
940 {
941 return adoptRefWillBeNoop(new PointsBack());
942 }
943
944 ~PointsBack()
945 {
946 --s_aliveCount;
947 }
948
949 void setBackPointer(SuperClass* backPointer)
950 {
951 m_backPointer = backPointer;
952 }
953
954 SuperClass* backPointer() const { return m_backPointer; }
955
956 void trace(Visitor* visitor)
957 {
958#if ENABLE_OILPAN
959 visitor->trace(m_backPointer);
960#endif
961 }
962
963 static int s_aliveCount;
964private:
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +0000965 PointsBack() : m_backPointer(nullptr)
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000966 {
967 ++s_aliveCount;
968 }
969
970 RawPtrWillBeWeakMember<SuperClass> m_backPointer;
971};
972
973int PointsBack::s_aliveCount = 0;
974
975class SuperClass : public RefCountedWillBeGarbageCollectedFinalized<SuperClass> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +0000976public:
977 static PassRefPtrWillBeRawPtr<SuperClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
978 {
979 return adoptRefWillBeNoop(new SuperClass(pointsBack));
980 }
981
982 virtual ~SuperClass()
983 {
984#if !ENABLE_OILPAN
985 m_pointsBack->setBackPointer(0);
986#endif
987 --s_aliveCount;
988 }
989
990 void doStuff(PassRefPtrWillBeRawPtr<SuperClass> targetPass, PointsBack* pointsBack, int superClassCount)
991 {
992 RefPtrWillBeRawPtr<SuperClass> target = targetPass;
993 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
994 EXPECT_EQ(pointsBack, target->pointsBack());
995 EXPECT_EQ(superClassCount, SuperClass::s_aliveCount);
996 }
997
998 virtual void trace(Visitor* visitor)
999 {
1000#if ENABLE_OILPAN
1001 visitor->trace(m_pointsBack);
1002#endif
1003 }
1004
1005 PointsBack* pointsBack() const { return m_pointsBack.get(); }
1006
1007 static int s_aliveCount;
1008protected:
1009 explicit SuperClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1010 : m_pointsBack(pointsBack)
1011 {
1012 m_pointsBack->setBackPointer(this);
1013 ++s_aliveCount;
1014 }
1015
1016private:
1017 RefPtrWillBeMember<PointsBack> m_pointsBack;
1018};
1019
1020int SuperClass::s_aliveCount = 0;
1021class SubData : public NoBaseWillBeGarbageCollectedFinalized<SubData> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001022public:
1023 SubData() { ++s_aliveCount; }
1024 ~SubData() { --s_aliveCount; }
1025
1026 void trace(Visitor*) { }
1027
1028 static int s_aliveCount;
1029};
1030
1031int SubData::s_aliveCount = 0;
1032
1033class SubClass : public SuperClass {
1034public:
1035 static PassRefPtrWillBeRawPtr<SubClass> create(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1036 {
1037 return adoptRefWillBeNoop(new SubClass(pointsBack));
1038 }
1039
1040 virtual ~SubClass()
1041 {
1042 --s_aliveCount;
1043 }
1044
1045 virtual void trace(Visitor* visitor)
1046 {
1047#if ENABLE_OILPAN
1048 SuperClass::trace(visitor);
1049 visitor->trace(m_data);
1050#endif
1051 }
1052
1053 static int s_aliveCount;
1054private:
1055 explicit SubClass(PassRefPtrWillBeRawPtr<PointsBack> pointsBack)
1056 : SuperClass(pointsBack)
1057 , m_data(adoptPtrWillBeNoop(new SubData()))
1058 {
1059 ++s_aliveCount;
1060 }
1061
1062private:
1063 OwnPtrWillBeMember<SubData> m_data;
1064};
1065
1066int SubClass::s_aliveCount = 0;
1067
1068class TransitionRefCounted : public RefCountedWillBeRefCountedGarbageCollected<TransitionRefCounted> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001069public:
1070 static PassRefPtrWillBeRawPtr<TransitionRefCounted> create()
1071 {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001072 return adoptRefWillBeRefCountedGarbageCollected(new TransitionRefCounted());
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001073 }
1074
1075 ~TransitionRefCounted()
1076 {
1077 --s_aliveCount;
1078 }
1079
1080 void trace(Visitor* visitor) { }
1081
1082 static int s_aliveCount;
1083
1084private:
1085 TransitionRefCounted()
1086 {
1087 ++s_aliveCount;
1088 }
1089};
1090
1091int TransitionRefCounted::s_aliveCount = 0;
1092
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001093class Mixin : public GarbageCollectedMixin {
1094public:
1095 virtual void trace(Visitor* visitor) { }
1096
1097 char getPayload(int i) { return m_padding[i]; }
1098
1099protected:
1100 // This is to force ptr diff for SimpleObject, Mixin, and UseMixin.
1101 int m_padding[8];
1102};
1103
1104class UseMixin : public SimpleObject, public Mixin {
1105 USING_GARBAGE_COLLECTED_MIXIN(UseMixin)
1106public:
1107 static UseMixin* create()
1108 {
1109 return new UseMixin();
1110 }
1111
1112 static int s_traceCount;
1113 virtual void trace(Visitor* visitor)
1114 {
1115 SimpleObject::trace(visitor);
1116 Mixin::trace(visitor);
1117 ++s_traceCount;
1118 }
1119
1120private:
1121 UseMixin()
1122 {
1123 s_traceCount = 0;
1124 }
1125};
1126
1127int UseMixin::s_traceCount = 0;
1128
1129class VectorObject {
1130 ALLOW_ONLY_INLINE_ALLOCATION();
1131public:
1132 VectorObject()
1133 {
1134 m_value = SimpleFinalizedObject::create();
1135 }
1136
1137 void trace(Visitor* visitor)
1138 {
1139 visitor->trace(m_value);
1140 }
1141
1142private:
1143 Member<SimpleFinalizedObject> m_value;
1144};
1145
1146class VectorObjectInheritedTrace : public VectorObject { };
1147
1148class VectorObjectNoTrace {
1149 ALLOW_ONLY_INLINE_ALLOCATION();
1150public:
1151 VectorObjectNoTrace()
1152 {
1153 m_value = SimpleFinalizedObject::create();
1154 }
1155
1156private:
1157 Member<SimpleFinalizedObject> m_value;
1158};
1159
1160class TerminatedArrayItem {
1161 ALLOW_ONLY_INLINE_ALLOCATION();
1162public:
1163 TerminatedArrayItem(IntWrapper* payload) : m_payload(payload), m_isLast(false) { }
1164
1165 void trace(Visitor* visitor) { visitor->trace(m_payload); }
1166
1167 bool isLastInArray() const { return m_isLast; }
1168 void setLastInArray(bool value) { m_isLast = value; }
1169
1170 IntWrapper* payload() const { return m_payload; }
1171
1172private:
1173 Member<IntWrapper> m_payload;
1174 bool m_isLast;
1175};
1176
1177} // WebCore namespace
1178
1179namespace WTF {
1180
1181// We need the below vector trait specialization for the above HeapVectors to behave correctly wrt. memset, memcmp etc.
1182template<> struct VectorTraits<WebCore::VectorObject> : public SimpleClassVectorTraits<WebCore::VectorObject> { };
1183template<> struct VectorTraits<WebCore::VectorObjectInheritedTrace> : public SimpleClassVectorTraits<WebCore::VectorObjectInheritedTrace> { };
1184template<> struct VectorTraits<WebCore::VectorObjectNoTrace> : public SimpleClassVectorTraits<WebCore::VectorObjectNoTrace> { };
1185
1186} // WTF namespace
1187
1188namespace WebCore {
1189
1190class OneKiloByteObject : public GarbageCollectedFinalized<OneKiloByteObject> {
1191public:
1192 ~OneKiloByteObject() { s_destructorCalls++; }
1193 char* data() { return m_data; }
1194 void trace(Visitor* visitor) { }
1195 static int s_destructorCalls;
1196
1197private:
1198 static const size_t s_length = 1024;
1199 char m_data[s_length];
1200};
1201
1202int OneKiloByteObject::s_destructorCalls = 0;
1203
1204class DynamicallySizedObject : public GarbageCollected<DynamicallySizedObject> {
1205public:
1206 static DynamicallySizedObject* create(size_t size)
1207 {
1208 void* slot = Heap::allocate<DynamicallySizedObject>(size);
1209 return new (slot) DynamicallySizedObject();
1210 }
1211
1212 void* operator new(std::size_t, void* location)
1213 {
1214 return location;
1215 }
1216
1217 uint8_t get(int i)
1218 {
1219 return *(reinterpret_cast<uint8_t*>(this) + i);
1220 }
1221
1222 void trace(Visitor*) { }
1223
1224private:
1225 DynamicallySizedObject() { }
1226};
1227
1228class FinalizationAllocator : public GarbageCollectedFinalized<FinalizationAllocator> {
1229public:
1230 FinalizationAllocator(Persistent<IntWrapper>* wrapper)
1231 : m_wrapper(wrapper)
1232 {
1233 }
1234
1235 ~FinalizationAllocator()
1236 {
1237 for (int i = 0; i < 10; ++i)
1238 *m_wrapper = IntWrapper::create(42);
1239 for (int i = 0; i < 512; ++i)
1240 new OneKiloByteObject();
1241 }
1242
1243 void trace(Visitor*) { }
1244
1245private:
1246 Persistent<IntWrapper>* m_wrapper;
1247};
1248
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001249TEST(HeapTest, Transition)
1250{
1251 {
1252 RefPtr<TransitionRefCounted> refCounted = TransitionRefCounted::create();
1253 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1254 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1255 EXPECT_EQ(1, TransitionRefCounted::s_aliveCount);
1256 }
1257 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1258 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1259
1260 RefPtrWillBePersistent<PointsBack> pointsBack1 = PointsBack::create();
1261 RefPtrWillBePersistent<PointsBack> pointsBack2 = PointsBack::create();
1262 RefPtrWillBePersistent<SuperClass> superClass = SuperClass::create(pointsBack1);
1263 RefPtrWillBePersistent<SubClass> subClass = SubClass::create(pointsBack2);
1264 EXPECT_EQ(2, PointsBack::s_aliveCount);
1265 EXPECT_EQ(2, SuperClass::s_aliveCount);
1266 EXPECT_EQ(1, SubClass::s_aliveCount);
1267 EXPECT_EQ(1, SubData::s_aliveCount);
1268
1269 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1270 EXPECT_EQ(0, TransitionRefCounted::s_aliveCount);
1271 EXPECT_EQ(2, PointsBack::s_aliveCount);
1272 EXPECT_EQ(2, SuperClass::s_aliveCount);
1273 EXPECT_EQ(1, SubClass::s_aliveCount);
1274 EXPECT_EQ(1, SubData::s_aliveCount);
1275
1276 superClass->doStuff(superClass.release(), pointsBack1.get(), 2);
1277 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1278 EXPECT_EQ(2, PointsBack::s_aliveCount);
1279 EXPECT_EQ(1, SuperClass::s_aliveCount);
1280 EXPECT_EQ(1, SubClass::s_aliveCount);
1281 EXPECT_EQ(1, SubData::s_aliveCount);
1282 EXPECT_EQ(0, pointsBack1->backPointer());
1283
1284 pointsBack1.release();
1285 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1286 EXPECT_EQ(1, PointsBack::s_aliveCount);
1287 EXPECT_EQ(1, SuperClass::s_aliveCount);
1288 EXPECT_EQ(1, SubClass::s_aliveCount);
1289 EXPECT_EQ(1, SubData::s_aliveCount);
1290
1291 subClass->doStuff(subClass.release(), pointsBack2.get(), 1);
1292 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1293 EXPECT_EQ(1, PointsBack::s_aliveCount);
1294 EXPECT_EQ(0, SuperClass::s_aliveCount);
1295 EXPECT_EQ(0, SubClass::s_aliveCount);
1296 EXPECT_EQ(0, SubData::s_aliveCount);
1297 EXPECT_EQ(0, pointsBack2->backPointer());
1298
1299 pointsBack2.release();
1300 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1301 EXPECT_EQ(0, PointsBack::s_aliveCount);
1302 EXPECT_EQ(0, SuperClass::s_aliveCount);
1303 EXPECT_EQ(0, SubClass::s_aliveCount);
1304 EXPECT_EQ(0, SubData::s_aliveCount);
1305
1306 EXPECT_TRUE(superClass == subClass);
1307}
1308
1309TEST(HeapTest, Threading)
1310{
1311 ThreadedHeapTester::test();
1312}
1313
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001314TEST(HeapTest, ThreadedWeakness)
1315{
1316 ThreadedWeaknessTester::test();
1317}
1318
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001319TEST(HeapTest, BasicFunctionality)
1320{
1321 HeapStats heapStats;
1322 clearOutOldGarbage(&heapStats);
1323 {
1324 size_t slack = 0;
1325
1326 // When the test starts there may already have been leaked some memory
1327 // on the heap, so we establish a base line.
1328 size_t baseLevel = heapStats.totalObjectSpace();
1329 bool testPagesAllocated = !baseLevel;
1330 if (testPagesAllocated)
1331 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1332
1333 // This allocates objects on the general heap which should add a page of memory.
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001334 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001335 slack += 4;
1336 memset(alloc32, 40, 32);
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001337 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001338 slack += 4;
1339 memset(alloc64, 27, 64);
1340
1341 size_t total = 96;
1342
1343 getHeapStats(&heapStats);
1344 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1345 if (testPagesAllocated)
1346 EXPECT_EQ(heapStats.totalAllocatedSpace(), blinkPageSize);
1347
1348 CheckWithSlack(alloc32 + 32 + sizeof(HeapObjectHeader), alloc64, slack);
1349
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001350 EXPECT_EQ(alloc32->get(0), 40);
1351 EXPECT_EQ(alloc32->get(31), 40);
1352 EXPECT_EQ(alloc64->get(0), 27);
1353 EXPECT_EQ(alloc64->get(63), 27);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001354
1355 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1356
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001357 EXPECT_EQ(alloc32->get(0), 40);
1358 EXPECT_EQ(alloc32->get(31), 40);
1359 EXPECT_EQ(alloc64->get(0), 27);
1360 EXPECT_EQ(alloc64->get(63), 27);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001361 }
1362
1363 clearOutOldGarbage(&heapStats);
1364 size_t total = 0;
1365 size_t slack = 0;
1366 size_t baseLevel = heapStats.totalObjectSpace();
1367 bool testPagesAllocated = !baseLevel;
1368 if (testPagesAllocated)
1369 EXPECT_EQ(heapStats.totalAllocatedSpace(), 0ul);
1370
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001371 size_t big = 1008;
1372 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(big);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001373 total += big;
1374 slack += 4;
1375
1376 size_t persistentCount = 0;
1377 const size_t numPersistents = 100000;
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001378 Persistent<DynamicallySizedObject>* persistents[numPersistents];
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001379
1380 for (int i = 0; i < 1000; i++) {
1381 size_t size = 128 + i * 8;
1382 total += size;
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001383 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(size));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001384 slack += 4;
1385 getHeapStats(&heapStats);
1386 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1387 if (testPagesAllocated)
1388 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1389 }
1390
1391 {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001392 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001393 slack += 4;
1394 memset(alloc32b, 40, 32);
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001395 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001396 slack += 4;
1397 memset(alloc64b, 27, 64);
1398 EXPECT_TRUE(alloc32b != alloc64b);
1399
1400 total += 96;
1401 getHeapStats(&heapStats);
1402 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1403 if (testPagesAllocated)
1404 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1405 }
1406
1407 clearOutOldGarbage(&heapStats);
1408 total -= 96;
1409 slack -= 8;
1410 if (testPagesAllocated)
1411 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1412
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001413 DynamicallySizedObject* bigAreaRaw = bigArea;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001414 // Clear the persistent, so that the big area will be garbage collected.
1415 bigArea.release();
1416 clearOutOldGarbage(&heapStats);
1417
1418 total -= big;
1419 slack -= 4;
1420 getHeapStats(&heapStats);
1421 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1422 if (testPagesAllocated)
1423 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1424
1425 // Endless loop unless we eventually get the memory back that we just freed.
1426 while (true) {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001427 Persistent<DynamicallySizedObject>* alloc = new Persistent<DynamicallySizedObject>(DynamicallySizedObject::create(big / 2));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001428 slack += 4;
1429 persistents[persistentCount++] = alloc;
1430 EXPECT_LT(persistentCount, numPersistents);
1431 total += big / 2;
1432 if (bigAreaRaw == alloc->get())
1433 break;
1434 }
1435
1436 getHeapStats(&heapStats);
1437 CheckWithSlack(baseLevel + total, heapStats.totalObjectSpace(), slack);
1438 if (testPagesAllocated)
1439 EXPECT_EQ(0ul, heapStats.totalAllocatedSpace() & (blinkPageSize - 1));
1440
1441 for (size_t i = 0; i < persistentCount; i++) {
1442 delete persistents[i];
1443 persistents[i] = 0;
1444 }
1445
1446 uint8_t* address = Heap::reallocate<uint8_t>(0, 100);
1447 for (int i = 0; i < 100; i++)
1448 address[i] = i;
1449 address = Heap::reallocate<uint8_t>(address, 100000);
1450 for (int i = 0; i < 100; i++)
1451 EXPECT_EQ(address[i], i);
1452 address = Heap::reallocate<uint8_t>(address, 50);
1453 for (int i = 0; i < 50; i++)
1454 EXPECT_EQ(address[i], i);
1455 // This should be equivalent to free(address).
1456 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<uint8_t>(address, 0)), 0ul);
1457 // This should be equivalent to malloc(0).
1458 EXPECT_EQ(reinterpret_cast<uintptr_t>(Heap::reallocate<uint8_t>(0, 0)), 0ul);
1459}
1460
1461TEST(HeapTest, SimpleAllocation)
1462{
1463 HeapStats initialHeapStats;
1464 clearOutOldGarbage(&initialHeapStats);
1465 EXPECT_EQ(0ul, initialHeapStats.totalObjectSpace());
1466
1467 // Allocate an object in the heap.
1468 HeapAllocatedArray* array = new HeapAllocatedArray();
1469 HeapStats statsAfterAllocation;
1470 getHeapStats(&statsAfterAllocation);
1471 EXPECT_TRUE(statsAfterAllocation.totalObjectSpace() >= sizeof(HeapAllocatedArray));
1472
1473 // Sanity check of the contents in the heap.
1474 EXPECT_EQ(0, array->at(0));
1475 EXPECT_EQ(42, array->at(42));
1476 EXPECT_EQ(0, array->at(128));
1477 EXPECT_EQ(999 % 128, array->at(999));
1478}
1479
1480TEST(HeapTest, SimplePersistent)
1481{
1482 Persistent<TraceCounter> traceCounter = TraceCounter::create();
1483 EXPECT_EQ(0, traceCounter->traceCount());
1484
1485 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1486 EXPECT_EQ(1, traceCounter->traceCount());
1487
1488 Persistent<ClassWithMember> classWithMember = ClassWithMember::create();
1489 EXPECT_EQ(0, classWithMember->traceCount());
1490
1491 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1492 EXPECT_EQ(1, classWithMember->traceCount());
1493 EXPECT_EQ(2, traceCounter->traceCount());
1494}
1495
1496TEST(HeapTest, SimpleFinalization)
1497{
1498 {
1499 Persistent<SimpleFinalizedObject> finalized = SimpleFinalizedObject::create();
1500 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1501 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1502 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
1503 }
1504
1505 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1506 EXPECT_EQ(1, SimpleFinalizedObject::s_destructorCalls);
1507}
1508
1509TEST(HeapTest, Finalization)
1510{
1511 {
1512 HeapTestSubClass* t1 = HeapTestSubClass::create();
1513 HeapTestSubClass* t2 = HeapTestSubClass::create();
1514 HeapTestSuperClass* t3 = HeapTestSuperClass::create();
1515 // FIXME(oilpan): Ignore unused variables.
1516 (void)t1;
1517 (void)t2;
1518 (void)t3;
1519 }
1520 // Nothing is marked so the GC should free everything and call
1521 // the finalizer on all three objects.
1522 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1523 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1524 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1525 // Destructors not called again when GCing again.
1526 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1527 EXPECT_EQ(2, HeapTestSubClass::s_destructorCalls);
1528 EXPECT_EQ(3, HeapTestSuperClass::s_destructorCalls);
1529}
1530
1531TEST(HeapTest, TypedHeapSanity)
1532{
1533 // We use TraceCounter for allocating an object on the general heap.
1534 Persistent<TraceCounter> generalHeapObject = TraceCounter::create();
1535 Persistent<TestTypedHeapClass> typedHeapObject = TestTypedHeapClass::create();
1536 EXPECT_NE(pageHeaderAddress(reinterpret_cast<Address>(generalHeapObject.get())),
1537 pageHeaderAddress(reinterpret_cast<Address>(typedHeapObject.get())));
1538}
1539
1540TEST(HeapTest, NoAllocation)
1541{
1542 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1543 {
1544 // Disallow allocation
1545 NoAllocationScope<AnyThread> noAllocationScope;
1546 EXPECT_FALSE(ThreadState::current()->isAllocationAllowed());
1547 }
1548 EXPECT_TRUE(ThreadState::current()->isAllocationAllowed());
1549}
1550
1551TEST(HeapTest, Members)
1552{
1553 Bar::s_live = 0;
1554 {
1555 Persistent<Baz> h1;
1556 Persistent<Baz> h2;
1557 {
1558 h1 = Baz::create(Bar::create());
1559 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1560 EXPECT_EQ(1u, Bar::s_live);
1561 h2 = Baz::create(Bar::create());
1562 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1563 EXPECT_EQ(2u, Bar::s_live);
1564 }
1565 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1566 EXPECT_EQ(2u, Bar::s_live);
1567 h1->clear();
1568 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1569 EXPECT_EQ(1u, Bar::s_live);
1570 }
1571 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1572 EXPECT_EQ(0u, Bar::s_live);
1573}
1574
1575TEST(HeapTest, MarkTest)
1576{
1577 {
1578 Bar::s_live = 0;
1579 Persistent<Bar> bar = Bar::create();
1580 EXPECT_TRUE(ThreadState::current()->contains(bar));
1581 EXPECT_EQ(1u, Bar::s_live);
1582 {
1583 Foo* foo = Foo::create(bar);
1584 EXPECT_TRUE(ThreadState::current()->contains(foo));
1585 EXPECT_EQ(2u, Bar::s_live);
1586 EXPECT_TRUE(reinterpret_cast<Address>(foo) != reinterpret_cast<Address>(bar.get()));
1587 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1588 EXPECT_TRUE(foo != bar); // To make sure foo is kept alive.
1589 EXPECT_EQ(2u, Bar::s_live);
1590 }
1591 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1592 EXPECT_EQ(1u, Bar::s_live);
1593 }
1594 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1595 EXPECT_EQ(0u, Bar::s_live);
1596}
1597
1598TEST(HeapTest, DeepTest)
1599{
1600 const unsigned depth = 100000;
1601 Bar::s_live = 0;
1602 {
1603 Bar* bar = Bar::create();
1604 EXPECT_TRUE(ThreadState::current()->contains(bar));
1605 Foo* foo = Foo::create(bar);
1606 EXPECT_TRUE(ThreadState::current()->contains(foo));
1607 EXPECT_EQ(2u, Bar::s_live);
1608 for (unsigned i = 0; i < depth; i++) {
1609 Foo* foo2 = Foo::create(foo);
1610 foo = foo2;
1611 EXPECT_TRUE(ThreadState::current()->contains(foo));
1612 }
1613 EXPECT_EQ(depth + 2, Bar::s_live);
1614 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1615 EXPECT_TRUE(foo != bar); // To make sure foo and bar are kept alive.
1616 EXPECT_EQ(depth + 2, Bar::s_live);
1617 }
1618 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1619 EXPECT_EQ(0u, Bar::s_live);
1620}
1621
1622TEST(HeapTest, WideTest)
1623{
1624 Bar::s_live = 0;
1625 {
1626 Bars* bars = Bars::create();
1627 unsigned width = Bars::width;
1628 EXPECT_EQ(width + 1, Bar::s_live);
1629 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1630 EXPECT_EQ(width + 1, Bar::s_live);
1631 // Use bars here to make sure that it will be on the stack
1632 // for the conservative stack scan to find.
1633 EXPECT_EQ(width, bars->getWidth());
1634 }
1635 EXPECT_EQ(Bars::width + 1, Bar::s_live);
1636 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1637 EXPECT_EQ(0u, Bar::s_live);
1638}
1639
1640TEST(HeapTest, HashMapOfMembers)
1641{
1642 HeapStats initialHeapSize;
1643 IntWrapper::s_destructorCalls = 0;
1644
1645 clearOutOldGarbage(&initialHeapSize);
1646 {
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001647 typedef HeapHashMap<
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001648 Member<IntWrapper>,
1649 Member<IntWrapper>,
1650 DefaultHash<Member<IntWrapper> >::Hash,
1651 HashTraits<Member<IntWrapper> >,
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001652 HashTraits<Member<IntWrapper> > > HeapObjectIdentityMap;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001653
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001654 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap();
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001655
1656 map->clear();
1657 HeapStats afterSetWasCreated;
1658 getHeapStats(&afterSetWasCreated);
1659 EXPECT_TRUE(afterSetWasCreated.totalObjectSpace() > initialHeapSize.totalObjectSpace());
1660
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001661 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001662 HeapStats afterGC;
1663 getHeapStats(&afterGC);
1664 EXPECT_EQ(afterGC.totalObjectSpace(), afterSetWasCreated.totalObjectSpace());
1665
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001666 // If the additions below cause garbage collections, these
1667 // pointers should be found by conservative stack scanning.
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001668 IntWrapper* one(IntWrapper::create(1));
1669 IntWrapper* anotherOne(IntWrapper::create(1));
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001670
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001671 map->add(one, one);
1672
1673 HeapStats afterOneAdd;
1674 getHeapStats(&afterOneAdd);
1675 EXPECT_TRUE(afterOneAdd.totalObjectSpace() > afterGC.totalObjectSpace());
1676
1677 HeapObjectIdentityMap::iterator it(map->begin());
1678 HeapObjectIdentityMap::iterator it2(map->begin());
1679 ++it;
1680 ++it2;
1681
1682 map->add(anotherOne, one);
1683
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001684 // The addition above can cause an allocation of a new
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001685 // backing store. We therefore garbage collect before
1686 // taking the heap stats in order to get rid of the old
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001687 // backing store. We make sure to not use conservative
1688 // stack scanning as that could find a pointer to the
1689 // old backing.
1690 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001691 HeapStats afterAddAndGC;
1692 getHeapStats(&afterAddAndGC);
1693 EXPECT_TRUE(afterAddAndGC.totalObjectSpace() >= afterOneAdd.totalObjectSpace());
1694
1695 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distinct.
1696
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001697 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001698 EXPECT_TRUE(map->contains(one));
1699 EXPECT_TRUE(map->contains(anotherOne));
1700
1701 IntWrapper* gotten(map->get(one));
1702 EXPECT_EQ(gotten->value(), one->value());
1703 EXPECT_EQ(gotten, one);
1704
1705 HeapStats afterGC2;
1706 getHeapStats(&afterGC2);
1707 EXPECT_EQ(afterGC2.totalObjectSpace(), afterAddAndGC.totalObjectSpace());
1708
1709 IntWrapper* dozen = 0;
1710
1711 for (int i = 1; i < 1000; i++) { // 999 iterations.
1712 IntWrapper* iWrapper(IntWrapper::create(i));
1713 IntWrapper* iSquared(IntWrapper::create(i * i));
1714 map->add(iWrapper, iSquared);
1715 if (i == 12)
1716 dozen = iWrapper;
1717 }
1718 HeapStats afterAdding1000;
1719 getHeapStats(&afterAdding1000);
1720 EXPECT_TRUE(afterAdding1000.totalObjectSpace() > afterGC2.totalObjectSpace());
1721
1722 IntWrapper* gross(map->get(dozen));
1723 EXPECT_EQ(gross->value(), 144);
1724
1725 // This should clear out junk created by all the adds.
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001726 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001727 HeapStats afterGC3;
1728 getHeapStats(&afterGC3);
1729 EXPECT_TRUE(afterGC3.totalObjectSpace() < afterAdding1000.totalObjectSpace());
1730 }
1731
1732 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1733 // The objects 'one', anotherOne, and the 999 other pairs.
1734 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000);
1735 HeapStats afterGC4;
1736 getHeapStats(&afterGC4);
1737 EXPECT_EQ(afterGC4.totalObjectSpace(), initialHeapSize.totalObjectSpace());
1738}
1739
1740TEST(HeapTest, NestedAllocation)
1741{
1742 HeapStats initialHeapSize;
1743 clearOutOldGarbage(&initialHeapSize);
1744 {
1745 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAllocation::create();
1746 }
1747 HeapStats afterFree;
1748 clearOutOldGarbage(&afterFree);
1749 EXPECT_TRUE(initialHeapSize == afterFree);
1750}
1751
1752TEST(HeapTest, LargeObjects)
1753{
1754 HeapStats initialHeapSize;
1755 clearOutOldGarbage(&initialHeapSize);
1756 IntWrapper::s_destructorCalls = 0;
1757 LargeObject::s_destructorCalls = 0;
1758 {
1759 int slack = 8; // LargeObject points to an IntWrapper that is also allocated.
1760 Persistent<LargeObject> object = LargeObject::create();
1761 HeapStats afterAllocation;
1762 clearOutOldGarbage(&afterAllocation);
1763 {
1764 object->set(0, 'a');
1765 EXPECT_EQ('a', object->get(0));
1766 object->set(object->length() - 1, 'b');
1767 EXPECT_EQ('b', object->get(object->length() - 1));
1768 size_t expectedObjectSpace = sizeof(LargeObject) + sizeof(IntWrapper);
1769 size_t actualObjectSpace =
1770 afterAllocation.totalObjectSpace() - initialHeapSize.totalObjectSpace();
1771 CheckWithSlack(expectedObjectSpace, actualObjectSpace, slack);
1772 // There is probably space for the IntWrapper in a heap page without
1773 // allocating extra pages. However, the IntWrapper allocation might cause
1774 // the addition of a heap page.
1775 size_t largeObjectAllocationSize =
1776 sizeof(LargeObject) + sizeof(LargeHeapObject<FinalizedHeapObjectHeader>) + sizeof(FinalizedHeapObjectHeader);
1777 size_t allocatedSpaceLowerBound =
1778 initialHeapSize.totalAllocatedSpace() + largeObjectAllocationSize;
1779 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize;
1780 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation.totalAllocatedSpace());
1781 EXPECT_LE(afterAllocation.totalAllocatedSpace(), allocatedSpaceUpperBound);
1782 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
1783 EXPECT_EQ(0, LargeObject::s_destructorCalls);
1784 for (int i = 0; i < 10; i++)
1785 object = LargeObject::create();
1786 }
1787 HeapStats oneLargeObject;
1788 clearOutOldGarbage(&oneLargeObject);
1789 EXPECT_TRUE(oneLargeObject == afterAllocation);
1790 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
1791 EXPECT_EQ(10, LargeObject::s_destructorCalls);
1792 }
1793 HeapStats backToInitial;
1794 clearOutOldGarbage(&backToInitial);
1795 EXPECT_TRUE(initialHeapSize == backToInitial);
1796 EXPECT_EQ(11, IntWrapper::s_destructorCalls);
1797 EXPECT_EQ(11, LargeObject::s_destructorCalls);
1798 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
1799}
1800
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001801typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped;
1802typedef std::pair<int, Member<IntWrapper> > PairUnwrappedWrapped;
1803typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper> > PairWeakStrong;
1804typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper> > PairStrongWeak;
1805typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped;
1806typedef std::pair<int, WeakMember<IntWrapper> > PairUnwrappedWeak;
1807
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001808class Container : public GarbageCollected<Container> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001809public:
1810 static Container* create() { return new Container(); }
1811 HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > map;
1812 HeapHashSet<Member<IntWrapper> > set;
1813 HeapHashSet<Member<IntWrapper> > set2;
1814 HeapVector<Member<IntWrapper>, 2> vector;
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001815 HeapVector<PairWrappedUnwrapped, 2> vectorWU;
1816 HeapVector<PairUnwrappedWrapped, 2> vectorUW;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001817 void trace(Visitor* visitor)
1818 {
1819 visitor->trace(map);
1820 visitor->trace(set);
1821 visitor->trace(set2);
1822 visitor->trace(vector);
1823 }
1824};
1825
1826struct ShouldBeTraced {
1827 explicit ShouldBeTraced(IntWrapper* wrapper) : m_wrapper(wrapper) { }
1828 void trace(Visitor* visitor) { visitor->trace(m_wrapper); }
1829 Member<IntWrapper> m_wrapper;
1830};
1831
1832class OffHeapContainer : public GarbageCollectedFinalized<OffHeapContainer> {
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001833public:
1834 static OffHeapContainer* create() { return new OffHeapContainer(); }
1835
1836 OffHeapContainer()
1837 {
1838 m_deque1.append(ShouldBeTraced(IntWrapper::create(1)));
1839 m_vector1.append(ShouldBeTraced(IntWrapper::create(2)));
1840 m_deque2.append(IntWrapper::create(3));
1841 m_vector2.append(IntWrapper::create(4));
1842 m_hashSet.add(IntWrapper::create(5));
1843 m_hashMap.add(this, IntWrapper::create(6));
1844 m_listHashSet.add(IntWrapper::create(7));
1845 }
1846
1847 void trace(Visitor* visitor)
1848 {
1849 visitor->trace(m_deque1);
1850 visitor->trace(m_vector1);
1851 visitor->trace(m_deque2);
1852 visitor->trace(m_vector2);
1853 visitor->trace(m_hashSet);
1854 visitor->trace(m_hashMap);
1855 visitor->trace(m_listHashSet);
1856 }
1857
1858 Deque<ShouldBeTraced> m_deque1;
1859 Vector<ShouldBeTraced> m_vector1;
1860 Deque<Member<IntWrapper> > m_deque2;
1861 Vector<Member<IntWrapper> > m_vector2;
1862 HashSet<Member<IntWrapper> > m_hashSet;
1863 HashMap<void*, Member<IntWrapper> > m_hashMap;
1864 ListHashSet<Member<IntWrapper> > m_listHashSet;
1865};
1866
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001867
1868// These class definitions test compile-time asserts with transition
1869// types. They are therefore unused in test code and just need to
1870// compile. This is intentional; do not delete the A and B classes below.
1871class A : public WillBeGarbageCollectedMixin {
1872};
1873
1874class B : public NoBaseWillBeGarbageCollected<B>, public A {
1875 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(B);
1876public:
1877 void trace(Visitor*) { }
1878};
1879
1880TEST(HeapTest, HeapVectorFilledWithValue)
1881{
1882 IntWrapper* val = IntWrapper::create(1);
1883 HeapVector<Member<IntWrapper> > vector(10, val);
1884 EXPECT_EQ(10u, vector.size());
1885 for (size_t i = 0; i < vector.size(); i++)
1886 EXPECT_EQ(val, vector[i]);
1887}
1888
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001889TEST(HeapTest, HeapVectorWithInlineCapacity)
1890{
1891 IntWrapper* one = IntWrapper::create(1);
1892 IntWrapper* two = IntWrapper::create(2);
1893 IntWrapper* three = IntWrapper::create(3);
1894 IntWrapper* four = IntWrapper::create(4);
1895 IntWrapper* five = IntWrapper::create(5);
1896 IntWrapper* six = IntWrapper::create(6);
1897 {
1898 HeapVector<Member<IntWrapper>, 2> vector;
1899 vector.append(one);
1900 vector.append(two);
1901 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1902 EXPECT_TRUE(vector.contains(one));
1903 EXPECT_TRUE(vector.contains(two));
1904
1905 vector.append(three);
1906 vector.append(four);
1907 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1908 EXPECT_TRUE(vector.contains(one));
1909 EXPECT_TRUE(vector.contains(two));
1910 EXPECT_TRUE(vector.contains(three));
1911 EXPECT_TRUE(vector.contains(four));
1912
1913 vector.shrink(1);
1914 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1915 EXPECT_TRUE(vector.contains(one));
1916 EXPECT_FALSE(vector.contains(two));
1917 EXPECT_FALSE(vector.contains(three));
1918 EXPECT_FALSE(vector.contains(four));
1919 }
1920 {
1921 HeapVector<Member<IntWrapper>, 2> vector1;
1922 HeapVector<Member<IntWrapper>, 2> vector2;
1923
1924 vector1.append(one);
1925 vector2.append(two);
1926 vector1.swap(vector2);
1927 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1928 EXPECT_TRUE(vector1.contains(two));
1929 EXPECT_TRUE(vector2.contains(one));
1930 }
1931 {
1932 HeapVector<Member<IntWrapper>, 2> vector1;
1933 HeapVector<Member<IntWrapper>, 2> vector2;
1934
1935 vector1.append(one);
1936 vector1.append(two);
1937 vector2.append(three);
1938 vector2.append(four);
1939 vector2.append(five);
1940 vector2.append(six);
1941 vector1.swap(vector2);
1942 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
1943 EXPECT_TRUE(vector1.contains(three));
1944 EXPECT_TRUE(vector1.contains(four));
1945 EXPECT_TRUE(vector1.contains(five));
1946 EXPECT_TRUE(vector1.contains(six));
1947 EXPECT_TRUE(vector2.contains(one));
1948 EXPECT_TRUE(vector2.contains(two));
1949 }
1950}
1951
1952TEST(HeapTest, HeapCollectionTypes)
1953{
1954 HeapStats initialHeapSize;
1955 IntWrapper::s_destructorCalls = 0;
1956
1957 typedef HeapHashMap<Member<IntWrapper>, Member<IntWrapper> > MemberMember;
1958 typedef HeapHashMap<Member<IntWrapper>, int> MemberPrimitive;
1959 typedef HeapHashMap<int, Member<IntWrapper> > PrimitiveMember;
1960
1961 typedef HeapHashSet<Member<IntWrapper> > MemberSet;
1962 typedef HeapHashSet<WeakMember<IntWrapper> > WeakMemberSet;
1963
1964 typedef HeapVector<Member<IntWrapper>, 2> MemberVector;
1965
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001966 typedef HeapVector<PairWrappedUnwrapped, 2> VectorWU;
1967 typedef HeapVector<PairUnwrappedWrapped, 2> VectorUW;
1968
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001969 Persistent<MemberMember> memberMember = new MemberMember();
1970 Persistent<MemberMember> memberMember2 = new MemberMember();
1971 Persistent<MemberMember> memberMember3 = new MemberMember();
1972 Persistent<MemberPrimitive> memberPrimitive = new MemberPrimitive();
1973 Persistent<PrimitiveMember> primitiveMember = new PrimitiveMember();
1974 Persistent<MemberSet> set = new MemberSet();
1975 Persistent<MemberSet> set2 = new MemberSet();
1976 Persistent<MemberVector> vector = new MemberVector();
1977 Persistent<MemberVector> vector2 = new MemberVector();
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001978 Persistent<VectorWU> vectorWU = new VectorWU();
1979 Persistent<VectorWU> vectorWU2 = new VectorWU();
1980 Persistent<VectorUW> vectorUW = new VectorUW();
1981 Persistent<VectorUW> vectorUW2 = new VectorUW();
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001982 Persistent<Container> container = Container::create();
1983
1984 clearOutOldGarbage(&initialHeapSize);
1985 {
1986 Persistent<IntWrapper> one(IntWrapper::create(1));
1987 Persistent<IntWrapper> two(IntWrapper::create(2));
1988 Persistent<IntWrapper> oneB(IntWrapper::create(1));
1989 Persistent<IntWrapper> twoB(IntWrapper::create(2));
1990 Persistent<IntWrapper> oneC(IntWrapper::create(1));
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001991 Persistent<IntWrapper> oneD(IntWrapper::create(1));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00001992 {
1993 IntWrapper* three(IntWrapper::create(3));
1994 IntWrapper* four(IntWrapper::create(4));
1995 IntWrapper* threeB(IntWrapper::create(3));
1996 IntWrapper* fourB(IntWrapper::create(4));
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00001997 IntWrapper* threeC(IntWrapper::create(3));
1998 IntWrapper* fourC(IntWrapper::create(4));
1999 IntWrapper* fiveC(IntWrapper::create(5));
2000 IntWrapper* threeD(IntWrapper::create(3));
2001 IntWrapper* fourD(IntWrapper::create(4));
2002 IntWrapper* fiveD(IntWrapper::create(5));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002003
2004 // Member Collections.
2005 memberMember2->add(one, two);
2006 memberMember2->add(two, three);
2007 memberMember2->add(three, four);
2008 memberMember2->add(four, one);
2009 primitiveMember->add(1, two);
2010 primitiveMember->add(2, three);
2011 primitiveMember->add(3, four);
2012 primitiveMember->add(4, one);
2013 memberPrimitive->add(one, 2);
2014 memberPrimitive->add(two, 3);
2015 memberPrimitive->add(three, 4);
2016 memberPrimitive->add(four, 1);
2017 set2->add(one);
2018 set2->add(two);
2019 set2->add(three);
2020 set2->add(four);
2021 set->add(oneB);
2022 vector->append(oneB);
2023 vector2->append(threeB);
2024 vector2->append(fourB);
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002025 vectorWU->append(PairWrappedUnwrapped(&*oneC, 42));
2026 vectorWU2->append(PairWrappedUnwrapped(&*threeC, 43));
2027 vectorWU2->append(PairWrappedUnwrapped(&*fourC, 44));
2028 vectorWU2->append(PairWrappedUnwrapped(&*fiveC, 45));
2029 vectorUW->append(PairUnwrappedWrapped(1, &*oneD));
2030 vectorUW2->append(PairUnwrappedWrapped(103, &*threeD));
2031 vectorUW2->append(PairUnwrappedWrapped(104, &*fourD));
2032 vectorUW2->append(PairUnwrappedWrapped(105, &*fiveD));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002033
2034 // Collect garbage. This should change nothing since we are keeping
2035 // alive the IntWrapper objects with on-stack pointers.
2036 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2037 EXPECT_EQ(0u, memberMember->size());
2038 EXPECT_EQ(4u, memberMember2->size());
2039 EXPECT_EQ(4u, primitiveMember->size());
2040 EXPECT_EQ(4u, memberPrimitive->size());
2041 EXPECT_EQ(1u, set->size());
2042 EXPECT_EQ(4u, set2->size());
2043 EXPECT_EQ(1u, vector->size());
2044 EXPECT_EQ(2u, vector2->size());
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002045 EXPECT_EQ(1u, vectorWU->size());
2046 EXPECT_EQ(3u, vectorWU2->size());
2047 EXPECT_EQ(1u, vectorUW->size());
2048 EXPECT_EQ(3u, vectorUW2->size());
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002049
2050 MemberVector& cvec = container->vector;
2051 cvec.swap(*vector.get());
2052 vector2->swap(cvec);
2053 vector->swap(cvec);
2054
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002055 VectorWU& cvecWU = container->vectorWU;
2056 cvecWU.swap(*vectorWU.get());
2057 vectorWU2->swap(cvecWU);
2058 vectorWU->swap(cvecWU);
2059
2060 VectorUW& cvecUW = container->vectorUW;
2061 cvecUW.swap(*vectorUW.get());
2062 vectorUW2->swap(cvecUW);
2063 vectorUW->swap(cvecUW);
2064
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002065 // Swap set and set2 in a roundabout way.
2066 MemberSet& cset1 = container->set;
2067 MemberSet& cset2 = container->set2;
2068 set->swap(cset1);
2069 set2->swap(cset2);
2070 set->swap(cset2);
2071 cset1.swap(cset2);
2072 cset2.swap(set2);
2073
2074 // Triple swap.
2075 container->map.swap(memberMember2);
2076 MemberMember& containedMap = container->map;
2077 memberMember3->swap(containedMap);
2078 memberMember3->swap(memberMember);
2079
2080 EXPECT_TRUE(memberMember->get(one) == two);
2081 EXPECT_TRUE(memberMember->get(two) == three);
2082 EXPECT_TRUE(memberMember->get(three) == four);
2083 EXPECT_TRUE(memberMember->get(four) == one);
2084 EXPECT_TRUE(primitiveMember->get(1) == two);
2085 EXPECT_TRUE(primitiveMember->get(2) == three);
2086 EXPECT_TRUE(primitiveMember->get(3) == four);
2087 EXPECT_TRUE(primitiveMember->get(4) == one);
2088 EXPECT_EQ(1, memberPrimitive->get(four));
2089 EXPECT_EQ(2, memberPrimitive->get(one));
2090 EXPECT_EQ(3, memberPrimitive->get(two));
2091 EXPECT_EQ(4, memberPrimitive->get(three));
2092 EXPECT_TRUE(set->contains(one));
2093 EXPECT_TRUE(set->contains(two));
2094 EXPECT_TRUE(set->contains(three));
2095 EXPECT_TRUE(set->contains(four));
2096 EXPECT_TRUE(set2->contains(oneB));
2097 EXPECT_TRUE(vector->contains(threeB));
2098 EXPECT_TRUE(vector->contains(fourB));
2099 EXPECT_TRUE(vector2->contains(oneB));
2100 EXPECT_FALSE(vector2->contains(threeB));
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002101 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*threeC, 43)));
2102 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fourC, 44)));
2103 EXPECT_TRUE(vectorWU->contains(PairWrappedUnwrapped(&*fiveC, 45)));
2104 EXPECT_TRUE(vectorWU2->contains(PairWrappedUnwrapped(&*oneC, 42)));
2105 EXPECT_FALSE(vectorWU2->contains(PairWrappedUnwrapped(&*threeC, 43)));
2106 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(103, &*threeD)));
2107 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(104, &*fourD)));
2108 EXPECT_TRUE(vectorUW->contains(PairUnwrappedWrapped(105, &*fiveD)));
2109 EXPECT_TRUE(vectorUW2->contains(PairUnwrappedWrapped(1, &*oneD)));
2110 EXPECT_FALSE(vectorUW2->contains(PairUnwrappedWrapped(103, &*threeD)));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002111 }
2112
2113 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2114
2115 EXPECT_EQ(4u, memberMember->size());
2116 EXPECT_EQ(0u, memberMember2->size());
2117 EXPECT_EQ(4u, primitiveMember->size());
2118 EXPECT_EQ(4u, memberPrimitive->size());
2119 EXPECT_EQ(4u, set->size());
2120 EXPECT_EQ(1u, set2->size());
2121 EXPECT_EQ(2u, vector->size());
2122 EXPECT_EQ(1u, vector2->size());
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002123 EXPECT_EQ(3u, vectorUW->size());
2124 EXPECT_EQ(1u, vector2->size());
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002125
2126 EXPECT_TRUE(memberMember->get(one) == two);
2127 EXPECT_TRUE(primitiveMember->get(1) == two);
2128 EXPECT_TRUE(primitiveMember->get(4) == one);
2129 EXPECT_EQ(2, memberPrimitive->get(one));
2130 EXPECT_EQ(3, memberPrimitive->get(two));
2131 EXPECT_TRUE(set->contains(one));
2132 EXPECT_TRUE(set->contains(two));
2133 EXPECT_FALSE(set->contains(oneB));
2134 EXPECT_TRUE(set2->contains(oneB));
2135 EXPECT_EQ(3, vector->at(0)->value());
2136 EXPECT_EQ(4, vector->at(1)->value());
2137 }
2138
2139 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2140 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2141
2142 EXPECT_EQ(4u, memberMember->size());
2143 EXPECT_EQ(4u, primitiveMember->size());
2144 EXPECT_EQ(4u, memberPrimitive->size());
2145 EXPECT_EQ(4u, set->size());
2146 EXPECT_EQ(1u, set2->size());
2147 EXPECT_EQ(2u, vector->size());
2148 EXPECT_EQ(1u, vector2->size());
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002149 EXPECT_EQ(3u, vectorWU->size());
2150 EXPECT_EQ(1u, vectorWU2->size());
2151 EXPECT_EQ(3u, vectorUW->size());
2152 EXPECT_EQ(1u, vectorUW2->size());
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002153}
2154
2155template<typename T>
2156void MapIteratorCheck(T& it, const T& end, int expected)
2157{
2158 int found = 0;
2159 while (it != end) {
2160 found++;
2161 int key = it->key->value();
2162 int value = it->value->value();
2163 EXPECT_TRUE(key >= 0 && key < 1100);
2164 EXPECT_TRUE(value >= 0 && value < 1100);
2165 ++it;
2166 }
2167 EXPECT_EQ(expected, found);
2168}
2169
2170template<typename T>
2171void SetIteratorCheck(T& it, const T& end, int expected)
2172{
2173 int found = 0;
2174 while (it != end) {
2175 found++;
2176 int value = (*it)->value();
2177 EXPECT_TRUE(value >= 0 && value < 1100);
2178 ++it;
2179 }
2180 EXPECT_EQ(expected, found);
2181}
2182
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002183TEST(HeapTest, HeapWeakCollectionSimple)
2184{
2185
2186 IntWrapper::s_destructorCalls = 0;
2187
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002188 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002189
2190 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2191 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2192 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2193 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2194
2195 Persistent<WeakStrong> weakStrong = new WeakStrong();
2196 Persistent<StrongWeak> strongWeak = new StrongWeak();
2197 Persistent<WeakWeak> weakWeak = new WeakWeak();
2198 Persistent<WeakSet> weakSet = new WeakSet();
2199
2200 Persistent<IntWrapper> two = IntWrapper::create(2);
2201
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002202 keepNumbersAlive.append(IntWrapper::create(103));
2203 keepNumbersAlive.append(IntWrapper::create(10));
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002204
2205 {
2206 weakStrong->add(IntWrapper::create(1), two);
2207 strongWeak->add(two, IntWrapper::create(1));
2208 weakWeak->add(two, IntWrapper::create(42));
2209 weakWeak->add(IntWrapper::create(42), two);
2210 weakSet->add(IntWrapper::create(0));
2211 weakSet->add(two);
2212 weakSet->add(keepNumbersAlive[0]);
2213 weakSet->add(keepNumbersAlive[1]);
2214 EXPECT_EQ(1u, weakStrong->size());
2215 EXPECT_EQ(1u, strongWeak->size());
2216 EXPECT_EQ(2u, weakWeak->size());
2217 EXPECT_EQ(4u, weakSet->size());
2218 }
2219
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002220 keepNumbersAlive[0] = nullptr;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002221
2222 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2223
2224 EXPECT_EQ(0u, weakStrong->size());
2225 EXPECT_EQ(0u, strongWeak->size());
2226 EXPECT_EQ(0u, weakWeak->size());
2227 EXPECT_EQ(2u, weakSet->size());
2228}
2229
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002230typedef HeapHashSet<PairWeakStrong> WeakStrongSet;
2231typedef HeapHashSet<PairWeakUnwrapped> WeakUnwrappedSet;
2232typedef HeapHashSet<PairStrongWeak> StrongWeakSet;
2233typedef HeapHashSet<PairUnwrappedWeak> UnwrappedWeakSet;
2234
2235void checkPairSets(
2236 Persistent<WeakStrongSet>& weakStrong,
2237 Persistent<StrongWeakSet>& strongWeak,
2238 Persistent<WeakUnwrappedSet>& weakUnwrapped,
2239 Persistent<UnwrappedWeakSet>& unwrappedWeak,
2240 bool ones,
2241 Persistent<IntWrapper>& two)
2242{
2243 WeakStrongSet::iterator itWS = weakStrong->begin();
2244 StrongWeakSet::iterator itSW = strongWeak->begin();
2245 WeakUnwrappedSet::iterator itWU = weakUnwrapped->begin();
2246 UnwrappedWeakSet::iterator itUW = unwrappedWeak->begin();
2247
2248 EXPECT_EQ(2u, weakStrong->size());
2249 EXPECT_EQ(2u, strongWeak->size());
2250 EXPECT_EQ(2u, weakUnwrapped->size());
2251 EXPECT_EQ(2u, unwrappedWeak->size());
2252
2253 PairWeakStrong p = *itWS;
2254 PairStrongWeak p2 = *itSW;
2255 PairWeakUnwrapped p3 = *itWU;
2256 PairUnwrappedWeak p4 = *itUW;
2257 if (p.first == two && p.second == two)
2258 ++itWS;
2259 if (p2.first == two && p2.second == two)
2260 ++itSW;
2261 if (p3.first == two && p3.second == 2)
2262 ++itWU;
2263 if (p4.first == 2 && p4.second == two)
2264 ++itUW;
2265 p = *itWS;
2266 p2 = *itSW;
2267 p3 = *itWU;
2268 p4 = *itUW;
2269 IntWrapper* nullWrapper = 0;
2270 if (ones) {
2271 EXPECT_EQ(p.first->value(), 1);
2272 EXPECT_EQ(p2.second->value(), 1);
2273 EXPECT_EQ(p3.first->value(), 1);
2274 EXPECT_EQ(p4.second->value(), 1);
2275 } else {
2276 EXPECT_EQ(p.first, nullWrapper);
2277 EXPECT_EQ(p2.second, nullWrapper);
2278 EXPECT_EQ(p3.first, nullWrapper);
2279 EXPECT_EQ(p4.second, nullWrapper);
2280 }
2281
2282 EXPECT_EQ(p.second->value(), 2);
2283 EXPECT_EQ(p2.first->value(), 2);
2284 EXPECT_EQ(p3.second, 2);
2285 EXPECT_EQ(p4.first, 2);
2286
2287 EXPECT_TRUE(weakStrong->contains(PairWeakStrong(&*two, &*two)));
2288 EXPECT_TRUE(strongWeak->contains(PairStrongWeak(&*two, &*two)));
2289 EXPECT_TRUE(weakUnwrapped->contains(PairWeakUnwrapped(&*two, 2)));
2290 EXPECT_TRUE(unwrappedWeak->contains(PairUnwrappedWeak(2, &*two)));
2291}
2292
2293TEST(HeapTest, HeapWeakPairs)
2294{
2295 IntWrapper::s_destructorCalls = 0;
2296
2297 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
2298
2299 Persistent<WeakStrongSet> weakStrong = new WeakStrongSet();
2300 Persistent<StrongWeakSet> strongWeak = new StrongWeakSet();
2301 Persistent<WeakUnwrappedSet> weakUnwrapped = new WeakUnwrappedSet();
2302 Persistent<UnwrappedWeakSet> unwrappedWeak = new UnwrappedWeakSet();
2303
2304 Persistent<IntWrapper> two = IntWrapper::create(2);
2305
2306 weakStrong->add(PairWeakStrong(IntWrapper::create(1), &*two));
2307 weakStrong->add(PairWeakStrong(&*two, &*two));
2308 strongWeak->add(PairStrongWeak(&*two, IntWrapper::create(1)));
2309 strongWeak->add(PairStrongWeak(&*two, &*two));
2310 weakUnwrapped->add(PairWeakUnwrapped(IntWrapper::create(1), 2));
2311 weakUnwrapped->add(PairWeakUnwrapped(&*two, 2));
2312 unwrappedWeak->add(PairUnwrappedWeak(2, IntWrapper::create(1)));
2313 unwrappedWeak->add(PairUnwrappedWeak(2, &*two));
2314
2315 checkPairSets(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, true, two);
2316
2317 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2318 checkPairSets(weakStrong, strongWeak, weakUnwrapped, unwrappedWeak, false, two);
2319}
2320
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002321TEST(HeapTest, HeapWeakCollectionTypes)
2322{
2323 HeapStats initialHeapSize;
2324 IntWrapper::s_destructorCalls = 0;
2325
2326 typedef HeapHashMap<WeakMember<IntWrapper>, Member<IntWrapper> > WeakStrong;
2327 typedef HeapHashMap<Member<IntWrapper>, WeakMember<IntWrapper> > StrongWeak;
2328 typedef HeapHashMap<WeakMember<IntWrapper>, WeakMember<IntWrapper> > WeakWeak;
2329 typedef HeapHashSet<WeakMember<IntWrapper> > WeakSet;
2330
2331 clearOutOldGarbage(&initialHeapSize);
2332
2333 const int weakStrongIndex = 0;
2334 const int strongWeakIndex = 1;
2335 const int weakWeakIndex = 2;
2336 const int numberOfMapIndices = 3;
2337 const int weakSetIndex = 3;
2338 const int numberOfCollections = 4;
2339
2340 for (int testRun = 0; testRun < 4; testRun++) {
2341 for (int collectionNumber = 0; collectionNumber < numberOfCollections; collectionNumber++) {
2342 bool testThatIteratorsMakeStrong = (testRun == weakSetIndex);
2343 bool deleteAfterwards = (testRun == 1);
2344 bool addAfterwards = (testRun == weakWeakIndex);
2345
2346 // The test doesn't work for strongWeak with deleting because we lost
2347 // the key from the keepNumbersAlive array, so we can't do the lookup.
2348 if (deleteAfterwards && collectionNumber == strongWeakIndex)
2349 continue;
2350
2351 unsigned added = addAfterwards ? 100 : 0;
2352
2353 Persistent<WeakStrong> weakStrong = new WeakStrong();
2354 Persistent<StrongWeak> strongWeak = new StrongWeak();
2355 Persistent<WeakWeak> weakWeak = new WeakWeak();
2356
2357 Persistent<WeakSet> weakSet = new WeakSet();
2358
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002359 PersistentHeapVector<Member<IntWrapper> > keepNumbersAlive;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002360 for (int i = 0; i < 128; i += 2) {
2361 IntWrapper* wrapped = IntWrapper::create(i);
2362 IntWrapper* wrapped2 = IntWrapper::create(i + 1);
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002363 keepNumbersAlive.append(wrapped);
2364 keepNumbersAlive.append(wrapped2);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002365 weakStrong->add(wrapped, wrapped2);
2366 strongWeak->add(wrapped2, wrapped);
2367 weakWeak->add(wrapped, wrapped2);
2368 weakSet->add(wrapped);
2369 }
2370
2371 EXPECT_EQ(64u, weakStrong->size());
2372 EXPECT_EQ(64u, strongWeak->size());
2373 EXPECT_EQ(64u, weakWeak->size());
2374 EXPECT_EQ(64u, weakSet->size());
2375
2376 // Collect garbage. This should change nothing since we are keeping
2377 // alive the IntWrapper objects.
2378 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2379
2380 EXPECT_EQ(64u, weakStrong->size());
2381 EXPECT_EQ(64u, strongWeak->size());
2382 EXPECT_EQ(64u, weakWeak->size());
2383 EXPECT_EQ(64u, weakSet->size());
2384
2385 for (int i = 0; i < 128; i += 2) {
2386 IntWrapper* wrapped = keepNumbersAlive[i];
2387 IntWrapper* wrapped2 = keepNumbersAlive[i + 1];
2388 EXPECT_EQ(wrapped2, weakStrong->get(wrapped));
2389 EXPECT_EQ(wrapped, strongWeak->get(wrapped2));
2390 EXPECT_EQ(wrapped2, weakWeak->get(wrapped));
2391 EXPECT_TRUE(weakSet->contains(wrapped));
2392 }
2393
2394 for (int i = 0; i < 128; i += 3)
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002395 keepNumbersAlive[i] = nullptr;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002396
2397 if (collectionNumber != weakStrongIndex)
2398 weakStrong->clear();
2399 if (collectionNumber != strongWeakIndex)
2400 strongWeak->clear();
2401 if (collectionNumber != weakWeakIndex)
2402 weakWeak->clear();
2403 if (collectionNumber != weakSetIndex)
2404 weakSet->clear();
2405
2406 if (testThatIteratorsMakeStrong) {
2407 WeakStrong::iterator it1 = weakStrong->begin();
2408 StrongWeak::iterator it2 = strongWeak->begin();
2409 WeakWeak::iterator it3 = weakWeak->begin();
2410 WeakSet::iterator it4 = weakSet->begin();
2411 // Collect garbage. This should change nothing since the
2412 // iterators make the collections strong.
2413 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2414 if (collectionNumber == weakStrongIndex) {
2415 EXPECT_EQ(64u, weakStrong->size());
2416 MapIteratorCheck(it1, weakStrong->end(), 64);
2417 } else if (collectionNumber == strongWeakIndex) {
2418 EXPECT_EQ(64u, strongWeak->size());
2419 MapIteratorCheck(it2, strongWeak->end(), 64);
2420 } else if (collectionNumber == weakWeakIndex) {
2421 EXPECT_EQ(64u, weakWeak->size());
2422 MapIteratorCheck(it3, weakWeak->end(), 64);
2423 } else if (collectionNumber == weakSetIndex) {
2424 EXPECT_EQ(64u, weakSet->size());
2425 SetIteratorCheck(it4, weakSet->end(), 64);
2426 }
2427 } else {
2428 // Collect garbage. This causes weak processing to remove
2429 // things from the collections.
2430 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2431 unsigned count = 0;
2432 for (int i = 0; i < 128; i += 2) {
2433 bool firstAlive = keepNumbersAlive[i];
2434 bool secondAlive = keepNumbersAlive[i + 1];
2435 if (firstAlive && (collectionNumber == weakStrongIndex || collectionNumber == strongWeakIndex))
2436 secondAlive = true;
2437 if (firstAlive && secondAlive && collectionNumber < numberOfMapIndices) {
2438 if (collectionNumber == weakStrongIndex) {
2439 if (deleteAfterwards)
2440 EXPECT_EQ(i + 1, weakStrong->take(keepNumbersAlive[i])->value());
2441 } else if (collectionNumber == strongWeakIndex) {
2442 if (deleteAfterwards)
2443 EXPECT_EQ(i, strongWeak->take(keepNumbersAlive[i + 1])->value());
2444 } else if (collectionNumber == weakWeakIndex) {
2445 if (deleteAfterwards)
2446 EXPECT_EQ(i + 1, weakWeak->take(keepNumbersAlive[i])->value());
2447 }
2448 if (!deleteAfterwards)
2449 count++;
2450 } else if (collectionNumber == weakSetIndex && firstAlive) {
2451 ASSERT_TRUE(weakSet->contains(keepNumbersAlive[i]));
2452 if (deleteAfterwards)
2453 weakSet->remove(keepNumbersAlive[i]);
2454 else
2455 count++;
2456 }
2457 }
2458 if (addAfterwards) {
2459 for (int i = 1000; i < 1100; i++) {
2460 IntWrapper* wrapped = IntWrapper::create(i);
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002461 keepNumbersAlive.append(wrapped);
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002462 weakStrong->add(wrapped, wrapped);
2463 strongWeak->add(wrapped, wrapped);
2464 weakWeak->add(wrapped, wrapped);
2465 weakSet->add(wrapped);
2466 }
2467 }
2468 if (collectionNumber == weakStrongIndex)
2469 EXPECT_EQ(count + added, weakStrong->size());
2470 else if (collectionNumber == strongWeakIndex)
2471 EXPECT_EQ(count + added, strongWeak->size());
2472 else if (collectionNumber == weakWeakIndex)
2473 EXPECT_EQ(count + added, weakWeak->size());
2474 else if (collectionNumber == weakSetIndex)
2475 EXPECT_EQ(count + added, weakSet->size());
2476 WeakStrong::iterator it1 = weakStrong->begin();
2477 StrongWeak::iterator it2 = strongWeak->begin();
2478 WeakWeak::iterator it3 = weakWeak->begin();
2479 WeakSet::iterator it4 = weakSet->begin();
2480 MapIteratorCheck(it1, weakStrong->end(), (collectionNumber == weakStrongIndex ? count : 0) + added);
2481 MapIteratorCheck(it2, strongWeak->end(), (collectionNumber == strongWeakIndex ? count : 0) + added);
2482 MapIteratorCheck(it3, weakWeak->end(), (collectionNumber == weakWeakIndex ? count : 0) + added);
2483 SetIteratorCheck(it4, weakSet->end(), (collectionNumber == weakSetIndex ? count : 0) + added);
2484 }
2485 for (unsigned i = 0; i < 128 + added; i++)
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002486 keepNumbersAlive[i] = nullptr;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002487 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2488 EXPECT_EQ(added, weakStrong->size());
2489 EXPECT_EQ(added, strongWeak->size());
2490 EXPECT_EQ(added, weakWeak->size());
2491 EXPECT_EQ(added, weakSet->size());
2492 }
2493 }
2494}
2495
2496TEST(HeapTest, RefCountedGarbageCollected)
2497{
2498 RefCountedAndGarbageCollected::s_destructorCalls = 0;
2499 {
2500 RefPtr<RefCountedAndGarbageCollected> refPtr3;
2501 {
2502 Persistent<RefCountedAndGarbageCollected> persistent;
2503 {
2504 RefPtr<RefCountedAndGarbageCollected> refPtr1 = RefCountedAndGarbageCollected::create();
2505 RefPtr<RefCountedAndGarbageCollected> refPtr2 = RefCountedAndGarbageCollected::create();
2506 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2507 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2508 persistent = refPtr1.get();
2509 }
2510 // Reference count is zero for both objects but one of
2511 // them is kept alive by a persistent handle.
2512 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2513 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2514 refPtr3 = persistent;
2515 }
2516 // The persistent handle is gone but the ref count has been
2517 // increased to 1.
2518 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2519 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2520 }
2521 // Both persistent handle is gone and ref count is zero so the
2522 // object can be collected.
2523 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2524 EXPECT_EQ(2, RefCountedAndGarbageCollected::s_destructorCalls);
2525}
2526
2527TEST(HeapTest, RefCountedGarbageCollectedWithStackPointers)
2528{
2529 RefCountedAndGarbageCollected::s_destructorCalls = 0;
2530 RefCountedAndGarbageCollected2::s_destructorCalls = 0;
2531 {
2532 RefCountedAndGarbageCollected* pointer1 = 0;
2533 RefCountedAndGarbageCollected2* pointer2 = 0;
2534 {
2535 RefPtr<RefCountedAndGarbageCollected> object1 = RefCountedAndGarbageCollected::create();
2536 RefPtr<RefCountedAndGarbageCollected2> object2 = RefCountedAndGarbageCollected2::create();
2537 pointer1 = object1.get();
2538 pointer2 = object2.get();
2539 void* objects[2] = { object1.get(), object2.get() };
2540 RefCountedGarbageCollectedVisitor visitor(2, objects);
2541 ThreadState::current()->visitPersistents(&visitor);
2542 EXPECT_TRUE(visitor.validate());
2543
2544 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2545 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2546 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2547 }
2548 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2549 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2550 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2551
2552 // At this point, the reference counts of object1 and object2 are 0.
2553 // Only pointer1 and pointer2 keep references to object1 and object2.
2554 void* objects[] = { 0 };
2555 RefCountedGarbageCollectedVisitor visitor(0, objects);
2556 ThreadState::current()->visitPersistents(&visitor);
2557 EXPECT_TRUE(visitor.validate());
2558
2559 {
2560 RefPtr<RefCountedAndGarbageCollected> object1(pointer1);
2561 RefPtr<RefCountedAndGarbageCollected2> object2(pointer2);
2562 void* objects[2] = { object1.get(), object2.get() };
2563 RefCountedGarbageCollectedVisitor visitor(2, objects);
2564 ThreadState::current()->visitPersistents(&visitor);
2565 EXPECT_TRUE(visitor.validate());
2566
2567 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2568 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2569 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2570 }
2571
2572 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2573 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls);
2574 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls);
2575 }
2576
2577 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2578 EXPECT_EQ(1, RefCountedAndGarbageCollected::s_destructorCalls);
2579 EXPECT_EQ(1, RefCountedAndGarbageCollected2::s_destructorCalls);
2580}
2581
2582TEST(HeapTest, WeakMembers)
2583{
2584 Bar::s_live = 0;
2585 {
2586 Persistent<Bar> h1 = Bar::create();
2587 Persistent<Weak> h4;
2588 Persistent<WithWeakMember> h5;
2589 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2590 ASSERT_EQ(1u, Bar::s_live); // h1 is live.
2591 {
2592 Bar* h2 = Bar::create();
2593 Bar* h3 = Bar::create();
2594 h4 = Weak::create(h2, h3);
2595 h5 = WithWeakMember::create(h2, h3);
2596 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2597 EXPECT_EQ(5u, Bar::s_live); // The on-stack pointer keeps h3 alive.
2598 EXPECT_TRUE(h4->strongIsThere());
2599 EXPECT_TRUE(h4->weakIsThere());
2600 EXPECT_TRUE(h5->strongIsThere());
2601 EXPECT_TRUE(h5->weakIsThere());
2602 }
2603 // h3 is collected, weak pointers from h4 and h5 don't keep it alive.
2604 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2605 EXPECT_EQ(4u, Bar::s_live);
2606 EXPECT_TRUE(h4->strongIsThere());
2607 EXPECT_FALSE(h4->weakIsThere()); // h3 is gone from weak pointer.
2608 EXPECT_TRUE(h5->strongIsThere());
2609 EXPECT_FALSE(h5->weakIsThere()); // h3 is gone from weak pointer.
2610 h1.release(); // Zero out h1.
2611 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2612 EXPECT_EQ(3u, Bar::s_live); // Only h4, h5 and h2 are left.
2613 EXPECT_TRUE(h4->strongIsThere()); // h2 is still pointed to from h4.
2614 EXPECT_TRUE(h5->strongIsThere()); // h2 is still pointed to from h5.
2615 }
2616 // h4 and h5 have gone out of scope now and they were keeping h2 alive.
2617 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2618 EXPECT_EQ(0u, Bar::s_live); // All gone.
2619}
2620
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002621TEST(HeapTest, FinalizationObserver)
2622{
2623 Persistent<FinalizationObserver<Observable> > o;
2624 {
2625 Observable* foo = Observable::create(Bar::create());
2626 // |o| observes |foo|.
2627 o = FinalizationObserver<Observable>::create(foo);
2628 }
2629 // FinalizationObserver doesn't have a strong reference to |foo|. So |foo|
2630 // and its member will be collected.
2631 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2632 EXPECT_EQ(0u, Bar::s_live);
2633 EXPECT_TRUE(o->didCallWillFinalize());
2634}
2635
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002636TEST(HeapTest, Comparisons)
2637{
2638 Persistent<Bar> barPersistent = Bar::create();
2639 Persistent<Foo> fooPersistent = Foo::create(barPersistent);
2640 EXPECT_TRUE(barPersistent != fooPersistent);
2641 barPersistent = fooPersistent;
2642 EXPECT_TRUE(barPersistent == fooPersistent);
2643}
2644
2645TEST(HeapTest, CheckAndMarkPointer)
2646{
2647 HeapStats initialHeapStats;
2648 clearOutOldGarbage(&initialHeapStats);
2649
2650 Vector<Address> objectAddresses;
2651 Vector<Address> endAddresses;
2652 Address largeObjectAddress;
2653 Address largeObjectEndAddress;
2654 CountingVisitor visitor;
2655 for (int i = 0; i < 10; i++) {
2656 SimpleObject* object = SimpleObject::create();
2657 Address objectAddress = reinterpret_cast<Address>(object);
2658 objectAddresses.append(objectAddress);
2659 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1);
2660 }
2661 LargeObject* largeObject = LargeObject::create();
2662 largeObjectAddress = reinterpret_cast<Address>(largeObject);
2663 largeObjectEndAddress = largeObjectAddress + sizeof(LargeObject) - 1;
2664
2665 // This is a low-level test where we call checkAndMarkPointer. This method
2666 // causes the object start bitmap to be computed which requires the heap
2667 // to be in a consistent state (e.g. the free allocation area must be put
2668 // into a free list header). However when we call makeConsistentForGC it
2669 // also clears out the freelists so we have to rebuild those before trying
2670 // to allocate anything again. We do this by forcing a GC after doing the
2671 // checkAndMarkPointer tests.
2672 {
2673 TestGCScope scope(ThreadState::HeapPointersOnStack);
2674 Heap::makeConsistentForGC();
2675 for (size_t i = 0; i < objectAddresses.size(); i++) {
2676 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
2677 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
2678 }
2679 EXPECT_EQ(objectAddresses.size() * 2, visitor.count());
2680 visitor.reset();
2681 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
2682 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
2683 EXPECT_EQ(2ul, visitor.count());
2684 visitor.reset();
2685 }
2686 // This forces a GC without stack scanning which results in the objects
2687 // being collected. This will also rebuild the above mentioned freelists,
2688 // however we don't rely on that below since we don't have any allocations.
2689 clearOutOldGarbage(&initialHeapStats);
2690 {
2691 TestGCScope scope(ThreadState::HeapPointersOnStack);
2692 Heap::makeConsistentForGC();
2693 for (size_t i = 0; i < objectAddresses.size(); i++) {
2694 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i]));
2695 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, endAddresses[i]));
2696 }
2697 EXPECT_EQ(0ul, visitor.count());
2698 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress));
2699 EXPECT_FALSE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress));
2700 EXPECT_EQ(0ul, visitor.count());
2701 }
2702 // This round of GC is important to make sure that the object start
2703 // bitmap are cleared out and that the free lists are rebuild.
2704 clearOutOldGarbage(&initialHeapStats);
2705}
2706
2707TEST(HeapTest, VisitOffHeapCollections)
2708{
2709 HeapStats initialHeapStats;
2710 clearOutOldGarbage(&initialHeapStats);
2711 IntWrapper::s_destructorCalls = 0;
2712 Persistent<OffHeapContainer> container = OffHeapContainer::create();
2713 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2714 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002715 container = nullptr;
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002716 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2717 EXPECT_EQ(7, IntWrapper::s_destructorCalls);
2718}
2719
2720TEST(HeapTest, PersistentHeapCollectionTypes)
2721{
2722 HeapStats initialHeapSize;
2723 IntWrapper::s_destructorCalls = 0;
2724
2725 typedef HeapVector<Member<IntWrapper> > Vec;
2726 typedef PersistentHeapVector<Member<IntWrapper> > PVec;
2727 typedef PersistentHeapHashSet<Member<IntWrapper> > PSet;
2728 typedef PersistentHeapHashMap<Member<IntWrapper>, Member<IntWrapper> > PMap;
2729
2730 clearOutOldGarbage(&initialHeapSize);
2731 {
2732 PVec pVec;
2733 PSet pSet;
2734 PMap pMap;
2735
2736 IntWrapper* one(IntWrapper::create(1));
2737 IntWrapper* two(IntWrapper::create(2));
2738 IntWrapper* three(IntWrapper::create(3));
2739 IntWrapper* four(IntWrapper::create(4));
2740 IntWrapper* five(IntWrapper::create(5));
2741 IntWrapper* six(IntWrapper::create(6));
2742
2743 pVec.append(one);
2744 pVec.append(two);
2745
2746 Vec* vec = new Vec();
2747 vec->swap(pVec);
2748
2749 pVec.append(two);
2750 pVec.append(three);
2751
2752 pSet.add(four);
2753 pMap.add(five, six);
2754
2755 // Collect |vec| and |one|.
2756 vec = 0;
2757 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2758 EXPECT_EQ(1, IntWrapper::s_destructorCalls);
2759
2760 EXPECT_EQ(2u, pVec.size());
2761 EXPECT_TRUE(pVec.at(0) == two);
2762 EXPECT_TRUE(pVec.at(1) == three);
2763
2764 EXPECT_EQ(1u, pSet.size());
2765 EXPECT_TRUE(pSet.contains(four));
2766
2767 EXPECT_EQ(1u, pMap.size());
2768 EXPECT_TRUE(pMap.get(five) == six);
2769 }
2770
2771 // Collect previous roots.
2772 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2773 EXPECT_EQ(6, IntWrapper::s_destructorCalls);
2774}
2775
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002776TEST(HeapTest, CollectionNesting)
2777{
2778 HeapStats initialStats;
2779 clearOutOldGarbage(&initialStats);
2780 void* key = &IntWrapper::s_destructorCalls;
2781 IntWrapper::s_destructorCalls = 0;
2782 typedef HeapVector<Member<IntWrapper> > IntVector;
2783 HeapHashMap<void*, IntVector>* map = new HeapHashMap<void*, IntVector>();
Torne (Richard Coles)09380292014-02-21 12:17:33 +00002784
Torne (Richard Coles)d5428f32014-03-18 10:21:16 +00002785 map->add(key, IntVector());
2786
2787 HeapHashMap<void*, IntVector>::iterator it = map->find(key);
2788 EXPECT_EQ(0u, map->get(key).size());
2789
2790 it->value.append(IntWrapper::create(42));
2791 EXPECT_EQ(1u, map->get(key).size());
2792
2793 Persistent<HeapHashMap<void*, IntVector> > keepAlive(map);
2794 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2795 EXPECT_EQ(1u, map->get(key).size());
2796 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2797}
2798
2799TEST(heap, GarbageCollectedMixin)
2800{
2801 HeapStats initialHeapStats;
2802 clearOutOldGarbage(&initialHeapStats);
2803
2804 Persistent<UseMixin> usemixin = UseMixin::create();
2805 ASSERT_EQ(0, UseMixin::s_traceCount);
2806 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2807 ASSERT_EQ(1, UseMixin::s_traceCount);
2808
2809 Persistent<Mixin> mixin = usemixin;
2810 usemixin = nullptr;
2811 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2812 ASSERT_EQ(2, UseMixin::s_traceCount);
2813}
2814
2815TEST(HeapTest, CollectionNesting2)
2816{
2817 HeapStats initialStats;
2818 clearOutOldGarbage(&initialStats);
2819 void* key = &IntWrapper::s_destructorCalls;
2820 IntWrapper::s_destructorCalls = 0;
2821 typedef HeapHashSet<Member<IntWrapper> > IntSet;
2822 HeapHashMap<void*, IntSet>* map = new HeapHashMap<void*, IntSet>();
2823
2824 map->add(key, IntSet());
2825
2826 HeapHashMap<void*, IntSet>::iterator it = map->find(key);
2827 EXPECT_EQ(0u, map->get(key).size());
2828
2829 it->value.add(IntWrapper::create(42));
2830 EXPECT_EQ(1u, map->get(key).size());
2831
2832 Persistent<HeapHashMap<void*, IntSet> > keepAlive(map);
2833 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2834 EXPECT_EQ(1u, map->get(key).size());
2835 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2836}
2837
2838TEST(HeapTest, CollectionNesting3)
2839{
2840 HeapStats initialStats;
2841 clearOutOldGarbage(&initialStats);
2842 IntWrapper::s_destructorCalls = 0;
2843 typedef HeapVector<Member<IntWrapper> > IntVector;
2844 HeapVector<IntVector>* vector = new HeapVector<IntVector>();
2845
2846 vector->append(IntVector());
2847
2848 HeapVector<IntVector>::iterator it = vector->begin();
2849 EXPECT_EQ(0u, it->size());
2850
2851 it->append(IntWrapper::create(42));
2852 EXPECT_EQ(1u, it->size());
2853
2854 Persistent<HeapVector<IntVector> > keepAlive(vector);
2855 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2856 EXPECT_EQ(1u, it->size());
2857 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2858}
2859
2860TEST(HeapTest, EmbeddedInVector)
2861{
2862 HeapStats initialStats;
2863 clearOutOldGarbage(&initialStats);
2864 SimpleFinalizedObject::s_destructorCalls = 0;
2865 {
2866 PersistentHeapVector<VectorObject, 2> inlineVector;
2867 PersistentHeapVector<VectorObject> outlineVector;
2868 VectorObject i1, i2;
2869 inlineVector.append(i1);
2870 inlineVector.append(i2);
2871
2872 VectorObject o1, o2;
2873 outlineVector.append(o1);
2874 outlineVector.append(o2);
2875
2876 PersistentHeapVector<VectorObjectInheritedTrace> vectorInheritedTrace;
2877 VectorObjectInheritedTrace it1, it2;
2878 vectorInheritedTrace.append(it1);
2879 vectorInheritedTrace.append(it2);
2880
2881 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2882 EXPECT_EQ(0, SimpleFinalizedObject::s_destructorCalls);
2883
2884 // Since VectorObjectNoTrace has no trace method it will
2885 // not be traced and hence be collected when doing GC.
2886 // We trace items in a collection braced on the item's
2887 // having a trace method. This is determined via the
2888 // NeedsTracing trait in wtf/TypeTraits.h.
2889 PersistentHeapVector<VectorObjectNoTrace> vectorNoTrace;
2890 VectorObjectNoTrace n1, n2;
2891 vectorNoTrace.append(n1);
2892 vectorNoTrace.append(n2);
2893 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2894 EXPECT_EQ(2, SimpleFinalizedObject::s_destructorCalls);
2895 }
2896 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2897 EXPECT_EQ(8, SimpleFinalizedObject::s_destructorCalls);
2898}
2899
2900TEST(HeapTest, RawPtrInHash)
2901{
2902 HashSet<RawPtr<int> > set;
2903 set.add(new int(42));
2904 set.add(new int(42));
2905 EXPECT_EQ(2u, set.size());
2906 for (HashSet<RawPtr<int> >::iterator it = set.begin(); it != set.end(); ++it)
2907 EXPECT_EQ(42, **it);
2908}
2909
2910TEST(HeapTest, HeapTerminatedArray)
2911{
2912 HeapStats initialHeapSize;
2913 clearOutOldGarbage(&initialHeapSize);
2914 IntWrapper::s_destructorCalls = 0;
2915
2916 HeapTerminatedArray<TerminatedArrayItem>* arr = 0;
2917
2918 const size_t prefixSize = 4;
2919 const size_t suffixSize = 4;
2920
2921 {
2922 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
2923 builder.grow(prefixSize);
2924 for (size_t i = 0; i < prefixSize; i++)
2925 builder.append(TerminatedArrayItem(IntWrapper::create(i)));
2926 arr = builder.release();
2927 }
2928
2929 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2930 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2931 EXPECT_EQ(prefixSize, arr->size());
2932 for (size_t i = 0; i < prefixSize; i++)
2933 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
2934
2935 {
2936 HeapTerminatedArrayBuilder<TerminatedArrayItem> builder(arr);
2937 builder.grow(suffixSize);
2938 for (size_t i = 0; i < suffixSize; i++)
2939 builder.append(TerminatedArrayItem(IntWrapper::create(prefixSize + i)));
2940 arr = builder.release();
2941 }
2942
2943 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2944 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2945 EXPECT_EQ(prefixSize + suffixSize, arr->size());
2946 for (size_t i = 0; i < prefixSize + suffixSize; i++)
2947 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
2948
2949 {
2950 Persistent<HeapTerminatedArray<TerminatedArrayItem> > persistentArr = arr;
2951 arr = 0;
2952 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2953 arr = persistentArr.get();
2954 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2955 EXPECT_EQ(prefixSize + suffixSize, arr->size());
2956 for (size_t i = 0; i < prefixSize + suffixSize; i++)
2957 EXPECT_EQ(i, static_cast<size_t>(arr->at(i).payload()->value()));
2958 }
2959
2960 arr = 0;
2961 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2962 EXPECT_EQ(8, IntWrapper::s_destructorCalls);
2963}
2964
2965TEST(HeapTest, HeapLinkedStack)
2966{
2967 HeapStats initialHeapSize;
2968 clearOutOldGarbage(&initialHeapSize);
2969 IntWrapper::s_destructorCalls = 0;
2970
2971 HeapLinkedStack<TerminatedArrayItem>* stack = new HeapLinkedStack<TerminatedArrayItem>();
2972
2973 const size_t stackSize = 10;
2974
2975 for (size_t i = 0; i < stackSize; i++)
2976 stack->push(TerminatedArrayItem(IntWrapper::create(i)));
2977
2978 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
2979 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
2980 EXPECT_EQ(stackSize, stack->size());
2981 while (!stack->isEmpty()) {
2982 EXPECT_EQ(stack->size() - 1, static_cast<size_t>(stack->peek().payload()->value()));
2983 stack->pop();
2984 }
2985
2986 Persistent<HeapLinkedStack<TerminatedArrayItem> > pStack = stack;
2987
2988 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
2989 EXPECT_EQ(stackSize, static_cast<size_t>(IntWrapper::s_destructorCalls));
2990 EXPECT_EQ(0u, pStack->size());
2991}
2992
2993TEST(HeapTest, AllocationDuringFinalization)
2994{
2995 HeapStats initialHeapSize;
2996 clearOutOldGarbage(&initialHeapSize);
2997 IntWrapper::s_destructorCalls = 0;
2998 OneKiloByteObject::s_destructorCalls = 0;
2999
3000 Persistent<IntWrapper> wrapper;
3001 new FinalizationAllocator(&wrapper);
3002
3003 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3004 EXPECT_EQ(0, IntWrapper::s_destructorCalls);
3005 // Check that the wrapper allocated during finalization is not
3006 // swept away and zapped later in the same sweeping phase.
3007 EXPECT_EQ(42, wrapper->value());
3008
3009 wrapper.clear();
3010 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
3011 EXPECT_EQ(10, IntWrapper::s_destructorCalls);
3012 EXPECT_EQ(512, OneKiloByteObject::s_destructorCalls);
3013}
3014
3015} // WebCore namespace