| 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 13 matching lines...) Expand all Loading... |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "platform/heap/HeapPage.h" | 32 #include "platform/heap/HeapPage.h" |
| 33 | 33 |
| 34 #include "base/trace_event/memory_allocator_dump.h" |
| 35 #include "base/trace_event/process_memory_dump.h" |
| 34 #include "platform/ScriptForbiddenScope.h" | 36 #include "platform/ScriptForbiddenScope.h" |
| 35 #include "platform/Task.h" | 37 #include "platform/Task.h" |
| 36 #include "platform/TraceEvent.h" | 38 #include "platform/TraceEvent.h" |
| 37 #include "platform/heap/BlinkGCMemoryDumpProvider.h" | 39 #include "platform/heap/BlinkGCMemoryDumpProvider.h" |
| 38 #include "platform/heap/CallbackStack.h" | 40 #include "platform/heap/CallbackStack.h" |
| 39 #include "platform/heap/Heap.h" | 41 #include "platform/heap/Heap.h" |
| 40 #include "platform/heap/MarkingVisitor.h" | 42 #include "platform/heap/MarkingVisitor.h" |
| 41 #include "platform/heap/PageMemory.h" | 43 #include "platform/heap/PageMemory.h" |
| 42 #include "platform/heap/PagePool.h" | 44 #include "platform/heap/PagePool.h" |
| 43 #include "platform/heap/SafePoint.h" | 45 #include "platform/heap/SafePoint.h" |
| 44 #include "platform/heap/ThreadState.h" | 46 #include "platform/heap/ThreadState.h" |
| 45 #include "public/platform/Platform.h" | 47 #include "public/platform/Platform.h" |
| 46 #include "public/platform/WebMemoryAllocatorDump.h" | |
| 47 #include "public/platform/WebProcessMemoryDump.h" | |
| 48 #include "wtf/Assertions.h" | 48 #include "wtf/Assertions.h" |
| 49 #include "wtf/ContainerAnnotations.h" | 49 #include "wtf/ContainerAnnotations.h" |
| 50 #include "wtf/LeakAnnotations.h" | 50 #include "wtf/LeakAnnotations.h" |
| 51 #include "wtf/MainThread.h" | 51 #include "wtf/MainThread.h" |
| 52 #include "wtf/PageAllocator.h" | 52 #include "wtf/PageAllocator.h" |
| 53 #include "wtf/Partitions.h" | 53 #include "wtf/Partitions.h" |
| 54 #include "wtf/PassOwnPtr.h" | 54 #include "wtf/PassOwnPtr.h" |
| 55 #if ENABLE(GC_PROFILING) | 55 #if ENABLE(GC_PROFILING) |
| 56 #include "platform/TracedValue.h" | 56 #include "platform/TracedValue.h" |
| 57 #include "wtf/HashMap.h" | 57 #include "wtf/HashMap.h" |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 90 static_cast<LargeObjectPage*>(largePage)->setIsVectorBackingPage(); \ | 90 static_cast<LargeObjectPage*>(largePage)->setIsVectorBackingPage(); \ |
| 91 } | 91 } |
| 92 #else | 92 #else |
| 93 #define ENABLE_ASAN_CONTAINER_ANNOTATIONS 0 | 93 #define ENABLE_ASAN_CONTAINER_ANNOTATIONS 0 |
| 94 #define ASAN_RETIRE_CONTAINER_ANNOTATION(payload, payloadSize) | 94 #define ASAN_RETIRE_CONTAINER_ANNOTATION(payload, payloadSize) |
| 95 #define ASAN_MARK_LARGE_VECTOR_CONTAINER(heap, largeObject) | 95 #define ASAN_MARK_LARGE_VECTOR_CONTAINER(heap, largeObject) |
| 96 #endif | 96 #endif |
| 97 | 97 |
| 98 namespace blink { | 98 namespace blink { |
| 99 | 99 |
| 100 using base::trace_event::MemoryAllocatorDump; |
| 101 |
| 100 #if ENABLE(GC_PROFILING) | 102 #if ENABLE(GC_PROFILING) |
| 101 static String classOf(const void* object) | 103 static String classOf(const void* object) |
| 102 { | 104 { |
| 103 if (const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_
cast<void*>(object)))) | 105 if (const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_
cast<void*>(object)))) |
| 104 return gcInfo->className(); | 106 return gcInfo->className(); |
| 105 return "unknown"; | 107 return "unknown"; |
| 106 } | 108 } |
| 107 #endif | 109 #endif |
| 108 | 110 |
| 109 #if ENABLE(ASSERT) | 111 #if ENABLE(ASSERT) |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 147 for (BasePage* page = m_firstPage; page; page = page->next()) { | 149 for (BasePage* page = m_firstPage; page; page = page->next()) { |
| 148 Heap::decreaseAllocatedSpace(page->size()); | 150 Heap::decreaseAllocatedSpace(page->size()); |
| 149 Heap::orphanedPagePool()->addOrphanedPage(heapIndex(), page); | 151 Heap::orphanedPagePool()->addOrphanedPage(heapIndex(), page); |
| 150 } | 152 } |
| 151 m_firstPage = nullptr; | 153 m_firstPage = nullptr; |
| 152 } | 154 } |
| 153 | 155 |
| 154 void BaseHeap::takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotI
nfo& info) | 156 void BaseHeap::takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshotI
nfo& info) |
| 155 { | 157 { |
| 156 // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName" | 158 // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName" |
| 157 WebMemoryAllocatorDump* allocatorDump = BlinkGCMemoryDumpProvider::instance(
)->createMemoryAllocatorDumpForCurrentGC(dumpBaseName); | 159 MemoryAllocatorDump* allocatorDump = BlinkGCMemoryDumpProvider::instance()->
createMemoryAllocatorDumpForCurrentGC(dumpBaseName); |
| 158 size_t pageIndex = 0; | 160 size_t pageIndex = 0; |
| 159 size_t heapTotalFreeSize = 0; | 161 size_t heapTotalFreeSize = 0; |
| 160 size_t heapTotalFreeCount = 0; | 162 size_t heapTotalFreeCount = 0; |
| 161 for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { | 163 for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { |
| 162 size_t heapPageFreeSize = 0; | 164 size_t heapPageFreeSize = 0; |
| 163 size_t heapPageFreeCount = 0; | 165 size_t heapPageFreeCount = 0; |
| 164 page->takeSnapshot(dumpBaseName, pageIndex, info, &heapPageFreeSize, &he
apPageFreeCount); | 166 page->takeSnapshot(dumpBaseName, pageIndex, info, &heapPageFreeSize, &he
apPageFreeCount); |
| 165 heapTotalFreeSize += heapPageFreeSize; | 167 heapTotalFreeSize += heapPageFreeSize; |
| 166 heapTotalFreeCount += heapPageFreeCount; | 168 heapTotalFreeCount += heapPageFreeCount; |
| 167 pageIndex++; | 169 pageIndex++; |
| (...skipping 303 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 if (page->contains(address)) | 473 if (page->contains(address)) |
| 472 return true; | 474 return true; |
| 473 } | 475 } |
| 474 return false; | 476 return false; |
| 475 } | 477 } |
| 476 #endif | 478 #endif |
| 477 | 479 |
| 478 void NormalPageHeap::takeFreelistSnapshot(const String& dumpName) | 480 void NormalPageHeap::takeFreelistSnapshot(const String& dumpName) |
| 479 { | 481 { |
| 480 if (m_freeList.takeSnapshot(dumpName)) { | 482 if (m_freeList.takeSnapshot(dumpName)) { |
| 481 WebMemoryAllocatorDump* bucketsDump = BlinkGCMemoryDumpProvider::instanc
e()->createMemoryAllocatorDumpForCurrentGC(dumpName + "/buckets"); | 483 MemoryAllocatorDump* bucketsDump = BlinkGCMemoryDumpProvider::instance()
->createMemoryAllocatorDumpForCurrentGC(dumpName + "/buckets"); |
| 482 WebMemoryAllocatorDump* pagesDump = BlinkGCMemoryDumpProvider::instance(
)->createMemoryAllocatorDumpForCurrentGC(dumpName + "/pages"); | 484 MemoryAllocatorDump* pagesDump = BlinkGCMemoryDumpProvider::instance()->
createMemoryAllocatorDumpForCurrentGC(dumpName + "/pages"); |
| 483 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->AddOw
nershipEdge(pagesDump->guid(), bucketsDump->guid()); | 485 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->AddOw
nershipEdge(pagesDump->guid(), bucketsDump->guid()); |
| 484 } | 486 } |
| 485 } | 487 } |
| 486 | 488 |
| 487 #if ENABLE(GC_PROFILING) | 489 #if ENABLE(GC_PROFILING) |
| 488 void NormalPageHeap::snapshotFreeList(TracedValue& json) | 490 void NormalPageHeap::snapshotFreeList(TracedValue& json) |
| 489 { | 491 { |
| 490 json.setInteger("cumulativeAllocationSize", m_cumulativeAllocationSize); | 492 json.setInteger("cumulativeAllocationSize", m_cumulativeAllocationSize); |
| 491 json.setDouble("inlineAllocationRate", static_cast<double>(m_inlineAllocatio
nCount) / m_allocationCount); | 493 json.setDouble("inlineAllocationRate", static_cast<double>(m_inlineAllocatio
nCount) / m_allocationCount); |
| 492 json.setInteger("inlineAllocationCount", m_inlineAllocationCount); | 494 json.setInteger("inlineAllocationCount", m_inlineAllocationCount); |
| (...skipping 640 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1133 bool didDumpBucketStats = false; | 1135 bool didDumpBucketStats = false; |
| 1134 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { | 1136 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { |
| 1135 size_t entryCount = 0; | 1137 size_t entryCount = 0; |
| 1136 size_t freeSize = 0; | 1138 size_t freeSize = 0; |
| 1137 for (FreeListEntry* entry = m_freeLists[i]; entry; entry = entry->next()
) { | 1139 for (FreeListEntry* entry = m_freeLists[i]; entry; entry = entry->next()
) { |
| 1138 ++entryCount; | 1140 ++entryCount; |
| 1139 freeSize += entry->size(); | 1141 freeSize += entry->size(); |
| 1140 } | 1142 } |
| 1141 | 1143 |
| 1142 String dumpName = dumpBaseName + String::format("/buckets/bucket_%lu", s
tatic_cast<unsigned long>(1 << i)); | 1144 String dumpName = dumpBaseName + String::format("/buckets/bucket_%lu", s
tatic_cast<unsigned long>(1 << i)); |
| 1143 WebMemoryAllocatorDump* bucketDump = BlinkGCMemoryDumpProvider::instance
()->createMemoryAllocatorDumpForCurrentGC(dumpName); | 1145 MemoryAllocatorDump* bucketDump = BlinkGCMemoryDumpProvider::instance()-
>createMemoryAllocatorDumpForCurrentGC(dumpName); |
| 1144 bucketDump->AddScalar("free_count", "objects", entryCount); | 1146 bucketDump->AddScalar("free_count", "objects", entryCount); |
| 1145 bucketDump->AddScalar("free_size", "bytes", freeSize); | 1147 bucketDump->AddScalar("free_size", "bytes", freeSize); |
| 1146 didDumpBucketStats = true; | 1148 didDumpBucketStats = true; |
| 1147 } | 1149 } |
| 1148 return didDumpBucketStats; | 1150 return didDumpBucketStats; |
| 1149 } | 1151 } |
| 1150 | 1152 |
| 1151 #if ENABLE(GC_PROFILING) | 1153 #if ENABLE(GC_PROFILING) |
| 1152 void FreeList::getFreeSizeStats(PerBucketFreeListStats bucketStats[], size_t& to
talFreeSize) const | 1154 void FreeList::getFreeSizeStats(PerBucketFreeListStats bucketStats[], size_t& to
talFreeSize) const |
| 1153 { | 1155 { |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 // Force unpoison memory before memset. | 1484 // Force unpoison memory before memset. |
| 1483 ASAN_UNPOISON_MEMORY_REGION(payload(), payloadSize()); | 1485 ASAN_UNPOISON_MEMORY_REGION(payload(), payloadSize()); |
| 1484 #endif | 1486 #endif |
| 1485 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); | 1487 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); |
| 1486 BasePage::markOrphaned(); | 1488 BasePage::markOrphaned(); |
| 1487 } | 1489 } |
| 1488 | 1490 |
| 1489 void NormalPage::takeSnapshot(String dumpName, size_t pageIndex, ThreadState::GC
SnapshotInfo& info, size_t* outFreeSize, size_t* outFreeCount) | 1491 void NormalPage::takeSnapshot(String dumpName, size_t pageIndex, ThreadState::GC
SnapshotInfo& info, size_t* outFreeSize, size_t* outFreeCount) |
| 1490 { | 1492 { |
| 1491 dumpName.append(String::format("/pages/page_%lu", static_cast<unsigned long>
(pageIndex))); | 1493 dumpName.append(String::format("/pages/page_%lu", static_cast<unsigned long>
(pageIndex))); |
| 1492 WebMemoryAllocatorDump* pageDump = BlinkGCMemoryDumpProvider::instance()->cr
eateMemoryAllocatorDumpForCurrentGC(dumpName); | 1494 MemoryAllocatorDump* pageDump = BlinkGCMemoryDumpProvider::instance()->creat
eMemoryAllocatorDumpForCurrentGC(dumpName); |
| 1493 | 1495 |
| 1494 HeapObjectHeader* header = nullptr; | 1496 HeapObjectHeader* header = nullptr; |
| 1495 size_t liveCount = 0; | 1497 size_t liveCount = 0; |
| 1496 size_t deadCount = 0; | 1498 size_t deadCount = 0; |
| 1497 size_t freeCount = 0; | 1499 size_t freeCount = 0; |
| 1498 size_t liveSize = 0; | 1500 size_t liveSize = 0; |
| 1499 size_t deadSize = 0; | 1501 size_t deadSize = 0; |
| 1500 size_t freeSize = 0; | 1502 size_t freeSize = 0; |
| 1501 for (Address headerAddress = payload(); headerAddress < payloadEnd(); header
Address += header->size()) { | 1503 for (Address headerAddress = payload(); headerAddress < payloadEnd(); header
Address += header->size()) { |
| 1502 header = reinterpret_cast<HeapObjectHeader*>(headerAddress); | 1504 header = reinterpret_cast<HeapObjectHeader*>(headerAddress); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1701 { | 1703 { |
| 1702 // Zap the payload with a recognizable value to detect any incorrect | 1704 // Zap the payload with a recognizable value to detect any incorrect |
| 1703 // cross thread pointer usage. | 1705 // cross thread pointer usage. |
| 1704 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); | 1706 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); |
| 1705 BasePage::markOrphaned(); | 1707 BasePage::markOrphaned(); |
| 1706 } | 1708 } |
| 1707 | 1709 |
| 1708 void LargeObjectPage::takeSnapshot(String dumpName, size_t pageIndex, ThreadStat
e::GCSnapshotInfo& info, size_t* outFreeSize, size_t* outFreeCount) | 1710 void LargeObjectPage::takeSnapshot(String dumpName, size_t pageIndex, ThreadStat
e::GCSnapshotInfo& info, size_t* outFreeSize, size_t* outFreeCount) |
| 1709 { | 1711 { |
| 1710 dumpName.append(String::format("/pages/page_%lu", static_cast<unsigned long>
(pageIndex))); | 1712 dumpName.append(String::format("/pages/page_%lu", static_cast<unsigned long>
(pageIndex))); |
| 1711 WebMemoryAllocatorDump* pageDump = BlinkGCMemoryDumpProvider::instance()->cr
eateMemoryAllocatorDumpForCurrentGC(dumpName); | 1713 MemoryAllocatorDump* pageDump = BlinkGCMemoryDumpProvider::instance()->creat
eMemoryAllocatorDumpForCurrentGC(dumpName); |
| 1712 | 1714 |
| 1713 size_t liveSize = 0; | 1715 size_t liveSize = 0; |
| 1714 size_t deadSize = 0; | 1716 size_t deadSize = 0; |
| 1715 size_t liveCount = 0; | 1717 size_t liveCount = 0; |
| 1716 size_t deadCount = 0; | 1718 size_t deadCount = 0; |
| 1717 HeapObjectHeader* header = heapObjectHeader(); | 1719 HeapObjectHeader* header = heapObjectHeader(); |
| 1718 size_t gcInfoIndex = header->gcInfoIndex(); | 1720 size_t gcInfoIndex = header->gcInfoIndex(); |
| 1719 if (header->isMarked()) { | 1721 if (header->isMarked()) { |
| 1720 liveCount = 1; | 1722 liveCount = 1; |
| 1721 liveSize += header->payloadSize(); | 1723 liveSize += header->payloadSize(); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 | 1842 |
| 1841 m_hasEntries = true; | 1843 m_hasEntries = true; |
| 1842 size_t index = hash(address); | 1844 size_t index = hash(address); |
| 1843 ASSERT(!(index & 1)); | 1845 ASSERT(!(index & 1)); |
| 1844 Address cachePage = roundToBlinkPageStart(address); | 1846 Address cachePage = roundToBlinkPageStart(address); |
| 1845 m_entries[index + 1] = m_entries[index]; | 1847 m_entries[index + 1] = m_entries[index]; |
| 1846 m_entries[index] = cachePage; | 1848 m_entries[index] = cachePage; |
| 1847 } | 1849 } |
| 1848 | 1850 |
| 1849 } // namespace blink | 1851 } // namespace blink |
| OLD | NEW |