Index: third_party/WebKit/Source/platform/heap/HeapPage.cpp |
diff --git a/third_party/WebKit/Source/platform/heap/HeapPage.cpp b/third_party/WebKit/Source/platform/heap/HeapPage.cpp |
index 8dc5d2d0155f2c76ae5d63252c4a9b1b2475f910..89a65566dbe00d96cb98946653cab24b50164ada 100644 |
--- a/third_party/WebKit/Source/platform/heap/HeapPage.cpp |
+++ b/third_party/WebKit/Source/platform/heap/HeapPage.cpp |
@@ -35,7 +35,6 @@ |
#include "platform/ScriptForbiddenScope.h" |
#include "platform/heap/BlinkGCMemoryDumpProvider.h" |
#include "platform/heap/CallbackStack.h" |
-#include "platform/heap/HeapCompact.h" |
#include "platform/heap/MarkingVisitor.h" |
#include "platform/heap/PageMemory.h" |
#include "platform/heap/PagePool.h" |
@@ -202,17 +201,6 @@ |
m_firstUnsweptPage = nullptr; |
} |
ASSERT(!m_firstUnsweptPage); |
- |
- HeapCompact* heapCompactor = getThreadState()->heap().compaction(); |
- if (!heapCompactor->isCompactingArena(arenaIndex())) |
- return; |
- |
- BasePage* nextPage = m_firstPage; |
- while (nextPage) { |
- if (!nextPage->isLargeObjectPage()) |
- heapCompactor->addCompactingPage(nextPage); |
- nextPage = nextPage->next(); |
- } |
} |
void BaseArena::makeConsistentForMutator() { |
@@ -452,125 +440,6 @@ |
m_freeList.clear(); |
} |
-size_t NormalPageArena::arenaSize() { |
- size_t size = 0; |
- BasePage* page = m_firstPage; |
- while (page) { |
- size += page->size(); |
- page = page->next(); |
- } |
- LOG_HEAP_FREELIST_VERBOSE("Heap size: %zu (%d)\n", size, arenaIndex()); |
- return size; |
-} |
- |
-size_t NormalPageArena::freeListSize() { |
- size_t freeSize = m_freeList.freeListSize(); |
- LOG_HEAP_FREELIST_VERBOSE("Free size: %zu (%d)\n", freeSize, arenaIndex()); |
- return freeSize; |
-} |
- |
-void NormalPageArena::sweepAndCompact() { |
- ThreadHeap& heap = getThreadState()->heap(); |
- if (!heap.compaction()->isCompactingArena(arenaIndex())) |
- return; |
- |
- if (!m_firstUnsweptPage) { |
- heap.compaction()->finishedArenaCompaction(this, 0, 0); |
- return; |
- } |
- |
- // Compaction is performed in-place, sliding objects down over unused |
- // holes for a smaller heap page footprint and improved locality. |
- // A "compaction pointer" is consequently kept, pointing to the next |
- // available address to move objects down to. It will belong to one |
- // of the already sweep-compacted pages for this arena, but as compaction |
- // proceeds, it will not belong to the same page as the one being |
- // currently compacted. |
- // |
- // The compaction pointer is represented by the |
- // |(currentPage, allocationPoint)| pair, with |allocationPoint| |
- // being the offset into |currentPage|, making up the next |
- // available location. When the compaction of an arena page causes the |
- // compaction pointer to exhaust the current page it is compacting into, |
- // page compaction will advance the current page of the compaction |
- // pointer, as well as the allocation point. |
- // |
- // By construction, the page compaction can be performed without having |
- // to allocate any new pages. So to arrange for the page compaction's |
- // supply of freed, available pages, we chain them together after each |
- // has been "compacted from". The page compaction will then reuse those |
- // as needed, and once finished, the chained, available pages can be |
- // released back to the OS. |
- // |
- // To ease the passing of the compaction state when iterating over an |
- // arena's pages, package it up into a |CompactionContext|. |
- NormalPage::CompactionContext context; |
- context.m_compactedPages = &m_firstPage; |
- |
- while (m_firstUnsweptPage) { |
- BasePage* page = m_firstUnsweptPage; |
- if (page->isEmpty()) { |
- page->unlink(&m_firstUnsweptPage); |
- page->removeFromHeap(); |
- continue; |
- } |
- // Large objects do not belong to this arena. |
- DCHECK(!page->isLargeObjectPage()); |
- NormalPage* normalPage = static_cast<NormalPage*>(page); |
- normalPage->unlink(&m_firstUnsweptPage); |
- normalPage->markAsSwept(); |
- // If not the first page, add |normalPage| onto the available pages chain. |
- if (!context.m_currentPage) |
- context.m_currentPage = normalPage; |
- else |
- normalPage->link(&context.m_availablePages); |
- normalPage->sweepAndCompact(context); |
- } |
- |
- size_t freedSize = 0; |
- size_t freedPageCount = 0; |
- |
- DCHECK(context.m_currentPage); |
- // If the current page hasn't been allocated into, add it to the available |
- // list, for subsequent release below. |
- size_t allocationPoint = context.m_allocationPoint; |
- if (!allocationPoint) { |
- context.m_currentPage->link(&context.m_availablePages); |
- } else { |
- NormalPage* currentPage = context.m_currentPage; |
- currentPage->link(&m_firstPage); |
- if (allocationPoint != currentPage->payloadSize()) { |
- // Put the remainder of the page onto the free list. |
- freedSize = currentPage->payloadSize() - allocationPoint; |
- Address payload = currentPage->payload(); |
- SET_MEMORY_INACCESSIBLE(payload + allocationPoint, freedSize); |
- currentPage->arenaForNormalPage()->addToFreeList( |
- payload + allocationPoint, freedSize); |
- } |
- } |
- |
- // Return available pages to the free page pool, decommitting them from |
- // the pagefile. |
- BasePage* availablePages = context.m_availablePages; |
- while (availablePages) { |
- size_t pageSize = availablePages->size(); |
-#if DEBUG_HEAP_COMPACTION |
- if (!freedPageCount) |
- LOG_HEAP_COMPACTION("Releasing:"); |
- LOG_HEAP_COMPACTION(" [%p, %p]", availablePages, availablePages + pageSize); |
-#endif |
- freedSize += pageSize; |
- freedPageCount++; |
- BasePage* nextPage; |
- availablePages->unlink(&nextPage); |
- availablePages->removeFromHeap(); |
- availablePages = static_cast<NormalPage*>(nextPage); |
- } |
- if (freedPageCount) |
- LOG_HEAP_COMPACTION("\n"); |
- heap.compaction()->finishedArenaCompaction(this, freedPageCount, freedSize); |
-} |
- |
#if ENABLE(ASSERT) |
bool NormalPageArena::isConsistentForGC() { |
// A thread heap is consistent for sweeping if none of the pages to be swept |
@@ -645,6 +514,7 @@ |
} |
} |
} |
+ |
NormalPage* page = |
new (pageMemory->writableStart()) NormalPage(pageMemory, this); |
page->link(&m_firstPage); |
@@ -1207,37 +1077,6 @@ |
} |
#endif |
-size_t FreeList::freeListSize() const { |
- size_t freeSize = 0; |
- for (unsigned i = 0; i < blinkPageSizeLog2; ++i) { |
- FreeListEntry* entry = m_freeLists[i]; |
- while (entry) { |
- freeSize += entry->size(); |
- entry = entry->next(); |
- } |
- } |
-#if DEBUG_HEAP_FREELIST |
- if (freeSize) { |
- LOG_HEAP_FREELIST_VERBOSE("FreeList(%p): %zu\n", this, freeSize); |
- for (unsigned i = 0; i < blinkPageSizeLog2; ++i) { |
- FreeListEntry* entry = m_freeLists[i]; |
- size_t bucket = 0; |
- size_t count = 0; |
- while (entry) { |
- bucket += entry->size(); |
- count++; |
- entry = entry->next(); |
- } |
- if (bucket) { |
- LOG_HEAP_FREELIST_VERBOSE("[%d, %d]: %zu (%zu)\n", 0x1 << i, |
- 0x1 << (i + 1), bucket, count); |
- } |
- } |
- } |
-#endif |
- return freeSize; |
-} |
- |
void FreeList::clear() { |
m_biggestFreeListIndex = 0; |
for (size_t i = 0; i < blinkPageSizeLog2; ++i) |
@@ -1405,114 +1244,6 @@ |
if (markedObjectSize) |
pageArena->getThreadState()->increaseMarkedObjectSize(markedObjectSize); |
-} |
- |
-void NormalPage::sweepAndCompact(CompactionContext& context) { |
- NormalPage*& currentPage = context.m_currentPage; |
- size_t& allocationPoint = context.m_allocationPoint; |
- |
- size_t markedObjectSize = 0; |
- NormalPageArena* pageArena = arenaForNormalPage(); |
-#if defined(ADDRESS_SANITIZER) |
- bool isVectorArena = ThreadState::isVectorArenaIndex(pageArena->arenaIndex()); |
-#endif |
- HeapCompact* compact = pageArena->getThreadState()->heap().compaction(); |
- for (Address headerAddress = payload(); headerAddress < payloadEnd();) { |
- HeapObjectHeader* header = |
- reinterpret_cast<HeapObjectHeader*>(headerAddress); |
- size_t size = header->size(); |
- DCHECK(size > 0 && size < blinkPagePayloadSize()); |
- |
- if (header->isPromptlyFreed()) |
- pageArena->decreasePromptlyFreedSize(size); |
- if (header->isFree()) { |
- // Unpoison the freelist entry so that we |
- // can compact into it as wanted. |
- ASAN_UNPOISON_MEMORY_REGION(headerAddress, size); |
- headerAddress += size; |
- continue; |
- } |
- // This is a fast version of header->payloadSize(). |
- size_t payloadSize = size - sizeof(HeapObjectHeader); |
- Address payload = header->payload(); |
- if (!header->isMarked()) { |
- // For ASan, unpoison the object before calling the finalizer. The |
- // finalized object will be zero-filled and poison'ed afterwards. |
- // Given all other unmarked objects are poisoned, ASan will detect |
- // an error if the finalizer touches any other on-heap object that |
- // die at the same GC cycle. |
- ASAN_UNPOISON_MEMORY_REGION(headerAddress, size); |
- header->finalize(payload, payloadSize); |
- |
-// As compaction is under way, leave the freed memory accessible |
-// while compacting the rest of the page. We just zap the payload |
-// to catch out other finalizers trying to access it. |
-#if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \ |
- defined(MEMORY_SANITIZER) |
- FreeList::zapFreedMemory(payload, payloadSize); |
-#endif |
- headerAddress += size; |
- continue; |
- } |
- header->unmark(); |
- // Allocate and copy over the live object. |
- Address compactFrontier = currentPage->payload() + allocationPoint; |
- if (compactFrontier + size > currentPage->payloadEnd()) { |
- // Can't fit on current allocation page; add remaining onto the |
- // freelist and advance to next available page. |
- // |
- // TODO(sof): be more clever & compact later objects into |
- // |currentPage|'s unused slop. |
- currentPage->link(context.m_compactedPages); |
- size_t freeSize = currentPage->payloadSize() - allocationPoint; |
- if (freeSize) { |
- SET_MEMORY_INACCESSIBLE(compactFrontier, freeSize); |
- currentPage->arenaForNormalPage()->addToFreeList(compactFrontier, |
- freeSize); |
- } |
- |
- BasePage* nextAvailablePage; |
- context.m_availablePages->unlink(&nextAvailablePage); |
- currentPage = reinterpret_cast<NormalPage*>(context.m_availablePages); |
- context.m_availablePages = nextAvailablePage; |
- allocationPoint = 0; |
- compactFrontier = currentPage->payload(); |
- } |
- if (LIKELY(compactFrontier != headerAddress)) { |
-#if defined(ADDRESS_SANITIZER) |
- // Unpoison the header + if it is a vector backing |
- // store object, let go of the container annotations. |
- // Do that by unpoisoning the payload entirely. |
- ASAN_UNPOISON_MEMORY_REGION(header, sizeof(HeapObjectHeader)); |
- if (isVectorArena) |
- ASAN_UNPOISON_MEMORY_REGION(payload, payloadSize); |
-#endif |
- // Use a non-overlapping copy, if possible. |
- if (currentPage == this) |
- memmove(compactFrontier, headerAddress, size); |
- else |
- memcpy(compactFrontier, headerAddress, size); |
- compact->relocate(payload, compactFrontier + sizeof(HeapObjectHeader)); |
- } |
- headerAddress += size; |
- markedObjectSize += size; |
- allocationPoint += size; |
- DCHECK(allocationPoint <= currentPage->payloadSize()); |
- } |
- if (markedObjectSize) |
- pageArena->getThreadState()->increaseMarkedObjectSize(markedObjectSize); |
- |
-#if ENABLE(ASSERT) || defined(LEAK_SANITIZER) || defined(ADDRESS_SANITIZER) || \ |
- defined(MEMORY_SANITIZER) |
- // Zap the page, which is now available and will either be compacted into |
- // or freed. |
- if (currentPage != this) { |
- FreeList::zapFreedMemory(payload(), payloadSize()); |
- } else { |
- FreeList::zapFreedMemory(payload() + allocationPoint, |
- payloadSize() - allocationPoint); |
- } |
-#endif |
} |
void NormalPage::makeConsistentForGC() { |