Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(446)

Side by Side Diff: third_party/WebKit/Source/platform/heap/HeapPage.cpp

Issue 2684633004: Remove orphaned pages from Oilpan (Closed)
Patch Set: temp Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 : m_firstPage(nullptr), 109 : m_firstPage(nullptr),
110 m_firstUnsweptPage(nullptr), 110 m_firstUnsweptPage(nullptr),
111 m_threadState(state), 111 m_threadState(state),
112 m_index(index) {} 112 m_index(index) {}
113 113
114 BaseArena::~BaseArena() { 114 BaseArena::~BaseArena() {
115 ASSERT(!m_firstPage); 115 ASSERT(!m_firstPage);
116 ASSERT(!m_firstUnsweptPage); 116 ASSERT(!m_firstUnsweptPage);
117 } 117 }
118 118
119 void BaseArena::cleanupPages() { 119 void BaseArena::removeAllPages() {
120 clearFreeLists(); 120 clearFreeLists();
121 121
122 ASSERT(!m_firstUnsweptPage); 122 ASSERT(!m_firstUnsweptPage);
123 // Add the BaseArena's pages to the orphanedPagePool. 123 while (m_firstPage) {
124 for (BasePage* page = m_firstPage; page; page = page->next()) { 124 BasePage* page = m_firstPage;
125 getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size()); 125 page->unlink(&m_firstPage);
126 getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage( 126 page->removeFromHeap();
127 arenaIndex(), page);
128 } 127 }
129 m_firstPage = nullptr;
130 } 128 }
131 129
132 void BaseArena::takeSnapshot(const String& dumpBaseName, 130 void BaseArena::takeSnapshot(const String& dumpBaseName,
133 ThreadState::GCSnapshotInfo& info) { 131 ThreadState::GCSnapshotInfo& info) {
134 // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName" 132 // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName"
135 base::trace_event::MemoryAllocatorDump* allocatorDump = 133 base::trace_event::MemoryAllocatorDump* allocatorDump =
136 BlinkGCMemoryDumpProvider::instance() 134 BlinkGCMemoryDumpProvider::instance()
137 ->createMemoryAllocatorDumpForCurrentGC(dumpBaseName); 135 ->createMemoryAllocatorDumpForCurrentGC(dumpBaseName);
138 size_t pageCount = 0; 136 size_t pageCount = 0;
139 BasePage::HeapSnapshotInfo heapInfo; 137 BasePage::HeapSnapshotInfo heapInfo;
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
669 for (size_t i = 0; i < page->payloadSize(); i++) 667 for (size_t i = 0; i < page->payloadSize(); i++)
670 address[i] = reuseAllowedZapValue; 668 address[i] = reuseAllowedZapValue;
671 ASAN_POISON_MEMORY_REGION(page->payload(), page->payloadSize()); 669 ASAN_POISON_MEMORY_REGION(page->payload(), page->payloadSize());
672 #endif 670 #endif
673 addToFreeList(page->payload(), page->payloadSize()); 671 addToFreeList(page->payload(), page->payloadSize());
674 } 672 }
675 673
676 void NormalPageArena::freePage(NormalPage* page) { 674 void NormalPageArena::freePage(NormalPage* page) {
677 getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size()); 675 getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size());
678 676
679 if (page->terminating()) { 677 PageMemory* memory = page->storage();
680 // The thread is shutting down and this page is being removed as a part 678 page->~NormalPage();
681 // of the thread local GC. In that case the object could be traced in 679 getThreadState()->heap().getFreePagePool()->addFreePage(arenaIndex(), memory);
682 // the next global GC if there is a dangling pointer from a live thread
683 // heap to this dead thread heap. To guard against this, we put the
684 // page into the orphaned page pool and zap the page memory. This
685 // ensures that tracing the dangling pointer in the next global GC just
686 // crashes instead of causing use-after-frees. After the next global
687 // GC, the orphaned pages are removed.
688 getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(
689 arenaIndex(), page);
690 } else {
691 PageMemory* memory = page->storage();
692 page->~NormalPage();
693 getThreadState()->heap().getFreePagePool()->addFreePage(arenaIndex(),
694 memory);
695 }
696 } 680 }
697 681
698 bool NormalPageArena::coalesce() { 682 bool NormalPageArena::coalesce() {
699 // Don't coalesce arenas if there are not enough promptly freed entries 683 // Don't coalesce arenas if there are not enough promptly freed entries
700 // to be coalesced. 684 // to be coalesced.
701 // 685 //
702 // FIXME: This threshold is determined just to optimize blink_perf 686 // FIXME: This threshold is determined just to optimize blink_perf
703 // benchmarks. Coalescing is very sensitive to the threashold and 687 // benchmarks. Coalescing is very sensitive to the threashold and
704 // we need further investigations on the coalescing scheme. 688 // we need further investigations on the coalescing scheme.
705 if (m_promptlyFreedSize < 1024 * 1024) 689 if (m_promptlyFreedSize < 1024 * 1024)
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1067 object->payloadSize()); 1051 object->payloadSize());
1068 getThreadState()->heap().heapStats().decreaseAllocatedSpace(object->size()); 1052 getThreadState()->heap().heapStats().decreaseAllocatedSpace(object->size());
1069 1053
1070 // Unpoison the object header and allocationGranularity bytes after the 1054 // Unpoison the object header and allocationGranularity bytes after the
1071 // object before freeing. 1055 // object before freeing.
1072 ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(), 1056 ASAN_UNPOISON_MEMORY_REGION(object->heapObjectHeader(),
1073 sizeof(HeapObjectHeader)); 1057 sizeof(HeapObjectHeader));
1074 ASAN_UNPOISON_MEMORY_REGION(object->getAddress() + object->size(), 1058 ASAN_UNPOISON_MEMORY_REGION(object->getAddress() + object->size(),
1075 allocationGranularity); 1059 allocationGranularity);
1076 1060
1077 if (object->terminating()) { 1061 PageMemory* memory = object->storage();
1078 ASSERT(ThreadState::current()->isTerminating()); 1062 object->~LargeObjectPage();
1079 // The thread is shutting down and this page is being removed as a part 1063 delete memory;
1080 // of the thread local GC. In that case the object could be traced in
1081 // the next global GC if there is a dangling pointer from a live thread
1082 // heap to this dead thread heap. To guard against this, we put the
1083 // page into the orphaned page pool and zap the page memory. This
1084 // ensures that tracing the dangling pointer in the next global GC just
1085 // crashes instead of causing use-after-frees. After the next global
1086 // GC, the orphaned pages are removed.
1087 getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(
1088 arenaIndex(), object);
1089 } else {
1090 ASSERT(!ThreadState::current()->isTerminating());
1091 PageMemory* memory = object->storage();
1092 object->~LargeObjectPage();
1093 delete memory;
1094 }
1095 } 1064 }
1096 1065
1097 Address LargeObjectArena::lazySweepPages(size_t allocationSize, 1066 Address LargeObjectArena::lazySweepPages(size_t allocationSize,
1098 size_t gcInfoIndex) { 1067 size_t gcInfoIndex) {
1099 Address result = nullptr; 1068 Address result = nullptr;
1100 size_t sweptSize = 0; 1069 size_t sweptSize = 0;
1101 while (m_firstUnsweptPage) { 1070 while (m_firstUnsweptPage) {
1102 BasePage* page = m_firstUnsweptPage; 1071 BasePage* page = m_firstUnsweptPage;
1103 if (page->isEmpty()) { 1072 if (page->isEmpty()) {
1104 sweptSize += static_cast<LargeObjectPage*>(page)->payloadSize() + 1073 sweptSize += static_cast<LargeObjectPage*>(page)->payloadSize() +
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1290 1259
1291 BasePage::BasePage(PageMemory* storage, BaseArena* arena) 1260 BasePage::BasePage(PageMemory* storage, BaseArena* arena)
1292 : m_storage(storage), 1261 : m_storage(storage),
1293 m_arena(arena), 1262 m_arena(arena),
1294 m_next(nullptr), 1263 m_next(nullptr),
1295 m_terminating(false), 1264 m_terminating(false),
1296 m_swept(true) { 1265 m_swept(true) {
1297 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); 1266 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
1298 } 1267 }
1299 1268
1300 void BasePage::markOrphaned() {
1301 m_arena = nullptr;
1302 m_terminating = false;
1303 // Since we zap the page payload for orphaned pages we need to mark it as
1304 // unused so a conservative pointer won't interpret the object headers.
1305 storage()->markUnused();
1306 }
1307
1308 NormalPage::NormalPage(PageMemory* storage, BaseArena* arena) 1269 NormalPage::NormalPage(PageMemory* storage, BaseArena* arena)
1309 : BasePage(storage, arena), m_objectStartBitMapComputed(false) { 1270 : BasePage(storage, arena), m_objectStartBitMapComputed(false) {
1310 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this))); 1271 ASSERT(isPageHeaderAddress(reinterpret_cast<Address>(this)));
1311 } 1272 }
1312 1273
1313 size_t NormalPage::objectPayloadSizeForTesting() { 1274 size_t NormalPage::objectPayloadSizeForTesting() {
1314 size_t objectPayloadSize = 0; 1275 size_t objectPayloadSize = 0;
1315 Address headerAddress = payload(); 1276 Address headerAddress = payload();
1316 markAsSwept(); 1277 markAsSwept();
1317 ASSERT(headerAddress != payloadEnd()); 1278 ASSERT(headerAddress != payloadEnd());
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
1714 MarkedPointerCallbackForTesting callback) { 1675 MarkedPointerCallbackForTesting callback) {
1715 DCHECK(contains(address)); 1676 DCHECK(contains(address));
1716 HeapObjectHeader* header = findHeaderFromAddress(address); 1677 HeapObjectHeader* header = findHeaderFromAddress(address);
1717 if (!header || header->isDead()) 1678 if (!header || header->isDead())
1718 return; 1679 return;
1719 if (!callback(header)) 1680 if (!callback(header))
1720 markPointer(visitor, header); 1681 markPointer(visitor, header);
1721 } 1682 }
1722 #endif 1683 #endif
1723 1684
1724 void NormalPage::markOrphaned() {
1725 // Zap the payload with a recognizable value to detect any incorrect
1726 // cross thread pointer usage.
1727 #if defined(ADDRESS_SANITIZER)
1728 // This needs to zap poisoned memory as well.
1729 // Force unpoison memory before memset.
1730 ASAN_UNPOISON_MEMORY_REGION(payload(), payloadSize());
1731 #endif
1732 OrphanedPagePool::asanDisabledMemset(
1733 payload(), OrphanedPagePool::orphanedZapValue, payloadSize());
1734 BasePage::markOrphaned();
1735 }
1736
1737 void NormalPage::takeSnapshot(base::trace_event::MemoryAllocatorDump* pageDump, 1685 void NormalPage::takeSnapshot(base::trace_event::MemoryAllocatorDump* pageDump,
1738 ThreadState::GCSnapshotInfo& info, 1686 ThreadState::GCSnapshotInfo& info,
1739 HeapSnapshotInfo& heapInfo) { 1687 HeapSnapshotInfo& heapInfo) {
1740 HeapObjectHeader* header = nullptr; 1688 HeapObjectHeader* header = nullptr;
1741 size_t liveCount = 0; 1689 size_t liveCount = 0;
1742 size_t deadCount = 0; 1690 size_t deadCount = 0;
1743 size_t freeCount = 0; 1691 size_t freeCount = 0;
1744 size_t liveSize = 0; 1692 size_t liveSize = 0;
1745 size_t deadSize = 0; 1693 size_t deadSize = 0;
1746 size_t freeSize = 0; 1694 size_t freeSize = 0;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1855 Address address, 1803 Address address,
1856 MarkedPointerCallbackForTesting callback) { 1804 MarkedPointerCallbackForTesting callback) {
1857 DCHECK(contains(address)); 1805 DCHECK(contains(address));
1858 if (!containedInObjectPayload(address) || heapObjectHeader()->isDead()) 1806 if (!containedInObjectPayload(address) || heapObjectHeader()->isDead())
1859 return; 1807 return;
1860 if (!callback(heapObjectHeader())) 1808 if (!callback(heapObjectHeader()))
1861 markPointer(visitor, heapObjectHeader()); 1809 markPointer(visitor, heapObjectHeader());
1862 } 1810 }
1863 #endif 1811 #endif
1864 1812
1865 void LargeObjectPage::markOrphaned() {
1866 // Zap the payload with a recognizable value to detect any incorrect
1867 // cross thread pointer usage.
1868 OrphanedPagePool::asanDisabledMemset(
1869 payload(), OrphanedPagePool::orphanedZapValue, payloadSize());
1870 BasePage::markOrphaned();
1871 }
1872
1873 void LargeObjectPage::takeSnapshot( 1813 void LargeObjectPage::takeSnapshot(
1874 base::trace_event::MemoryAllocatorDump* pageDump, 1814 base::trace_event::MemoryAllocatorDump* pageDump,
1875 ThreadState::GCSnapshotInfo& info, 1815 ThreadState::GCSnapshotInfo& info,
1876 HeapSnapshotInfo&) { 1816 HeapSnapshotInfo&) {
1877 size_t liveSize = 0; 1817 size_t liveSize = 0;
1878 size_t deadSize = 0; 1818 size_t deadSize = 0;
1879 size_t liveCount = 0; 1819 size_t liveCount = 0;
1880 size_t deadCount = 0; 1820 size_t deadCount = 0;
1881 HeapObjectHeader* header = heapObjectHeader(); 1821 HeapObjectHeader* header = heapObjectHeader();
1882 size_t gcInfoIndex = header->gcInfoIndex(); 1822 size_t gcInfoIndex = header->gcInfoIndex();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1940 1880
1941 m_hasEntries = true; 1881 m_hasEntries = true;
1942 size_t index = hash(address); 1882 size_t index = hash(address);
1943 ASSERT(!(index & 1)); 1883 ASSERT(!(index & 1));
1944 Address cachePage = roundToBlinkPageStart(address); 1884 Address cachePage = roundToBlinkPageStart(address);
1945 m_entries[index + 1] = m_entries[index]; 1885 m_entries[index + 1] = m_entries[index];
1946 m_entries[index] = cachePage; 1886 m_entries[index] = cachePage;
1947 } 1887 }
1948 1888
1949 } // namespace blink 1889 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698