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