| 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 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 namespace blink { | 237 namespace blink { |
| 238 | 238 |
| 239 class TestGCScope { | 239 class TestGCScope { |
| 240 public: | 240 public: |
| 241 explicit TestGCScope(BlinkGC::StackState state) | 241 explicit TestGCScope(BlinkGC::StackState state) |
| 242 : m_state(ThreadState::current()) | 242 : m_state(ThreadState::current()) |
| 243 , m_safePointScope(state) | 243 , m_safePointScope(state) |
| 244 , m_parkedAllThreads(false) | 244 , m_parkedAllThreads(false) |
| 245 { | 245 { |
| 246 ASSERT(m_state->checkThread()); | 246 ASSERT(m_state->checkThread()); |
| 247 if (LIKELY(ThreadState::stopThreads())) { | 247 if (LIKELY(m_state->heap().park())) { |
| 248 ThreadHeap::preGC(); | 248 m_state->heap().preGC(); |
| 249 m_parkedAllThreads = true; | 249 m_parkedAllThreads = true; |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 | 252 |
| 253 bool allThreadsParked() { return m_parkedAllThreads; } | 253 bool allThreadsParked() { return m_parkedAllThreads; } |
| 254 | 254 |
| 255 ~TestGCScope() | 255 ~TestGCScope() |
| 256 { | 256 { |
| 257 // Only cleanup if we parked all threads in which case the GC happened | 257 // Only cleanup if we parked all threads in which case the GC happened |
| 258 // and we need to resume the other threads. | 258 // and we need to resume the other threads. |
| 259 if (LIKELY(m_parkedAllThreads)) { | 259 if (LIKELY(m_parkedAllThreads)) { |
| 260 ThreadHeap::postGC(BlinkGC::GCWithSweep); | 260 m_state->heap().postGC(BlinkGC::GCWithSweep); |
| 261 ThreadState::resumeThreads(); | 261 m_state->heap().resume(); |
| 262 } | 262 } |
| 263 } | 263 } |
| 264 | 264 |
| 265 private: | 265 private: |
| 266 ThreadState* m_state; | 266 ThreadState* m_state; |
| 267 SafePointScope m_safePointScope; | 267 SafePointScope m_safePointScope; |
| 268 bool m_parkedAllThreads; // False if we fail to park all threads | 268 bool m_parkedAllThreads; // False if we fail to park all threads |
| 269 }; | 269 }; |
| 270 | 270 |
| 271 #define DEFINE_VISITOR_METHODS(Type) \ | 271 #define DEFINE_VISITOR_METHODS(Type) \ |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 407 DEFINE_INLINE_TRACE() { } | 407 DEFINE_INLINE_TRACE() { } |
| 408 private: | 408 private: |
| 409 static const int s_arraySize = 1000; | 409 static const int s_arraySize = 1000; |
| 410 int8_t m_array[s_arraySize]; | 410 int8_t m_array[s_arraySize]; |
| 411 }; | 411 }; |
| 412 | 412 |
| 413 // Do several GCs to make sure that later GCs don't free up old memory from | 413 // Do several GCs to make sure that later GCs don't free up old memory from |
| 414 // previously run tests in this process. | 414 // previously run tests in this process. |
| 415 static void clearOutOldGarbage() | 415 static void clearOutOldGarbage() |
| 416 { | 416 { |
| 417 ThreadHeap& heap = ThreadState::current()->heap(); |
| 417 while (true) { | 418 while (true) { |
| 418 size_t used = ThreadHeap::objectPayloadSizeForTesting(); | 419 size_t used = heap.objectPayloadSizeForTesting(); |
| 419 preciselyCollectGarbage(); | 420 preciselyCollectGarbage(); |
| 420 if (ThreadHeap::objectPayloadSizeForTesting() >= used) | 421 if (heap.objectPayloadSizeForTesting() >= used) |
| 421 break; | 422 break; |
| 422 } | 423 } |
| 423 } | 424 } |
| 424 | 425 |
| 425 class OffHeapInt : public RefCounted<OffHeapInt> { | 426 class OffHeapInt : public RefCounted<OffHeapInt> { |
| 426 public: | 427 public: |
| 427 static RefPtr<OffHeapInt> create(int x) | 428 static RefPtr<OffHeapInt> create(int x) |
| 428 { | 429 { |
| 429 return adoptRef(new OffHeapInt(x)); | 430 return adoptRef(new OffHeapInt(x)); |
| 430 } | 431 } |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 556 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 557 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 557 testing::yieldCurrentThread(); | 558 testing::yieldCurrentThread(); |
| 558 } | 559 } |
| 559 | 560 |
| 560 // Intentionally leak the cross-thread persistent so as to verify | 561 // Intentionally leak the cross-thread persistent so as to verify |
| 561 // that later GCs correctly handle cross-thread persistents that | 562 // that later GCs correctly handle cross-thread persistents that |
| 562 // refer to finalized objects after their heaps have been detached | 563 // refer to finalized objects after their heaps have been detached |
| 563 // and freed. | 564 // and freed. |
| 564 EXPECT_TRUE(longLivingPersistent.leakPtr()); | 565 EXPECT_TRUE(longLivingPersistent.leakPtr()); |
| 565 | 566 |
| 566 ThreadState::detach(); | 567 ThreadState::detachCurrentThread(); |
| 567 atomicDecrement(&m_threadsToFinish); | 568 atomicDecrement(&m_threadsToFinish); |
| 568 } | 569 } |
| 569 }; | 570 }; |
| 570 | 571 |
| 571 class ThreadedWeaknessTester : public ThreadedTesterBase { | 572 class ThreadedWeaknessTester : public ThreadedTesterBase { |
| 572 public: | 573 public: |
| 573 static void test() | 574 static void test() |
| 574 { | 575 { |
| 575 ThreadedTesterBase::test(new ThreadedWeaknessTester); | 576 ThreadedTesterBase::test(new ThreadedWeaknessTester); |
| 576 } | 577 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 604 // TODO(haraken): This snapshot GC causes crashes, so disable | 605 // TODO(haraken): This snapshot GC causes crashes, so disable |
| 605 // it at the moment. Fix the crash and enable it. | 606 // it at the moment. Fix the crash and enable it. |
| 606 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, Bl
inkGC::TakeSnapshot, BlinkGC::ForcedGC); | 607 // ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, Bl
inkGC::TakeSnapshot, BlinkGC::ForcedGC); |
| 607 preciselyCollectGarbage(); | 608 preciselyCollectGarbage(); |
| 608 EXPECT_TRUE(weakMap->isEmpty()); | 609 EXPECT_TRUE(weakMap->isEmpty()); |
| 609 EXPECT_TRUE(weakMap2.isEmpty()); | 610 EXPECT_TRUE(weakMap2.isEmpty()); |
| 610 } | 611 } |
| 611 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); | 612 SafePointScope scope(BlinkGC::NoHeapPointersOnStack); |
| 612 testing::yieldCurrentThread(); | 613 testing::yieldCurrentThread(); |
| 613 } | 614 } |
| 614 ThreadState::detach(); | 615 ThreadState::detachCurrentThread(); |
| 615 atomicDecrement(&m_threadsToFinish); | 616 atomicDecrement(&m_threadsToFinish); |
| 616 } | 617 } |
| 617 }; | 618 }; |
| 618 | 619 |
| 619 class ThreadPersistentHeapTester : public ThreadedTesterBase { | 620 class ThreadPersistentHeapTester : public ThreadedTesterBase { |
| 620 public: | 621 public: |
| 621 static void test() | 622 static void test() |
| 622 { | 623 { |
| 623 ThreadedTesterBase::test(new ThreadPersistentHeapTester); | 624 ThreadedTesterBase::test(new ThreadPersistentHeapTester); |
| 624 } | 625 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 void runThread() override | 674 void runThread() override |
| 674 { | 675 { |
| 675 ThreadState::attach(); | 676 ThreadState::attach(); |
| 676 | 677 |
| 677 PersistentChain::create(100); | 678 PersistentChain::create(100); |
| 678 | 679 |
| 679 // Upon thread detach, GCs will run until all persistents have been | 680 // Upon thread detach, GCs will run until all persistents have been |
| 680 // released. We verify that the draining of persistents proceeds | 681 // released. We verify that the draining of persistents proceeds |
| 681 // as expected by dropping one Persistent<> per GC until there | 682 // as expected by dropping one Persistent<> per GC until there |
| 682 // are none left. | 683 // are none left. |
| 683 ThreadState::detach(); | 684 ThreadState::detachCurrentThread(); |
| 684 atomicDecrement(&m_threadsToFinish); | 685 atomicDecrement(&m_threadsToFinish); |
| 685 } | 686 } |
| 686 }; | 687 }; |
| 687 | 688 |
| 688 // The accounting for memory includes the memory used by rounding up object | 689 // The accounting for memory includes the memory used by rounding up object |
| 689 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to | 690 // sizes. This is done in a different way on 32 bit and 64 bit, so we have to |
| 690 // have some slack in the tests. | 691 // have some slack in the tests. |
| 691 template<typename T> | 692 template<typename T> |
| 692 void CheckWithSlack(T expected, T actual, int slack) | 693 void CheckWithSlack(T expected, T actual, int slack) |
| 693 { | 694 { |
| (...skipping 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1759 ThreadedWeaknessTester::test(); | 1760 ThreadedWeaknessTester::test(); |
| 1760 } | 1761 } |
| 1761 | 1762 |
| 1762 TEST(HeapTest, ThreadPersistent) | 1763 TEST(HeapTest, ThreadPersistent) |
| 1763 { | 1764 { |
| 1764 ThreadPersistentHeapTester::test(); | 1765 ThreadPersistentHeapTester::test(); |
| 1765 } | 1766 } |
| 1766 | 1767 |
| 1767 TEST(HeapTest, BasicFunctionality) | 1768 TEST(HeapTest, BasicFunctionality) |
| 1768 { | 1769 { |
| 1770 ThreadHeap& heap = ThreadState::current()->heap(); |
| 1769 clearOutOldGarbage(); | 1771 clearOutOldGarbage(); |
| 1770 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); | 1772 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); |
| 1771 { | 1773 { |
| 1772 size_t slack = 0; | 1774 size_t slack = 0; |
| 1773 | 1775 |
| 1774 // When the test starts there may already have been leaked some memory | 1776 // When the test starts there may already have been leaked some memory |
| 1775 // on the heap, so we establish a base line. | 1777 // on the heap, so we establish a base line. |
| 1776 size_t baseLevel = initialObjectPayloadSize; | 1778 size_t baseLevel = initialObjectPayloadSize; |
| 1777 bool testPagesAllocated = !baseLevel; | 1779 bool testPagesAllocated = !baseLevel; |
| 1778 if (testPagesAllocated) | 1780 if (testPagesAllocated) |
| 1779 EXPECT_EQ(ThreadHeap::heapStats().allocatedSpace(), 0ul); | 1781 EXPECT_EQ(heap.heapStats().allocatedSpace(), 0ul); |
| 1780 | 1782 |
| 1781 // This allocates objects on the general heap which should add a page of
memory. | 1783 // This allocates objects on the general heap which should add a page of
memory. |
| 1782 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); | 1784 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); |
| 1783 slack += 4; | 1785 slack += 4; |
| 1784 memset(alloc32, 40, 32); | 1786 memset(alloc32, 40, 32); |
| 1785 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); | 1787 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); |
| 1786 slack += 4; | 1788 slack += 4; |
| 1787 memset(alloc64, 27, 64); | 1789 memset(alloc64, 27, 64); |
| 1788 | 1790 |
| 1789 size_t total = 96; | 1791 size_t total = 96; |
| 1790 | 1792 |
| 1791 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTestin
g(), slack); | 1793 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), sl
ack); |
| 1792 if (testPagesAllocated) | 1794 if (testPagesAllocated) |
| 1793 EXPECT_EQ(ThreadHeap::heapStats().allocatedSpace(), blinkPageSize *
2); | 1795 EXPECT_EQ(heap.heapStats().allocatedSpace(), blinkPageSize * 2); |
| 1794 | 1796 |
| 1795 EXPECT_EQ(alloc32->get(0), 40); | 1797 EXPECT_EQ(alloc32->get(0), 40); |
| 1796 EXPECT_EQ(alloc32->get(31), 40); | 1798 EXPECT_EQ(alloc32->get(31), 40); |
| 1797 EXPECT_EQ(alloc64->get(0), 27); | 1799 EXPECT_EQ(alloc64->get(0), 27); |
| 1798 EXPECT_EQ(alloc64->get(63), 27); | 1800 EXPECT_EQ(alloc64->get(63), 27); |
| 1799 | 1801 |
| 1800 conservativelyCollectGarbage(); | 1802 conservativelyCollectGarbage(); |
| 1801 | 1803 |
| 1802 EXPECT_EQ(alloc32->get(0), 40); | 1804 EXPECT_EQ(alloc32->get(0), 40); |
| 1803 EXPECT_EQ(alloc32->get(31), 40); | 1805 EXPECT_EQ(alloc32->get(31), 40); |
| 1804 EXPECT_EQ(alloc64->get(0), 27); | 1806 EXPECT_EQ(alloc64->get(0), 27); |
| 1805 EXPECT_EQ(alloc64->get(63), 27); | 1807 EXPECT_EQ(alloc64->get(63), 27); |
| 1806 } | 1808 } |
| 1807 | 1809 |
| 1808 clearOutOldGarbage(); | 1810 clearOutOldGarbage(); |
| 1809 size_t total = 0; | 1811 size_t total = 0; |
| 1810 size_t slack = 0; | 1812 size_t slack = 0; |
| 1811 size_t baseLevel = ThreadHeap::objectPayloadSizeForTesting(); | 1813 size_t baseLevel = heap.objectPayloadSizeForTesting(); |
| 1812 bool testPagesAllocated = !baseLevel; | 1814 bool testPagesAllocated = !baseLevel; |
| 1813 if (testPagesAllocated) | 1815 if (testPagesAllocated) |
| 1814 EXPECT_EQ(ThreadHeap::heapStats().allocatedSpace(), 0ul); | 1816 EXPECT_EQ(heap.heapStats().allocatedSpace(), 0ul); |
| 1815 | 1817 |
| 1816 size_t big = 1008; | 1818 size_t big = 1008; |
| 1817 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(
big); | 1819 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create(
big); |
| 1818 total += big; | 1820 total += big; |
| 1819 slack += 4; | 1821 slack += 4; |
| 1820 | 1822 |
| 1821 size_t persistentCount = 0; | 1823 size_t persistentCount = 0; |
| 1822 const size_t numPersistents = 100000; | 1824 const size_t numPersistents = 100000; |
| 1823 Persistent<DynamicallySizedObject>* persistents[numPersistents]; | 1825 Persistent<DynamicallySizedObject>* persistents[numPersistents]; |
| 1824 | 1826 |
| 1825 for (int i = 0; i < 1000; i++) { | 1827 for (int i = 0; i < 1000; i++) { |
| 1826 size_t size = 128 + i * 8; | 1828 size_t size = 128 + i * 8; |
| 1827 total += size; | 1829 total += size; |
| 1828 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(
DynamicallySizedObject::create(size)); | 1830 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>(
DynamicallySizedObject::create(size)); |
| 1829 slack += 4; | 1831 slack += 4; |
| 1830 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTestin
g(), slack); | 1832 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), sl
ack); |
| 1831 if (testPagesAllocated) | 1833 if (testPagesAllocated) |
| 1832 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPage
Size - 1)); | 1834 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize -
1)); |
| 1833 } | 1835 } |
| 1834 | 1836 |
| 1835 { | 1837 { |
| 1836 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32)); | 1838 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32)); |
| 1837 slack += 4; | 1839 slack += 4; |
| 1838 memset(alloc32b, 40, 32); | 1840 memset(alloc32b, 40, 32); |
| 1839 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64)); | 1841 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64)); |
| 1840 slack += 4; | 1842 slack += 4; |
| 1841 memset(alloc64b, 27, 64); | 1843 memset(alloc64b, 27, 64); |
| 1842 EXPECT_TRUE(alloc32b != alloc64b); | 1844 EXPECT_TRUE(alloc32b != alloc64b); |
| 1843 | 1845 |
| 1844 total += 96; | 1846 total += 96; |
| 1845 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTestin
g(), slack); | 1847 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), sl
ack); |
| 1846 if (testPagesAllocated) | 1848 if (testPagesAllocated) |
| 1847 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPage
Size - 1)); | 1849 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize -
1)); |
| 1848 } | 1850 } |
| 1849 | 1851 |
| 1850 clearOutOldGarbage(); | 1852 clearOutOldGarbage(); |
| 1851 total -= 96; | 1853 total -= 96; |
| 1852 slack -= 8; | 1854 slack -= 8; |
| 1853 if (testPagesAllocated) | 1855 if (testPagesAllocated) |
| 1854 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPageSize
- 1)); | 1856 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize - 1)); |
| 1855 | 1857 |
| 1856 // Clear the persistent, so that the big area will be garbage collected. | 1858 // Clear the persistent, so that the big area will be garbage collected. |
| 1857 bigArea.release(); | 1859 bigArea.release(); |
| 1858 clearOutOldGarbage(); | 1860 clearOutOldGarbage(); |
| 1859 | 1861 |
| 1860 total -= big; | 1862 total -= big; |
| 1861 slack -= 4; | 1863 slack -= 4; |
| 1862 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTesting(),
slack); | 1864 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), slack)
; |
| 1863 if (testPagesAllocated) | 1865 if (testPagesAllocated) |
| 1864 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPageSize
- 1)); | 1866 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize - 1)); |
| 1865 | 1867 |
| 1866 CheckWithSlack(baseLevel + total, ThreadHeap::objectPayloadSizeForTesting(),
slack); | 1868 CheckWithSlack(baseLevel + total, heap.objectPayloadSizeForTesting(), slack)
; |
| 1867 if (testPagesAllocated) | 1869 if (testPagesAllocated) |
| 1868 EXPECT_EQ(0ul, ThreadHeap::heapStats().allocatedSpace() & (blinkPageSize
- 1)); | 1870 EXPECT_EQ(0ul, heap.heapStats().allocatedSpace() & (blinkPageSize - 1)); |
| 1869 | 1871 |
| 1870 for (size_t i = 0; i < persistentCount; i++) { | 1872 for (size_t i = 0; i < persistentCount; i++) { |
| 1871 delete persistents[i]; | 1873 delete persistents[i]; |
| 1872 persistents[i] = 0; | 1874 persistents[i] = 0; |
| 1873 } | 1875 } |
| 1874 | 1876 |
| 1875 uint8_t* address = reinterpret_cast<uint8_t*>(ThreadHeap::allocate<Dynamical
lySizedObject>(100)); | 1877 uint8_t* address = reinterpret_cast<uint8_t*>(ThreadHeap::allocate<Dynamical
lySizedObject>(100)); |
| 1876 for (int i = 0; i < 100; i++) | 1878 for (int i = 0; i < 100; i++) |
| 1877 address[i] = i; | 1879 address[i] = i; |
| 1878 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 100000)); | 1880 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 100000)); |
| 1879 for (int i = 0; i < 100; i++) | 1881 for (int i = 0; i < 100; i++) |
| 1880 EXPECT_EQ(address[i], i); | 1882 EXPECT_EQ(address[i], i); |
| 1881 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 50)); | 1883 address = reinterpret_cast<uint8_t*>(ThreadHeap::reallocate<DynamicallySized
Object>(address, 50)); |
| 1882 for (int i = 0; i < 50; i++) | 1884 for (int i = 0; i < 50; i++) |
| 1883 EXPECT_EQ(address[i], i); | 1885 EXPECT_EQ(address[i], i); |
| 1884 // This should be equivalent to free(address). | 1886 // This should be equivalent to free(address). |
| 1885 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(address, 0)), 0ul); | 1887 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(address, 0)), 0ul); |
| 1886 // This should be equivalent to malloc(0). | 1888 // This should be equivalent to malloc(0). |
| 1887 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(0, 0)), 0ul); | 1889 EXPECT_EQ(reinterpret_cast<uintptr_t>(ThreadHeap::reallocate<DynamicallySize
dObject>(0, 0)), 0ul); |
| 1888 } | 1890 } |
| 1889 | 1891 |
| 1890 TEST(HeapTest, SimpleAllocation) | 1892 TEST(HeapTest, SimpleAllocation) |
| 1891 { | 1893 { |
| 1894 ThreadHeap& heap = ThreadState::current()->heap(); |
| 1892 clearOutOldGarbage(); | 1895 clearOutOldGarbage(); |
| 1893 EXPECT_EQ(0ul, ThreadHeap::objectPayloadSizeForTesting()); | 1896 EXPECT_EQ(0ul, heap.objectPayloadSizeForTesting()); |
| 1894 | 1897 |
| 1895 // Allocate an object in the heap. | 1898 // Allocate an object in the heap. |
| 1896 HeapAllocatedArray* array = new HeapAllocatedArray(); | 1899 HeapAllocatedArray* array = new HeapAllocatedArray(); |
| 1897 EXPECT_TRUE(ThreadHeap::objectPayloadSizeForTesting() >= sizeof(HeapAllocate
dArray)); | 1900 EXPECT_TRUE(heap.objectPayloadSizeForTesting() >= sizeof(HeapAllocatedArray)
); |
| 1898 | 1901 |
| 1899 // Sanity check of the contents in the heap. | 1902 // Sanity check of the contents in the heap. |
| 1900 EXPECT_EQ(0, array->at(0)); | 1903 EXPECT_EQ(0, array->at(0)); |
| 1901 EXPECT_EQ(42, array->at(42)); | 1904 EXPECT_EQ(42, array->at(42)); |
| 1902 EXPECT_EQ(0, array->at(128)); | 1905 EXPECT_EQ(0, array->at(128)); |
| 1903 EXPECT_EQ(999 % 128, array->at(999)); | 1906 EXPECT_EQ(999 % 128, array->at(999)); |
| 1904 } | 1907 } |
| 1905 | 1908 |
| 1906 TEST(HeapTest, SimplePersistent) | 1909 TEST(HeapTest, SimplePersistent) |
| 1907 { | 1910 { |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2215 // for the conservative stack scan to find. | 2218 // for the conservative stack scan to find. |
| 2216 EXPECT_EQ(width, bars->getWidth()); | 2219 EXPECT_EQ(width, bars->getWidth()); |
| 2217 } | 2220 } |
| 2218 EXPECT_EQ(Bars::width + 1, Bar::s_live); | 2221 EXPECT_EQ(Bars::width + 1, Bar::s_live); |
| 2219 preciselyCollectGarbage(); | 2222 preciselyCollectGarbage(); |
| 2220 EXPECT_EQ(0u, Bar::s_live); | 2223 EXPECT_EQ(0u, Bar::s_live); |
| 2221 } | 2224 } |
| 2222 | 2225 |
| 2223 TEST(HeapTest, HashMapOfMembers) | 2226 TEST(HeapTest, HashMapOfMembers) |
| 2224 { | 2227 { |
| 2228 ThreadHeap& heap = ThreadState::current()->heap(); |
| 2225 IntWrapper::s_destructorCalls = 0; | 2229 IntWrapper::s_destructorCalls = 0; |
| 2226 | 2230 |
| 2227 clearOutOldGarbage(); | 2231 clearOutOldGarbage(); |
| 2228 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); | 2232 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); |
| 2229 { | 2233 { |
| 2230 typedef HeapHashMap< | 2234 typedef HeapHashMap< |
| 2231 Member<IntWrapper>, | 2235 Member<IntWrapper>, |
| 2232 Member<IntWrapper>, | 2236 Member<IntWrapper>, |
| 2233 DefaultHash<Member<IntWrapper>>::Hash, | 2237 DefaultHash<Member<IntWrapper>>::Hash, |
| 2234 HashTraits<Member<IntWrapper>>, | 2238 HashTraits<Member<IntWrapper>>, |
| 2235 HashTraits<Member<IntWrapper>>> HeapObjectIdentityMap; | 2239 HashTraits<Member<IntWrapper>>> HeapObjectIdentityMap; |
| 2236 | 2240 |
| 2237 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap(); | 2241 Persistent<HeapObjectIdentityMap> map = new HeapObjectIdentityMap(); |
| 2238 | 2242 |
| 2239 map->clear(); | 2243 map->clear(); |
| 2240 size_t afterSetWasCreated = ThreadHeap::objectPayloadSizeForTesting(); | 2244 size_t afterSetWasCreated = heap.objectPayloadSizeForTesting(); |
| 2241 EXPECT_TRUE(afterSetWasCreated > initialObjectPayloadSize); | 2245 EXPECT_TRUE(afterSetWasCreated > initialObjectPayloadSize); |
| 2242 | 2246 |
| 2243 preciselyCollectGarbage(); | 2247 preciselyCollectGarbage(); |
| 2244 size_t afterGC = ThreadHeap::objectPayloadSizeForTesting(); | 2248 size_t afterGC = heap.objectPayloadSizeForTesting(); |
| 2245 EXPECT_EQ(afterGC, afterSetWasCreated); | 2249 EXPECT_EQ(afterGC, afterSetWasCreated); |
| 2246 | 2250 |
| 2247 // If the additions below cause garbage collections, these | 2251 // If the additions below cause garbage collections, these |
| 2248 // pointers should be found by conservative stack scanning. | 2252 // pointers should be found by conservative stack scanning. |
| 2249 IntWrapper* one(IntWrapper::create(1)); | 2253 IntWrapper* one(IntWrapper::create(1)); |
| 2250 IntWrapper* anotherOne(IntWrapper::create(1)); | 2254 IntWrapper* anotherOne(IntWrapper::create(1)); |
| 2251 | 2255 |
| 2252 map->add(one, one); | 2256 map->add(one, one); |
| 2253 | 2257 |
| 2254 size_t afterOneAdd = ThreadHeap::objectPayloadSizeForTesting(); | 2258 size_t afterOneAdd = heap.objectPayloadSizeForTesting(); |
| 2255 EXPECT_TRUE(afterOneAdd > afterGC); | 2259 EXPECT_TRUE(afterOneAdd > afterGC); |
| 2256 | 2260 |
| 2257 HeapObjectIdentityMap::iterator it(map->begin()); | 2261 HeapObjectIdentityMap::iterator it(map->begin()); |
| 2258 HeapObjectIdentityMap::iterator it2(map->begin()); | 2262 HeapObjectIdentityMap::iterator it2(map->begin()); |
| 2259 ++it; | 2263 ++it; |
| 2260 ++it2; | 2264 ++it2; |
| 2261 | 2265 |
| 2262 map->add(anotherOne, one); | 2266 map->add(anotherOne, one); |
| 2263 | 2267 |
| 2264 // The addition above can cause an allocation of a new | 2268 // The addition above can cause an allocation of a new |
| 2265 // backing store. We therefore garbage collect before | 2269 // backing store. We therefore garbage collect before |
| 2266 // taking the heap stats in order to get rid of the old | 2270 // taking the heap stats in order to get rid of the old |
| 2267 // backing store. We make sure to not use conservative | 2271 // backing store. We make sure to not use conservative |
| 2268 // stack scanning as that could find a pointer to the | 2272 // stack scanning as that could find a pointer to the |
| 2269 // old backing. | 2273 // old backing. |
| 2270 preciselyCollectGarbage(); | 2274 preciselyCollectGarbage(); |
| 2271 size_t afterAddAndGC = ThreadHeap::objectPayloadSizeForTesting(); | 2275 size_t afterAddAndGC = heap.objectPayloadSizeForTesting(); |
| 2272 EXPECT_TRUE(afterAddAndGC >= afterOneAdd); | 2276 EXPECT_TRUE(afterAddAndGC >= afterOneAdd); |
| 2273 | 2277 |
| 2274 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distin
ct. | 2278 EXPECT_EQ(map->size(), 2u); // Two different wrappings of '1' are distin
ct. |
| 2275 | 2279 |
| 2276 preciselyCollectGarbage(); | 2280 preciselyCollectGarbage(); |
| 2277 EXPECT_TRUE(map->contains(one)); | 2281 EXPECT_TRUE(map->contains(one)); |
| 2278 EXPECT_TRUE(map->contains(anotherOne)); | 2282 EXPECT_TRUE(map->contains(anotherOne)); |
| 2279 | 2283 |
| 2280 IntWrapper* gotten(map->get(one)); | 2284 IntWrapper* gotten(map->get(one)); |
| 2281 EXPECT_EQ(gotten->value(), one->value()); | 2285 EXPECT_EQ(gotten->value(), one->value()); |
| 2282 EXPECT_EQ(gotten, one); | 2286 EXPECT_EQ(gotten, one); |
| 2283 | 2287 |
| 2284 size_t afterGC2 = ThreadHeap::objectPayloadSizeForTesting(); | 2288 size_t afterGC2 = heap.objectPayloadSizeForTesting(); |
| 2285 EXPECT_EQ(afterGC2, afterAddAndGC); | 2289 EXPECT_EQ(afterGC2, afterAddAndGC); |
| 2286 | 2290 |
| 2287 IntWrapper* dozen = 0; | 2291 IntWrapper* dozen = 0; |
| 2288 | 2292 |
| 2289 for (int i = 1; i < 1000; i++) { // 999 iterations. | 2293 for (int i = 1; i < 1000; i++) { // 999 iterations. |
| 2290 IntWrapper* iWrapper(IntWrapper::create(i)); | 2294 IntWrapper* iWrapper(IntWrapper::create(i)); |
| 2291 IntWrapper* iSquared(IntWrapper::create(i * i)); | 2295 IntWrapper* iSquared(IntWrapper::create(i * i)); |
| 2292 map->add(iWrapper, iSquared); | 2296 map->add(iWrapper, iSquared); |
| 2293 if (i == 12) | 2297 if (i == 12) |
| 2294 dozen = iWrapper; | 2298 dozen = iWrapper; |
| 2295 } | 2299 } |
| 2296 size_t afterAdding1000 = ThreadHeap::objectPayloadSizeForTesting(); | 2300 size_t afterAdding1000 = heap.objectPayloadSizeForTesting(); |
| 2297 EXPECT_TRUE(afterAdding1000 > afterGC2); | 2301 EXPECT_TRUE(afterAdding1000 > afterGC2); |
| 2298 | 2302 |
| 2299 IntWrapper* gross(map->get(dozen)); | 2303 IntWrapper* gross(map->get(dozen)); |
| 2300 EXPECT_EQ(gross->value(), 144); | 2304 EXPECT_EQ(gross->value(), 144); |
| 2301 | 2305 |
| 2302 // This should clear out any junk backings created by all the adds. | 2306 // This should clear out any junk backings created by all the adds. |
| 2303 preciselyCollectGarbage(); | 2307 preciselyCollectGarbage(); |
| 2304 size_t afterGC3 = ThreadHeap::objectPayloadSizeForTesting(); | 2308 size_t afterGC3 = heap.objectPayloadSizeForTesting(); |
| 2305 EXPECT_TRUE(afterGC3 <= afterAdding1000); | 2309 EXPECT_TRUE(afterGC3 <= afterAdding1000); |
| 2306 } | 2310 } |
| 2307 | 2311 |
| 2308 preciselyCollectGarbage(); | 2312 preciselyCollectGarbage(); |
| 2309 // The objects 'one', anotherOne, and the 999 other pairs. | 2313 // The objects 'one', anotherOne, and the 999 other pairs. |
| 2310 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000); | 2314 EXPECT_EQ(IntWrapper::s_destructorCalls, 2000); |
| 2311 size_t afterGC4 = ThreadHeap::objectPayloadSizeForTesting(); | 2315 size_t afterGC4 = heap.objectPayloadSizeForTesting(); |
| 2312 EXPECT_EQ(afterGC4, initialObjectPayloadSize); | 2316 EXPECT_EQ(afterGC4, initialObjectPayloadSize); |
| 2313 } | 2317 } |
| 2314 | 2318 |
| 2315 TEST(HeapTest, NestedAllocation) | 2319 TEST(HeapTest, NestedAllocation) |
| 2316 { | 2320 { |
| 2321 ThreadHeap& heap = ThreadState::current()->heap(); |
| 2317 clearOutOldGarbage(); | 2322 clearOutOldGarbage(); |
| 2318 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); | 2323 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); |
| 2319 { | 2324 { |
| 2320 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAll
ocation::create(); | 2325 Persistent<ConstructorAllocation> constructorAllocation = ConstructorAll
ocation::create(); |
| 2321 } | 2326 } |
| 2322 clearOutOldGarbage(); | 2327 clearOutOldGarbage(); |
| 2323 size_t afterFree = ThreadHeap::objectPayloadSizeForTesting(); | 2328 size_t afterFree = heap.objectPayloadSizeForTesting(); |
| 2324 EXPECT_TRUE(initialObjectPayloadSize == afterFree); | 2329 EXPECT_TRUE(initialObjectPayloadSize == afterFree); |
| 2325 } | 2330 } |
| 2326 | 2331 |
| 2327 TEST(HeapTest, LargeHeapObjects) | 2332 TEST(HeapTest, LargeHeapObjects) |
| 2328 { | 2333 { |
| 2334 ThreadHeap& heap = ThreadState::current()->heap(); |
| 2329 clearOutOldGarbage(); | 2335 clearOutOldGarbage(); |
| 2330 size_t initialObjectPayloadSize = ThreadHeap::objectPayloadSizeForTesting(); | 2336 size_t initialObjectPayloadSize = heap.objectPayloadSizeForTesting(); |
| 2331 size_t initialAllocatedSpace = ThreadHeap::heapStats().allocatedSpace(); | 2337 size_t initialAllocatedSpace = heap.heapStats().allocatedSpace(); |
| 2332 IntWrapper::s_destructorCalls = 0; | 2338 IntWrapper::s_destructorCalls = 0; |
| 2333 LargeHeapObject::s_destructorCalls = 0; | 2339 LargeHeapObject::s_destructorCalls = 0; |
| 2334 { | 2340 { |
| 2335 int slack = 8; // LargeHeapObject points to an IntWrapper that is also a
llocated. | 2341 int slack = 8; // LargeHeapObject points to an IntWrapper that is also a
llocated. |
| 2336 Persistent<LargeHeapObject> object = LargeHeapObject::create(); | 2342 Persistent<LargeHeapObject> object = LargeHeapObject::create(); |
| 2337 ASSERT(ThreadState::current()->findPageFromAddress(object)); | 2343 ASSERT(ThreadState::current()->findPageFromAddress(object)); |
| 2338 ASSERT(ThreadState::current()->findPageFromAddress(reinterpret_cast<char
*>(object.get()) + sizeof(LargeHeapObject) - 1)); | 2344 ASSERT(ThreadState::current()->findPageFromAddress(reinterpret_cast<char
*>(object.get()) + sizeof(LargeHeapObject) - 1)); |
| 2339 clearOutOldGarbage(); | 2345 clearOutOldGarbage(); |
| 2340 size_t afterAllocation = ThreadHeap::heapStats().allocatedSpace(); | 2346 size_t afterAllocation = heap.heapStats().allocatedSpace(); |
| 2341 { | 2347 { |
| 2342 object->set(0, 'a'); | 2348 object->set(0, 'a'); |
| 2343 EXPECT_EQ('a', object->get(0)); | 2349 EXPECT_EQ('a', object->get(0)); |
| 2344 object->set(object->length() - 1, 'b'); | 2350 object->set(object->length() - 1, 'b'); |
| 2345 EXPECT_EQ('b', object->get(object->length() - 1)); | 2351 EXPECT_EQ('b', object->get(object->length() - 1)); |
| 2346 size_t expectedLargeHeapObjectPayloadSize = ThreadHeap::allocationSi
zeFromSize(sizeof(LargeHeapObject)); | 2352 size_t expectedLargeHeapObjectPayloadSize = ThreadHeap::allocationSi
zeFromSize(sizeof(LargeHeapObject)); |
| 2347 size_t expectedObjectPayloadSize = expectedLargeHeapObjectPayloadSiz
e + sizeof(IntWrapper); | 2353 size_t expectedObjectPayloadSize = expectedLargeHeapObjectPayloadSiz
e + sizeof(IntWrapper); |
| 2348 size_t actualObjectPayloadSize = ThreadHeap::objectPayloadSizeForTes
ting() - initialObjectPayloadSize; | 2354 size_t actualObjectPayloadSize = heap.objectPayloadSizeForTesting()
- initialObjectPayloadSize; |
| 2349 CheckWithSlack(expectedObjectPayloadSize, actualObjectPayloadSize, s
lack); | 2355 CheckWithSlack(expectedObjectPayloadSize, actualObjectPayloadSize, s
lack); |
| 2350 // There is probably space for the IntWrapper in a heap page without | 2356 // There is probably space for the IntWrapper in a heap page without |
| 2351 // allocating extra pages. However, the IntWrapper allocation might
cause | 2357 // allocating extra pages. However, the IntWrapper allocation might
cause |
| 2352 // the addition of a heap page. | 2358 // the addition of a heap page. |
| 2353 size_t largeObjectAllocationSize = sizeof(LargeObjectPage) + expecte
dLargeHeapObjectPayloadSize; | 2359 size_t largeObjectAllocationSize = sizeof(LargeObjectPage) + expecte
dLargeHeapObjectPayloadSize; |
| 2354 size_t allocatedSpaceLowerBound = initialAllocatedSpace + largeObjec
tAllocationSize; | 2360 size_t allocatedSpaceLowerBound = initialAllocatedSpace + largeObjec
tAllocationSize; |
| 2355 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack +
blinkPageSize; | 2361 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack +
blinkPageSize; |
| 2356 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation); | 2362 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation); |
| 2357 EXPECT_LE(afterAllocation, allocatedSpaceUpperBound); | 2363 EXPECT_LE(afterAllocation, allocatedSpaceUpperBound); |
| 2358 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | 2364 EXPECT_EQ(0, IntWrapper::s_destructorCalls); |
| 2359 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); | 2365 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); |
| 2360 for (int i = 0; i < 10; i++) | 2366 for (int i = 0; i < 10; i++) |
| 2361 object = LargeHeapObject::create(); | 2367 object = LargeHeapObject::create(); |
| 2362 } | 2368 } |
| 2363 clearOutOldGarbage(); | 2369 clearOutOldGarbage(); |
| 2364 EXPECT_TRUE(ThreadHeap::heapStats().allocatedSpace() == afterAllocation)
; | 2370 EXPECT_TRUE(heap.heapStats().allocatedSpace() == afterAllocation); |
| 2365 EXPECT_EQ(10, IntWrapper::s_destructorCalls); | 2371 EXPECT_EQ(10, IntWrapper::s_destructorCalls); |
| 2366 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); | 2372 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); |
| 2367 } | 2373 } |
| 2368 clearOutOldGarbage(); | 2374 clearOutOldGarbage(); |
| 2369 EXPECT_TRUE(initialObjectPayloadSize == ThreadHeap::objectPayloadSizeForTest
ing()); | 2375 EXPECT_TRUE(initialObjectPayloadSize == heap.objectPayloadSizeForTesting()); |
| 2370 EXPECT_TRUE(initialAllocatedSpace == ThreadHeap::heapStats().allocatedSpace(
)); | 2376 EXPECT_TRUE(initialAllocatedSpace == heap.heapStats().allocatedSpace()); |
| 2371 EXPECT_EQ(11, IntWrapper::s_destructorCalls); | 2377 EXPECT_EQ(11, IntWrapper::s_destructorCalls); |
| 2372 EXPECT_EQ(11, LargeHeapObject::s_destructorCalls); | 2378 EXPECT_EQ(11, LargeHeapObject::s_destructorCalls); |
| 2373 preciselyCollectGarbage(); | 2379 preciselyCollectGarbage(); |
| 2374 } | 2380 } |
| 2375 | 2381 |
| 2376 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped; | 2382 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped; |
| 2377 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped; | 2383 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped; |
| 2378 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong; | 2384 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong; |
| 2379 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak; | 2385 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak; |
| 2380 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped; | 2386 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped; |
| (...skipping 1368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3749 { | 3755 { |
| 3750 Persistent<Bar> barPersistent = Bar::create(); | 3756 Persistent<Bar> barPersistent = Bar::create(); |
| 3751 Persistent<Foo> fooPersistent = Foo::create(barPersistent); | 3757 Persistent<Foo> fooPersistent = Foo::create(barPersistent); |
| 3752 EXPECT_TRUE(barPersistent != fooPersistent); | 3758 EXPECT_TRUE(barPersistent != fooPersistent); |
| 3753 barPersistent = fooPersistent; | 3759 barPersistent = fooPersistent; |
| 3754 EXPECT_TRUE(barPersistent == fooPersistent); | 3760 EXPECT_TRUE(barPersistent == fooPersistent); |
| 3755 } | 3761 } |
| 3756 | 3762 |
| 3757 TEST(HeapTest, CheckAndMarkPointer) | 3763 TEST(HeapTest, CheckAndMarkPointer) |
| 3758 { | 3764 { |
| 3765 ThreadHeap& heap = ThreadState::current()->heap(); |
| 3759 clearOutOldGarbage(); | 3766 clearOutOldGarbage(); |
| 3760 | 3767 |
| 3761 Vector<Address> objectAddresses; | 3768 Vector<Address> objectAddresses; |
| 3762 Vector<Address> endAddresses; | 3769 Vector<Address> endAddresses; |
| 3763 Address largeObjectAddress; | 3770 Address largeObjectAddress; |
| 3764 Address largeObjectEndAddress; | 3771 Address largeObjectEndAddress; |
| 3765 for (int i = 0; i < 10; i++) { | 3772 for (int i = 0; i < 10; i++) { |
| 3766 SimpleObject* object = SimpleObject::create(); | 3773 SimpleObject* object = SimpleObject::create(); |
| 3767 Address objectAddress = reinterpret_cast<Address>(object); | 3774 Address objectAddress = reinterpret_cast<Address>(object); |
| 3768 objectAddresses.append(objectAddress); | 3775 objectAddresses.append(objectAddress); |
| 3769 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); | 3776 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); |
| 3770 } | 3777 } |
| 3771 LargeHeapObject* largeObject = LargeHeapObject::create(); | 3778 LargeHeapObject* largeObject = LargeHeapObject::create(); |
| 3772 largeObjectAddress = reinterpret_cast<Address>(largeObject); | 3779 largeObjectAddress = reinterpret_cast<Address>(largeObject); |
| 3773 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; | 3780 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; |
| 3774 | 3781 |
| 3775 // This is a low-level test where we call checkAndMarkPointer. This method | 3782 // This is a low-level test where we call checkAndMarkPointer. This method |
| 3776 // causes the object start bitmap to be computed which requires the heap | 3783 // causes the object start bitmap to be computed which requires the heap |
| 3777 // to be in a consistent state (e.g. the free allocation area must be put | 3784 // to be in a consistent state (e.g. the free allocation area must be put |
| 3778 // into a free list header). However when we call makeConsistentForGC it | 3785 // into a free list header). However when we call makeConsistentForGC it |
| 3779 // also clears out the freelists so we have to rebuild those before trying | 3786 // also clears out the freelists so we have to rebuild those before trying |
| 3780 // to allocate anything again. We do this by forcing a GC after doing the | 3787 // to allocate anything again. We do this by forcing a GC after doing the |
| 3781 // checkAndMarkPointer tests. | 3788 // checkAndMarkPointer tests. |
| 3782 { | 3789 { |
| 3783 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3790 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3784 CountingVisitor visitor(ThreadState::current()); | 3791 CountingVisitor visitor(ThreadState::current()); |
| 3785 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not
park all threads. | 3792 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not
park all threads. |
| 3786 ThreadHeap::flushHeapDoesNotContainCache(); | 3793 heap.flushHeapDoesNotContainCache(); |
| 3787 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3794 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3788 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, objectAddresse
s[i])); | 3795 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, objectAddresses[i])); |
| 3789 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, endAddresses[i
])); | 3796 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, endAddresses[i])); |
| 3790 } | 3797 } |
| 3791 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 3798 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); |
| 3792 visitor.reset(); | 3799 visitor.reset(); |
| 3793 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, largeObjectAddress
)); | 3800 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectAddress)); |
| 3794 EXPECT_TRUE(ThreadHeap::checkAndMarkPointer(&visitor, largeObjectEndAddr
ess)); | 3801 EXPECT_TRUE(heap.checkAndMarkPointer(&visitor, largeObjectEndAddress)); |
| 3795 EXPECT_EQ(2ul, visitor.count()); | 3802 EXPECT_EQ(2ul, visitor.count()); |
| 3796 visitor.reset(); | 3803 visitor.reset(); |
| 3797 } | 3804 } |
| 3798 // This forces a GC without stack scanning which results in the objects | 3805 // This forces a GC without stack scanning which results in the objects |
| 3799 // being collected. This will also rebuild the above mentioned freelists, | 3806 // being collected. This will also rebuild the above mentioned freelists, |
| 3800 // however we don't rely on that below since we don't have any allocations. | 3807 // however we don't rely on that below since we don't have any allocations. |
| 3801 clearOutOldGarbage(); | 3808 clearOutOldGarbage(); |
| 3802 { | 3809 { |
| 3803 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3810 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3804 CountingVisitor visitor(ThreadState::current()); | 3811 CountingVisitor visitor(ThreadState::current()); |
| 3805 EXPECT_TRUE(scope.allThreadsParked()); | 3812 EXPECT_TRUE(scope.allThreadsParked()); |
| 3806 ThreadHeap::flushHeapDoesNotContainCache(); | 3813 heap.flushHeapDoesNotContainCache(); |
| 3807 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3814 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3808 // We would like to assert that checkAndMarkPointer returned false | 3815 // We would like to assert that checkAndMarkPointer returned false |
| 3809 // here because the pointers no longer point into a valid object | 3816 // here because the pointers no longer point into a valid object |
| 3810 // (it's been freed by the GCs. But checkAndMarkPointer will return | 3817 // (it's been freed by the GCs. But checkAndMarkPointer will return |
| 3811 // true for any pointer that points into a heap page, regardless of | 3818 // true for any pointer that points into a heap page, regardless of |
| 3812 // whether it points at a valid object (this ensures the | 3819 // whether it points at a valid object (this ensures the |
| 3813 // correctness of the page-based on-heap address caches), so we | 3820 // correctness of the page-based on-heap address caches), so we |
| 3814 // can't make that assert. | 3821 // can't make that assert. |
| 3815 ThreadHeap::checkAndMarkPointer(&visitor, objectAddresses[i]); | 3822 heap.checkAndMarkPointer(&visitor, objectAddresses[i]); |
| 3816 ThreadHeap::checkAndMarkPointer(&visitor, endAddresses[i]); | 3823 heap.checkAndMarkPointer(&visitor, endAddresses[i]); |
| 3817 } | 3824 } |
| 3818 EXPECT_EQ(0ul, visitor.count()); | 3825 EXPECT_EQ(0ul, visitor.count()); |
| 3819 ThreadHeap::checkAndMarkPointer(&visitor, largeObjectAddress); | 3826 heap.checkAndMarkPointer(&visitor, largeObjectAddress); |
| 3820 ThreadHeap::checkAndMarkPointer(&visitor, largeObjectEndAddress); | 3827 heap.checkAndMarkPointer(&visitor, largeObjectEndAddress); |
| 3821 EXPECT_EQ(0ul, visitor.count()); | 3828 EXPECT_EQ(0ul, visitor.count()); |
| 3822 } | 3829 } |
| 3823 // This round of GC is important to make sure that the object start | 3830 // This round of GC is important to make sure that the object start |
| 3824 // bitmap are cleared out and that the free lists are rebuild. | 3831 // bitmap are cleared out and that the free lists are rebuild. |
| 3825 clearOutOldGarbage(); | 3832 clearOutOldGarbage(); |
| 3826 } | 3833 } |
| 3827 | 3834 |
| 3828 TEST(HeapTest, PersistentHeapCollectionTypes) | 3835 TEST(HeapTest, PersistentHeapCollectionTypes) |
| 3829 { | 3836 { |
| 3830 IntWrapper::s_destructorCalls = 0; | 3837 IntWrapper::s_destructorCalls = 0; |
| (...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4724 static void sleeperMainFunc() | 4731 static void sleeperMainFunc() |
| 4725 { | 4732 { |
| 4726 ThreadState::attach(); | 4733 ThreadState::attach(); |
| 4727 s_sleeperRunning = true; | 4734 s_sleeperRunning = true; |
| 4728 | 4735 |
| 4729 // Simulate a long running op that is not entering a safepoint. | 4736 // Simulate a long running op that is not entering a safepoint. |
| 4730 while (!s_sleeperDone) { | 4737 while (!s_sleeperDone) { |
| 4731 testing::yieldCurrentThread(); | 4738 testing::yieldCurrentThread(); |
| 4732 } | 4739 } |
| 4733 | 4740 |
| 4734 ThreadState::detach(); | 4741 ThreadState::detachCurrentThread(); |
| 4735 s_sleeperRunning = false; | 4742 s_sleeperRunning = false; |
| 4736 } | 4743 } |
| 4737 | 4744 |
| 4738 static volatile bool s_sleeperRunning; | 4745 static volatile bool s_sleeperRunning; |
| 4739 static volatile bool s_sleeperDone; | 4746 static volatile bool s_sleeperDone; |
| 4740 }; | 4747 }; |
| 4741 | 4748 |
| 4742 volatile bool GCParkingThreadTester::s_sleeperRunning = false; | 4749 volatile bool GCParkingThreadTester::s_sleeperRunning = false; |
| 4743 volatile bool GCParkingThreadTester::s_sleeperDone = false; | 4750 volatile bool GCParkingThreadTester::s_sleeperDone = false; |
| 4744 | 4751 |
| (...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5430 | 5437 |
| 5431 // Wake up the main thread when done sweeping. | 5438 // Wake up the main thread when done sweeping. |
| 5432 wakeMainThread(); | 5439 wakeMainThread(); |
| 5433 | 5440 |
| 5434 // Wait with detach until the main thread says so. This is not strictly | 5441 // Wait with detach until the main thread says so. This is not strictly |
| 5435 // necessary, but it means the worker thread will not do its thread loca
l | 5442 // necessary, but it means the worker thread will not do its thread loca
l |
| 5436 // GCs just yet, making it easier to reason about that no new GC has occ
urred | 5443 // GCs just yet, making it easier to reason about that no new GC has occ
urred |
| 5437 // and the above sweep was the one finalizing the worker object. | 5444 // and the above sweep was the one finalizing the worker object. |
| 5438 parkWorkerThread(); | 5445 parkWorkerThread(); |
| 5439 | 5446 |
| 5440 ThreadState::detach(); | 5447 ThreadState::detachCurrentThread(); |
| 5441 } | 5448 } |
| 5442 | 5449 |
| 5443 static volatile uintptr_t s_workerObjectPointer; | 5450 static volatile uintptr_t s_workerObjectPointer; |
| 5444 }; | 5451 }; |
| 5445 | 5452 |
| 5446 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; | 5453 volatile uintptr_t DeadBitTester::s_workerObjectPointer = 0; |
| 5447 | 5454 |
| 5448 TEST(HeapTest, ObjectDeadBit) | 5455 TEST(HeapTest, ObjectDeadBit) |
| 5449 { | 5456 { |
| 5450 DeadBitTester::test(); | 5457 DeadBitTester::test(); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5543 EXPECT_EQ(32, it->value->value()); | 5550 EXPECT_EQ(32, it->value->value()); |
| 5544 } | 5551 } |
| 5545 | 5552 |
| 5546 // Disregarding the iterator but keeping the collection alive | 5553 // Disregarding the iterator but keeping the collection alive |
| 5547 // with a persistent should lead to weak processing. | 5554 // with a persistent should lead to weak processing. |
| 5548 preciselyCollectGarbage(); | 5555 preciselyCollectGarbage(); |
| 5549 EXPECT_EQ(0u, collection->size()); | 5556 EXPECT_EQ(0u, collection->size()); |
| 5550 } | 5557 } |
| 5551 | 5558 |
| 5552 wakeMainThread(); | 5559 wakeMainThread(); |
| 5553 ThreadState::detach(); | 5560 ThreadState::detachCurrentThread(); |
| 5554 } | 5561 } |
| 5555 | 5562 |
| 5556 static volatile uintptr_t s_workerObjectPointer; | 5563 static volatile uintptr_t s_workerObjectPointer; |
| 5557 }; | 5564 }; |
| 5558 | 5565 |
| 5559 TEST(HeapTest, ThreadedStrongification) | 5566 TEST(HeapTest, ThreadedStrongification) |
| 5560 { | 5567 { |
| 5561 ThreadedStrongificationTester::test(); | 5568 ThreadedStrongificationTester::test(); |
| 5562 } | 5569 } |
| 5563 | 5570 |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5711 parkWorkerThread(); | 5718 parkWorkerThread(); |
| 5712 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), BlinkGC::NoH
eapPointersOnStack); | 5719 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), BlinkGC::NoH
eapPointersOnStack); |
| 5713 | 5720 |
| 5714 // We won't get here unless the lock is recursive since the sweep done | 5721 // We won't get here unless the lock is recursive since the sweep done |
| 5715 // in the constructor of SafePointAwareMutexLocker after | 5722 // in the constructor of SafePointAwareMutexLocker after |
| 5716 // getting the lock will not complete given the "dlo" destructor is | 5723 // getting the lock will not complete given the "dlo" destructor is |
| 5717 // waiting to get the same lock. | 5724 // waiting to get the same lock. |
| 5718 // Tell the main thread the worker has done its sweep. | 5725 // Tell the main thread the worker has done its sweep. |
| 5719 wakeMainThread(); | 5726 wakeMainThread(); |
| 5720 | 5727 |
| 5721 ThreadState::detach(); | 5728 ThreadState::detachCurrentThread(); |
| 5722 } | 5729 } |
| 5723 | 5730 |
| 5724 static volatile IntWrapper* s_workerObjectPointer; | 5731 static volatile IntWrapper* s_workerObjectPointer; |
| 5725 }; | 5732 }; |
| 5726 | 5733 |
| 5727 TEST(HeapTest, RecursiveMutex) | 5734 TEST(HeapTest, RecursiveMutex) |
| 5728 { | 5735 { |
| 5729 RecursiveLockingTester::test(); | 5736 RecursiveLockingTester::test(); |
| 5730 } | 5737 } |
| 5731 | 5738 |
| (...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6381 *object = DestructorLockingObject::create(); | 6388 *object = DestructorLockingObject::create(); |
| 6382 wakeMainThread(); | 6389 wakeMainThread(); |
| 6383 parkWorkerThread(); | 6390 parkWorkerThread(); |
| 6384 | 6391 |
| 6385 // Step 4: Run a GC. | 6392 // Step 4: Run a GC. |
| 6386 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSw
eep, BlinkGC::ForcedGC); | 6393 ThreadHeap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSw
eep, BlinkGC::ForcedGC); |
| 6387 wakeMainThread(); | 6394 wakeMainThread(); |
| 6388 parkWorkerThread(); | 6395 parkWorkerThread(); |
| 6389 | 6396 |
| 6390 // Step 6: Finish. | 6397 // Step 6: Finish. |
| 6391 ThreadState::detach(); | 6398 ThreadState::detachCurrentThread(); |
| 6392 wakeMainThread(); | 6399 wakeMainThread(); |
| 6393 } | 6400 } |
| 6394 | 6401 |
| 6395 } // anonymous namespace | 6402 } // anonymous namespace |
| 6396 | 6403 |
| 6397 TEST(HeapTest, CrossThreadWeakPersistent) | 6404 TEST(HeapTest, CrossThreadWeakPersistent) |
| 6398 { | 6405 { |
| 6399 // Create an object in the worker thread, have a CrossThreadWeakPersistent p
ointing to it on the main thread, | 6406 // Create an object in the worker thread, have a CrossThreadWeakPersistent p
ointing to it on the main thread, |
| 6400 // clear the reference in the worker thread, run a GC in the worker thread,
and see if the | 6407 // clear the reference in the worker thread, run a GC in the worker thread,
and see if the |
| 6401 // CrossThreadWeakPersistent is cleared. | 6408 // CrossThreadWeakPersistent is cleared. |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6496 IntWrapper::s_destructorCalls = 0; | 6503 IntWrapper::s_destructorCalls = 0; |
| 6497 ThreadedTesterBase::test(new ThreadedClearOnShutdownTester); | 6504 ThreadedTesterBase::test(new ThreadedClearOnShutdownTester); |
| 6498 EXPECT_EQ(numberOfThreads, IntWrapper::s_destructorCalls); | 6505 EXPECT_EQ(numberOfThreads, IntWrapper::s_destructorCalls); |
| 6499 } | 6506 } |
| 6500 | 6507 |
| 6501 private: | 6508 private: |
| 6502 void runThread() override | 6509 void runThread() override |
| 6503 { | 6510 { |
| 6504 ThreadState::attach(); | 6511 ThreadState::attach(); |
| 6505 EXPECT_EQ(42, threadSpecificIntWrapper().value()); | 6512 EXPECT_EQ(42, threadSpecificIntWrapper().value()); |
| 6506 ThreadState::detach(); | 6513 ThreadState::detachCurrentThread(); |
| 6507 atomicDecrement(&m_threadsToFinish); | 6514 atomicDecrement(&m_threadsToFinish); |
| 6508 } | 6515 } |
| 6509 | 6516 |
| 6510 static IntWrapper& threadSpecificIntWrapper() | 6517 static IntWrapper& threadSpecificIntWrapper() |
| 6511 { | 6518 { |
| 6512 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 6519 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
| 6513 ThreadSpecific<Persistent<IntWrapper>>, intWrapper, | 6520 ThreadSpecific<Persistent<IntWrapper>>, intWrapper, |
| 6514 new ThreadSpecific<Persistent<IntWrapper>>); | 6521 new ThreadSpecific<Persistent<IntWrapper>>); |
| 6515 Persistent<IntWrapper>& handle = *intWrapper; | 6522 Persistent<IntWrapper>& handle = *intWrapper; |
| 6516 if (!handle) { | 6523 if (!handle) { |
| 6517 handle = new IntWrapper(42); | 6524 handle = new IntWrapper(42); |
| 6518 handle.clearOnThreadShutdown(); | 6525 handle.clearOnThreadShutdown(); |
| 6519 } | 6526 } |
| 6520 return *handle; | 6527 return *handle; |
| 6521 } | 6528 } |
| 6522 }; | 6529 }; |
| 6523 | 6530 |
| 6524 } // namespace | 6531 } // namespace |
| 6525 | 6532 |
| 6526 TEST(HeapTest, TestClearOnShutdown) | 6533 TEST(HeapTest, TestClearOnShutdown) |
| 6527 { | 6534 { |
| 6528 ThreadedClearOnShutdownTester::test(); | 6535 ThreadedClearOnShutdownTester::test(); |
| 6529 } | 6536 } |
| 6530 | 6537 |
| 6531 } // namespace blink | 6538 } // namespace blink |
| OLD | NEW |