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