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

commit 31b373b8f21fe9165ae60dad09ad4493d862628d
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Wed Apr 23 10:46:23 2025 +0200

    copy space: Palliate a failure mode due to fragmentation
---
 src/copy-space.h | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/copy-space.h b/src/copy-space.h
index 7f262c221..bf0d3930c 100644
--- a/src/copy-space.h
+++ b/src/copy-space.h
@@ -409,11 +409,23 @@ copy_space_allocator_acquire_block(struct 
copy_space_allocator *alloc,
   return 0;
 }
 
+static struct copy_space_block*
+copy_space_obtain_empty_block_during_gc(struct copy_space *space,
+                                        const struct gc_lock *lock) {
+  GC_ASSERT(!copy_space_pop_empty_block(space, lock));
+  struct copy_space_block *block = copy_space_page_in_block(space, lock);
+  if (block)
+    atomic_fetch_add(&space->bytes_to_page_out, COPY_SPACE_BLOCK_SIZE);
+  return block;
+}
+
 static int
 copy_space_allocator_acquire_empty_block(struct copy_space_allocator *alloc,
                                          struct copy_space *space) {
   struct gc_lock lock = copy_space_lock(space);
   struct copy_space_block *block = copy_space_pop_empty_block(space, &lock);
+  if (!block && space->in_gc)
+    block = copy_space_obtain_empty_block_during_gc(space, &lock);
   gc_lock_release(&lock);
   if (copy_space_allocator_acquire_block(alloc, block, space->active_region)) {
     block->in_core = 1;
@@ -925,7 +937,10 @@ static int
 copy_space_init(struct copy_space *space, size_t size, uint32_t flags,
                 struct gc_background_thread *thread) {
   size = align_up(size, COPY_SPACE_BLOCK_SIZE);
-  size_t reserved = align_up(size, COPY_SPACE_SLAB_SIZE);
+  // Reserve a few extra blocks to handle the fragmentation problem
+  // 
(https://wingolog.org/archives/2024/07/10/copying-collectors-with-block-structured-heaps-are-unreliable).
+  size_t reserved = size + COPY_SPACE_BLOCK_SIZE * 16;
+  reserved = align_up(reserved, COPY_SPACE_SLAB_SIZE);
   if (flags & COPY_SPACE_ALIGNED)
     reserved = copy_space_round_up_power_of_two(reserved);
   size_t nslabs = reserved / COPY_SPACE_SLAB_SIZE;

Reply via email to