| 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() {
 | 
| 
 |