#include "GCActivityCallback.h"
#include "Heap.h"
-#include "JSGlobalData.h"
+#include "IncrementalSweeper.h"
+#include "VM.h"
#include <wtf/CurrentTime.h>
namespace JSC {
bool MarkedAllocator::isPagedOut(double deadline)
{
unsigned itersSinceLastTimeCheck = 0;
- HeapBlock* block = m_blockList.head();
+ MarkedBlock* block = m_blockList.head();
while (block) {
block = block->next();
++itersSinceLastTimeCheck;
return false;
}
-inline void* MarkedAllocator::tryAllocateHelper()
+inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
{
if (!m_freeList.head) {
- for (MarkedBlock*& block = m_currentBlock; block; block = static_cast<MarkedBlock*>(block->next())) {
- m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
- if (m_freeList.head)
- break;
- block->didConsumeFreeList();
+ for (MarkedBlock*& block = m_blocksToSweep; block; block = block->next()) {
+ MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
+ if (!freeList.head) {
+ block->didConsumeFreeList();
+ continue;
+ }
+
+ if (bytes > block->cellSize()) {
+ block->canonicalizeCellLivenessData(freeList);
+ continue;
+ }
+
+ m_currentBlock = block;
+ m_freeList = freeList;
+ break;
}
- if (!m_freeList.head)
+ if (!m_freeList.head) {
+ m_currentBlock = 0;
return 0;
+ }
}
MarkedBlock::FreeCell* head = m_freeList.head;
return head;
}
-inline void* MarkedAllocator::tryAllocate()
+inline void* MarkedAllocator::tryAllocate(size_t bytes)
{
ASSERT(!m_heap->isBusy());
m_heap->m_operationInProgress = Allocation;
- void* result = tryAllocateHelper();
+ void* result = tryAllocateHelper(bytes);
m_heap->m_operationInProgress = NoOperation;
return result;
}
-void* MarkedAllocator::allocateSlowCase()
+void* MarkedAllocator::allocateSlowCase(size_t bytes)
{
- ASSERT(m_heap->globalData()->apiLock().currentThreadIsHoldingLock());
+ ASSERT(m_heap->vm()->apiLock().currentThreadIsHoldingLock());
#if COLLECT_ON_EVERY_ALLOCATION
m_heap->collectAllGarbage();
ASSERT(m_heap->m_operationInProgress == NoOperation);
ASSERT(!m_freeList.head);
m_heap->didAllocate(m_freeList.bytes);
- void* result = tryAllocate();
+ void* result = tryAllocate(bytes);
if (LIKELY(result != 0))
return result;
if (m_heap->shouldCollect()) {
m_heap->collect(Heap::DoNotSweep);
- result = tryAllocate();
+ result = tryAllocate(bytes);
if (result)
return result;
}
ASSERT(!m_heap->shouldCollect());
- MarkedBlock* block = allocateBlock();
+ MarkedBlock* block = allocateBlock(bytes);
ASSERT(block);
addBlock(block);
- result = tryAllocate();
+ result = tryAllocate(bytes);
ASSERT(result);
return result;
}
-
-MarkedBlock* MarkedAllocator::allocateBlock()
+
+MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes)
{
- MarkedBlock* block = static_cast<MarkedBlock*>(m_heap->blockAllocator().allocate());
- if (block)
- block = MarkedBlock::recycle(block, m_heap, m_cellSize, m_cellsNeedDestruction);
- else
- block = MarkedBlock::create(m_heap, m_cellSize, m_cellsNeedDestruction);
-
- m_markedSpace->didAddBlock(block);
-
- return block;
+ size_t minBlockSize = MarkedBlock::blockSize;
+ size_t minAllocationSize = WTF::roundUpToMultipleOf(WTF::pageSize(), sizeof(MarkedBlock) + bytes);
+ size_t blockSize = std::max(minBlockSize, minAllocationSize);
+
+ size_t cellSize = m_cellSize ? m_cellSize : WTF::roundUpToMultipleOf<MarkedBlock::atomSize>(bytes);
+
+ if (blockSize == MarkedBlock::blockSize)
+ return MarkedBlock::create(m_heap->blockAllocator().allocate<MarkedBlock>(), this, cellSize, m_destructorType);
+ return MarkedBlock::create(m_heap->blockAllocator().allocateCustomSize(blockSize, MarkedBlock::blockSize), this, cellSize, m_destructorType);
}
void MarkedAllocator::addBlock(MarkedBlock* block)
ASSERT(!m_freeList.head);
m_blockList.append(block);
- m_currentBlock = block;
+ m_blocksToSweep = m_currentBlock = block;
m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
+ m_markedSpace->didAddBlock(block);
}
void MarkedAllocator::removeBlock(MarkedBlock* block)
{
- if (m_currentBlock == block)
- m_currentBlock = 0;
+ if (m_currentBlock == block) {
+ m_currentBlock = m_currentBlock->next();
+ m_freeList = MarkedBlock::FreeList();
+ }
+ if (m_blocksToSweep == block)
+ m_blocksToSweep = m_blocksToSweep->next();
m_blockList.remove(block);
}