diff --git a/Libraries/LibGC/BlockAllocator.cpp b/Libraries/LibGC/BlockAllocator.cpp index a049417c07..cb8f11cff6 100644 --- a/Libraries/LibGC/BlockAllocator.cpp +++ b/Libraries/LibGC/BlockAllocator.cpp @@ -372,7 +372,7 @@ void* BlockAllocator::allocate_block([[maybe_unused]] char const* name) return block; } -void BlockAllocator::deallocate_block(void* block) +void BlockAllocator::deallocate_block(void* block, DeferDecommit defer_decommit) { VERIFY(block); @@ -385,12 +385,12 @@ void BlockAllocator::deallocate_block(void* block) { Sync::MutexLocker locker(m_mutex); m_freshly_freed.append(block); - if (!m_in_decommit_registry) { + if (defer_decommit == DeferDecommit::Yes && !m_in_decommit_registry) { m_in_decommit_registry = true; need_to_register = true; } } - if (need_to_register) + if (need_to_register && defer_decommit == DeferDecommit::Yes) DecommitWorker::the().register_pending(*this); } diff --git a/Libraries/LibGC/BlockAllocator.h b/Libraries/LibGC/BlockAllocator.h index 84377df16c..aa418247bf 100644 --- a/Libraries/LibGC/BlockAllocator.h +++ b/Libraries/LibGC/BlockAllocator.h @@ -14,6 +14,11 @@ namespace GC { +enum class DeferDecommit { + No, + Yes, +}; + class DecommitWorker; class GC_API BlockAllocator { @@ -22,7 +27,7 @@ public: ~BlockAllocator(); void* allocate_block(char const* name); - void deallocate_block(void*); + void deallocate_block(void*, DeferDecommit = DeferDecommit::Yes); size_t block_count(); diff --git a/Libraries/LibGC/CellAllocator.cpp b/Libraries/LibGC/CellAllocator.cpp index 7e37102f8d..45927ea6a7 100644 --- a/Libraries/LibGC/CellAllocator.cpp +++ b/Libraries/LibGC/CellAllocator.cpp @@ -53,13 +53,13 @@ Cell* CellAllocator::allocate_cell(Heap& heap) return cell; } -void CellAllocator::block_did_become_empty(Badge, HeapBlock& block) +void CellAllocator::block_did_become_empty(Badge, HeapBlock& block, DeferDecommit defer_decommit) { block.m_list_node.remove(); block.heap().m_live_heap_blocks.remove(&block); // NOTE: HeapBlocks are managed by the BlockAllocator, so we don't want to `delete` the block here. block.~HeapBlock(); - m_block_allocator.deallocate_block(&block); + m_block_allocator.deallocate_block(&block, defer_decommit); } void CellAllocator::block_did_become_usable(Badge, HeapBlock& block) diff --git a/Libraries/LibGC/CellAllocator.h b/Libraries/LibGC/CellAllocator.h index fd5fcb51ce..05056caf66 100644 --- a/Libraries/LibGC/CellAllocator.h +++ b/Libraries/LibGC/CellAllocator.h @@ -46,7 +46,7 @@ public: return IterationDecision::Continue; } - void block_did_become_empty(Badge, HeapBlock&); + void block_did_become_empty(Badge, HeapBlock&, DeferDecommit = DeferDecommit::Yes); void block_did_become_usable(Badge, HeapBlock&); bool has_blocks_pending_sweep() const { return !m_blocks_pending_sweep.is_empty(); } diff --git a/Libraries/LibGC/Heap.cpp b/Libraries/LibGC/Heap.cpp index 6869236806..c4b2ddbdd4 100644 --- a/Libraries/LibGC/Heap.cpp +++ b/Libraries/LibGC/Heap.cpp @@ -1125,7 +1125,7 @@ void Heap::sweep_dead_cells(bool print_report, Core::ElapsedTimer const& measure ScopedPhaseTimer timer { g_recording_phase_timings, g_phase_timings.sweep_block_reclassify_us }; for (auto* block : empty_blocks) { dbgln_if(HEAP_DEBUG, " - HeapBlock empty @ {}: cell_size={}", block, block->cell_size()); - block->cell_allocator().block_did_become_empty({}, *block); + block->cell_allocator().block_did_become_empty({}, *block, DeferDecommit::No); } for (auto* block : full_blocks_that_became_usable) { @@ -1158,9 +1158,9 @@ void Heap::sweep_dead_cells(bool print_report, Core::ElapsedTimer const& measure } (void)measurement_timer; - // Sweep is done; kick the global decommit worker so the slots we just - // freed get madvise()'d off the GC pause path. - BlockAllocator::wake_decommit_worker_async(); + // CollectEverything finishes synchronously, and is currently only used + // when the heap is going away. Do not spin up background decommit work + // from process teardown. } void Heap::sweep_block(HeapBlock& block)