| 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 12 matching lines...) Expand all Loading... |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 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 "platform/heap/HeapPage.h" | 31 #include "platform/heap/HeapPage.h" |
| 32 | 32 |
| 33 #include "base/trace_event/process_memory_dump.h" |
| 33 #include "platform/ScriptForbiddenScope.h" | 34 #include "platform/ScriptForbiddenScope.h" |
| 34 #include "platform/TraceEvent.h" | 35 #include "platform/TraceEvent.h" |
| 35 #include "platform/heap/BlinkGCMemoryDumpProvider.h" | 36 #include "platform/heap/BlinkGCMemoryDumpProvider.h" |
| 36 #include "platform/heap/CallbackStack.h" | 37 #include "platform/heap/CallbackStack.h" |
| 37 #include "platform/heap/Heap.h" | 38 #include "platform/heap/Heap.h" |
| 38 #include "platform/heap/MarkingVisitor.h" | 39 #include "platform/heap/MarkingVisitor.h" |
| 39 #include "platform/heap/PageMemory.h" | 40 #include "platform/heap/PageMemory.h" |
| 40 #include "platform/heap/PagePool.h" | 41 #include "platform/heap/PagePool.h" |
| 41 #include "platform/heap/SafePoint.h" | 42 #include "platform/heap/SafePoint.h" |
| 42 #include "platform/heap/ThreadState.h" | 43 #include "platform/heap/ThreadState.h" |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 for (BasePage* page = m_firstPage; page; page = page->next()) { | 129 for (BasePage* page = m_firstPage; page; page = page->next()) { |
| 129 getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size()
); | 130 getThreadState()->heap().heapStats().decreaseAllocatedSpace(page->size()
); |
| 130 getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(arenaInd
ex(), page); | 131 getThreadState()->heap().getOrphanedPagePool()->addOrphanedPage(arenaInd
ex(), page); |
| 131 } | 132 } |
| 132 m_firstPage = nullptr; | 133 m_firstPage = nullptr; |
| 133 } | 134 } |
| 134 | 135 |
| 135 void BaseArena::takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshot
Info& info) | 136 void BaseArena::takeSnapshot(const String& dumpBaseName, ThreadState::GCSnapshot
Info& info) |
| 136 { | 137 { |
| 137 // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName" | 138 // |dumpBaseName| at this point is "blink_gc/thread_X/heaps/HeapName" |
| 138 WebMemoryAllocatorDump* allocatorDump = BlinkGCMemoryDumpProvider::instance(
)->createMemoryAllocatorDumpForCurrentGC(dumpBaseName); | 139 base::trace_event::MemoryAllocatorDump* allocatorDump = BlinkGCMemoryDumpPro
vider::instance()->createMemoryAllocatorDumpForCurrentGC(dumpBaseName); |
| 139 size_t pageCount = 0; | 140 size_t pageCount = 0; |
| 140 BasePage::HeapSnapshotInfo heapInfo; | 141 BasePage::HeapSnapshotInfo heapInfo; |
| 141 for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { | 142 for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { |
| 142 String dumpName = dumpBaseName + String::format("/pages/page_%lu", stati
c_cast<unsigned long>(pageCount++)); | 143 String dumpName = dumpBaseName + String::format("/pages/page_%lu", stati
c_cast<unsigned long>(pageCount++)); |
| 143 WebMemoryAllocatorDump* pageDump = BlinkGCMemoryDumpProvider::instance()
->createMemoryAllocatorDumpForCurrentGC(dumpName); | 144 base::trace_event::MemoryAllocatorDump* pageDump = BlinkGCMemoryDumpProv
ider::instance()->createMemoryAllocatorDumpForCurrentGC(dumpName); |
| 144 | 145 |
| 145 page->takeSnapshot(pageDump, info, heapInfo); | 146 page->takeSnapshot(pageDump, info, heapInfo); |
| 146 } | 147 } |
| 147 allocatorDump->addScalar("blink_page_count", "objects", pageCount); | 148 allocatorDump->AddScalar("blink_page_count", "objects", pageCount); |
| 148 | 149 |
| 149 // When taking a full dump (w/ freelist), both the /buckets and /pages | 150 // When taking a full dump (w/ freelist), both the /buckets and /pages |
| 150 // report their free size but they are not meant to be added together. | 151 // report their free size but they are not meant to be added together. |
| 151 // Therefore, here we override the free_size of the parent heap to be | 152 // Therefore, here we override the free_size of the parent heap to be |
| 152 // equal to the free_size of the sum of its heap pages. | 153 // equal to the free_size of the sum of its heap pages. |
| 153 allocatorDump->addScalar("free_size", "bytes", heapInfo.freeSize); | 154 allocatorDump->AddScalar("free_size", "bytes", heapInfo.freeSize); |
| 154 allocatorDump->addScalar("free_count", "objects", heapInfo.freeCount); | 155 allocatorDump->AddScalar("free_count", "objects", heapInfo.freeCount); |
| 155 } | 156 } |
| 156 | 157 |
| 157 #if ENABLE(ASSERT) | 158 #if ENABLE(ASSERT) |
| 158 BasePage* BaseArena::findPageFromAddress(Address address) | 159 BasePage* BaseArena::findPageFromAddress(Address address) |
| 159 { | 160 { |
| 160 for (BasePage* page = m_firstPage; page; page = page->next()) { | 161 for (BasePage* page = m_firstPage; page; page = page->next()) { |
| 161 if (page->contains(address)) | 162 if (page->contains(address)) |
| 162 return page; | 163 return page; |
| 163 } | 164 } |
| 164 for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { | 165 for (BasePage* page = m_firstUnsweptPage; page; page = page->next()) { |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 382 if (page->contains(address)) | 383 if (page->contains(address)) |
| 383 return true; | 384 return true; |
| 384 } | 385 } |
| 385 return false; | 386 return false; |
| 386 } | 387 } |
| 387 #endif | 388 #endif |
| 388 | 389 |
| 389 void NormalPageArena::takeFreelistSnapshot(const String& dumpName) | 390 void NormalPageArena::takeFreelistSnapshot(const String& dumpName) |
| 390 { | 391 { |
| 391 if (m_freeList.takeSnapshot(dumpName)) { | 392 if (m_freeList.takeSnapshot(dumpName)) { |
| 392 WebMemoryAllocatorDump* bucketsDump = BlinkGCMemoryDumpProvider::instanc
e()->createMemoryAllocatorDumpForCurrentGC(dumpName + "/buckets"); | 393 base::trace_event::MemoryAllocatorDump* bucketsDump = BlinkGCMemoryDumpP
rovider::instance()->createMemoryAllocatorDumpForCurrentGC(dumpName + "/buckets"
); |
| 393 WebMemoryAllocatorDump* pagesDump = BlinkGCMemoryDumpProvider::instance(
)->createMemoryAllocatorDumpForCurrentGC(dumpName + "/pages"); | 394 base::trace_event::MemoryAllocatorDump* pagesDump = BlinkGCMemoryDumpPro
vider::instance()->createMemoryAllocatorDumpForCurrentGC(dumpName + "/pages"); |
| 394 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->addOw
nershipEdge(pagesDump->guid(), bucketsDump->guid()); | 395 BlinkGCMemoryDumpProvider::instance()->currentProcessMemoryDump()->AddOw
nershipEdge(pagesDump->guid(), bucketsDump->guid()); |
| 395 } | 396 } |
| 396 } | 397 } |
| 397 | 398 |
| 398 void NormalPageArena::allocatePage() | 399 void NormalPageArena::allocatePage() |
| 399 { | 400 { |
| 400 getThreadState()->shouldFlushHeapDoesNotContainCache(); | 401 getThreadState()->shouldFlushHeapDoesNotContainCache(); |
| 401 PageMemory* pageMemory = getThreadState()->heap().getFreePagePool()->takeFre
ePage(arenaIndex()); | 402 PageMemory* pageMemory = getThreadState()->heap().getFreePagePool()->takeFre
ePage(arenaIndex()); |
| 402 | 403 |
| 403 if (!pageMemory) { | 404 if (!pageMemory) { |
| 404 // Allocate a memory region for blinkPagesPerRegion pages that | 405 // Allocate a memory region for blinkPagesPerRegion pages that |
| (...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1012 bool didDumpBucketStats = false; | 1013 bool didDumpBucketStats = false; |
| 1013 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { | 1014 for (size_t i = 0; i < blinkPageSizeLog2; ++i) { |
| 1014 size_t entryCount = 0; | 1015 size_t entryCount = 0; |
| 1015 size_t freeSize = 0; | 1016 size_t freeSize = 0; |
| 1016 for (FreeListEntry* entry = m_freeLists[i]; entry; entry = entry->next()
) { | 1017 for (FreeListEntry* entry = m_freeLists[i]; entry; entry = entry->next()
) { |
| 1017 ++entryCount; | 1018 ++entryCount; |
| 1018 freeSize += entry->size(); | 1019 freeSize += entry->size(); |
| 1019 } | 1020 } |
| 1020 | 1021 |
| 1021 String dumpName = dumpBaseName + String::format("/buckets/bucket_%lu", s
tatic_cast<unsigned long>(1 << i)); | 1022 String dumpName = dumpBaseName + String::format("/buckets/bucket_%lu", s
tatic_cast<unsigned long>(1 << i)); |
| 1022 WebMemoryAllocatorDump* bucketDump = BlinkGCMemoryDumpProvider::instance
()->createMemoryAllocatorDumpForCurrentGC(dumpName); | 1023 base::trace_event::MemoryAllocatorDump* bucketDump = BlinkGCMemoryDumpPr
ovider::instance()->createMemoryAllocatorDumpForCurrentGC(dumpName); |
| 1023 bucketDump->addScalar("free_count", "objects", entryCount); | 1024 bucketDump->AddScalar("free_count", "objects", entryCount); |
| 1024 bucketDump->addScalar("free_size", "bytes", freeSize); | 1025 bucketDump->AddScalar("free_size", "bytes", freeSize); |
| 1025 didDumpBucketStats = true; | 1026 didDumpBucketStats = true; |
| 1026 } | 1027 } |
| 1027 return didDumpBucketStats; | 1028 return didDumpBucketStats; |
| 1028 } | 1029 } |
| 1029 | 1030 |
| 1030 BasePage::BasePage(PageMemory* storage, BaseArena* arena) | 1031 BasePage::BasePage(PageMemory* storage, BaseArena* arena) |
| 1031 : m_storage(storage) | 1032 : m_storage(storage) |
| 1032 , m_arena(arena) | 1033 , m_arena(arena) |
| 1033 , m_next(nullptr) | 1034 , m_next(nullptr) |
| 1034 , m_terminating(false) | 1035 , m_terminating(false) |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1353 // cross thread pointer usage. | 1354 // cross thread pointer usage. |
| 1354 #if defined(ADDRESS_SANITIZER) | 1355 #if defined(ADDRESS_SANITIZER) |
| 1355 // This needs to zap poisoned memory as well. | 1356 // This needs to zap poisoned memory as well. |
| 1356 // Force unpoison memory before memset. | 1357 // Force unpoison memory before memset. |
| 1357 ASAN_UNPOISON_MEMORY_REGION(payload(), payloadSize()); | 1358 ASAN_UNPOISON_MEMORY_REGION(payload(), payloadSize()); |
| 1358 #endif | 1359 #endif |
| 1359 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); | 1360 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); |
| 1360 BasePage::markOrphaned(); | 1361 BasePage::markOrphaned(); |
| 1361 } | 1362 } |
| 1362 | 1363 |
| 1363 void NormalPage::takeSnapshot(WebMemoryAllocatorDump* pageDump, ThreadState::GCS
napshotInfo& info, HeapSnapshotInfo& heapInfo) | 1364 void NormalPage::takeSnapshot(base::trace_event::MemoryAllocatorDump* pageDump,
ThreadState::GCSnapshotInfo& info, HeapSnapshotInfo& heapInfo) |
| 1364 { | 1365 { |
| 1365 HeapObjectHeader* header = nullptr; | 1366 HeapObjectHeader* header = nullptr; |
| 1366 size_t liveCount = 0; | 1367 size_t liveCount = 0; |
| 1367 size_t deadCount = 0; | 1368 size_t deadCount = 0; |
| 1368 size_t freeCount = 0; | 1369 size_t freeCount = 0; |
| 1369 size_t liveSize = 0; | 1370 size_t liveSize = 0; |
| 1370 size_t deadSize = 0; | 1371 size_t deadSize = 0; |
| 1371 size_t freeSize = 0; | 1372 size_t freeSize = 0; |
| 1372 for (Address headerAddress = payload(); headerAddress < payloadEnd(); header
Address += header->size()) { | 1373 for (Address headerAddress = payload(); headerAddress < payloadEnd(); header
Address += header->size()) { |
| 1373 header = reinterpret_cast<HeapObjectHeader*>(headerAddress); | 1374 header = reinterpret_cast<HeapObjectHeader*>(headerAddress); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1384 } else { | 1385 } else { |
| 1385 deadCount++; | 1386 deadCount++; |
| 1386 deadSize += header->size(); | 1387 deadSize += header->size(); |
| 1387 | 1388 |
| 1388 size_t gcInfoIndex = header->gcInfoIndex(); | 1389 size_t gcInfoIndex = header->gcInfoIndex(); |
| 1389 info.deadCount[gcInfoIndex]++; | 1390 info.deadCount[gcInfoIndex]++; |
| 1390 info.deadSize[gcInfoIndex] += header->size(); | 1391 info.deadSize[gcInfoIndex] += header->size(); |
| 1391 } | 1392 } |
| 1392 } | 1393 } |
| 1393 | 1394 |
| 1394 pageDump->addScalar("live_count", "objects", liveCount); | 1395 pageDump->AddScalar("live_count", "objects", liveCount); |
| 1395 pageDump->addScalar("dead_count", "objects", deadCount); | 1396 pageDump->AddScalar("dead_count", "objects", deadCount); |
| 1396 pageDump->addScalar("free_count", "objects", freeCount); | 1397 pageDump->AddScalar("free_count", "objects", freeCount); |
| 1397 pageDump->addScalar("live_size", "bytes", liveSize); | 1398 pageDump->AddScalar("live_size", "bytes", liveSize); |
| 1398 pageDump->addScalar("dead_size", "bytes", deadSize); | 1399 pageDump->AddScalar("dead_size", "bytes", deadSize); |
| 1399 pageDump->addScalar("free_size", "bytes", freeSize); | 1400 pageDump->AddScalar("free_size", "bytes", freeSize); |
| 1400 heapInfo.freeSize += freeSize; | 1401 heapInfo.freeSize += freeSize; |
| 1401 heapInfo.freeCount += freeCount; | 1402 heapInfo.freeCount += freeCount; |
| 1402 } | 1403 } |
| 1403 | 1404 |
| 1404 #if ENABLE(ASSERT) | 1405 #if ENABLE(ASSERT) |
| 1405 bool NormalPage::contains(Address addr) | 1406 bool NormalPage::contains(Address addr) |
| 1406 { | 1407 { |
| 1407 Address blinkPageStart = roundToBlinkPageStart(getAddress()); | 1408 Address blinkPageStart = roundToBlinkPageStart(getAddress()); |
| 1408 ASSERT(blinkPageStart == getAddress() - blinkGuardPageSize); // Page is at a
ligned address plus guard page size. | 1409 ASSERT(blinkPageStart == getAddress() - blinkGuardPageSize); // Page is at a
ligned address plus guard page size. |
| 1409 return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize; | 1410 return blinkPageStart <= addr && addr < blinkPageStart + blinkPageSize; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1482 } | 1483 } |
| 1483 | 1484 |
| 1484 void LargeObjectPage::markOrphaned() | 1485 void LargeObjectPage::markOrphaned() |
| 1485 { | 1486 { |
| 1486 // Zap the payload with a recognizable value to detect any incorrect | 1487 // Zap the payload with a recognizable value to detect any incorrect |
| 1487 // cross thread pointer usage. | 1488 // cross thread pointer usage. |
| 1488 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); | 1489 OrphanedPagePool::asanDisabledMemset(payload(), OrphanedPagePool::orphanedZa
pValue, payloadSize()); |
| 1489 BasePage::markOrphaned(); | 1490 BasePage::markOrphaned(); |
| 1490 } | 1491 } |
| 1491 | 1492 |
| 1492 void LargeObjectPage::takeSnapshot(WebMemoryAllocatorDump* pageDump, ThreadState
::GCSnapshotInfo& info, HeapSnapshotInfo&) | 1493 void LargeObjectPage::takeSnapshot(base::trace_event::MemoryAllocatorDump* pageD
ump, ThreadState::GCSnapshotInfo& info, HeapSnapshotInfo&) |
| 1493 { | 1494 { |
| 1494 size_t liveSize = 0; | 1495 size_t liveSize = 0; |
| 1495 size_t deadSize = 0; | 1496 size_t deadSize = 0; |
| 1496 size_t liveCount = 0; | 1497 size_t liveCount = 0; |
| 1497 size_t deadCount = 0; | 1498 size_t deadCount = 0; |
| 1498 HeapObjectHeader* header = heapObjectHeader(); | 1499 HeapObjectHeader* header = heapObjectHeader(); |
| 1499 size_t gcInfoIndex = header->gcInfoIndex(); | 1500 size_t gcInfoIndex = header->gcInfoIndex(); |
| 1500 size_t payloadSize = header->payloadSize(); | 1501 size_t payloadSize = header->payloadSize(); |
| 1501 if (header->isMarked()) { | 1502 if (header->isMarked()) { |
| 1502 liveCount = 1; | 1503 liveCount = 1; |
| 1503 liveSize += payloadSize; | 1504 liveSize += payloadSize; |
| 1504 info.liveCount[gcInfoIndex]++; | 1505 info.liveCount[gcInfoIndex]++; |
| 1505 info.liveSize[gcInfoIndex] += payloadSize; | 1506 info.liveSize[gcInfoIndex] += payloadSize; |
| 1506 } else { | 1507 } else { |
| 1507 deadCount = 1; | 1508 deadCount = 1; |
| 1508 deadSize += payloadSize; | 1509 deadSize += payloadSize; |
| 1509 info.deadCount[gcInfoIndex]++; | 1510 info.deadCount[gcInfoIndex]++; |
| 1510 info.deadSize[gcInfoIndex] += payloadSize; | 1511 info.deadSize[gcInfoIndex] += payloadSize; |
| 1511 } | 1512 } |
| 1512 | 1513 |
| 1513 pageDump->addScalar("live_count", "objects", liveCount); | 1514 pageDump->AddScalar("live_count", "objects", liveCount); |
| 1514 pageDump->addScalar("dead_count", "objects", deadCount); | 1515 pageDump->AddScalar("dead_count", "objects", deadCount); |
| 1515 pageDump->addScalar("live_size", "bytes", liveSize); | 1516 pageDump->AddScalar("live_size", "bytes", liveSize); |
| 1516 pageDump->addScalar("dead_size", "bytes", deadSize); | 1517 pageDump->AddScalar("dead_size", "bytes", deadSize); |
| 1517 } | 1518 } |
| 1518 | 1519 |
| 1519 #if ENABLE(ASSERT) | 1520 #if ENABLE(ASSERT) |
| 1520 bool LargeObjectPage::contains(Address object) | 1521 bool LargeObjectPage::contains(Address object) |
| 1521 { | 1522 { |
| 1522 return roundToBlinkPageStart(getAddress()) <= object && object < roundToBlin
kPageEnd(getAddress() + size()); | 1523 return roundToBlinkPageStart(getAddress()) <= object && object < roundToBlin
kPageEnd(getAddress() + size()); |
| 1523 } | 1524 } |
| 1524 #endif | 1525 #endif |
| 1525 | 1526 |
| 1526 void HeapDoesNotContainCache::flush() | 1527 void HeapDoesNotContainCache::flush() |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1561 | 1562 |
| 1562 m_hasEntries = true; | 1563 m_hasEntries = true; |
| 1563 size_t index = hash(address); | 1564 size_t index = hash(address); |
| 1564 ASSERT(!(index & 1)); | 1565 ASSERT(!(index & 1)); |
| 1565 Address cachePage = roundToBlinkPageStart(address); | 1566 Address cachePage = roundToBlinkPageStart(address); |
| 1566 m_entries[index + 1] = m_entries[index]; | 1567 m_entries[index + 1] = m_entries[index]; |
| 1567 m_entries[index] = cachePage; | 1568 m_entries[index] = cachePage; |
| 1568 } | 1569 } |
| 1569 | 1570 |
| 1570 } // namespace blink | 1571 } // namespace blink |
| OLD | NEW |