1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
#include "config.h"
#include "MarkedAllocator.h"
#include "GCActivityCallback.h"
#include "Heap.h"
#include "IncrementalSweeper.h"
#include "VM.h"
#include <wtf/CurrentTime.h>
namespace JSC {
bool MarkedAllocator::isPagedOut(double deadline)
{
unsigned itersSinceLastTimeCheck = 0;
MarkedBlock* block = m_blockList.head();
while (block) {
block = block->next();
++itersSinceLastTimeCheck;
if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) {
double currentTime = WTF::monotonicallyIncreasingTime();
if (currentTime > deadline)
return true;
itersSinceLastTimeCheck = 0;
}
}
return false;
}
inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
{
if (!m_freeList.head) {
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) {
m_currentBlock = 0;
return 0;
}
}
MarkedBlock::FreeCell* head = m_freeList.head;
m_freeList.head = head->next;
ASSERT(head);
return head;
}
inline void* MarkedAllocator::tryAllocate(size_t bytes)
{
ASSERT(!m_heap->isBusy());
m_heap->m_operationInProgress = Allocation;
void* result = tryAllocateHelper(bytes);
m_heap->m_operationInProgress = NoOperation;
return result;
}
void* MarkedAllocator::allocateSlowCase(size_t bytes)
{
ASSERT(m_heap->vm()->apiLock().currentThreadIsHoldingLock());
#if COLLECT_ON_EVERY_ALLOCATION
m_heap->collectAllGarbage();
ASSERT(m_heap->m_operationInProgress == NoOperation);
#endif
ASSERT(!m_freeList.head);
m_heap->didAllocate(m_freeList.bytes);
void* result = tryAllocate(bytes);
if (LIKELY(result != 0))
return result;
if (m_heap->shouldCollect()) {
m_heap->collect(Heap::DoNotSweep);
result = tryAllocate(bytes);
if (result)
return result;
}
ASSERT(!m_heap->shouldCollect());
MarkedBlock* block = allocateBlock(bytes);
ASSERT(block);
addBlock(block);
result = tryAllocate(bytes);
ASSERT(result);
return result;
}
MarkedBlock* MarkedAllocator::allocateBlock(size_t bytes)
{
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_currentBlock);
ASSERT(!m_freeList.head);
m_blockList.append(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 = m_currentBlock->next();
m_freeList = MarkedBlock::FreeList();
}
if (m_blocksToSweep == block)
m_blocksToSweep = m_blocksToSweep->next();
m_blockList.remove(block);
}
} // namespace JSC
|