| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 namespace blink { | 242 namespace blink { |
| 243 | 243 |
| 244 class TestGCScope { | 244 class TestGCScope { |
| 245 public: | 245 public: |
| 246 explicit TestGCScope(BlinkGC::StackState state) | 246 explicit TestGCScope(BlinkGC::StackState state) |
| 247 : m_state(ThreadState::current()) | 247 : m_state(ThreadState::current()) |
| 248 , m_safePointScope(state) | 248 , m_safePointScope(state) |
| 249 , m_parkedAllThreads(false) | 249 , m_parkedAllThreads(false) |
| 250 { | 250 { |
| 251 ASSERT(m_state->checkThread()); | 251 ASSERT(m_state->checkThread()); |
| 252 if (LIKELY(m_state->heap().park())) { | 252 if (LIKELY(ThreadState::stopThreads())) { |
| 253 m_state->heap().preGC(); | 253 ThreadHeap::preGC(); |
| 254 m_parkedAllThreads = true; | 254 m_parkedAllThreads = true; |
| 255 } | 255 } |
| 256 } | 256 } |
| 257 | 257 |
| 258 bool allThreadsParked() { return m_parkedAllThreads; } | 258 bool allThreadsParked() { return m_parkedAllThreads; } |
| 259 | 259 |
| 260 ~TestGCScope() | 260 ~TestGCScope() |
| 261 { | 261 { |
| 262 // Only cleanup if we parked all threads in which case the GC happened | 262 // Only cleanup if we parked all threads in which case the GC happened |
| 263 // and we need to resume the other threads. | 263 // and we need to resume the other threads. |
| 264 if (LIKELY(m_parkedAllThreads)) { | 264 if (LIKELY(m_parkedAllThreads)) { |
| 265 m_state->heap().postGC(BlinkGC::GCWithSweep); | 265 ThreadHeap::postGC(BlinkGC::GCWithSweep); |
| 266 m_state->heap().resume(); | 266 ThreadState::resumeThreads(); |
| 267 } | 267 } |
| 268 } | 268 } |
| 269 | 269 |
| 270 private: | 270 private: |
| 271 ThreadState* m_state; | 271 ThreadState* m_state; |
| 272 SafePointScope m_safePointScope; | 272 SafePointScope m_safePointScope; |
| 273 bool m_parkedAllThreads; // False if we fail to park all threads | 273 bool m_parkedAllThreads; // False if we fail to park all threads |
| 274 }; | 274 }; |
| 275 | 275 |
| 276 #define DEFINE_VISITOR_METHODS(Type) \ | 276 #define DEFINE_VISITOR_METHODS(Type) \ |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 DEFINE_INLINE_TRACE() { } | 412 DEFINE_INLINE_TRACE() { } |
| 413 private: | 413 private: |
| 414 static const int s_arraySize = 1000; | 414 static const int s_arraySize = 1000; |
| 415 int8_t m_array[s_arraySize]; | 415 int8_t m_array[s_arraySize]; |
| 416 }; | 416 }; |
| 417 | 417 |
| 418 // Do several GCs to make sure that later GCs don't free up old memory from | 418 // Do several GCs to make sure that later GCs don't free up old memory from |
| 419 // previously run tests in this process. | 419 // previously run tests in this process. |
| 420 static void clearOutOldGarbage() | 420 static void clearOutOldGarbage() |
| 421 { | 421 { |
| 422 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 423 while (true) { | 422 while (true) { |
| 424 size_t used = heap.objectPayloadSizeForTesting(); | 423 size_t used = ThreadHeap::objectPayloadSizeForTesting(); |
| 425 preciselyCollectGarbage(); | 424 preciselyCollectGarbage(); |
| 426 if (heap.objectPayloadSizeForTesting() >= used) | 425 if (ThreadHeap::objectPayloadSizeForTesting() >= used) |
| 427 break; | 426 break; |
| 428 } | 427 } |
| 429 } | 428 } |
| 430 | 429 |
| 431 class OffHeapInt : public RefCounted<OffHeapInt> { | 430 class OffHeapInt : public RefCounted<OffHeapInt> { |
| 432 public: | 431 public: |
| 433 static RefPtr<OffHeapInt> create(int x) | 432 static RefPtr<OffHeapInt> create(int x) |
| 434 { | 433 { |
| 435 return adoptRef(new OffHeapInt(x)); | 434 return adoptRef(new OffHeapInt(x)); |
| 436 } | 435 } |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>; | 517 using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>; |
| 519 | 518 |
| 520 PassOwnPtr<GlobalIntWrapperPersistent> createGlobalPersistent(int value) | 519 PassOwnPtr<GlobalIntWrapperPersistent> createGlobalPersistent(int value) |
| 521 { | 520 { |
| 522 return adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(value)
)); | 521 return adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(value)
)); |
| 523 } | 522 } |
| 524 | 523 |
| 525 void runThread() override | 524 void runThread() override |
| 526 { | 525 { |
| 527 OwnPtr<GlobalIntWrapperPersistent> longLivingPersistent; | 526 OwnPtr<GlobalIntWrapperPersistent> longLivingPersistent; |
| 528 ThreadState::attachCurrentThread(); | 527 ThreadState::attach(); |
| 529 | 528 |
| 530 longLivingPersistent = createGlobalPersistent(0x2a2a2a2a); | 529 longLivingPersistent = createGlobalPersistent(0x2a2a2a2a); |
| 531 int gcCount = 0; | 530 int gcCount = 0; |
| 532 while (!done()) { | 531 while (!done()) { |
| 533 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); | 532 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 534 { | 533 { |
| 535 Persistent<IntWrapper> wrapper; | 534 Persistent<IntWrapper> wrapper; |
| 536 | 535 |
| 537 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = createGlob
alPersistent(0x0ed0cabb); | 536 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = createGlob
alPersistent(0x0ed0cabb); |
| 538 | 537 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 562 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 561 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 563 testing::yieldCurrentThread(); | 562 testing::yieldCurrentThread(); |
| 564 } | 563 } |
| 565 | 564 |
| 566 // Intentionally leak the cross-thread persistent so as to verify | 565 // Intentionally leak the cross-thread persistent so as to verify |
| 567 // that later GCs correctly handle cross-thread persistents that | 566 // that later GCs correctly handle cross-thread persistents that |
| 568 // refer to finalized objects after their heaps have been detached | 567 // refer to finalized objects after their heaps have been detached |
| 569 // and freed. | 568 // and freed. |
| 570 EXPECT_TRUE(longLivingPersistent.leakPtr()); | 569 EXPECT_TRUE(longLivingPersistent.leakPtr()); |
| 571 | 570 |
| 572 ThreadState::detachCurrentThread(); | 571 ThreadState::detach(); |
| 573 atomicDecrement(&m_threadsToFinish); | 572 atomicDecrement(&m_threadsToFinish); |
| 574 } | 573 } |
| 575 }; | 574 }; |
| 576 | 575 |
| 577 class ThreadedWeaknessTester : public ThreadedTesterBase { | 576 class ThreadedWeaknessTester : public ThreadedTesterBase { |
| 578 public: | 577 public: |
| 579 static void test() | 578 static void test() |
| 580 { | 579 { |
| 581 ThreadedTesterBase::test(new ThreadedWeaknessTester); | 580 ThreadedTesterBase::test(new ThreadedWeaknessTester); |
| 582 } | 581 } |
| 583 | 582 |
| 584 private: | 583 private: |
| 585 void runThread() override | 584 void runThread() override |
| 586 { | 585 { |
| 587 ThreadState::attachCurrentThread(); | 586 ThreadState::attach(); |
| 588 | 587 |
| 589 int gcCount = 0; | 588 int gcCount = 0; |
| 590 while (!done()) { | 589 while (!done()) { |
| 591 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); | 590 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 592 { | 591 { |
| 593 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> we
akMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>; | 592 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> we
akMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>; |
| 594 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper>> weak
Map2; | 593 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper>> weak
Map2; |
| 595 | 594 |
| 596 for (int i = 0; i < numberOfAllocations; i++) { | 595 for (int i = 0; i < numberOfAllocations; i++) { |
| 597 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0)
); | 596 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0)
); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 610 // TODO(haraken): This snapshot GC causes crashes, so disable | 609 // TODO(haraken): This snapshot GC causes crashes, so disable |
| 611 // it at the moment. Fix the crash and enable it. | 610 // it at the moment. Fix the crash and enable it. |
| 612 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, Bl
inkGC::TakeSnapshot, BlinkGC::ForcedGC); | 611 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, Bl
inkGC::TakeSnapshot, BlinkGC::ForcedGC); |
| 613 preciselyCollectGarbage(); | 612 preciselyCollectGarbage(); |
| 614 EXPECT_TRUE(weakMap->isEmpty()); | 613 EXPECT_TRUE(weakMap->isEmpty()); |
| 615 EXPECT_TRUE(weakMap2.isEmpty()); | 614 EXPECT_TRUE(weakMap2.isEmpty()); |
| 616 } | 615 } |
| 617 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 616 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 618 testing::yieldCurrentThread(); | 617 testing::yieldCurrentThread(); |
| 619 } | 618 } |
| 620 ThreadState::detachCurrentThread(); | 619 ThreadState::detach(); |
| 621 atomicDecrement(&m_threadsToFinish); | 620 atomicDecrement(&m_threadsToFinish); |
| 622 } | 621 } |
| 623 }; | 622 }; |
| 624 | 623 |
| 625 class ThreadPersistentHeapTester : public ThreadedTesterBase { | 624 class ThreadPersistentHeapTester : public ThreadedTesterBase { |
| 626 public: | 625 public: |
| 627 static void test() | 626 static void test() |
| 628 { | 627 { |
| 629 ThreadedTesterBase::test(new ThreadPersistentHeapTester); | 628 ThreadedTesterBase::test(new ThreadPersistentHeapTester); |
| 630 } | 629 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 671 explicit PersistentChain(int count) | 670 explicit PersistentChain(int count) |
| 672 { | 671 { |
| 673 m_refCountedChain = adoptRef(RefCountedChain::create(count)); | 672 m_refCountedChain = adoptRef(RefCountedChain::create(count)); |
| 674 } | 673 } |
| 675 | 674 |
| 676 RefPtr<RefCountedChain> m_refCountedChain; | 675 RefPtr<RefCountedChain> m_refCountedChain; |
| 677 }; | 676 }; |
| 678 | 677 |
| 679 void runThread() override | 678 void runThread() override |
| 680 { | 679 { |
| 681 ThreadState::attachCurrentThread(); | 680 ThreadState::attach(); |
| 682 | 681 |
| 683 PersistentChain::create(100); | 682 PersistentChain::create(100); |
| 684 | 683 |
| 685 // Upon thread detach, GCs will run until all persistents have been | 684 // Upon thread detach, GCs will run until all persistents have been |
| 686 // released. We verify that the draining of persistents proceeds | 685 // released. We verify that the draining of persistents proceeds |
| 687 // as expected by dropping one Persistent<> per GC until there | 686 // as expected by dropping one Persistent<> per GC until there |
| 688 // are none left. | 687 // are none left. |
| 689 ThreadState::detachCurrentThread(); | 688 ThreadState::detach(); |
| 690 atomicDecrement(&m_threadsToFinish); | 689 atomicDecrement(&m_threadsToFinish); |
| 691 } | 690 } |
| 692 }; | 691 }; |
| 693 | 692 |
| 694 // The accounting for memory includes the memory used by rounding up object | 693 // The accounting for memory includes the memory used by rounding up object |
| 695 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to | 694 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to |
| 696 // have some slack in the tests. | 695 // have some slack in the tests. |
| 697 template<typename T> | 696 template<typename T> |
| 698 void CheckWithSlack(T expected, T actual, int slack) | 697 void CheckWithSlack(T expected, T actual, int slack) |
| 699 { | 698 { |
| (...skipping 1087 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1787 ThreadedWeaknessTester::test(); | 1786 ThreadedWeaknessTester::test(); |
| 1788 } | 1787 } |
| 1789 | 1788 |
| 1790 TEST(HeapTest, ThreadPersistent) | 1789 TEST(HeapTest, ThreadPersistent) |
| 1791 { | 1790 { |
| 1792 ThreadPersistentHeapTester::test(); | 1791 ThreadPersistentHeapTester::test(); |
| 1793 } | 1792 } |
| 1794 | 1793 |
| 1795 TEST(HeapTest, BasicFunctionality) | 1794 TEST(HeapTest, BasicFunctionality) |
| 1796 { | 1795 { |
| 1797 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 1798 clearOutOldGarbage(); | 1796 clearOutOldGarbage(); |
| 1799 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); | 1797 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); |
| 1800 { | 1798 { |
| 1801 size_t slack = 0; | 1799 size_t slack = 0; |
| 1802 | 1800 |
| 1803 // When the test starts there may already have been leaked some memory | 1801 // When the test starts there may already have been leaked some memory |
| 1804 // on the heap, so we establish a base line. | 1802 // on the heap, so we establish a base line. |
| 1805 size_t baseLevel = initialObjectPayloadSize; | 1803 size_t baseLevel = initialObjectPayloadSize; |
| 1806 bool testPagesAllocated = !baseLevel; | 1804 bool testPagesAllocated = !baseLevel; |
| 1807 if (testPagesAllocated) | 1805 if (testPagesAllocated) |
| 1808 EXPECT_EQ(heap.heapStats().allocatedSpace(), 0ul); | 1806 EXPECT_EQ(ThreadHeap::heapStats().allocatedSpace(), 0ul); |
| 1809 | 1807 |
| 1810 // This allocates objects on the general heap which should add a page of
memory. | 1808 // This allocates objects on the general heap which should add a page of
memory. |
| 1811 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); | 1809 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); |
| 1812 slack += 4; | 1810 slack += 4; |
| 1813 memset(alloc32, 40, 32); | 1811 memset(alloc32, 40, 32); |
| 1814 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); | 1812 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); |
| 1815 slack += 4; | 1813 slack += 4; |
| 1816 memset(alloc64, 27, 64); | 1814 memset(alloc64, 27, 64); |
| 1817 | 1815 |
| 1818 size_t total = 96; | 1816 size_t total = 96; |
| 1819 | 1817 |
| 1820 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), sl
ack); | 1818 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTestin
g(), slack); |
| 1821 if (testPagesAllocated) | 1819 if (testPagesAllocated) |
| 1822 EXPECT_EQ(heap.heapStats().allocatedSpace(), blinkPageSize * 2); | 1820 EXPECT_EQ(ThreadHeap::heapStats().allocatedSpace(), blinkPageSize *
2); |
| 1823 | 1821 |
| 1824 EXPECT_EQ(alloc32->get(0), 40); | 1822 EXPECT_EQ(alloc32->get(0), 40); |
| 1825 EXPECT_EQ(alloc32->get(31), 40); | 1823 EXPECT_EQ(alloc32->get(31), 40); |
| 1826 EXPECT_EQ(alloc64->get(0), 27); | 1824 EXPECT_EQ(alloc64->get(0), 27); |
| 1827 EXPECT_EQ(alloc64->get(63), 27); | 1825 EXPECT_EQ(alloc64->get(63), 27); |
| 1828 | 1826 |
| 1829 conservativelyCollectGarbage(); | 1827 conservativelyCollectGarbage(); |
| 1830 | 1828 |
| 1831 EXPECT_EQ(alloc32->get(0), 40); | 1829 EXPECT_EQ(alloc32->get(0), 40); |
| 1832 EXPECT_EQ(alloc32->get(31), 40); | 1830 EXPECT_EQ(alloc32->get(31), 40); |
| 1833 EXPECT_EQ(alloc64->get(0), 27); | 1831 EXPECT_EQ(alloc64->get(0), 27); |
| 1834 EXPECT_EQ(alloc64->get(63), 27); | 1832 EXPECT_EQ(alloc64->get(63), 27); |
| 1835 } | 1833 } |
| 1836 | 1834 |
| 1837 clearOutOldGarbage(); | 1835 clearOutOldGarbage(); |
| 1838 size_t total = 0; | 1836 size_t total = 0; |
| 1839 size_t slack = 0; | 1837 size_t slack = 0; |
| 1840 size_t baseLevel = heap.objectPayloadSizeForTesting(); | 1838 size_t baseLevel = ThreadHeap::objectPayloadSizeForTesting(); |
| 1841 bool testPagesAllocated = !baseLevel; | 1839 bool testPagesAllocated = !baseLevel; |
| 1842 if (testPagesAllocated) | 1840 if (testPagesAllocated) |
| 1843 EXPECT_EQ(heap.heapStats().allocatedSpace(), 0ul); | 1841 EXPECT_EQ(ThreadHeap::heapStats().allocatedSpace(), 0ul); |
| 1844 | 1842 |
| 1845 size_t big = 1008; | 1843 size_t big = 1008; |
| 1846 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(
big); | 1844 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(
big); |
| 1847 total += big; | 1845 total += big; |
| 1848 slack += 4; | 1846 slack += 4; |
| 1849 | 1847 |
| 1850 size_t persistentCount = 0; | 1848 size_t persistentCount = 0; |
| 1851 const size_t numPersistents = 100000; | 1849 const size_t numPersistents = 100000; |
| 1852 Persistent<DynamicallySizedObject>* persistents[numPersistents]; | 1850 Persistent<DynamicallySizedObject>* persistents[numPersistents]; |
| 1853 | 1851 |
| 1854 for (int i = 0; i < 1000; i++) { | 1852 for (int i = 0; i < 1000; i++) { |
| 1855 size_t size = 128 + i * 8; | 1853 size_t size = 128 + i * 8; |
| 1856 total += size; | 1854 total += size; |
| 1857 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(
DynamicallySizedObject::create(size)); | 1855 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(
DynamicallySizedObject::create(size)); |
| 1858 slack += 4; | 1856 slack += 4; |
| 1859 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), sl
ack); | 1857 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTestin
g(), slack); |
| 1860 if (testPagesAllocated) | 1858 if (testPagesAllocated) |
| 1861 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize -
1)); | 1859 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPage
Size - 1)); |
| 1862 } | 1860 } |
| 1863 | 1861 |
| 1864 { | 1862 { |
| 1865 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32)); | 1863 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32)); |
| 1866 slack += 4; | 1864 slack += 4; |
| 1867 memset(alloc32b, 40, 32); | 1865 memset(alloc32b, 40, 32); |
| 1868 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64)); | 1866 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64)); |
| 1869 slack += 4; | 1867 slack += 4; |
| 1870 memset(alloc64b, 27, 64); | 1868 memset(alloc64b, 27, 64); |
| 1871 EXPECT_TRUE(alloc32b != alloc64b); | 1869 EXPECT_TRUE(alloc32b != alloc64b); |
| 1872 | 1870 |
| 1873 total += 96; | 1871 total += 96; |
| 1874 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), sl
ack); | 1872 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTestin
g(), slack); |
| 1875 if (testPagesAllocated) | 1873 if (testPagesAllocated) |
| 1876 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize -
1)); | 1874 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPage
Size - 1)); |
| 1877 } | 1875 } |
| 1878 | 1876 |
| 1879 clearOutOldGarbage(); | 1877 clearOutOldGarbage(); |
| 1880 total -= 96; | 1878 total -= 96; |
| 1881 slack -= 8; | 1879 slack -= 8; |
| 1882 if (testPagesAllocated) | 1880 if (testPagesAllocated) |
| 1883 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize - 1)); | 1881 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPageSize
- 1)); |
| 1884 | 1882 |
| 1885 // Clear the persistent, so that the big area will be garbage collected. | 1883 // Clear the persistent, so that the big area will be garbage collected. |
| 1886 bigArea.release(); | 1884 bigArea.release(); |
| 1887 clearOutOldGarbage(); | 1885 clearOutOldGarbage(); |
| 1888 | 1886 |
| 1889 total -= big; | 1887 total -= big; |
| 1890 slack -= 4; | 1888 slack -= 4; |
| 1891 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), slack)
; | 1889 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTesting(),
slack); |
| 1892 if (testPagesAllocated) | 1890 if (testPagesAllocated) |
| 1893 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize - 1)); | 1891 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPageSize
- 1)); |
| 1894 | 1892 |
| 1895 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), slack)
; | 1893 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTesting(),
slack); |
| 1896 if (testPagesAllocated) | 1894 if (testPagesAllocated) |
| 1897 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize - 1)); | 1895 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPageSize
- 1)); |
| 1898 | 1896 |
| 1899 for (size_t i = 0; i < persistentCount; i++) { | 1897 for (size_t i = 0; i < persistentCount; i++) { |
| 1900 delete persistents[i]; | 1898 delete persistents[i]; |
| 1901 persistents[i] = 0; | 1899 persistents[i] = 0; |
| 1902 } | 1900 } |
| 1903 | 1901 |
| 1904 uint8_t* address = reinterpret_cast<uint8_t*>(ThreadHeap::allocate<Dynamical
lySizedObject>(100)); | 1902 uint8_t* address = reinterpret_cast<uint8_t*>(ThreadHeap::allocate<Dynamical
lySizedObject>(100)); |
| 1905 for (int i = 0; i < 100; i++) | 1903 for (int i = 0; i < 100; i++) |
| 1906 address[i] = i; | 1904 address[i] = i; |
| 1907 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 100000)); | 1905 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 100000)); |
| 1908 for (int i = 0; i < 100; i++) | 1906 for (int i = 0; i < 100; i++) |
| 1909 EXPECT_EQ(address[i], i); | 1907 EXPECT_EQ(address[i], i); |
| 1910 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 50)); | 1908 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 50)); |
| 1911 for (int i = 0; i < 50; i++) | 1909 for (int i = 0; i < 50; i++) |
| 1912 EXPECT_EQ(address[i], i); | 1910 EXPECT_EQ(address[i], i); |
| 1913 // This should be equivalent to free(address). | 1911 // This should be equivalent to free(address). |
| 1914 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(address, 0)), 0ul); | 1912 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(address, 0)), 0ul); |
| 1915 // This should be equivalent to malloc(0). | 1913 // This should be equivalent to malloc(0). |
| 1916 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(0, 0)), 0ul); | 1914 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(0, 0)), 0ul); |
| 1917 } | 1915 } |
| 1918 | 1916 |
| 1919 TEST(HeapTest, SimpleAllocation) | 1917 TEST(HeapTest, SimpleAllocation) |
| 1920 { | 1918 { |
| 1921 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 1922 clearOutOldGarbage(); | 1919 clearOutOldGarbage(); |
| 1923 EXPECT_EQ(0ul, heap.objectPayloadSizeForTesting()); | 1920 EXPECT_EQ(0ul, ThreadHeap::objectPayloadSizeForTesting()); |
| 1924 | 1921 |
| 1925 // Allocate an object in the heap. | 1922 // Allocate an object in the heap. |
| 1926 HeapAllocatedArray* array = new HeapAllocatedArray(); | 1923 HeapAllocatedArray* array = new HeapAllocatedArray(); |
| 1927 EXPECT_TRUE(heap.objectPayloadSizeForTesting() >= sizeof(HeapAllocatedArray)
); | 1924 EXPECT_TRUE(ThreadHeap::objectPayloadSizeForTesting() >= sizeof(HeapAllocate
dArray)); |
| 1928 | 1925 |
| 1929 // Sanity check of the contents in the heap. | 1926 // Sanity check of the contents in the heap. |
| 1930 EXPECT_EQ(0, array->at(0)); | 1927 EXPECT_EQ(0, array->at(0)); |
| 1931 EXPECT_EQ(42, array->at(42)); | 1928 EXPECT_EQ(42, array->at(42)); |
| 1932 EXPECT_EQ(0, array->at(128)); | 1929 EXPECT_EQ(0, array->at(128)); |
| 1933 EXPECT_EQ(999 % 128, array->at(999)); | 1930 EXPECT_EQ(999 % 128, array->at(999)); |
| 1934 } | 1931 } |
| 1935 | 1932 |
| 1936 TEST(HeapTest, SimplePersistent) | 1933 TEST(HeapTest, SimplePersistent) |
| 1937 { | 1934 { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2245 // for the conservative stack scan to find. | 2242 // for the conservative stack scan to find. |
| 2246 EXPECT_EQ(width, bars->getWidth()); | 2243 EXPECT_EQ(width, bars->getWidth()); |
| 2247 } | 2244 } |
| 2248 EXPECT_EQ(Bars::width + 1, Bar::s_live); | 2245 EXPECT_EQ(Bars::width + 1, Bar::s_live); |
| 2249 preciselyCollectGarbage(); | 2246 preciselyCollectGarbage(); |
| 2250 EXPECT_EQ(0u, Bar::s_live); | 2247 EXPECT_EQ(0u, Bar::s_live); |
| 2251 } | 2248 } |
| 2252 | 2249 |
| 2253 TEST(HeapTest, HashMapOfMembers) | 2250 TEST(HeapTest, HashMapOfMembers) |
| 2254 { | 2251 { |
| 2255 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 2256 IntWrapper::s_destructorCalls = 0; | 2252 IntWrapper::s_destructorCalls = 0; |
| 2257 | 2253 |
| 2258 clearOutOldGarbage(); | 2254 clearOutOldGarbage(); |
| 2259 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); | 2255 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); |
| 2260 { | 2256 { |
| 2261 typedef HeapHashMap< | 2257 typedef HeapHashMap< |
| 2262 Member<IntWrapper>, | 2258 Member<IntWrapper>, |
| 2263 Member<IntWrapper>, | 2259 Member<IntWrapper>, |
| 2264 DefaultHash<Member<IntWrapper>>::Hash, | 2260 DefaultHash<Member<IntWrapper>>::Hash, |
| 2265 HashTraits<Member<IntWrapper>>, | 2261 HashTraits<Member<IntWrapper>>, |
| 2266 HashTraits<Member<IntWrapper>>> HeapObjectIdentityMap; | 2262 HashTraits<Member<IntWrapper>>> HeapObjectIdentityMap; |
| 2267 | 2263 |
| 2268 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap(); | 2264 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap(); |
| 2269 | 2265 |
| 2270 map->clear(); | 2266 map->clear(); |
| 2271 size_t afterSetWasCreated = heap.objectPayloadSizeForTesting(); | 2267 size_t afterSetWasCreated = ThreadHeap::objectPayloadSizeForTesting(); |
| 2272 EXPECT_TRUE(afterSetWasCreated > initialObjectPayloadSize); | 2268 EXPECT_TRUE(afterSetWasCreated > initialObjectPayloadSize); |
| 2273 | 2269 |
| 2274 preciselyCollectGarbage(); | 2270 preciselyCollectGarbage(); |
| 2275 size_t afterGC = heap.objectPayloadSizeForTesting(); | 2271 size_t afterGC = ThreadHeap::objectPayloadSizeForTesting(); |
| 2276 EXPECT_EQ(afterGC, afterSetWasCreated); | 2272 EXPECT_EQ(afterGC, afterSetWasCreated); |
| 2277 | 2273 |
| 2278 // If the additions below cause garbage collections, these | 2274 // If the additions below cause garbage collections, these |
| 2279 // pointers should be found by conservative stack scanning. | 2275 // pointers should be found by conservative stack scanning. |
| 2280 IntWrapper* one(IntWrapper::create(1)); | 2276 IntWrapper* one(IntWrapper::create(1)); |
| 2281 IntWrapper* anotherOne(IntWrapper::create(1)); | 2277 IntWrapper* anotherOne(IntWrapper::create(1)); |
| 2282 | 2278 |
| 2283 map->add(one, one); | 2279 map->add(one, one); |
| 2284 | 2280 |
| 2285 size_t afterOneAdd = heap.objectPayloadSizeForTesting(); | 2281 size_t afterOneAdd = ThreadHeap::objectPayloadSizeForTesting(); |
| 2286 EXPECT_TRUE(afterOneAdd > afterGC); | 2282 EXPECT_TRUE(afterOneAdd > afterGC); |
| 2287 | 2283 |
| 2288 HeapObjectIdentityMap::iterator it(map->begin()); | 2284 HeapObjectIdentityMap::iterator it(map->begin()); |
| 2289 HeapObjectIdentityMap::iterator it2(map->begin()); | 2285 HeapObjectIdentityMap::iterator it2(map->begin()); |
| 2290 ++it; | 2286 ++it; |
| 2291 ++it2; | 2287 ++it2; |
| 2292 | 2288 |
| 2293 map->add(anotherOne, one); | 2289 map->add(anotherOne, one); |
| 2294 | 2290 |
| 2295 // The addition above can cause an allocation of a new | 2291 // The addition above can cause an allocation of a new |
| 2296 // backing store. We therefore garbage collect before | 2292 // backing store. We therefore garbage collect before |
| 2297 // taking the heap stats in order to get rid of the old | 2293 // taking the heap stats in order to get rid of the old |
| 2298 // backing store. We make sure to not use conservative | 2294 // backing store. We make sure to not use conservative |
| 2299 // stack scanning as that could find a pointer to the | 2295 // stack scanning as that could find a pointer to the |
| 2300 // old backing. | 2296 // old backing. |
| 2301 preciselyCollectGarbage(); | 2297 preciselyCollectGarbage(); |
| 2302 size_t afterAddAndGC = heap.objectPayloadSizeForTesting(); | 2298 size_t afterAddAndGC = ThreadHeap::objectPayloadSizeForTesting(); |
| 2303 EXPECT_TRUE(afterAddAndGC >= afterOneAdd); | 2299 EXPECT_TRUE(afterAddAndGC >= afterOneAdd); |
| 2304 | 2300 |
| 2305 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distin
ct. | 2301 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distin
ct. |
| 2306 | 2302 |
| 2307 preciselyCollectGarbage(); | 2303 preciselyCollectGarbage(); |
| 2308 EXPECT_TRUE(map->contains(one)); | 2304 EXPECT_TRUE(map->contains(one)); |
| 2309 EXPECT_TRUE(map->contains(anotherOne)); | 2305 EXPECT_TRUE(map->contains(anotherOne)); |
| 2310 | 2306 |
| 2311 IntWrapper* gotten(map->get(one)); | 2307 IntWrapper* gotten(map->get(one)); |
| 2312 EXPECT_EQ(gotten->value(), one->value()); | 2308 EXPECT_EQ(gotten->value(), one->value()); |
| 2313 EXPECT_EQ(gotten, one); | 2309 EXPECT_EQ(gotten, one); |
| 2314 | 2310 |
| 2315 size_t afterGC2 = heap.objectPayloadSizeForTesting(); | 2311 size_t afterGC2 = ThreadHeap::objectPayloadSizeForTesting(); |
| 2316 EXPECT_EQ(afterGC2, afterAddAndGC); | 2312 EXPECT_EQ(afterGC2, afterAddAndGC); |
| 2317 | 2313 |
| 2318 IntWrapper* dozen = 0; | 2314 IntWrapper* dozen = 0; |
| 2319 | 2315 |
| 2320 for (int i = 1; i < 1000; i++) { // 999 iterations. | 2316 for (int i = 1; i < 1000; i++) { // 999 iterations. |
| 2321 IntWrapper* iWrapper(IntWrapper::create(i)); | 2317 IntWrapper* iWrapper(IntWrapper::create(i)); |
| 2322 IntWrapper* iSquared(IntWrapper::create(i * i)); | 2318 IntWrapper* iSquared(IntWrapper::create(i * i)); |
| 2323 map->add(iWrapper, iSquared); | 2319 map->add(iWrapper, iSquared); |
| 2324 if (i == 12) | 2320 if (i == 12) |
| 2325 dozen = iWrapper; | 2321 dozen = iWrapper; |
| 2326 } | 2322 } |
| 2327 size_t afterAdding1000 = heap.objectPayloadSizeForTesting(); | 2323 size_t afterAdding1000 = ThreadHeap::objectPayloadSizeForTesting(); |
| 2328 EXPECT_TRUE(afterAdding1000 > afterGC2); | 2324 EXPECT_TRUE(afterAdding1000 > afterGC2); |
| 2329 | 2325 |
| 2330 IntWrapper* gross(map->get(dozen)); | 2326 IntWrapper* gross(map->get(dozen)); |
| 2331 EXPECT_EQ(gross->value(), 144); | 2327 EXPECT_EQ(gross->value(), 144); |
| 2332 | 2328 |
| 2333 // This should clear out any junk backings created by all the adds. | 2329 // This should clear out any junk backings created by all the adds. |
| 2334 preciselyCollectGarbage(); | 2330 preciselyCollectGarbage(); |
| 2335 size_t afterGC3 = heap.objectPayloadSizeForTesting(); | 2331 size_t afterGC3 = ThreadHeap::objectPayloadSizeForTesting(); |
| 2336 EXPECT_TRUE(afterGC3 <= afterAdding1000); | 2332 EXPECT_TRUE(afterGC3 <= afterAdding1000); |
| 2337 } | 2333 } |
| 2338 | 2334 |
| 2339 preciselyCollectGarbage(); | 2335 preciselyCollectGarbage(); |
| 2340 // The objects 'one', anotherOne, and the 999 other pairs. | 2336 // The objects 'one', anotherOne, and the 999 other pairs. |
| 2341 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000); | 2337 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000); |
| 2342 size_t afterGC4 = heap.objectPayloadSizeForTesting(); | 2338 size_t afterGC4 = ThreadHeap::objectPayloadSizeForTesting(); |
| 2343 EXPECT_EQ(afterGC4, initialObjectPayloadSize); | 2339 EXPECT_EQ(afterGC4, initialObjectPayloadSize); |
| 2344 } | 2340 } |
| 2345 | 2341 |
| 2346 TEST(HeapTest, NestedAllocation) | 2342 TEST(HeapTest, NestedAllocation) |
| 2347 { | 2343 { |
| 2348 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 2349 clearOutOldGarbage(); | 2344 clearOutOldGarbage(); |
| 2350 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); | 2345 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); |
| 2351 { | 2346 { |
| 2352 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAll
ocation::create(); | 2347 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAll
ocation::create(); |
| 2353 } | 2348 } |
| 2354 clearOutOldGarbage(); | 2349 clearOutOldGarbage(); |
| 2355 size_t afterFree = heap.objectPayloadSizeForTesting(); | 2350 size_t afterFree = ThreadHeap::objectPayloadSizeForTesting(); |
| 2356 EXPECT_TRUE(initialObjectPayloadSize == afterFree); | 2351 EXPECT_TRUE(initialObjectPayloadSize == afterFree); |
| 2357 } | 2352 } |
| 2358 | 2353 |
| 2359 TEST(HeapTest, LargeHeapObjects) | 2354 TEST(HeapTest, LargeHeapObjects) |
| 2360 { | 2355 { |
| 2361 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 2362 clearOutOldGarbage(); | 2356 clearOutOldGarbage(); |
| 2363 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); | 2357 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); |
| 2364 size_t initialAllocatedSpace = heap.heapStats().allocatedSpace(); | 2358 size_t initialAllocatedSpace = ThreadHeap::heapStats().allocatedSpace(); |
| 2365 IntWrapper::s_destructorCalls = 0; | 2359 IntWrapper::s_destructorCalls = 0; |
| 2366 LargeHeapObject::s_destructorCalls = 0; | 2360 LargeHeapObject::s_destructorCalls = 0; |
| 2367 { | 2361 { |
| 2368 int slack = 8; // LargeHeapObject points to an IntWrapper that is also a
llocated. | 2362 int slack = 8; // LargeHeapObject points to an IntWrapper that is also a
llocated. |
| 2369 Persistent<LargeHeapObject> object = LargeHeapObject::create(); | 2363 Persistent<LargeHeapObject> object = LargeHeapObject::create(); |
| 2370 ASSERT(ThreadState::current()->findPageFromAddress(object)); | 2364 ASSERT(ThreadState::current()->findPageFromAddress(object)); |
| 2371 ASSERT(ThreadState::current()->findPageFromAddress(reinterpret_cast<char
*>(object.get()) + sizeof(LargeHeapObject) - 1)); | 2365 ASSERT(ThreadState::current()->findPageFromAddress(reinterpret_cast<char
*>(object.get()) + sizeof(LargeHeapObject) - 1)); |
| 2372 clearOutOldGarbage(); | 2366 clearOutOldGarbage(); |
| 2373 size_t afterAllocation = heap.heapStats().allocatedSpace(); | 2367 size_t afterAllocation = ThreadHeap::heapStats().allocatedSpace(); |
| 2374 { | 2368 { |
| 2375 object->set(0, 'a'); | 2369 object->set(0, 'a'); |
| 2376 EXPECT_EQ('a', object->get(0)); | 2370 EXPECT_EQ('a', object->get(0)); |
| 2377 object->set(object->length() - 1, 'b'); | 2371 object->set(object->length() - 1, 'b'); |
| 2378 EXPECT_EQ('b', object->get(object->length() - 1)); | 2372 EXPECT_EQ('b', object->get(object->length() - 1)); |
| 2379 size_t expectedLargeHeapObjectPayloadSize = ThreadHeap::allocationSi
zeFromSize(sizeof(LargeHeapObject)); | 2373 size_t expectedLargeHeapObjectPayloadSize = ThreadHeap::allocationSi
zeFromSize(sizeof(LargeHeapObject)); |
| 2380 size_t expectedObjectPayloadSize = expectedLargeHeapObjectPayloadSiz
e + sizeof(IntWrapper); | 2374 size_t expectedObjectPayloadSize = expectedLargeHeapObjectPayloadSiz
e + sizeof(IntWrapper); |
| 2381 size_t actualObjectPayloadSize = heap.objectPayloadSizeForTesting()
- initialObjectPayloadSize; | 2375 size_t actualObjectPayloadSize = ThreadHeap::objectPayloadSizeForTes
ting() - initialObjectPayloadSize; |
| 2382 CheckWithSlack(expectedObjectPayloadSize, actualObjectPayloadSize, s
lack); | 2376 CheckWithSlack(expectedObjectPayloadSize, actualObjectPayloadSize, s
lack); |
| 2383 // There is probably space for the IntWrapper in a heap page without | 2377 // There is probably space for the IntWrapper in a heap page without |
| 2384 // allocating extra pages. However, the IntWrapper allocation might
cause | 2378 // allocating extra pages. However, the IntWrapper allocation might
cause |
| 2385 // the addition of a heap page. | 2379 // the addition of a heap page. |
| 2386 size_t largeObjectAllocationSize = sizeof(LargeObjectPage) + expecte
dLargeHeapObjectPayloadSize; | 2380 size_t largeObjectAllocationSize = sizeof(LargeObjectPage) + expecte
dLargeHeapObjectPayloadSize; |
| 2387 size_t allocatedSpaceLowerBound = initialAllocatedSpace + largeObjec
tAllocationSize; | 2381 size_t allocatedSpaceLowerBound = initialAllocatedSpace + largeObjec
tAllocationSize; |
| 2388 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack +
blinkPageSize; | 2382 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack +
blinkPageSize; |
| 2389 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation); | 2383 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation); |
| 2390 EXPECT_LE(afterAllocation, allocatedSpaceUpperBound); | 2384 EXPECT_LE(afterAllocation, allocatedSpaceUpperBound); |
| 2391 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | 2385 EXPECT_EQ(0, IntWrapper::s_destructorCalls); |
| 2392 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); | 2386 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); |
| 2393 for (int i = 0; i < 10; i++) | 2387 for (int i = 0; i < 10; i++) |
| 2394 object = LargeHeapObject::create(); | 2388 object = LargeHeapObject::create(); |
| 2395 } | 2389 } |
| 2396 clearOutOldGarbage(); | 2390 clearOutOldGarbage(); |
| 2397 EXPECT_TRUE(heap.heapStats().allocatedSpace() == afterAllocation); | 2391 EXPECT_TRUE(ThreadHeap::heapStats().allocatedSpace() == afterAllocation)
; |
| 2398 EXPECT_EQ(10, IntWrapper::s_destructorCalls); | 2392 EXPECT_EQ(10, IntWrapper::s_destructorCalls); |
| 2399 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); | 2393 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); |
| 2400 } | 2394 } |
| 2401 clearOutOldGarbage(); | 2395 clearOutOldGarbage(); |
| 2402 EXPECT_TRUE(initialObjectPayloadSize == heap.objectPayloadSizeForTesting()); | 2396 EXPECT_TRUE(initialObjectPayloadSize == ThreadHeap::objectPayloadSizeForTest
ing()); |
| 2403 EXPECT_TRUE(initialAllocatedSpace == heap.heapStats().allocatedSpace()); | 2397 EXPECT_TRUE(initialAllocatedSpace == ThreadHeap::heapStats().allocatedSpace(
)); |
| 2404 EXPECT_EQ(11, IntWrapper::s_destructorCalls); | 2398 EXPECT_EQ(11, IntWrapper::s_destructorCalls); |
| 2405 EXPECT_EQ(11, LargeHeapObject::s_destructorCalls); | 2399 EXPECT_EQ(11, LargeHeapObject::s_destructorCalls); |
| 2406 preciselyCollectGarbage(); | 2400 preciselyCollectGarbage(); |
| 2407 } | 2401 } |
| 2408 | 2402 |
| 2409 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped; | 2403 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped; |
| 2410 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped; | 2404 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped; |
| 2411 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong; | 2405 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong; |
| 2412 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak; | 2406 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak; |
| 2413 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped; | 2407 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped; |
| (...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3782 { | 3776 { |
| 3783 Persistent<Bar> barPersistent = Bar::create(); | 3777 Persistent<Bar> barPersistent = Bar::create(); |
| 3784 Persistent<Foo> fooPersistent = Foo::create(barPersistent); | 3778 Persistent<Foo> fooPersistent = Foo::create(barPersistent); |
| 3785 EXPECT_TRUE(barPersistent != fooPersistent); | 3779 EXPECT_TRUE(barPersistent != fooPersistent); |
| 3786 barPersistent = fooPersistent; | 3780 barPersistent = fooPersistent; |
| 3787 EXPECT_TRUE(barPersistent == fooPersistent); | 3781 EXPECT_TRUE(barPersistent == fooPersistent); |
| 3788 } | 3782 } |
| 3789 | 3783 |
| 3790 TEST(HeapTest, CheckAndMarkPointer) | 3784 TEST(HeapTest, CheckAndMarkPointer) |
| 3791 { | 3785 { |
| 3792 ThreadHeap& heap = ThreadState::current()->heap(); | |
| 3793 clearOutOldGarbage(); | 3786 clearOutOldGarbage(); |
| 3794 | 3787 |
| 3795 Vector<Address> objectAddresses; | 3788 Vector<Address> objectAddresses; |
| 3796 Vector<Address> endAddresses; | 3789 Vector<Address> endAddresses; |
| 3797 Address largeObjectAddress; | 3790 Address largeObjectAddress; |
| 3798 Address largeObjectEndAddress; | 3791 Address largeObjectEndAddress; |
| 3799 for (int i = 0; i < 10; i++) { | 3792 for (int i = 0; i < 10; i++) { |
| 3800 SimpleObject* object = SimpleObject::create(); | 3793 SimpleObject* object = SimpleObject::create(); |
| 3801 Address objectAddress = reinterpret_cast<Address>(object); | 3794 Address objectAddress = reinterpret_cast<Address>(object); |
| 3802 objectAddresses.append(objectAddress); | 3795 objectAddresses.append(objectAddress); |
| 3803 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); | 3796 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); |
| 3804 } | 3797 } |
| 3805 LargeHeapObject* largeObject = LargeHeapObject::create(); | 3798 LargeHeapObject* largeObject = LargeHeapObject::create(); |
| 3806 largeObjectAddress = reinterpret_cast<Address>(largeObject); | 3799 largeObjectAddress = reinterpret_cast<Address>(largeObject); |
| 3807 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; | 3800 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; |
| 3808 | 3801 |
| 3809 // This is a low-level test where we call checkAndMarkPointer. This method | 3802 // This is a low-level test where we call checkAndMarkPointer. This method |
| 3810 // causes the object start bitmap to be computed which requires the heap | 3803 // causes the object start bitmap to be computed which requires the heap |
| 3811 // to be in a consistent state (e.g. the free allocation area must be put | 3804 // to be in a consistent state (e.g. the free allocation area must be put |
| 3812 // into a free list header). However when we call makeConsistentForGC it | 3805 // into a free list header). However when we call makeConsistentForGC it |
| 3813 // also clears out the freelists so we have to rebuild those before trying | 3806 // also clears out the freelists so we have to rebuild those before trying |
| 3814 // to allocate anything again. We do this by forcing a GC after doing the | 3807 // to allocate anything again. We do this by forcing a GC after doing the |
| 3815 // checkAndMarkPointer tests. | 3808 // checkAndMarkPointer tests. |
| 3816 { | 3809 { |
| 3817 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3810 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3818 CountingVisitor visitor(ThreadState::current()); | 3811 CountingVisitor visitor(ThreadState::current()); |
| 3819 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not
park all threads. | 3812 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not
park all threads. |
| 3820 heap.flushHeapDoesNotContainCache(); | 3813 ThreadHeap::flushHeapDoesNotContainCache(); |
| 3821 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3814 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3822 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, objectAddresses[i])); | 3815 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, objectAddresse
s[i])); |
| 3823 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, endAddresses[i])); | 3816 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, endAddresses[i
])); |
| 3824 } | 3817 } |
| 3825 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 3818 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); |
| 3826 visitor.reset(); | 3819 visitor.reset(); |
| 3827 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectAddress)); | 3820 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, largeObjectAddress
)); |
| 3828 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectEndAddress)); | 3821 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, largeObjectEndAddr
ess)); |
| 3829 EXPECT_EQ(2ul, visitor.count()); | 3822 EXPECT_EQ(2ul, visitor.count()); |
| 3830 visitor.reset(); | 3823 visitor.reset(); |
| 3831 } | 3824 } |
| 3832 // This forces a GC without stack scanning which results in the objects | 3825 // This forces a GC without stack scanning which results in the objects |
| 3833 // being collected. This will also rebuild the above mentioned freelists, | 3826 // being collected. This will also rebuild the above mentioned freelists, |
| 3834 // however we don't rely on that below since we don't have any allocations. | 3827 // however we don't rely on that below since we don't have any allocations. |
| 3835 clearOutOldGarbage(); | 3828 clearOutOldGarbage(); |
| 3836 { | 3829 { |
| 3837 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3830 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3838 CountingVisitor visitor(ThreadState::current()); | 3831 CountingVisitor visitor(ThreadState::current()); |
| 3839 EXPECT_TRUE(scope.allThreadsParked()); | 3832 EXPECT_TRUE(scope.allThreadsParked()); |
| 3840 heap.flushHeapDoesNotContainCache(); | 3833 ThreadHeap::flushHeapDoesNotContainCache(); |
| 3841 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3834 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3842 // We would like to assert that checkAndMarkPointer returned false | 3835 // We would like to assert that checkAndMarkPointer returned false |
| 3843 // here because the pointers no longer point into a valid object | 3836 // here because the pointers no longer point into a valid object |
| 3844 // (it's been freed by the GCs. But checkAndMarkPointer will return | 3837 // (it's been freed by the GCs. But checkAndMarkPointer will return |
| 3845 // true for any pointer that points into a heap page, regardless of | 3838 // true for any pointer that points into a heap page, regardless of |
| 3846 // whether it points at a valid object (this ensures the | 3839 // whether it points at a valid object (this ensures the |
| 3847 // correctness of the page-based on-heap address caches), so we | 3840 // correctness of the page-based on-heap address caches), so we |
| 3848 // can't make that assert. | 3841 // can't make that assert. |
| 3849 heap.checkAndMarkPointer(&visitor, objectAddresses[i]); | 3842 ThreadHeap::checkAndMarkPointer(&visitor, objectAddresses[i]); |
| 3850 heap.checkAndMarkPointer(&visitor, endAddresses[i]); | 3843 ThreadHeap::checkAndMarkPointer(&visitor, endAddresses[i]); |
| 3851 } | 3844 } |
| 3852 EXPECT_EQ(0ul, visitor.count()); | 3845 EXPECT_EQ(0ul, visitor.count()); |
| 3853 heap.checkAndMarkPointer(&visitor, largeObjectAddress); | 3846 ThreadHeap::checkAndMarkPointer(&visitor, largeObjectAddress); |
| 3854 heap.checkAndMarkPointer(&visitor, largeObjectEndAddress); | 3847 ThreadHeap::checkAndMarkPointer(&visitor, largeObjectEndAddress); |
| 3855 EXPECT_EQ(0ul, visitor.count()); | 3848 EXPECT_EQ(0ul, visitor.count()); |
| 3856 } | 3849 } |
| 3857 // This round of GC is important to make sure that the object start | 3850 // This round of GC is important to make sure that the object start |
| 3858 // bitmap are cleared out and that the free lists are rebuild. | 3851 // bitmap are cleared out and that the free lists are rebuild. |
| 3859 clearOutOldGarbage(); | 3852 clearOutOldGarbage(); |
| 3860 } | 3853 } |
| 3861 | 3854 |
| 3862 TEST(HeapTest, PersistentHeapCollectionTypes) | 3855 TEST(HeapTest, PersistentHeapCollectionTypes) |
| 3863 { | 3856 { |
| 3864 IntWrapper::s_destructorCalls = 0; | 3857 IntWrapper::s_destructorCalls = 0; |
| (...skipping 848 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4713 { | 4706 { |
| 4714 // Since the sleeper thread has detached this is the only thread. | 4707 // Since the sleeper thread has detached this is the only thread. |
| 4715 TestGCScope scope(BlinkGC::NoHeapPointersOnStack); | 4708 TestGCScope scope(BlinkGC::NoHeapPointersOnStack); |
| 4716 EXPECT_TRUE(scope.allThreadsParked()); | 4709 EXPECT_TRUE(scope.allThreadsParked()); |
| 4717 } | 4710 } |
| 4718 } | 4711 } |
| 4719 | 4712 |
| 4720 private: | 4713 private: |
| 4721 static void sleeperMainFunc() | 4714 static void sleeperMainFunc() |
| 4722 { | 4715 { |
| 4723 ThreadState::attachCurrentThread(); | 4716 ThreadState::attach(); |
| 4724 s_sleeperRunning = true; | 4717 s_sleeperRunning = true; |
| 4725 | 4718 |
| 4726 // Simulate a long running op that is not entering a safepoint. | 4719 // Simulate a long running op that is not entering a safepoint. |
| 4727 while (!s_sleeperDone) { | 4720 while (!s_sleeperDone) { |
| 4728 testing::yieldCurrentThread(); | 4721 testing::yieldCurrentThread(); |
| 4729 } | 4722 } |
| 4730 | 4723 |
| 4731 ThreadState::detachCurrentThread(); | 4724 ThreadState::detach(); |
| 4732 s_sleeperRunning = false; | 4725 s_sleeperRunning = false; |
| 4733 } | 4726 } |
| 4734 | 4727 |
| 4735 static volatile bool s_sleeperRunning; | 4728 static volatile bool s_sleeperRunning; |
| 4736 static volatile bool s_sleeperDone; | 4729 static volatile bool s_sleeperDone; |
| 4737 }; | 4730 }; |
| 4738 | 4731 |
| 4739 volatile bool GCParkingThreadTester::s_sleeperRunning = false; | 4732 volatile bool GCParkingThreadTester::s_sleeperRunning = false; |
| 4740 volatile bool GCParkingThreadTester::s_sleeperDone = false; | 4733 volatile bool GCParkingThreadTester::s_sleeperDone = false; |
| 4741 | 4734 |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5398 // shutdown. | 5391 // shutdown. |
| 5399 wakeWorkerThread(); | 5392 wakeWorkerThread(); |
| 5400 } | 5393 } |
| 5401 | 5394 |
| 5402 private: | 5395 private: |
| 5403 | 5396 |
| 5404 static void workerThreadMain() | 5397 static void workerThreadMain() |
| 5405 { | 5398 { |
| 5406 MutexLocker locker(workerThreadMutex()); | 5399 MutexLocker locker(workerThreadMutex()); |
| 5407 | 5400 |
| 5408 ThreadState::attachCurrentThread(); | 5401 ThreadState::attach(); |
| 5409 | 5402 |
| 5410 { | 5403 { |
| 5411 // Create a worker object that is not kept alive except the | 5404 // Create a worker object that is not kept alive except the |
| 5412 // main thread will keep it as an integer value on its stack. | 5405 // main thread will keep it as an integer value on its stack. |
| 5413 IntWrapper* workerObject = IntWrapper::create(42); | 5406 IntWrapper* workerObject = IntWrapper::create(42); |
| 5414 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); | 5407 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); |
| 5415 } | 5408 } |
| 5416 | 5409 |
| 5417 // Signal the main thread that the worker is done with its allocation. | 5410 // Signal the main thread that the worker is done with its allocation. |
| 5418 wakeMainThread(); | 5411 wakeMainThread(); |
| 5419 | 5412 |
| 5420 { | 5413 { |
| 5421 // Wait for the main thread to do two GCs without sweeping this thre
ad | 5414 // Wait for the main thread to do two GCs without sweeping this thre
ad |
| 5422 // heap. The worker waits within a safepoint, but there is no sweepi
ng | 5415 // heap. The worker waits within a safepoint, but there is no sweepi
ng |
| 5423 // until leaving the safepoint scope. | 5416 // until leaving the safepoint scope. |
| 5424 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 5417 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 5425 parkWorkerThread(); | 5418 parkWorkerThread(); |
| 5426 } | 5419 } |
| 5427 | 5420 |
| 5428 // Wake up the main thread when done sweeping. | 5421 // Wake up the main thread when done sweeping. |
| 5429 wakeMainThread(); | 5422 wakeMainThread(); |
| 5430 | 5423 |
| 5431 // Wait with detach until the main thread says so. This is not strictly | 5424 // Wait with detach until the main thread says so. This is not strictly |
| 5432 // necessary, but it means the worker thread will not do its thread loca
l | 5425 // necessary, but it means the worker thread will not do its thread loca
l |
| 5433 // GCs just yet, making it easier to reason about that no new GC has occ
urred | 5426 // GCs just yet, making it easier to reason about that no new GC has occ
urred |
| 5434 // and the above sweep was the one finalizing the worker object. | 5427 // and the above sweep was the one finalizing the worker object. |
| 5435 parkWorkerThread(); | 5428 parkWorkerThread(); |
| 5436 | 5429 |
| 5437 ThreadState::detachCurrentThread(); | 5430 ThreadState::detach(); |
| 5438 } | 5431 } |
| 5439 | 5432 |
| 5440 static volatile uintptr_t s_workerObjectPointer; | 5433 static volatile uintptr_t s_workerObjectPointer; |
| 5441 }; | 5434 }; |
| 5442 | 5435 |
| 5443 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; | 5436 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; |
| 5444 | 5437 |
| 5445 TEST(HeapTest, ObjectDeadBit) | 5438 TEST(HeapTest, ObjectDeadBit) |
| 5446 { | 5439 { |
| 5447 DeadBitTester::test(); | 5440 DeadBitTester::test(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5519 parkWorkerThread(); | 5512 parkWorkerThread(); |
| 5520 } | 5513 } |
| 5521 | 5514 |
| 5522 return weakCollection; | 5515 return weakCollection; |
| 5523 } | 5516 } |
| 5524 | 5517 |
| 5525 static void workerThreadMain() | 5518 static void workerThreadMain() |
| 5526 { | 5519 { |
| 5527 MutexLocker locker(workerThreadMutex()); | 5520 MutexLocker locker(workerThreadMutex()); |
| 5528 | 5521 |
| 5529 ThreadState::attachCurrentThread(); | 5522 ThreadState::attach(); |
| 5530 | 5523 |
| 5531 { | 5524 { |
| 5532 Persistent<WeakCollectionType> collection = allocateCollection(); | 5525 Persistent<WeakCollectionType> collection = allocateCollection(); |
| 5533 { | 5526 { |
| 5534 // Prevent weak processing with an iterator and GC. | 5527 // Prevent weak processing with an iterator and GC. |
| 5535 WeakCollectionType::iterator it = collection->begin(); | 5528 WeakCollectionType::iterator it = collection->begin(); |
| 5536 conservativelyCollectGarbage(); | 5529 conservativelyCollectGarbage(); |
| 5537 | 5530 |
| 5538 // The backing should be strongified because of the iterator. | 5531 // The backing should be strongified because of the iterator. |
| 5539 EXPECT_EQ(6u, collection->size()); | 5532 EXPECT_EQ(6u, collection->size()); |
| 5540 EXPECT_EQ(32, it->value->value()); | 5533 EXPECT_EQ(32, it->value->value()); |
| 5541 } | 5534 } |
| 5542 | 5535 |
| 5543 // Disregarding the iterator but keeping the collection alive | 5536 // Disregarding the iterator but keeping the collection alive |
| 5544 // with a persistent should lead to weak processing. | 5537 // with a persistent should lead to weak processing. |
| 5545 preciselyCollectGarbage(); | 5538 preciselyCollectGarbage(); |
| 5546 EXPECT_EQ(0u, collection->size()); | 5539 EXPECT_EQ(0u, collection->size()); |
| 5547 } | 5540 } |
| 5548 | 5541 |
| 5549 wakeMainThread(); | 5542 wakeMainThread(); |
| 5550 ThreadState::detachCurrentThread(); | 5543 ThreadState::detach(); |
| 5551 } | 5544 } |
| 5552 | 5545 |
| 5553 static volatile uintptr_t s_workerObjectPointer; | 5546 static volatile uintptr_t s_workerObjectPointer; |
| 5554 }; | 5547 }; |
| 5555 | 5548 |
| 5556 TEST(HeapTest, ThreadedStrongification) | 5549 TEST(HeapTest, ThreadedStrongification) |
| 5557 { | 5550 { |
| 5558 ThreadedStrongificationTester::test(); | 5551 ThreadedStrongificationTester::test(); |
| 5559 } | 5552 } |
| 5560 | 5553 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5680 // can acquire it and do its sweep of its arenas. Just wait for the work
er | 5673 // can acquire it and do its sweep of its arenas. Just wait for the work
er |
| 5681 // to complete its sweep and check the result. | 5674 // to complete its sweep and check the result. |
| 5682 parkMainThread(); | 5675 parkMainThread(); |
| 5683 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls); | 5676 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls); |
| 5684 } | 5677 } |
| 5685 | 5678 |
| 5686 private: | 5679 private: |
| 5687 static void workerThreadMain() | 5680 static void workerThreadMain() |
| 5688 { | 5681 { |
| 5689 MutexLocker locker(workerThreadMutex()); | 5682 MutexLocker locker(workerThreadMutex()); |
| 5690 ThreadState::attachCurrentThread(); | 5683 ThreadState::attach(); |
| 5691 | 5684 |
| 5692 DestructorLockingObject* dlo = DestructorLockingObject::create(); | 5685 DestructorLockingObject* dlo = DestructorLockingObject::create(); |
| 5693 ASSERT_UNUSED(dlo, dlo); | 5686 ASSERT_UNUSED(dlo, dlo); |
| 5694 | 5687 |
| 5695 // Wake up the main thread which is waiting for the worker to do its | 5688 // Wake up the main thread which is waiting for the worker to do its |
| 5696 // allocation. | 5689 // allocation. |
| 5697 wakeMainThread(); | 5690 wakeMainThread(); |
| 5698 | 5691 |
| 5699 // Wait for the main thread to get the global lock to ensure it has | 5692 // Wait for the main thread to get the global lock to ensure it has |
| 5700 // it before the worker tries to acquire it. We want the worker to | 5693 // it before the worker tries to acquire it. We want the worker to |
| 5701 // block in the SafePointAwareMutexLocker until the main thread | 5694 // block in the SafePointAwareMutexLocker until the main thread |
| 5702 // has done a GC. The GC will not mark the "dlo" object since the worker | 5695 // has done a GC. The GC will not mark the "dlo" object since the worker |
| 5703 // is entering the safepoint with NoHeapPointersOnStack. When the worker | 5696 // is entering the safepoint with NoHeapPointersOnStack. When the worker |
| 5704 // subsequently gets the global lock and leaves the safepoint it will | 5697 // subsequently gets the global lock and leaves the safepoint it will |
| 5705 // sweep its heap and finalize "dlo". The destructor of "dlo" will try | 5698 // sweep its heap and finalize "dlo". The destructor of "dlo" will try |
| 5706 // to acquire the same global lock that the thread just got and deadlock | 5699 // to acquire the same global lock that the thread just got and deadlock |
| 5707 // unless the global lock is recursive. | 5700 // unless the global lock is recursive. |
| 5708 parkWorkerThread(); | 5701 parkWorkerThread(); |
| 5709 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), BlinkGC::NoH
eapPointersOnStack); | 5702 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), BlinkGC::NoH
eapPointersOnStack); |
| 5710 | 5703 |
| 5711 // We won't get here unless the lock is recursive since the sweep done | 5704 // We won't get here unless the lock is recursive since the sweep done |
| 5712 // in the constructor of SafePointAwareMutexLocker after | 5705 // in the constructor of SafePointAwareMutexLocker after |
| 5713 // getting the lock will not complete given the "dlo" destructor is | 5706 // getting the lock will not complete given the "dlo" destructor is |
| 5714 // waiting to get the same lock. | 5707 // waiting to get the same lock. |
| 5715 // Tell the main thread the worker has done its sweep. | 5708 // Tell the main thread the worker has done its sweep. |
| 5716 wakeMainThread(); | 5709 wakeMainThread(); |
| 5717 | 5710 |
| 5718 ThreadState::detachCurrentThread(); | 5711 ThreadState::detach(); |
| 5719 } | 5712 } |
| 5720 | 5713 |
| 5721 static volatile IntWrapper* s_workerObjectPointer; | 5714 static volatile IntWrapper* s_workerObjectPointer; |
| 5722 }; | 5715 }; |
| 5723 | 5716 |
| 5724 TEST(HeapTest, RecursiveMutex) | 5717 TEST(HeapTest, RecursiveMutex) |
| 5725 { | 5718 { |
| 5726 RecursiveLockingTester::test(); | 5719 RecursiveLockingTester::test(); |
| 5727 } | 5720 } |
| 5728 | 5721 |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6369 preciselyCollectGarbage(); | 6362 preciselyCollectGarbage(); |
| 6370 EXPECT_FALSE(holder->object()); | 6363 EXPECT_FALSE(holder->object()); |
| 6371 } | 6364 } |
| 6372 | 6365 |
| 6373 namespace { | 6366 namespace { |
| 6374 | 6367 |
| 6375 void workerThreadMainForCrossThreadWeakPersistentTest(DestructorLockingObject**
object) | 6368 void workerThreadMainForCrossThreadWeakPersistentTest(DestructorLockingObject**
object) |
| 6376 { | 6369 { |
| 6377 // Step 2: Create an object and store the pointer. | 6370 // Step 2: Create an object and store the pointer. |
| 6378 MutexLocker locker(workerThreadMutex()); | 6371 MutexLocker locker(workerThreadMutex()); |
| 6379 ThreadState::attachCurrentThread(); | 6372 ThreadState::attach(); |
| 6380 *object = DestructorLockingObject::create(); | 6373 *object = DestructorLockingObject::create(); |
| 6381 wakeMainThread(); | 6374 wakeMainThread(); |
| 6382 parkWorkerThread(); | 6375 parkWorkerThread(); |
| 6383 | 6376 |
| 6384 // Step 4: Run a GC. | 6377 // Step 4: Run a GC. |
| 6385 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSw
eep, BlinkGC::ForcedGC); | 6378 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSw
eep, BlinkGC::ForcedGC); |
| 6386 wakeMainThread(); | 6379 wakeMainThread(); |
| 6387 parkWorkerThread(); | 6380 parkWorkerThread(); |
| 6388 | 6381 |
| 6389 // Step 6: Finish. | 6382 // Step 6: Finish. |
| 6390 ThreadState::detachCurrentThread(); | 6383 ThreadState::detach(); |
| 6391 wakeMainThread(); | 6384 wakeMainThread(); |
| 6392 } | 6385 } |
| 6393 | 6386 |
| 6394 } // anonymous namespace | 6387 } // anonymous namespace |
| 6395 | 6388 |
| 6396 TEST(HeapTest, CrossThreadWeakPersistent) | 6389 TEST(HeapTest, CrossThreadWeakPersistent) |
| 6397 { | 6390 { |
| 6398 // Create an object in the worker thread, have a CrossThreadWeakPersistent p
ointing to it on the main thread, | 6391 // Create an object in the worker thread, have a CrossThreadWeakPersistent p
ointing to it on the main thread, |
| 6399 // clear the reference in the worker thread, run a GC in the worker thread,
and see if the | 6392 // clear the reference in the worker thread, run a GC in the worker thread,
and see if the |
| 6400 // CrossThreadWeakPersistent is cleared. | 6393 // CrossThreadWeakPersistent is cleared. |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6493 static void test() | 6486 static void test() |
| 6494 { | 6487 { |
| 6495 IntWrapper::s_destructorCalls = 0; | 6488 IntWrapper::s_destructorCalls = 0; |
| 6496 ThreadedTesterBase::test(new ThreadedClearOnShutdownTester); | 6489 ThreadedTesterBase::test(new ThreadedClearOnShutdownTester); |
| 6497 EXPECT_EQ(numberOfThreads, IntWrapper::s_destructorCalls); | 6490 EXPECT_EQ(numberOfThreads, IntWrapper::s_destructorCalls); |
| 6498 } | 6491 } |
| 6499 | 6492 |
| 6500 private: | 6493 private: |
| 6501 void runThread() override | 6494 void runThread() override |
| 6502 { | 6495 { |
| 6503 ThreadState::attachCurrentThread(); | 6496 ThreadState::attach(); |
| 6504 EXPECT_EQ(42, threadSpecificIntWrapper().value()); | 6497 EXPECT_EQ(42, threadSpecificIntWrapper().value()); |
| 6505 ThreadState::detachCurrentThread(); | 6498 ThreadState::detach(); |
| 6506 atomicDecrement(&m_threadsToFinish); | 6499 atomicDecrement(&m_threadsToFinish); |
| 6507 } | 6500 } |
| 6508 | 6501 |
| 6509 static IntWrapper& threadSpecificIntWrapper() | 6502 static IntWrapper& threadSpecificIntWrapper() |
| 6510 { | 6503 { |
| 6511 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 6504 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
| 6512 ThreadSpecific<Persistent<IntWrapper>>, intWrapper, | 6505 ThreadSpecific<Persistent<IntWrapper>>, intWrapper, |
| 6513 new ThreadSpecific<Persistent<IntWrapper>>); | 6506 new ThreadSpecific<Persistent<IntWrapper>>); |
| 6514 Persistent<IntWrapper>& handle = *intWrapper; | 6507 Persistent<IntWrapper>& handle = *intWrapper; |
| 6515 if (!handle) { | 6508 if (!handle) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6560 conservativelyCollectGarbage(); | 6553 conservativelyCollectGarbage(); |
| 6561 EXPECT_EQ(wrapper, weakWrapper->value()); | 6554 EXPECT_EQ(wrapper, weakWrapper->value()); |
| 6562 // Stub out any stack reference. | 6555 // Stub out any stack reference. |
| 6563 wrapper = nullptr; | 6556 wrapper = nullptr; |
| 6564 } | 6557 } |
| 6565 preciselyCollectGarbage(); | 6558 preciselyCollectGarbage(); |
| 6566 EXPECT_EQ(nullptr, weakWrapper->value()); | 6559 EXPECT_EQ(nullptr, weakWrapper->value()); |
| 6567 } | 6560 } |
| 6568 | 6561 |
| 6569 } // namespace blink | 6562 } // namespace blink |
| OLD | NEW |