Esempio n. 1
0
inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
{
    // We need a while loop to check the free list because the DelayedReleaseScope 
    // could cause arbitrary code to execute and exhaust the free list that we 
    // thought had elements in it.
    while (!m_freeList.head) {
        DelayedReleaseScope delayedReleaseScope(*m_markedSpace);
        if (m_currentBlock) {
            ASSERT(m_currentBlock == m_nextBlockToSweep);
            m_currentBlock->didConsumeFreeList();
            m_nextBlockToSweep = m_currentBlock->next();
        }

        MarkedBlock* next;
        for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) {
            next = block->next();

            MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
            
            if (!freeList.head) {
                block->didConsumeEmptyFreeList();
                m_blockList.remove(block);
                m_blockList.push(block);
                if (!m_lastFullBlock)
                    m_lastFullBlock = block;
                continue;
            }

            if (bytes > block->cellSize()) {
                block->stopAllocating(freeList);
                continue;
            }

            m_currentBlock = block;
            m_freeList = freeList;
            break;
        }
        
        if (!m_freeList.head) {
            m_currentBlock = 0;
            return 0;
        }
    }

    ASSERT(m_freeList.head);
    void* head = tryPopFreeList(bytes);
    ASSERT(head);
    m_markedSpace->didAllocateInBlock(m_currentBlock);
    return head;
}
Esempio n. 2
0
inline void* MarkedAllocator::tryAllocateHelper(size_t bytes)
{
    if (m_currentBlock) {
        ASSERT(m_currentBlock == m_nextBlockToSweep);
        m_currentBlock->didConsumeFreeList();
        m_nextBlockToSweep = m_currentBlock->next();
    }

    MarkedBlock* next;
    for (MarkedBlock*& block = m_nextBlockToSweep; block; block = next) {
        next = block->next();

        MarkedBlock::FreeList freeList = block->sweep(MarkedBlock::SweepToFreeList);
        
        double utilization = ((double)MarkedBlock::blockSize - (double)freeList.bytes) / (double)MarkedBlock::blockSize;
        if (utilization >= Options::minMarkedBlockUtilization()) {
            ASSERT(freeList.bytes || !freeList.head);
            m_blockList.remove(block);
            m_retiredBlocks.push(block);
            block->didRetireBlock(freeList);
            continue;
        }

        if (bytes > block->cellSize()) {
            block->stopAllocating(freeList);
            continue;
        }

        m_currentBlock = block;
        m_freeList = freeList;
        break;
    }
    
    if (!m_freeList.head) {
        m_currentBlock = 0;
        return 0;
    }

    ASSERT(m_freeList.head);
    void* head = tryPopFreeList(bytes);
    ASSERT(head);
    m_markedSpace->didAllocateInBlock(m_currentBlock);
    return head;
}
Esempio n. 3
0
inline void* MarkedAllocator::tryAllocate(size_t bytes)
{
    ASSERT(!m_heap->isBusy());
    m_heap->m_operationInProgress = Allocation;
    void* result = tryAllocateHelper(bytes);

    // Due to the DelayedReleaseScope in tryAllocateHelper, some other thread might have
    // created a new block after we thought we didn't find any free cells. 
    while (!result && m_currentBlock) {
        // A new block was added by another thread so try popping the free list.
        result = tryPopFreeList(bytes);
        if (result)
            break;
        // The free list was empty, so call tryAllocateHelper to do the normal sweeping stuff.
        result = tryAllocateHelper(bytes);
    }

    m_heap->m_operationInProgress = NoOperation;
    ASSERT(result || !m_currentBlock);
    return result;
}