Chromium Code Reviews| 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 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 236 namespace blink { | 236 namespace blink { |
| 237 | 237 |
| 238 class TestGCScope { | 238 class TestGCScope { |
| 239 public: | 239 public: |
| 240 explicit TestGCScope(BlinkGC::StackState state) | 240 explicit TestGCScope(BlinkGC::StackState state) |
| 241 : m_state(ThreadState::current()) | 241 : m_state(ThreadState::current()) |
| 242 , m_safePointScope(state) | 242 , m_safePointScope(state) |
| 243 , m_parkedAllThreads(false) | 243 , m_parkedAllThreads(false) |
| 244 { | 244 { |
| 245 ASSERT(m_state->checkThread()); | 245 ASSERT(m_state->checkThread()); |
| 246 if (LIKELY(ThreadState::stopThreads())) { | 246 if (LIKELY(m_state->gcGroup()->park())) { |
| 247 Heap::preGC(); | 247 Heap::preGC(); |
| 248 m_parkedAllThreads = true; | 248 m_parkedAllThreads = true; |
| 249 } | 249 } |
| 250 } | 250 } |
| 251 | 251 |
| 252 bool allThreadsParked() { return m_parkedAllThreads; } | 252 bool allThreadsParked() { return m_parkedAllThreads; } |
| 253 | 253 |
| 254 ~TestGCScope() | 254 ~TestGCScope() |
| 255 { | 255 { |
| 256 // Only cleanup if we parked all threads in which case the GC happened | 256 // Only cleanup if we parked all threads in which case the GC happened |
| 257 // and we need to resume the other threads. | 257 // and we need to resume the other threads. |
| 258 if (LIKELY(m_parkedAllThreads)) { | 258 if (LIKELY(m_parkedAllThreads)) { |
| 259 Heap::postGC(BlinkGC::GCWithSweep); | 259 Heap::postGC(BlinkGC::GCWithSweep); |
| 260 ThreadState::resumeThreads(); | 260 m_state->gcGroup()->resume(); |
| 261 } | 261 } |
| 262 } | 262 } |
| 263 | 263 |
| 264 private: | 264 private: |
| 265 ThreadState* m_state; | 265 ThreadState* m_state; |
| 266 SafePointScope m_safePointScope; | 266 SafePointScope m_safePointScope; |
| 267 bool m_parkedAllThreads; // False if we fail to park all threads | 267 bool m_parkedAllThreads; // False if we fail to park all threads |
| 268 }; | 268 }; |
| 269 | 269 |
| 270 #define DEFINE_VISITOR_METHODS(Type) \ | 270 #define DEFINE_VISITOR_METHODS(Type) \ |
| 271 void mark(const Type* object, TraceCallback callback) override \ | 271 void mark(const Type* object, TraceCallback callback) override \ |
| 272 { \ | 272 { \ |
| 273 if (object) \ | 273 if (object) \ |
| 274 m_count++; \ | 274 m_count++; \ |
| 275 } \ | 275 } \ |
| 276 bool isMarked(const Type*) override { return false; } \ | 276 bool isMarked(const Type*) override { return false; } \ |
| 277 bool ensureMarked(const Type* objectPointer) override \ | 277 bool ensureMarked(const Type* objectPointer) override \ |
| 278 { \ | 278 { \ |
| 279 return ensureMarked(objectPointer); \ | 279 return ensureMarked(objectPointer); \ |
| 280 } | 280 } |
| 281 | 281 |
| 282 class CountingVisitor : public Visitor { | 282 class CountingVisitor : public Visitor { |
| 283 public: | 283 public: |
| 284 CountingVisitor() | 284 CountingVisitor(GCData* gcData) |
|
haraken
2016/01/28 15:52:50
Add explicit.
keishi
2016/02/29 06:02:33
Done.
| |
| 285 : Visitor(Visitor::ThreadLocalMarking) | 285 : Visitor(Visitor::ThreadLocalMarking, gcData) |
| 286 , m_count(0) | 286 , m_count(0) |
| 287 { | 287 { |
| 288 } | 288 } |
| 289 | 289 |
| 290 void mark(const void* object, TraceCallback) override | 290 void mark(const void* object, TraceCallback) override |
| 291 { | 291 { |
| 292 if (object) | 292 if (object) |
| 293 m_count++; | 293 m_count++; |
| 294 } | 294 } |
| 295 | 295 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 507 using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>; | 507 using GlobalIntWrapperPersistent = CrossThreadPersistent<IntWrapper>; |
| 508 | 508 |
| 509 PassOwnPtr<GlobalIntWrapperPersistent> createGlobalPersistent(int value) | 509 PassOwnPtr<GlobalIntWrapperPersistent> createGlobalPersistent(int value) |
| 510 { | 510 { |
| 511 return adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(value) )); | 511 return adoptPtr(new GlobalIntWrapperPersistent(IntWrapper::create(value) )); |
| 512 } | 512 } |
| 513 | 513 |
| 514 void runThread() override | 514 void runThread() override |
| 515 { | 515 { |
| 516 OwnPtr<GlobalIntWrapperPersistent> longLivingPersistent; | 516 OwnPtr<GlobalIntWrapperPersistent> longLivingPersistent; |
| 517 ThreadState::attach(); | 517 ThreadState::prepareForCurrentThread(); |
| 518 | 518 |
| 519 longLivingPersistent = createGlobalPersistent(0x2a2a2a2a); | 519 longLivingPersistent = createGlobalPersistent(0x2a2a2a2a); |
| 520 int gcCount = 0; | 520 int gcCount = 0; |
| 521 while (!done()) { | 521 while (!done()) { |
| 522 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); | 522 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 523 { | 523 { |
| 524 Persistent<IntWrapper> wrapper; | 524 Persistent<IntWrapper> wrapper; |
| 525 | 525 |
| 526 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = createGlob alPersistent(0x0ed0cabb); | 526 OwnPtr<GlobalIntWrapperPersistent> globalPersistent = createGlob alPersistent(0x0ed0cabb); |
| 527 | 527 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 566 class ThreadedWeaknessTester : public ThreadedTesterBase { | 566 class ThreadedWeaknessTester : public ThreadedTesterBase { |
| 567 public: | 567 public: |
| 568 static void test() | 568 static void test() |
| 569 { | 569 { |
| 570 ThreadedTesterBase::test(new ThreadedWeaknessTester); | 570 ThreadedTesterBase::test(new ThreadedWeaknessTester); |
| 571 } | 571 } |
| 572 | 572 |
| 573 private: | 573 private: |
| 574 void runThread() override | 574 void runThread() override |
| 575 { | 575 { |
| 576 ThreadState::attach(); | 576 ThreadState::prepareForCurrentThread(); |
| 577 | 577 |
| 578 int gcCount = 0; | 578 int gcCount = 0; |
| 579 while (!done()) { | 579 while (!done()) { |
| 580 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); | 580 ThreadState::current()->safePoint(BlinkGC::NoHeapPointersOnStack); |
| 581 { | 581 { |
| 582 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> we akMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>; | 582 Persistent<HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>> we akMap = new HeapHashMap<ThreadMarker, WeakMember<IntWrapper>>; |
| 583 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper>> weak Map2; | 583 PersistentHeapHashMap<ThreadMarker, WeakMember<IntWrapper>> weak Map2; |
| 584 | 584 |
| 585 for (int i = 0; i < numberOfAllocations; i++) { | 585 for (int i = 0; i < numberOfAllocations; i++) { |
| 586 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0) ); | 586 weakMap->add(static_cast<unsigned>(i), IntWrapper::create(0) ); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 660 explicit PersistentChain(int count) | 660 explicit PersistentChain(int count) |
| 661 { | 661 { |
| 662 m_refCountedChain = adoptRef(RefCountedChain::create(count)); | 662 m_refCountedChain = adoptRef(RefCountedChain::create(count)); |
| 663 } | 663 } |
| 664 | 664 |
| 665 RefPtr<RefCountedChain> m_refCountedChain; | 665 RefPtr<RefCountedChain> m_refCountedChain; |
| 666 }; | 666 }; |
| 667 | 667 |
| 668 void runThread() override | 668 void runThread() override |
| 669 { | 669 { |
| 670 ThreadState::attach(); | 670 ThreadState::prepareForCurrentThread(); |
| 671 | 671 |
| 672 PersistentChain::create(100); | 672 PersistentChain::create(100); |
| 673 | 673 |
| 674 // Upon thread detach, GCs will run until all persistents have been | 674 // Upon thread detach, GCs will run until all persistents have been |
| 675 // released. We verify that the draining of persistents proceeds | 675 // released. We verify that the draining of persistents proceeds |
| 676 // as expected by dropping one Persistent<> per GC until there | 676 // as expected by dropping one Persistent<> per GC until there |
| 677 // are none left. | 677 // are none left. |
| 678 ThreadState::detach(); | 678 ThreadState::detach(); |
| 679 atomicDecrement(&m_threadsToFinish); | 679 atomicDecrement(&m_threadsToFinish); |
| 680 } | 680 } |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1025 int RefCountedAndGarbageCollected2::s_destructorCalls = 0; | 1025 int RefCountedAndGarbageCollected2::s_destructorCalls = 0; |
| 1026 | 1026 |
| 1027 #define DEFINE_VISITOR_METHODS(Type) \ | 1027 #define DEFINE_VISITOR_METHODS(Type) \ |
| 1028 void mark(const Type* object, TraceCallback callback) override \ | 1028 void mark(const Type* object, TraceCallback callback) override \ |
| 1029 { \ | 1029 { \ |
| 1030 mark(object); \ | 1030 mark(object); \ |
| 1031 } \ | 1031 } \ |
| 1032 | 1032 |
| 1033 class RefCountedGarbageCollectedVisitor : public CountingVisitor { | 1033 class RefCountedGarbageCollectedVisitor : public CountingVisitor { |
| 1034 public: | 1034 public: |
| 1035 RefCountedGarbageCollectedVisitor(int expected, void** objects) | 1035 RefCountedGarbageCollectedVisitor(int expected, void** objects, GCData* gcDa ta) |
| 1036 : m_count(0) | 1036 : CountingVisitor(gcData) |
| 1037 , m_count(0) | |
| 1037 , m_expectedCount(expected) | 1038 , m_expectedCount(expected) |
| 1038 , m_expectedObjects(objects) | 1039 , m_expectedObjects(objects) |
| 1039 { | 1040 { |
| 1040 } | 1041 } |
| 1041 | 1042 |
| 1042 void mark(const void* ptr) { markNoTrace(ptr); } | 1043 void mark(const void* ptr) { markNoTrace(ptr); } |
| 1043 | 1044 |
| 1044 virtual void markNoTrace(const void* ptr) | 1045 virtual void markNoTrace(const void* ptr) |
| 1045 { | 1046 { |
| 1046 if (!ptr) | 1047 if (!ptr) |
| (...skipping 717 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1764 clearOutOldGarbage(); | 1765 clearOutOldGarbage(); |
| 1765 size_t initialObjectPayloadSize = Heap::objectPayloadSizeForTesting(); | 1766 size_t initialObjectPayloadSize = Heap::objectPayloadSizeForTesting(); |
| 1766 { | 1767 { |
| 1767 size_t slack = 0; | 1768 size_t slack = 0; |
| 1768 | 1769 |
| 1769 // When the test starts there may already have been leaked some memory | 1770 // When the test starts there may already have been leaked some memory |
| 1770 // on the heap, so we establish a base line. | 1771 // on the heap, so we establish a base line. |
| 1771 size_t baseLevel = initialObjectPayloadSize; | 1772 size_t baseLevel = initialObjectPayloadSize; |
| 1772 bool testPagesAllocated = !baseLevel; | 1773 bool testPagesAllocated = !baseLevel; |
| 1773 if (testPagesAllocated) | 1774 if (testPagesAllocated) |
| 1774 EXPECT_EQ(Heap::allocatedSpace(), 0ul); | 1775 EXPECT_EQ(ThreadState::current()->gcGroup()->heapStats().allocatedSp ace(), 0ul); |
| 1775 | 1776 |
| 1776 // This allocates objects on the general heap which should add a page of memory. | 1777 // This allocates objects on the general heap which should add a page of memory. |
| 1777 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); | 1778 DynamicallySizedObject* alloc32 = DynamicallySizedObject::create(32); |
| 1778 slack += 4; | 1779 slack += 4; |
| 1779 memset(alloc32, 40, 32); | 1780 memset(alloc32, 40, 32); |
| 1780 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); | 1781 DynamicallySizedObject* alloc64 = DynamicallySizedObject::create(64); |
| 1781 slack += 4; | 1782 slack += 4; |
| 1782 memset(alloc64, 27, 64); | 1783 memset(alloc64, 27, 64); |
| 1783 | 1784 |
| 1784 size_t total = 96; | 1785 size_t total = 96; |
| 1785 | 1786 |
| 1786 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), s lack); | 1787 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), s lack); |
| 1787 if (testPagesAllocated) | 1788 if (testPagesAllocated) |
| 1788 EXPECT_EQ(Heap::allocatedSpace(), blinkPageSize * 2); | 1789 EXPECT_EQ(ThreadState::current()->gcGroup()->heapStats().allocatedSp ace(), blinkPageSize * 2); |
| 1789 | 1790 |
| 1790 EXPECT_EQ(alloc32->get(0), 40); | 1791 EXPECT_EQ(alloc32->get(0), 40); |
| 1791 EXPECT_EQ(alloc32->get(31), 40); | 1792 EXPECT_EQ(alloc32->get(31), 40); |
| 1792 EXPECT_EQ(alloc64->get(0), 27); | 1793 EXPECT_EQ(alloc64->get(0), 27); |
| 1793 EXPECT_EQ(alloc64->get(63), 27); | 1794 EXPECT_EQ(alloc64->get(63), 27); |
| 1794 | 1795 |
| 1795 conservativelyCollectGarbage(); | 1796 conservativelyCollectGarbage(); |
| 1796 | 1797 |
| 1797 EXPECT_EQ(alloc32->get(0), 40); | 1798 EXPECT_EQ(alloc32->get(0), 40); |
| 1798 EXPECT_EQ(alloc32->get(31), 40); | 1799 EXPECT_EQ(alloc32->get(31), 40); |
| 1799 EXPECT_EQ(alloc64->get(0), 27); | 1800 EXPECT_EQ(alloc64->get(0), 27); |
| 1800 EXPECT_EQ(alloc64->get(63), 27); | 1801 EXPECT_EQ(alloc64->get(63), 27); |
| 1801 } | 1802 } |
| 1802 | 1803 |
| 1803 clearOutOldGarbage(); | 1804 clearOutOldGarbage(); |
| 1804 size_t total = 0; | 1805 size_t total = 0; |
| 1805 size_t slack = 0; | 1806 size_t slack = 0; |
| 1806 size_t baseLevel = Heap::objectPayloadSizeForTesting(); | 1807 size_t baseLevel = Heap::objectPayloadSizeForTesting(); |
| 1807 bool testPagesAllocated = !baseLevel; | 1808 bool testPagesAllocated = !baseLevel; |
| 1808 if (testPagesAllocated) | 1809 if (testPagesAllocated) |
| 1809 EXPECT_EQ(Heap::allocatedSpace(), 0ul); | 1810 EXPECT_EQ(ThreadState::current()->gcGroup()->heapStats().allocatedSpace( ), 0ul); |
| 1810 | 1811 |
| 1811 size_t big = 1008; | 1812 size_t big = 1008; |
| 1812 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create( big); | 1813 Persistent<DynamicallySizedObject> bigArea = DynamicallySizedObject::create( big); |
| 1813 total += big; | 1814 total += big; |
| 1814 slack += 4; | 1815 slack += 4; |
| 1815 | 1816 |
| 1816 size_t persistentCount = 0; | 1817 size_t persistentCount = 0; |
| 1817 const size_t numPersistents = 100000; | 1818 const size_t numPersistents = 100000; |
| 1818 Persistent<DynamicallySizedObject>* persistents[numPersistents]; | 1819 Persistent<DynamicallySizedObject>* persistents[numPersistents]; |
| 1819 | 1820 |
| 1820 for (int i = 0; i < 1000; i++) { | 1821 for (int i = 0; i < 1000; i++) { |
| 1821 size_t size = 128 + i * 8; | 1822 size_t size = 128 + i * 8; |
| 1822 total += size; | 1823 total += size; |
| 1823 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>( DynamicallySizedObject::create(size)); | 1824 persistents[persistentCount++] = new Persistent<DynamicallySizedObject>( DynamicallySizedObject::create(size)); |
| 1824 slack += 4; | 1825 slack += 4; |
| 1825 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), s lack); | 1826 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), s lack); |
| 1826 if (testPagesAllocated) | 1827 if (testPagesAllocated) |
| 1827 EXPECT_EQ(0ul, Heap::allocatedSpace() & (blinkPageSize - 1)); | 1828 EXPECT_EQ(0ul, ThreadState::current()->gcGroup()->heapStats().alloca tedSpace() & (blinkPageSize - 1)); |
| 1828 } | 1829 } |
| 1829 | 1830 |
| 1830 { | 1831 { |
| 1831 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32)); | 1832 DynamicallySizedObject* alloc32b(DynamicallySizedObject::create(32)); |
| 1832 slack += 4; | 1833 slack += 4; |
| 1833 memset(alloc32b, 40, 32); | 1834 memset(alloc32b, 40, 32); |
| 1834 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64)); | 1835 DynamicallySizedObject* alloc64b(DynamicallySizedObject::create(64)); |
| 1835 slack += 4; | 1836 slack += 4; |
| 1836 memset(alloc64b, 27, 64); | 1837 memset(alloc64b, 27, 64); |
| 1837 EXPECT_TRUE(alloc32b != alloc64b); | 1838 EXPECT_TRUE(alloc32b != alloc64b); |
| 1838 | 1839 |
| 1839 total += 96; | 1840 total += 96; |
| 1840 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), s lack); | 1841 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), s lack); |
| 1841 if (testPagesAllocated) | 1842 if (testPagesAllocated) |
| 1842 EXPECT_EQ(0ul, Heap::allocatedSpace() & (blinkPageSize - 1)); | 1843 EXPECT_EQ(0ul, ThreadState::current()->gcGroup()->heapStats().alloca tedSpace() & (blinkPageSize - 1)); |
| 1843 } | 1844 } |
| 1844 | 1845 |
| 1845 clearOutOldGarbage(); | 1846 clearOutOldGarbage(); |
| 1846 total -= 96; | 1847 total -= 96; |
| 1847 slack -= 8; | 1848 slack -= 8; |
| 1848 if (testPagesAllocated) | 1849 if (testPagesAllocated) |
| 1849 EXPECT_EQ(0ul, Heap::allocatedSpace() & (blinkPageSize - 1)); | 1850 EXPECT_EQ(0ul, ThreadState::current()->gcGroup()->heapStats().allocatedS pace() & (blinkPageSize - 1)); |
| 1850 | 1851 |
| 1851 // Clear the persistent, so that the big area will be garbage collected. | 1852 // Clear the persistent, so that the big area will be garbage collected. |
| 1852 bigArea.release(); | 1853 bigArea.release(); |
| 1853 clearOutOldGarbage(); | 1854 clearOutOldGarbage(); |
| 1854 | 1855 |
| 1855 total -= big; | 1856 total -= big; |
| 1856 slack -= 4; | 1857 slack -= 4; |
| 1857 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), slack ); | 1858 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), slack ); |
| 1858 if (testPagesAllocated) | 1859 if (testPagesAllocated) |
| 1859 EXPECT_EQ(0ul, Heap::allocatedSpace() & (blinkPageSize - 1)); | 1860 EXPECT_EQ(0ul, ThreadState::current()->gcGroup()->heapStats().allocatedS pace() & (blinkPageSize - 1)); |
| 1860 | 1861 |
| 1861 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), slack ); | 1862 CheckWithSlack(baseLevel + total, Heap::objectPayloadSizeForTesting(), slack ); |
| 1862 if (testPagesAllocated) | 1863 if (testPagesAllocated) |
| 1863 EXPECT_EQ(0ul, Heap::allocatedSpace() & (blinkPageSize - 1)); | 1864 EXPECT_EQ(0ul, ThreadState::current()->gcGroup()->heapStats().allocatedS pace() & (blinkPageSize - 1)); |
| 1864 | 1865 |
| 1865 for (size_t i = 0; i < persistentCount; i++) { | 1866 for (size_t i = 0; i < persistentCount; i++) { |
| 1866 delete persistents[i]; | 1867 delete persistents[i]; |
| 1867 persistents[i] = 0; | 1868 persistents[i] = 0; |
| 1868 } | 1869 } |
| 1869 | 1870 |
| 1870 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::allocate<DynamicallySize dObject>(100)); | 1871 uint8_t* address = reinterpret_cast<uint8_t*>(Heap::allocate<DynamicallySize dObject>(100)); |
| 1871 for (int i = 0; i < 100; i++) | 1872 for (int i = 0; i < 100; i++) |
| 1872 address[i] = i; | 1873 address[i] = i; |
| 1873 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject >(address, 100000)); | 1874 address = reinterpret_cast<uint8_t*>(Heap::reallocate<DynamicallySizedObject >(address, 100000)); |
| (...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2316 } | 2317 } |
| 2317 clearOutOldGarbage(); | 2318 clearOutOldGarbage(); |
| 2318 size_t afterFree = Heap::objectPayloadSizeForTesting(); | 2319 size_t afterFree = Heap::objectPayloadSizeForTesting(); |
| 2319 EXPECT_TRUE(initialObjectPayloadSize == afterFree); | 2320 EXPECT_TRUE(initialObjectPayloadSize == afterFree); |
| 2320 } | 2321 } |
| 2321 | 2322 |
| 2322 TEST(HeapTest, LargeHeapObjects) | 2323 TEST(HeapTest, LargeHeapObjects) |
| 2323 { | 2324 { |
| 2324 clearOutOldGarbage(); | 2325 clearOutOldGarbage(); |
| 2325 size_t initialObjectPayloadSize = Heap::objectPayloadSizeForTesting(); | 2326 size_t initialObjectPayloadSize = Heap::objectPayloadSizeForTesting(); |
| 2326 size_t initialAllocatedSpace = Heap::allocatedSpace(); | 2327 size_t initialAllocatedSpace = ThreadState::current()->gcGroup()->heapStats( ).allocatedSpace(); |
| 2327 IntWrapper::s_destructorCalls = 0; | 2328 IntWrapper::s_destructorCalls = 0; |
| 2328 LargeHeapObject::s_destructorCalls = 0; | 2329 LargeHeapObject::s_destructorCalls = 0; |
| 2329 { | 2330 { |
| 2330 int slack = 8; // LargeHeapObject points to an IntWrapper that is also a llocated. | 2331 int slack = 8; // LargeHeapObject points to an IntWrapper that is also a llocated. |
| 2331 Persistent<LargeHeapObject> object = LargeHeapObject::create(); | 2332 Persistent<LargeHeapObject> object = LargeHeapObject::create(); |
| 2332 ASSERT(ThreadState::current()->findPageFromAddress(object)); | 2333 ASSERT(ThreadState::current()->findPageFromAddress(object)); |
| 2333 ASSERT(ThreadState::current()->findPageFromAddress(reinterpret_cast<char *>(object.get()) + sizeof(LargeHeapObject) - 1)); | 2334 ASSERT(ThreadState::current()->findPageFromAddress(reinterpret_cast<char *>(object.get()) + sizeof(LargeHeapObject) - 1)); |
| 2334 clearOutOldGarbage(); | 2335 clearOutOldGarbage(); |
| 2335 size_t afterAllocation = Heap::allocatedSpace(); | 2336 size_t afterAllocation = ThreadState::current()->gcGroup()->heapStats(). allocatedSpace(); |
| 2336 { | 2337 { |
| 2337 object->set(0, 'a'); | 2338 object->set(0, 'a'); |
| 2338 EXPECT_EQ('a', object->get(0)); | 2339 EXPECT_EQ('a', object->get(0)); |
| 2339 object->set(object->length() - 1, 'b'); | 2340 object->set(object->length() - 1, 'b'); |
| 2340 EXPECT_EQ('b', object->get(object->length() - 1)); | 2341 EXPECT_EQ('b', object->get(object->length() - 1)); |
| 2341 size_t expectedLargeHeapObjectPayloadSize = Heap::allocationSizeFrom Size(sizeof(LargeHeapObject)); | 2342 size_t expectedLargeHeapObjectPayloadSize = Heap::allocationSizeFrom Size(sizeof(LargeHeapObject)); |
| 2342 size_t expectedObjectPayloadSize = expectedLargeHeapObjectPayloadSiz e + sizeof(IntWrapper); | 2343 size_t expectedObjectPayloadSize = expectedLargeHeapObjectPayloadSiz e + sizeof(IntWrapper); |
| 2343 size_t actualObjectPayloadSize = Heap::objectPayloadSizeForTesting() - initialObjectPayloadSize; | 2344 size_t actualObjectPayloadSize = Heap::objectPayloadSizeForTesting() - initialObjectPayloadSize; |
| 2344 CheckWithSlack(expectedObjectPayloadSize, actualObjectPayloadSize, s lack); | 2345 CheckWithSlack(expectedObjectPayloadSize, actualObjectPayloadSize, s lack); |
| 2345 // There is probably space for the IntWrapper in a heap page without | 2346 // There is probably space for the IntWrapper in a heap page without |
| 2346 // allocating extra pages. However, the IntWrapper allocation might cause | 2347 // allocating extra pages. However, the IntWrapper allocation might cause |
| 2347 // the addition of a heap page. | 2348 // the addition of a heap page. |
| 2348 size_t largeObjectAllocationSize = sizeof(LargeObjectPage) + expecte dLargeHeapObjectPayloadSize; | 2349 size_t largeObjectAllocationSize = sizeof(LargeObjectPage) + expecte dLargeHeapObjectPayloadSize; |
| 2349 size_t allocatedSpaceLowerBound = initialAllocatedSpace + largeObjec tAllocationSize; | 2350 size_t allocatedSpaceLowerBound = initialAllocatedSpace + largeObjec tAllocationSize; |
| 2350 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize; | 2351 size_t allocatedSpaceUpperBound = allocatedSpaceLowerBound + slack + blinkPageSize; |
| 2351 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation); | 2352 EXPECT_LE(allocatedSpaceLowerBound, afterAllocation); |
| 2352 EXPECT_LE(afterAllocation, allocatedSpaceUpperBound); | 2353 EXPECT_LE(afterAllocation, allocatedSpaceUpperBound); |
| 2353 EXPECT_EQ(0, IntWrapper::s_destructorCalls); | 2354 EXPECT_EQ(0, IntWrapper::s_destructorCalls); |
| 2354 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); | 2355 EXPECT_EQ(0, LargeHeapObject::s_destructorCalls); |
| 2355 for (int i = 0; i < 10; i++) | 2356 for (int i = 0; i < 10; i++) |
| 2356 object = LargeHeapObject::create(); | 2357 object = LargeHeapObject::create(); |
| 2357 } | 2358 } |
| 2358 clearOutOldGarbage(); | 2359 clearOutOldGarbage(); |
| 2359 EXPECT_TRUE(Heap::allocatedSpace() == afterAllocation); | 2360 EXPECT_TRUE(ThreadState::current()->gcGroup()->heapStats().allocatedSpac e() == afterAllocation); |
| 2360 EXPECT_EQ(10, IntWrapper::s_destructorCalls); | 2361 EXPECT_EQ(10, IntWrapper::s_destructorCalls); |
| 2361 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); | 2362 EXPECT_EQ(10, LargeHeapObject::s_destructorCalls); |
| 2362 } | 2363 } |
| 2363 clearOutOldGarbage(); | 2364 clearOutOldGarbage(); |
| 2364 EXPECT_TRUE(initialObjectPayloadSize == Heap::objectPayloadSizeForTesting()) ; | 2365 EXPECT_TRUE(initialObjectPayloadSize == Heap::objectPayloadSizeForTesting()) ; |
| 2365 EXPECT_TRUE(initialAllocatedSpace == Heap::allocatedSpace()); | 2366 EXPECT_TRUE(initialAllocatedSpace == ThreadState::current()->gcGroup()->heap Stats().allocatedSpace()); |
| 2366 EXPECT_EQ(11, IntWrapper::s_destructorCalls); | 2367 EXPECT_EQ(11, IntWrapper::s_destructorCalls); |
| 2367 EXPECT_EQ(11, LargeHeapObject::s_destructorCalls); | 2368 EXPECT_EQ(11, LargeHeapObject::s_destructorCalls); |
| 2368 preciselyCollectGarbage(); | 2369 preciselyCollectGarbage(); |
| 2369 } | 2370 } |
| 2370 | 2371 |
| 2371 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped; | 2372 typedef std::pair<Member<IntWrapper>, int> PairWrappedUnwrapped; |
| 2372 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped; | 2373 typedef std::pair<int, Member<IntWrapper>> PairUnwrappedWrapped; |
| 2373 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong; | 2374 typedef std::pair<WeakMember<IntWrapper>, Member<IntWrapper>> PairWeakStrong; |
| 2374 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak; | 2375 typedef std::pair<Member<IntWrapper>, WeakMember<IntWrapper>> PairStrongWeak; |
| 2375 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped; | 2376 typedef std::pair<WeakMember<IntWrapper>, int> PairWeakUnwrapped; |
| (...skipping 1212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3588 RefCountedAndGarbageCollected2::s_destructorCalls = 0; | 3589 RefCountedAndGarbageCollected2::s_destructorCalls = 0; |
| 3589 { | 3590 { |
| 3590 RefCountedAndGarbageCollected* pointer1 = 0; | 3591 RefCountedAndGarbageCollected* pointer1 = 0; |
| 3591 RefCountedAndGarbageCollected2* pointer2 = 0; | 3592 RefCountedAndGarbageCollected2* pointer2 = 0; |
| 3592 { | 3593 { |
| 3593 Persistent<RefCountedAndGarbageCollected> object1 = RefCountedAndGar bageCollected::create(); | 3594 Persistent<RefCountedAndGarbageCollected> object1 = RefCountedAndGar bageCollected::create(); |
| 3594 Persistent<RefCountedAndGarbageCollected2> object2 = RefCountedAndGa rbageCollected2::create(); | 3595 Persistent<RefCountedAndGarbageCollected2> object2 = RefCountedAndGa rbageCollected2::create(); |
| 3595 pointer1 = object1.get(); | 3596 pointer1 = object1.get(); |
| 3596 pointer2 = object2.get(); | 3597 pointer2 = object2.get(); |
| 3597 void* objects[2] = { object1.get(), object2.get() }; | 3598 void* objects[2] = { object1.get(), object2.get() }; |
| 3598 RefCountedGarbageCollectedVisitor visitor(2, objects); | 3599 GCData gcData(ThreadState::current(), BlinkGC::NoHeapPointersOnStack , BlinkGC::GCWithSweep); |
| 3600 RefCountedGarbageCollectedVisitor visitor(2, objects, &gcData); | |
| 3599 ThreadState::current()->visitPersistents(&visitor); | 3601 ThreadState::current()->visitPersistents(&visitor); |
| 3600 EXPECT_TRUE(visitor.validate()); | 3602 EXPECT_TRUE(visitor.validate()); |
| 3601 | 3603 |
| 3602 conservativelyCollectGarbage(); | 3604 conservativelyCollectGarbage(); |
| 3603 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | 3605 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); |
| 3604 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | 3606 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); |
| 3605 } | 3607 } |
| 3606 conservativelyCollectGarbage(); | 3608 conservativelyCollectGarbage(); |
| 3607 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | 3609 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); |
| 3608 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | 3610 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); |
| 3609 | 3611 |
| 3610 // At this point, the reference counts of object1 and object2 are 0. | 3612 // At this point, the reference counts of object1 and object2 are 0. |
| 3611 // Only pointer1 and pointer2 keep references to object1 and object2. | 3613 // Only pointer1 and pointer2 keep references to object1 and object2. |
| 3612 void* objects[] = { 0 }; | 3614 void* objects[] = { 0 }; |
| 3613 RefCountedGarbageCollectedVisitor visitor(0, objects); | 3615 GCData gcData(ThreadState::current(), BlinkGC::NoHeapPointersOnStack, Bl inkGC::GCWithSweep); |
| 3616 RefCountedGarbageCollectedVisitor visitor(0, objects, &gcData); | |
| 3614 ThreadState::current()->visitPersistents(&visitor); | 3617 ThreadState::current()->visitPersistents(&visitor); |
| 3615 EXPECT_TRUE(visitor.validate()); | 3618 EXPECT_TRUE(visitor.validate()); |
| 3616 | 3619 |
| 3617 { | 3620 { |
| 3618 Persistent<RefCountedAndGarbageCollected> object1(pointer1); | 3621 Persistent<RefCountedAndGarbageCollected> object1(pointer1); |
| 3619 Persistent<RefCountedAndGarbageCollected2> object2(pointer2); | 3622 Persistent<RefCountedAndGarbageCollected2> object2(pointer2); |
| 3620 void* objects[2] = { object1.get(), object2.get() }; | 3623 void* objects[2] = { object1.get(), object2.get() }; |
| 3621 RefCountedGarbageCollectedVisitor visitor(2, objects); | 3624 GCData gcData(ThreadState::current(), BlinkGC::NoHeapPointersOnStack , BlinkGC::GCWithSweep); |
| 3625 RefCountedGarbageCollectedVisitor visitor(2, objects, &gcData); | |
| 3622 ThreadState::current()->visitPersistents(&visitor); | 3626 ThreadState::current()->visitPersistents(&visitor); |
| 3623 EXPECT_TRUE(visitor.validate()); | 3627 EXPECT_TRUE(visitor.validate()); |
| 3624 | 3628 |
| 3625 conservativelyCollectGarbage(); | 3629 conservativelyCollectGarbage(); |
| 3626 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | 3630 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); |
| 3627 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); | 3631 EXPECT_EQ(0, RefCountedAndGarbageCollected2::s_destructorCalls); |
| 3628 } | 3632 } |
| 3629 | 3633 |
| 3630 conservativelyCollectGarbage(); | 3634 conservativelyCollectGarbage(); |
| 3631 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); | 3635 EXPECT_EQ(0, RefCountedAndGarbageCollected::s_destructorCalls); |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3761 } | 3765 } |
| 3762 | 3766 |
| 3763 TEST(HeapTest, CheckAndMarkPointer) | 3767 TEST(HeapTest, CheckAndMarkPointer) |
| 3764 { | 3768 { |
| 3765 clearOutOldGarbage(); | 3769 clearOutOldGarbage(); |
| 3766 | 3770 |
| 3767 Vector<Address> objectAddresses; | 3771 Vector<Address> objectAddresses; |
| 3768 Vector<Address> endAddresses; | 3772 Vector<Address> endAddresses; |
| 3769 Address largeObjectAddress; | 3773 Address largeObjectAddress; |
| 3770 Address largeObjectEndAddress; | 3774 Address largeObjectEndAddress; |
| 3771 CountingVisitor visitor; | 3775 GCData gcData(ThreadState::current(), BlinkGC::NoHeapPointersOnStack, BlinkG C::GCWithSweep); |
| 3776 CountingVisitor visitor(&gcData); | |
| 3772 for (int i = 0; i < 10; i++) { | 3777 for (int i = 0; i < 10; i++) { |
| 3773 SimpleObject* object = SimpleObject::create(); | 3778 SimpleObject* object = SimpleObject::create(); |
| 3774 Address objectAddress = reinterpret_cast<Address>(object); | 3779 Address objectAddress = reinterpret_cast<Address>(object); |
| 3775 objectAddresses.append(objectAddress); | 3780 objectAddresses.append(objectAddress); |
| 3776 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); | 3781 endAddresses.append(objectAddress + sizeof(SimpleObject) - 1); |
| 3777 } | 3782 } |
| 3778 LargeHeapObject* largeObject = LargeHeapObject::create(); | 3783 LargeHeapObject* largeObject = LargeHeapObject::create(); |
| 3779 largeObjectAddress = reinterpret_cast<Address>(largeObject); | 3784 largeObjectAddress = reinterpret_cast<Address>(largeObject); |
| 3780 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; | 3785 largeObjectEndAddress = largeObjectAddress + sizeof(LargeHeapObject) - 1; |
| 3781 | 3786 |
| 3782 // This is a low-level test where we call checkAndMarkPointer. This method | 3787 // This is a low-level test where we call checkAndMarkPointer. This method |
| 3783 // causes the object start bitmap to be computed which requires the heap | 3788 // causes the object start bitmap to be computed which requires the heap |
| 3784 // to be in a consistent state (e.g. the free allocation area must be put | 3789 // to be in a consistent state (e.g. the free allocation area must be put |
| 3785 // into a free list header). However when we call makeConsistentForGC it | 3790 // into a free list header). However when we call makeConsistentForGC it |
| 3786 // also clears out the freelists so we have to rebuild those before trying | 3791 // also clears out the freelists so we have to rebuild those before trying |
| 3787 // to allocate anything again. We do this by forcing a GC after doing the | 3792 // to allocate anything again. We do this by forcing a GC after doing the |
| 3788 // checkAndMarkPointer tests. | 3793 // checkAndMarkPointer tests. |
| 3789 { | 3794 { |
| 3790 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3795 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3791 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads. | 3796 EXPECT_TRUE(scope.allThreadsParked()); // Fail the test if we could not park all threads. |
| 3792 Heap::flushHeapDoesNotContainCache(); | 3797 ThreadState::current()->gcGroup()->flushHeapDoesNotContainCache(); |
| 3793 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3798 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3794 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i])) ; | 3799 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, objectAddresses[i])) ; |
| 3795 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); | 3800 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, endAddresses[i])); |
| 3796 } | 3801 } |
| 3797 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); | 3802 EXPECT_EQ(objectAddresses.size() * 2, visitor.count()); |
| 3798 visitor.reset(); | 3803 visitor.reset(); |
| 3799 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); | 3804 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectAddress)); |
| 3800 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)); | 3805 EXPECT_TRUE(Heap::checkAndMarkPointer(&visitor, largeObjectEndAddress)); |
| 3801 EXPECT_EQ(2ul, visitor.count()); | 3806 EXPECT_EQ(2ul, visitor.count()); |
| 3802 visitor.reset(); | 3807 visitor.reset(); |
| 3803 } | 3808 } |
| 3804 // This forces a GC without stack scanning which results in the objects | 3809 // This forces a GC without stack scanning which results in the objects |
| 3805 // being collected. This will also rebuild the above mentioned freelists, | 3810 // being collected. This will also rebuild the above mentioned freelists, |
| 3806 // however we don't rely on that below since we don't have any allocations. | 3811 // however we don't rely on that below since we don't have any allocations. |
| 3807 clearOutOldGarbage(); | 3812 clearOutOldGarbage(); |
| 3808 { | 3813 { |
| 3809 TestGCScope scope(BlinkGC::HeapPointersOnStack); | 3814 TestGCScope scope(BlinkGC::HeapPointersOnStack); |
| 3810 EXPECT_TRUE(scope.allThreadsParked()); | 3815 EXPECT_TRUE(scope.allThreadsParked()); |
| 3811 Heap::flushHeapDoesNotContainCache(); | 3816 ThreadState::current()->gcGroup()->flushHeapDoesNotContainCache(); |
| 3812 for (size_t i = 0; i < objectAddresses.size(); i++) { | 3817 for (size_t i = 0; i < objectAddresses.size(); i++) { |
| 3813 // We would like to assert that checkAndMarkPointer returned false | 3818 // We would like to assert that checkAndMarkPointer returned false |
| 3814 // here because the pointers no longer point into a valid object | 3819 // here because the pointers no longer point into a valid object |
| 3815 // (it's been freed by the GCs. But checkAndMarkPointer will return | 3820 // (it's been freed by the GCs. But checkAndMarkPointer will return |
| 3816 // true for any pointer that points into a heap page, regardless of | 3821 // true for any pointer that points into a heap page, regardless of |
| 3817 // whether it points at a valid object (this ensures the | 3822 // whether it points at a valid object (this ensures the |
| 3818 // correctness of the page-based on-heap address caches), so we | 3823 // correctness of the page-based on-heap address caches), so we |
| 3819 // can't make that assert. | 3824 // can't make that assert. |
| 3820 Heap::checkAndMarkPointer(&visitor, objectAddresses[i]); | 3825 Heap::checkAndMarkPointer(&visitor, objectAddresses[i]); |
| 3821 Heap::checkAndMarkPointer(&visitor, endAddresses[i]); | 3826 Heap::checkAndMarkPointer(&visitor, endAddresses[i]); |
| (...skipping 905 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4727 { | 4732 { |
| 4728 // Since the sleeper thread has detached this is the only thread. | 4733 // Since the sleeper thread has detached this is the only thread. |
| 4729 TestGCScope scope(BlinkGC::NoHeapPointersOnStack); | 4734 TestGCScope scope(BlinkGC::NoHeapPointersOnStack); |
| 4730 EXPECT_TRUE(scope.allThreadsParked()); | 4735 EXPECT_TRUE(scope.allThreadsParked()); |
| 4731 } | 4736 } |
| 4732 } | 4737 } |
| 4733 | 4738 |
| 4734 private: | 4739 private: |
| 4735 static void sleeperMainFunc() | 4740 static void sleeperMainFunc() |
| 4736 { | 4741 { |
| 4737 ThreadState::attach(); | 4742 ThreadState::prepareForCurrentThread(); |
| 4738 s_sleeperRunning = true; | 4743 s_sleeperRunning = true; |
| 4739 | 4744 |
| 4740 // Simulate a long running op that is not entering a safepoint. | 4745 // Simulate a long running op that is not entering a safepoint. |
| 4741 while (!s_sleeperDone) { | 4746 while (!s_sleeperDone) { |
| 4742 Platform::current()->yieldCurrentThread(); | 4747 Platform::current()->yieldCurrentThread(); |
| 4743 } | 4748 } |
| 4744 | 4749 |
| 4745 ThreadState::detach(); | 4750 ThreadState::detach(); |
| 4746 s_sleeperRunning = false; | 4751 s_sleeperRunning = false; |
| 4747 } | 4752 } |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5417 // shutdown. | 5422 // shutdown. |
| 5418 wakeWorkerThread(); | 5423 wakeWorkerThread(); |
| 5419 } | 5424 } |
| 5420 | 5425 |
| 5421 private: | 5426 private: |
| 5422 | 5427 |
| 5423 static void workerThreadMain() | 5428 static void workerThreadMain() |
| 5424 { | 5429 { |
| 5425 MutexLocker locker(workerThreadMutex()); | 5430 MutexLocker locker(workerThreadMutex()); |
| 5426 | 5431 |
| 5427 ThreadState::attach(); | 5432 ThreadState::prepareForCurrentThread(); |
| 5428 | 5433 |
| 5429 { | 5434 { |
| 5430 // Create a worker object that is not kept alive except the | 5435 // Create a worker object that is not kept alive except the |
| 5431 // main thread will keep it as an integer value on its stack. | 5436 // main thread will keep it as an integer value on its stack. |
| 5432 IntWrapper* workerObject = IntWrapper::create(42); | 5437 IntWrapper* workerObject = IntWrapper::create(42); |
| 5433 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); | 5438 s_workerObjectPointer = reinterpret_cast<uintptr_t>(workerObject); |
| 5434 } | 5439 } |
| 5435 | 5440 |
| 5436 // Signal the main thread that the worker is done with its allocation. | 5441 // Signal the main thread that the worker is done with its allocation. |
| 5437 wakeMainThread(); | 5442 wakeMainThread(); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5538 parkWorkerThread(); | 5543 parkWorkerThread(); |
| 5539 } | 5544 } |
| 5540 | 5545 |
| 5541 return weakCollection; | 5546 return weakCollection; |
| 5542 } | 5547 } |
| 5543 | 5548 |
| 5544 static void workerThreadMain() | 5549 static void workerThreadMain() |
| 5545 { | 5550 { |
| 5546 MutexLocker locker(workerThreadMutex()); | 5551 MutexLocker locker(workerThreadMutex()); |
| 5547 | 5552 |
| 5548 ThreadState::attach(); | 5553 ThreadState::prepareForCurrentThread(); |
| 5549 | 5554 |
| 5550 { | 5555 { |
| 5551 Persistent<WeakCollectionType> collection = allocateCollection(); | 5556 Persistent<WeakCollectionType> collection = allocateCollection(); |
| 5552 { | 5557 { |
| 5553 // Prevent weak processing with an iterator and GC. | 5558 // Prevent weak processing with an iterator and GC. |
| 5554 WeakCollectionType::iterator it = collection->begin(); | 5559 WeakCollectionType::iterator it = collection->begin(); |
| 5555 conservativelyCollectGarbage(); | 5560 conservativelyCollectGarbage(); |
| 5556 | 5561 |
| 5557 // The backing should be strongified because of the iterator. | 5562 // The backing should be strongified because of the iterator. |
| 5558 EXPECT_EQ(6u, collection->size()); | 5563 EXPECT_EQ(6u, collection->size()); |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5699 // can acquire it and do its sweep of its heaps. Just wait for the worke r | 5704 // can acquire it and do its sweep of its heaps. Just wait for the worke r |
| 5700 // to complete its sweep and check the result. | 5705 // to complete its sweep and check the result. |
| 5701 parkMainThread(); | 5706 parkMainThread(); |
| 5702 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls); | 5707 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls); |
| 5703 } | 5708 } |
| 5704 | 5709 |
| 5705 private: | 5710 private: |
| 5706 static void workerThreadMain() | 5711 static void workerThreadMain() |
| 5707 { | 5712 { |
| 5708 MutexLocker locker(workerThreadMutex()); | 5713 MutexLocker locker(workerThreadMutex()); |
| 5709 ThreadState::attach(); | 5714 ThreadState::prepareForCurrentThread(); |
| 5710 | 5715 |
| 5711 DestructorLockingObject* dlo = DestructorLockingObject::create(); | 5716 DestructorLockingObject* dlo = DestructorLockingObject::create(); |
| 5712 ASSERT_UNUSED(dlo, dlo); | 5717 ASSERT_UNUSED(dlo, dlo); |
| 5713 | 5718 |
| 5714 // Wake up the main thread which is waiting for the worker to do its | 5719 // Wake up the main thread which is waiting for the worker to do its |
| 5715 // allocation. | 5720 // allocation. |
| 5716 wakeMainThread(); | 5721 wakeMainThread(); |
| 5717 | 5722 |
| 5718 // Wait for the main thread to get the global lock to ensure it has | 5723 // Wait for the main thread to get the global lock to ensure it has |
| 5719 // it before the worker tries to acquire it. We want the worker to | 5724 // it before the worker tries to acquire it. We want the worker to |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5754 workerThread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSaf eBind(workerThreadMain))); | 5759 workerThread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSaf eBind(workerThreadMain))); |
| 5755 | 5760 |
| 5756 parkMainThread(); | 5761 parkMainThread(); |
| 5757 | 5762 |
| 5758 // (Temporarily) detach main thread and wake the worker thread, so that it | 5763 // (Temporarily) detach main thread and wake the worker thread, so that it |
| 5759 // can do its detach(). | 5764 // can do its detach(). |
| 5760 ThreadState::detachMainThread(); | 5765 ThreadState::detachMainThread(); |
| 5761 wakeWorkerThread(); | 5766 wakeWorkerThread(); |
| 5762 | 5767 |
| 5763 parkMainThread(); | 5768 parkMainThread(); |
| 5764 ThreadState::attachMainThread(); | 5769 ThreadState::prepareForMainThread(); |
| 5765 } | 5770 } |
| 5766 | 5771 |
| 5767 private: | 5772 private: |
| 5768 | 5773 |
| 5769 static void workerThreadMain() | 5774 static void workerThreadMain() |
| 5770 { | 5775 { |
| 5771 MutexLocker locker(workerThreadMutex()); | 5776 MutexLocker locker(workerThreadMutex()); |
| 5772 | 5777 |
| 5773 // Start up a worker thread and have it detach after the main thread has . | 5778 // Start up a worker thread and have it detach after the main thread has . |
| 5774 // Do this to verify that CrossThreadPersistent<>s referring to objects | 5779 // Do this to verify that CrossThreadPersistent<>s referring to objects |
| 5775 // on one of the main thread's heaps does not upset the CTP invalidation | 5780 // on one of the main thread's heaps does not upset the CTP invalidation |
| 5776 // pass that ThreadState::detach() performs. | 5781 // pass that ThreadState::detach() performs. |
| 5777 ThreadState::attach(); | 5782 ThreadState::prepareForCurrentThread(); |
| 5778 | 5783 |
| 5779 CrossThreadPersistent<IntWrapper> persistent(IntWrapper::create(43)); | 5784 CrossThreadPersistent<IntWrapper> persistent(IntWrapper::create(43)); |
| 5780 | 5785 |
| 5781 // Wait for the main thread to detach. | 5786 // Wait for the main thread to detach. |
| 5782 wakeMainThread(); | 5787 wakeMainThread(); |
| 5783 parkWorkerThread(); | 5788 parkWorkerThread(); |
| 5784 | 5789 |
| 5785 ThreadState::detach(); | 5790 ThreadState::detach(); |
| 5786 wakeMainThread(); | 5791 wakeMainThread(); |
| 5787 } | 5792 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 5811 DISALLOW_NEW(); | 5816 DISALLOW_NEW(); |
| 5812 public: | 5817 public: |
| 5813 PartObject() : m_obj(SimpleObject::create()) { } | 5818 PartObject() : m_obj(SimpleObject::create()) { } |
| 5814 DEFINE_INLINE_TRACE() { visitor->trace(m_obj); } | 5819 DEFINE_INLINE_TRACE() { visitor->trace(m_obj); } |
| 5815 private: | 5820 private: |
| 5816 Member<SimpleObject> m_obj; | 5821 Member<SimpleObject> m_obj; |
| 5817 }; | 5822 }; |
| 5818 | 5823 |
| 5819 TEST(HeapTest, TraceIfNeeded) | 5824 TEST(HeapTest, TraceIfNeeded) |
| 5820 { | 5825 { |
| 5821 CountingVisitor visitor; | 5826 GCData gcData(ThreadState::current(), BlinkGC::NoHeapPointersOnStack, BlinkG C::GCWithSweep); |
| 5827 CountingVisitor visitor(&gcData); | |
| 5822 | 5828 |
| 5823 { | 5829 { |
| 5824 TraceIfNeededTester<RefPtr<OffHeapInt>>* m_offHeap = TraceIfNeededTester <RefPtr<OffHeapInt>>::create(OffHeapInt::create(42)); | 5830 TraceIfNeededTester<RefPtr<OffHeapInt>>* m_offHeap = TraceIfNeededTester <RefPtr<OffHeapInt>>::create(OffHeapInt::create(42)); |
| 5825 visitor.reset(); | 5831 visitor.reset(); |
| 5826 m_offHeap->trace(&visitor); | 5832 m_offHeap->trace(&visitor); |
| 5827 EXPECT_EQ(0u, visitor.count()); | 5833 EXPECT_EQ(0u, visitor.count()); |
| 5828 } | 5834 } |
| 5829 | 5835 |
| 5830 { | 5836 { |
| 5831 TraceIfNeededTester<PartObject>* m_part = TraceIfNeededTester<PartObject >::create(); | 5837 TraceIfNeededTester<PartObject>* m_part = TraceIfNeededTester<PartObject >::create(); |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6434 preciselyCollectGarbage(); | 6440 preciselyCollectGarbage(); |
| 6435 EXPECT_FALSE(holder->object()); | 6441 EXPECT_FALSE(holder->object()); |
| 6436 } | 6442 } |
| 6437 | 6443 |
| 6438 namespace { | 6444 namespace { |
| 6439 | 6445 |
| 6440 void workerThreadMainForCrossThreadWeakPersistentTest(DestructorLockingObject** object) | 6446 void workerThreadMainForCrossThreadWeakPersistentTest(DestructorLockingObject** object) |
| 6441 { | 6447 { |
| 6442 // Step 2: Create an object and store the pointer. | 6448 // Step 2: Create an object and store the pointer. |
| 6443 MutexLocker locker(workerThreadMutex()); | 6449 MutexLocker locker(workerThreadMutex()); |
| 6444 ThreadState::attach(); | 6450 ThreadState::prepareForCurrentThread(); |
| 6445 *object = DestructorLockingObject::create(); | 6451 *object = DestructorLockingObject::create(); |
| 6446 wakeMainThread(); | 6452 wakeMainThread(); |
| 6447 parkWorkerThread(); | 6453 parkWorkerThread(); |
| 6448 | 6454 |
| 6449 // Step 4: Run a GC. | 6455 // Step 4: Run a GC. |
| 6450 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, B linkGC::ForcedGC); | 6456 Heap::collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, B linkGC::ForcedGC); |
| 6451 wakeMainThread(); | 6457 wakeMainThread(); |
| 6452 parkWorkerThread(); | 6458 parkWorkerThread(); |
| 6453 | 6459 |
| 6454 // Step 6: Finish. | 6460 // Step 6: Finish. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6524 EXPECT_EQ(1u, vector2.size()); | 6530 EXPECT_EQ(1u, vector2.size()); |
| 6525 // TODO(Oilpan): when Vector.h's contiguous container support no longer disables | 6531 // TODO(Oilpan): when Vector.h's contiguous container support no longer disables |
| 6526 // Vector<>s with inline capacity, remove. | 6532 // Vector<>s with inline capacity, remove. |
| 6527 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER) | 6533 #if !defined(ANNOTATE_CONTIGUOUS_CONTAINER) |
| 6528 EXPECT_EQ(16u, vector1.capacity()); | 6534 EXPECT_EQ(16u, vector1.capacity()); |
| 6529 EXPECT_EQ(16u, vector2.capacity()); | 6535 EXPECT_EQ(16u, vector2.capacity()); |
| 6530 #endif | 6536 #endif |
| 6531 } | 6537 } |
| 6532 | 6538 |
| 6533 } // namespace blink | 6539 } // namespace blink |
| OLD | NEW |