Пример #1
0
MarkedBlock::FreeCell* MarkedBlock::sweep(SweepMode sweepMode)
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);

    switch (m_state) {
    case New:
        ASSERT(sweepMode == SweepToFreeList);
        return specializedSweep<New, SweepToFreeList>();
    case FreeListed:
        // Happens when a block transitions to fully allocated.
        ASSERT(sweepMode == SweepToFreeList);
        return 0;
    case Allocated:
        ASSERT_NOT_REACHED();
        return 0;
    case Marked:
        return sweepMode == SweepToFreeList
            ? specializedSweep<Marked, SweepToFreeList>()
            : specializedSweep<Marked, SweepOnly>();
    case Zapped:
        return sweepMode == SweepToFreeList
            ? specializedSweep<Zapped, SweepToFreeList>()
            : specializedSweep<Zapped, SweepOnly>();
    }

    ASSERT_NOT_REACHED();
    return 0;
}
Пример #2
0
void MarkedBlock::canonicalizeCellLivenessData(const FreeList& freeList)
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
    FreeCell* head = freeList.head;

    if (m_state == Marked) {
        // If the block is in the Marked state then we know that:
        // 1) It was not used for allocation during the previous allocation cycle.
        // 2) It may have dead objects, and we only know them to be dead by the
        //    fact that their mark bits are unset.
        // Hence if the block is Marked we need to leave it Marked.
        
        ASSERT(!head);
        return;
    }
   
    ASSERT(m_state == FreeListed);
    
    // Roll back to a coherent state for Heap introspection. Cells newly
    // allocated from our free list are not currently marked, so we need another
    // way to tell what's live vs dead. 
    
    SetAllMarksFunctor functor;
    forEachCell(functor);

    FreeCell* next;
    for (FreeCell* current = head; current; current = next) {
        next = current->next;
        reinterpret_cast<JSCell*>(current)->zap();
        clearMarked(current);
    }
    
    m_state = Marked;
}
Пример #3
0
MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize)
    : m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
    , m_state(New) // All cells start out unmarked.
    , m_allocation(allocation)
    , m_heap(heap)
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
Пример #4
0
MarkedBlock::MarkedBlock(PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction)
    : HeapBlock(allocation)
    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
    , m_cellsNeedDestruction(cellsNeedDestruction)
    , m_state(New) // All cells start out unmarked.
    , m_heap(heap)
{
    ASSERT(heap);
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
Пример #5
0
MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);

    if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
        return FreeList();

    if (m_cellsNeedDestruction)
        return sweepHelper<true>(sweepMode);
    return sweepHelper<false>(sweepMode);
}
Пример #6
0
MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, Heap* heap, size_t cellSize, bool cellsNeedDestruction, bool onlyContainsStructures)
    : HeapBlock<MarkedBlock>(allocation)
    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
    , m_cellsNeedDestruction(cellsNeedDestruction)
    , m_onlyContainsStructures(onlyContainsStructures)
    , m_state(New) // All cells start out unmarked.
    , m_weakSet(heap)
{
    ASSERT(heap);
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
Пример #7
0
MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, MarkedAllocator* allocator, size_t cellSize, DestructorType destructorType)
    : HeapBlock<MarkedBlock>(allocation)
    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    , m_endAtom(atomsPerBlock - m_atomsPerCell + 1)
    , m_destructorType(destructorType)
    , m_allocator(allocator)
    , m_state(New) // All cells start out unmarked.
    , m_weakSet(allocator->heap()->globalData())
{
    ASSERT(allocator);
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
MarkedBlock::MarkedBlock(Region* region, MarkedAllocator* allocator, size_t cellSize, DestructorType destructorType)
    : HeapBlock<MarkedBlock>(region)
    , m_atomsPerCell((cellSize + atomSize - 1) / atomSize)
    , m_endAtom((allocator->cellSize() ? atomsPerBlock : region->blockSize() / atomSize) - m_atomsPerCell + 1)
    , m_destructorType(destructorType)
    , m_allocator(allocator)
    , m_state(New) // All cells start out unmarked.
    , m_weakSet(allocator->heap()->vm())
{
    ASSERT(allocator);
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
}
Пример #9
0
MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);

    m_weakSet.sweep();

    if (sweepMode == SweepOnly && m_destructorType == MarkedBlock::None)
        return FreeList();

    if (m_destructorType == MarkedBlock::ImmortalStructure)
        return sweepHelper<MarkedBlock::ImmortalStructure>(sweepMode);
    if (m_destructorType == MarkedBlock::Normal)
        return sweepHelper<MarkedBlock::Normal>(sweepMode);
    return sweepHelper<MarkedBlock::None>(sweepMode);
}
Пример #10
0
MarkedBlock::FreeList MarkedBlock::resumeAllocating()
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);

    ASSERT(m_state == Marked);

    if (!m_newlyAllocated) {
        // We didn't have to create a "newly allocated" bitmap. That means we were already Marked
        // when we last stopped allocation, so return an empty free list and stay in the Marked state.
        return FreeList();
    }

    // Re-create our free list from before stopping allocation. 
    return sweep(SweepToFreeList);
}
Пример #11
0
void MarkedBlock::zapFreeList(const FreeList& freeList)
{
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
    FreeCell* head = freeList.head;

    if (m_state == Marked) {
        // If the block is in the Marked state then we know that:
        // 1) It was not used for allocation during the previous allocation cycle.
        // 2) It may have dead objects, and we only know them to be dead by the
        //    fact that their mark bits are unset.
        // Hence if the block is Marked we need to leave it Marked.
        
        ASSERT(!head);
        
        return;
    }
    
    if (m_state == Zapped) {
        // If the block is in the Zapped state then we know that someone already
        // zapped it for us. This could not have happened during a GC, but might
        // be the result of someone having done a GC scan to perform some operation
        // over all live objects (or all live blocks). It also means that somebody
        // had allocated in this block since the last GC, swept all dead objects
        // onto the free list, left the block in the FreeListed state, then the heap
        // scan happened, and canonicalized the block, leading to all dead objects
        // being zapped. Therefore, it is safe for us to simply do nothing, since
        // dead objects will have 0 in their vtables and live objects will have
        // non-zero vtables, which is consistent with the block being zapped.
        
        ASSERT(!head);
        
        return;
    }
    
    ASSERT(m_state == FreeListed);
    
    // Roll back to a coherent state for Heap introspection. Cells newly
    // allocated from our free list are not currently marked, so we need another
    // way to tell what's live vs dead. We use zapping for that.
    
    FreeCell* next;
    for (FreeCell* current = head; current; current = next) {
        next = current->next;
        reinterpret_cast<JSCell*>(current)->zap();
    }
    
    m_state = Zapped;
}
Пример #12
0
MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
{
    ASSERT(DelayedReleaseScope::isInEffectFor(heap()->m_objectSpace));
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);

    m_weakSet.sweep();

    if (sweepMode == SweepOnly && m_destructorType == MarkedBlock::None)
        return FreeList();

    if (m_destructorType == MarkedBlock::ImmortalStructure)
        return sweepHelper<MarkedBlock::ImmortalStructure>(sweepMode);
    if (m_destructorType == MarkedBlock::Normal)
        return sweepHelper<MarkedBlock::Normal>(sweepMode);
    return sweepHelper<MarkedBlock::None>(sweepMode);
}
Пример #13
0
void MarkedBlock::clearMarksWithCollectionType()
{
    ASSERT(collectionType == FullCollection || collectionType == EdenCollection);
    HEAP_LOG_BLOCK_STATE_TRANSITION(this);

    ASSERT(m_state != New && m_state != FreeListed);
    if (collectionType == FullCollection) {
        m_marks.clearAll();
#if ENABLE(GGC)
        m_rememberedSet.clearAll();
#endif
    }

    // This will become true at the end of the mark phase. We set it now to
    // avoid an extra pass to do so later.
    m_state = Marked;
}