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

commit fbd42700454bcff04f597f02d50199a0b2b14afe
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Thu Aug 7 10:44:28 2025 +0200

    mmc: Use heap sizer to possibly grow instead of collecting
---
 src/mmc.c | 57 +++++++++++++++++++++++++++------------------------------
 1 file changed, 27 insertions(+), 30 deletions(-)

diff --git a/src/mmc.c b/src/mmc.c
index 158dab6bb..a2cde87b9 100644
--- a/src/mmc.c
+++ b/src/mmc.c
@@ -946,38 +946,35 @@ collect(struct gc_mutator *mut, enum gc_collection_kind 
requested_kind) {
 }
 
 static int
-maybe_grow_heap (struct gc_heap *heap, size_t for_allocation)
+maybe_grow_heap_instead_of_collecting(struct gc_heap *heap,
+                                      size_t for_allocation)
 {
-  if (!for_allocation)
-    return 0;
-  if (heap->sizer.policy != GC_HEAP_SIZE_GROWABLE)
-    return 0;
-
-  pthread_mutex_lock(&heap->lock);
-  if (heap->count_at_last_growth == heap->count)
-    {
-      pthread_mutex_unlock(&heap->lock);
-      return 0;
-    }
-
-  uint64_t progress = 0;
-  nofl_space_add_to_allocation_counter(heap_nofl_space(heap), &progress);
-  large_object_space_add_to_allocation_counter(heap_large_object_space(heap),
-                                               &progress);
-  double yield_at_last_gc = heap_last_gc_yield (heap);
-  uint64_t live_at_last_gc = heap->size_at_last_gc * (1.0 - yield_at_last_gc);
-  uint64_t expected_progress =
-    live_at_last_gc * (heap->sizer.growable->multiplier - 1.0);
-  uint64_t minimum_progress = expected_progress / 2;
-  if (progress < minimum_progress)
-    {
-      resize_heap(heap, heap->size + minimum_progress);
-      pthread_mutex_unlock(&heap->lock);
-      return 1;
+  // Sometimes when we have exhausted allocatable blocks, we should grow
+  // the heap instead of collecting.
+
+  int did_grow = 0;
+
+  // Only grow if this GC is triggered in response to allocation.
+  if (for_allocation) {
+    pthread_mutex_lock(&heap->lock);
+    // Only grow instead of collecting once in a cycle.
+    if (heap->count_at_last_growth != heap->count) {
+      double yield_at_last_gc = heap_last_gc_yield (heap);
+      uint64_t live_at_last_gc =
+        heap->size_at_last_gc * (1.0 - yield_at_last_gc);
+      size_t target_size = gc_heap_sizer_target_size(heap->sizer, heap->size,
+                                                     live_at_last_gc);
+      // Only grow if target heap size is greater than current heap size.
+      if (target_size > heap->size) {
+        target_size = align_up(target_size, NOFL_BLOCK_SIZE);
+        resize_heap(heap, target_size);
+        did_grow = 1;
+      }
     }
+    pthread_mutex_unlock(&heap->lock);
+  }
 
-  pthread_mutex_unlock(&heap->lock);
-  return 0;
+  return did_grow;
 }
 
 static int
@@ -986,7 +983,7 @@ trigger_collection(struct gc_mutator *mut,
                    size_t for_allocation) {
   struct gc_heap *heap = mutator_heap(mut);
 
-  if (maybe_grow_heap (heap, for_allocation))
+  if (maybe_grow_heap_instead_of_collecting(heap, for_allocation))
     return 1;
 
   int prev_kind = -1;

Reply via email to