void CopiedSpace::didStartFullCollection() { ASSERT(heap()->operationInProgress() == FullCollection); ASSERT(m_fromSpace->isEmpty()); for (CopiedBlock* block = m_toSpace->head(); block; block = block->next()) block->didSurviveGC(); for (CopiedBlock* block = m_oversizeBlocks.head(); block; block = block->next()) block->didSurviveGC(); }
void CopiedSpace::doneCopying() { { MutexLocker locker(m_loanedBlocksLock); while (m_numberOfLoanedBlocks > 0) m_loanedBlocksCondition.wait(m_loanedBlocksLock); } ASSERT(m_inCopyingPhase == m_shouldDoCopyPhase); m_inCopyingPhase = false; while (!m_fromSpace->isEmpty()) { CopiedBlock* block = m_fromSpace->removeHead(); // All non-pinned blocks in from-space should have been reclaimed as they were evacuated. ASSERT(block->isPinned() || !m_shouldDoCopyPhase); block->didSurviveGC(); // We don't add the block to the blockSet because it was never removed. ASSERT(m_blockSet.contains(block)); m_blockFilter.add(reinterpret_cast<Bits>(block)); m_toSpace->push(block); } if (!m_toSpace->head()) allocateBlock(); else m_allocator.setCurrentBlock(m_toSpace->head()); m_shouldDoCopyPhase = false; }
void CopiedSpace::didStartFullCollection() { ASSERT(heap()->operationInProgress() == FullCollection); ASSERT(m_oldGen.fromSpace->isEmpty()); ASSERT(m_newGen.fromSpace->isEmpty()); #ifndef NDEBUG for (CopiedBlock* block = m_newGen.toSpace->head(); block; block = block->next()) ASSERT(!block->liveBytes()); for (CopiedBlock* block = m_newGen.oversizeBlocks.head(); block; block = block->next()) ASSERT(!block->liveBytes()); #endif for (CopiedBlock* block = m_oldGen.toSpace->head(); block; block = block->next()) block->didSurviveGC(); for (CopiedBlock* block = m_oldGen.oversizeBlocks.head(); block; block = block->next()) block->didSurviveGC(); }
void CopiedSpace::startedCopying() { std::swap(m_fromSpace, m_toSpace); m_blockFilter.reset(); m_allocator.resetCurrentBlock(); CopiedBlock* next = 0; size_t totalLiveBytes = 0; size_t totalUsableBytes = 0; for (CopiedBlock* block = m_fromSpace->head(); block; block = next) { next = block->next(); if (!block->isPinned() && block->canBeRecycled()) { recycleEvacuatedBlock(block); continue; } totalLiveBytes += block->liveBytes(); totalUsableBytes += block->payloadCapacity(); } CopiedBlock* block = m_oversizeBlocks.head(); while (block) { CopiedBlock* next = block->next(); if (block->isPinned()) { m_blockFilter.add(reinterpret_cast<Bits>(block)); totalLiveBytes += block->payloadCapacity(); totalUsableBytes += block->payloadCapacity(); block->didSurviveGC(); } else { m_oversizeBlocks.remove(block); m_blockSet.remove(block); m_heap->blockAllocator().deallocateCustomSize(CopiedBlock::destroy(block)); } block = next; } double markedSpaceBytes = m_heap->objectSpace().capacity(); double totalFragmentation = ((double)totalLiveBytes + markedSpaceBytes) / ((double)totalUsableBytes + markedSpaceBytes); m_shouldDoCopyPhase = totalFragmentation <= Options::minHeapUtilization(); if (!m_shouldDoCopyPhase) return; ASSERT(m_shouldDoCopyPhase); ASSERT(!m_inCopyingPhase); ASSERT(!m_numberOfLoanedBlocks); m_inCopyingPhase = true; }
void CopiedSpace::doneCopying() { RELEASE_ASSERT(!m_numberOfLoanedBlocks); RELEASE_ASSERT(m_inCopyingPhase == m_shouldDoCopyPhase); m_inCopyingPhase = false; DoublyLinkedList<CopiedBlock>* toSpace; DoublyLinkedList<CopiedBlock>* fromSpace; TinyBloomFilter* blockFilter; if (heap()->operationInProgress() == FullCollection) { toSpace = m_oldGen.toSpace; fromSpace = m_oldGen.fromSpace; blockFilter = &m_oldGen.blockFilter; } else { toSpace = m_newGen.toSpace; fromSpace = m_newGen.fromSpace; blockFilter = &m_newGen.blockFilter; } while (!fromSpace->isEmpty()) { CopiedBlock* block = fromSpace->removeHead(); // We don't add the block to the blockSet because it was never removed. ASSERT(m_blockSet.contains(block)); blockFilter->add(reinterpret_cast<Bits>(block)); block->didSurviveGC(); toSpace->push(block); } if (heap()->operationInProgress() == EdenCollection) { m_oldGen.toSpace->append(*m_newGen.toSpace); m_oldGen.oversizeBlocks.append(m_newGen.oversizeBlocks); m_oldGen.blockFilter.add(m_newGen.blockFilter); m_newGen.blockFilter.reset(); } ASSERT(m_newGen.toSpace->isEmpty()); ASSERT(m_newGen.fromSpace->isEmpty()); ASSERT(m_newGen.oversizeBlocks.isEmpty()); allocateBlock(); m_shouldDoCopyPhase = false; }