void Heap::collect(SweepToggle sweepToggle) { ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); JAVASCRIPTCORE_GC_BEGIN(); markRoots(); m_handleHeap.finalizeWeakHandles(); m_globalData->smallStrings.finalizeSmallStrings(); JAVASCRIPTCORE_GC_MARKED(); resetAllocator(); #if ENABLE(JSC_ZOMBIES) sweepToggle = DoSweep; #endif if (sweepToggle == DoSweep) { sweep(); shrink(); } // To avoid pathological GC churn in large heaps, we set the allocation high // water mark to be proportional to the current size of the heap. The exact // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : // new bytes allocated) proportion, and seems to work well in benchmarks. size_t proportionalBytes = 2 * size(); m_newSpace.setHighWaterMark(max(proportionalBytes, minBytesPerCycle)); JAVASCRIPTCORE_GC_END(); (*m_activityCallback)(); }
void WeakSet::sweep() { for (WeakBlock* block = m_blocks.head(); block; block = block->next()) block->sweep(); resetAllocator(); }
void Heap::collect(SweepToggle sweepToggle) { GCPHASE(Collect); ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); #if ENABLE(GGC) bool fullGC = sweepToggle == DoSweep; if (!fullGC) fullGC = (capacity() > 4 * m_lastFullGCSize); #else bool fullGC = true; #endif { GCPHASE(Canonicalize); canonicalizeCellLivenessData(); } markRoots(fullGC); { GCPHASE(HarvestWeakReferences); harvestWeakReferences(); m_handleHeap.finalizeWeakHandles(); m_globalData->smallStrings.finalizeSmallStrings(); } JAVASCRIPTCORE_GC_MARKED(); { GCPHASE(ResetAllocator); resetAllocator(); } if (sweepToggle == DoSweep) { GCPHASE(Sweeping); sweep(); shrink(); } // To avoid pathological GC churn in large heaps, we set the allocation high // water mark to be proportional to the current size of the heap. The exact // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : // new bytes allocated) proportion, and seems to work well in benchmarks. size_t newSize = size(); size_t proportionalBytes = 2 * newSize; if (fullGC) { m_lastFullGCSize = newSize; m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle)); } JAVASCRIPTCORE_GC_END(); (*m_activityCallback)(); }
void WeakSet::shrink() { WeakBlock* next; for (WeakBlock* block = m_blocks.head(); block; block = next) { next = block->next(); if (block->isEmpty()) removeAllocator(block); } resetAllocator(); if (m_blocks.isEmpty() && isOnList()) remove(); }
void WeakSet::sweep() { for (WeakBlock* block = m_blocks.head(); block;) { heap()->sweepNextLogicallyEmptyWeakBlock(); WeakBlock* nextBlock = block->next(); block->sweep(); if (block->isLogicallyEmptyButNotFree()) { // If this WeakBlock is logically empty, but still has Weaks pointing into it, // we can't destroy it just yet. Detach it from the WeakSet and hand ownership // to the Heap so we don't pin down the entire MarkedBlock or LargeAllocation. m_blocks.remove(block); heap()->addLogicallyEmptyWeakBlock(block); block->disconnectContainer(); } block = nextBlock; } resetAllocator(); }