wingo pushed a commit to branch wip-whippet
in repository guile.

commit 50836264268baed97323b2f7a750a6fd6757d2ae
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Tue Aug 5 11:20:05 2025 +0200

    Fix hole collection
---
 src/mmc.c          |  4 ++--
 src/nofl-holeset.h |  1 +
 src/nofl-space.h   | 25 ++++++++++++++++---------
 3 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/src/mmc.c b/src/mmc.c
index 0ad5e12b8..6d20cffa6 100644
--- a/src/mmc.c
+++ b/src/mmc.c
@@ -133,7 +133,7 @@ gc_trace_worker_call_with_data(void (*f)(struct gc_tracer 
*tracer,
                                struct gc_heap *heap,
                                struct gc_trace_worker *worker) {
   struct gc_trace_worker_data data;
-  nofl_allocator_reset(&data.allocator);
+  nofl_allocator_init(&data.allocator);
   f(tracer, heap, worker, &data);
   nofl_allocator_finish(&data.allocator, heap_nofl_space(heap));
 }
@@ -240,7 +240,7 @@ add_mutator(struct gc_heap *heap, struct gc_mutator *mut) {
   mut->heap = heap;
   mut->event_listener_data =
     heap->event_listener.mutator_added(heap->event_listener_data);
-  nofl_allocator_reset(&mut->allocator);
+  nofl_allocator_init(&mut->allocator);
   gc_field_set_writer_init(&mut->logger, &heap->remembered_set);
   heap_lock(heap);
   // We have no roots.  If there is a GC currently in progress, we have
diff --git a/src/nofl-holeset.h b/src/nofl-holeset.h
index 6a3cfda9f..1cba592ec 100644
--- a/src/nofl-holeset.h
+++ b/src/nofl-holeset.h
@@ -115,6 +115,7 @@ nofl_holeset_try_pop(struct nofl_holeset *holes, size_t 
granules) {
   } else {
     struct nofl_hole_with_size *hole_with_size = ret;
     hole_granules = hole_with_size->granules;
+    GC_ASSERT(hole_granules);
     hole_with_size->granules = 0;
   }
 
diff --git a/src/nofl-space.h b/src/nofl-space.h
index a623acd8e..82dbfc5d9 100644
--- a/src/nofl-space.h
+++ b/src/nofl-space.h
@@ -614,6 +614,11 @@ static void
 nofl_allocator_reset(struct nofl_allocator *alloc) {
   alloc->alloc = alloc->sweep = 0;
   alloc->block = nofl_block_null();
+}
+
+static void
+nofl_allocator_init(struct nofl_allocator *alloc) {
+  nofl_allocator_reset(alloc);
   nofl_holeset_clear(&alloc->holes);
 }
 
@@ -739,11 +744,12 @@ nofl_allocator_acquire_evacuation_target(struct 
nofl_allocator* alloc,
   return nofl_allocator_acquire_empty_block(alloc, space);
 }
 
-static void
-nofl_allocator_finish_hole(struct nofl_allocator *alloc) {
+static inline void
+nofl_allocator_finish_hole(struct nofl_allocator *alloc, int collect_holes) {
   size_t granules = (alloc->sweep - alloc->alloc) / NOFL_GRANULE_SIZE;
   if (granules) {
-    nofl_holeset_push_local(&alloc->holes, alloc->alloc, granules);
+    if (collect_holes)
+      nofl_holeset_push_local(&alloc->holes, alloc->alloc, granules);
     alloc->block.summary->holes_with_fragmentation++;
     alloc->block.summary->fragmentation_granules += granules;
     alloc->alloc = alloc->sweep;
@@ -819,9 +825,10 @@ nofl_allocator_next_hole_in_block(struct nofl_allocator 
*alloc,
 
 static void
 nofl_allocator_finish_sweeping_in_block(struct nofl_allocator *alloc,
-                                        uint8_t survivor_mark) {
+                                        uint8_t survivor_mark,
+                                        int collect_holes) {
   do {
-    nofl_allocator_finish_hole(alloc);
+    nofl_allocator_finish_hole(alloc, collect_holes);
   } while (nofl_allocator_next_hole_in_block(alloc, survivor_mark));
 }
 
@@ -836,7 +843,7 @@ nofl_allocator_release_block(struct nofl_allocator *alloc,
   } else if (space->evacuating) {
     nofl_allocator_release_full_evacuation_target(alloc, space);
   } else {
-    nofl_allocator_finish_sweeping_in_block(alloc, space->survivor_mark);
+    nofl_allocator_finish_sweeping_in_block(alloc, space->survivor_mark, 1);
     nofl_allocator_release_full_block(alloc, space);
   }
 }
@@ -867,7 +874,7 @@ nofl_allocator_next_hole_in_block_of_size(struct 
nofl_allocator *alloc,
     return 0;
 
   while (1) {
-    nofl_allocator_finish_hole(alloc);
+    nofl_allocator_finish_hole(alloc, min_granules != 0);
     size_t granules =
       nofl_allocator_next_hole_in_block(alloc, space->survivor_mark);
     if (granules == 0) {
@@ -929,7 +936,7 @@ nofl_allocator_next_hole(struct nofl_allocator *alloc,
         break;
       if (min_granules <= granules)
         return granules;
-      nofl_allocator_finish_hole(alloc);
+      nofl_allocator_finish_hole(alloc, 1);
       nofl_allocator_release_full_block(alloc, space);
     }
 
@@ -1397,7 +1404,7 @@ nofl_space_promote_blocks(struct nofl_space *space) {
     block.summary->holes_with_fragmentation = 0;
     block.summary->fragmentation_granules = 0;
     struct nofl_allocator alloc = { block.addr, block.addr, block };
-    nofl_allocator_finish_sweeping_in_block(&alloc, space->current_mark);
+    nofl_allocator_finish_sweeping_in_block(&alloc, space->current_mark, 0);
     atomic_fetch_add(&space->old_generation_granules,
                      NOFL_GRANULES_PER_BLOCK - block.summary->hole_granules);
     nofl_block_list_push(&space->old, block);

Reply via email to