summaryrefslogtreecommitdiff
path: root/rts/sm/GC.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/sm/GC.c')
-rw-r--r--rts/sm/GC.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/rts/sm/GC.c b/rts/sm/GC.c
index 15aef3a9fc..71c1ecbfeb 100644
--- a/rts/sm/GC.c
+++ b/rts/sm/GC.c
@@ -442,6 +442,11 @@ GarbageCollect (uint32_t collect_gen,
memInventory(DEBUG_gc);
#endif
+ // Defer all free calls for the megablock allocator to avoid quadratic runtime
+ // explosion when freeing a lot of memory in a single GC
+ // (https://gitlab.haskell.org/ghc/ghc/-/issues/19897).
+ deferMBlockFreeing();
+
// do this *before* we start scavenging
collectFreshWeakPtrs();
@@ -977,6 +982,11 @@ GarbageCollect (uint32_t collect_gen,
resurrectThreads(resurrected_threads);
ACQUIRE_SM_LOCK;
+ // Finally free the deferred mblocks by sorting the deferred free list and
+ // merging it into the actual sorted free list. This needs to happen here so
+ // that the `returnMemoryToOS` call down below can successfully free memory.
+ commitMBlockFreeing();
+
if (major_gc) {
W_ need_prealloc, need_live, need, got;
uint32_t i;