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

commit c9063b8027ff9b7f3bc033f61320905933f0a7c8
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Wed Apr 23 17:28:46 2025 +0200

    bdw: Disable thread-local freelists for pointerless allocations
    
    There was a race between GC and popping the head off freelists.  We
    could have separate freelists for tagged and untagged normal allocations
    though.
---
 api/bdw-attrs.h  | 18 +++++++++-------
 api/gc-api.h     |  8 +++----
 api/gc-attrs.h   | 10 ++++-----
 api/mmc-attrs.h  |  4 ++--
 api/pcc-attrs.h  |  4 ++--
 api/semi-attrs.h |  5 +++--
 src/bdw.c        | 64 ++++++++++++++++++++------------------------------------
 7 files changed, 50 insertions(+), 63 deletions(-)

diff --git a/api/bdw-attrs.h b/api/bdw-attrs.h
index 7f8000b3f..7a68618cc 100644
--- a/api/bdw-attrs.h
+++ b/api/bdw-attrs.h
@@ -4,8 +4,15 @@
 #include "gc-attrs.h"
 #include "gc-assert.h"
 
-static inline enum gc_allocator_kind gc_allocator_kind(void) {
-  return GC_ALLOCATOR_INLINE_FREELIST;
+static inline enum gc_inline_allocator_kind
+gc_inline_allocator_kind(enum gc_allocation_kind kind) {
+  switch (kind) {
+    case GC_ALLOCATION_TAGGED:
+    case GC_ALLOCATION_UNTAGGED_CONSERVATIVE:
+      return GC_INLINE_ALLOCATOR_FREELIST;
+    default:
+      return GC_INLINE_ALLOCATOR_NONE;
+  }
 }
 static inline size_t gc_allocator_small_granule_size(void) {
   return 2 * sizeof(void *);
@@ -30,11 +37,8 @@ static inline size_t gc_allocator_freelist_offset(size_t 
size,
     case GC_ALLOCATION_UNTAGGED_CONSERVATIVE:
       base = 0;
       break;
-    case GC_ALLOCATION_UNTAGGED_POINTERLESS:
-    case GC_ALLOCATION_TAGGED_POINTERLESS:
-      base = (sizeof(void*) * gc_allocator_large_threshold() /
-              gc_allocator_small_granule_size());
-      break;
+    default:
+      GC_CRASH();
   }
   size_t bucket = (size - 1) / gc_allocator_small_granule_size();
   return base + sizeof(void*) * bucket;
diff --git a/api/gc-api.h b/api/gc-api.h
index 58f40b779..b040b7d0a 100644
--- a/api/gc-api.h
+++ b/api/gc-api.h
@@ -154,12 +154,12 @@ static inline void* gc_allocate_small_fast(struct 
gc_mutator *mut, size_t size,
   GC_ASSERT(size != 0);
   GC_ASSERT(size <= gc_allocator_large_threshold());
 
-  switch (gc_allocator_kind()) {
-  case GC_ALLOCATOR_INLINE_BUMP_POINTER:
+  switch (gc_inline_allocator_kind(kind)) {
+  case GC_INLINE_ALLOCATOR_BUMP_POINTER:
     return gc_allocate_small_fast_bump_pointer(mut, size, kind);
-  case GC_ALLOCATOR_INLINE_FREELIST:
+  case GC_INLINE_ALLOCATOR_FREELIST:
     return gc_allocate_small_fast_freelist(mut, size, kind);
-  case GC_ALLOCATOR_INLINE_NONE:
+  case GC_INLINE_ALLOCATOR_NONE:
     return NULL;
   default:
     GC_CRASH();
diff --git a/api/gc-attrs.h b/api/gc-attrs.h
index 4c801c1c8..1ce2c854b 100644
--- a/api/gc-attrs.h
+++ b/api/gc-attrs.h
@@ -7,13 +7,13 @@
 #include <stddef.h>
 #include <stdint.h>
 
-enum gc_allocator_kind {
-  GC_ALLOCATOR_INLINE_BUMP_POINTER,
-  GC_ALLOCATOR_INLINE_FREELIST,
-  GC_ALLOCATOR_INLINE_NONE
+enum gc_inline_allocator_kind {
+  GC_INLINE_ALLOCATOR_BUMP_POINTER,
+  GC_INLINE_ALLOCATOR_FREELIST,
+  GC_INLINE_ALLOCATOR_NONE
 };
 
-static inline enum gc_allocator_kind gc_allocator_kind(void) GC_ALWAYS_INLINE;
+static inline enum gc_inline_allocator_kind gc_inline_allocator_kind(enum 
gc_allocation_kind) GC_ALWAYS_INLINE;
 static inline size_t gc_allocator_large_threshold(void) GC_ALWAYS_INLINE;
 static inline size_t gc_allocator_small_granule_size(void) GC_ALWAYS_INLINE;
 
diff --git a/api/mmc-attrs.h b/api/mmc-attrs.h
index 9371f8abe..49ff5630b 100644
--- a/api/mmc-attrs.h
+++ b/api/mmc-attrs.h
@@ -5,8 +5,8 @@
 #include "gc-assert.h"
 #include "gc-attrs.h"
 
-static inline enum gc_allocator_kind gc_allocator_kind(void) {
-  return GC_ALLOCATOR_INLINE_BUMP_POINTER;
+static inline enum gc_inline_allocator_kind gc_inline_allocator_kind(enum 
gc_allocation_kind kind) {
+  return GC_INLINE_ALLOCATOR_BUMP_POINTER;
 }
 static inline size_t gc_allocator_small_granule_size(void) {
   return 16;
diff --git a/api/pcc-attrs.h b/api/pcc-attrs.h
index 12a555a5d..d7ec30768 100644
--- a/api/pcc-attrs.h
+++ b/api/pcc-attrs.h
@@ -8,8 +8,8 @@
 static const uintptr_t GC_ALIGNMENT = 8;
 static const size_t GC_LARGE_OBJECT_THRESHOLD = 8192;
 
-static inline enum gc_allocator_kind gc_allocator_kind(void) {
-  return GC_ALLOCATOR_INLINE_BUMP_POINTER;
+static inline enum gc_inline_allocator_kind gc_inline_allocator_kind(enum 
gc_allocation_kind kind) {
+  return GC_INLINE_ALLOCATOR_BUMP_POINTER;
 }
 static inline size_t gc_allocator_small_granule_size(void) {
   return GC_ALIGNMENT;
diff --git a/api/semi-attrs.h b/api/semi-attrs.h
index f2efbd831..fb4d7ab91 100644
--- a/api/semi-attrs.h
+++ b/api/semi-attrs.h
@@ -7,8 +7,9 @@
 static const uintptr_t GC_ALIGNMENT = 8;
 static const size_t GC_LARGE_OBJECT_THRESHOLD = 8192;
 
-static inline enum gc_allocator_kind gc_allocator_kind(void) {
-  return GC_ALLOCATOR_INLINE_BUMP_POINTER;
+static inline enum gc_inline_allocator_kind
+gc_inline_allocator_kind(enum gc_allocation_kind kind) {
+  return GC_INLINE_ALLOCATOR_BUMP_POINTER;
 }
 static inline size_t gc_allocator_small_granule_size(void) {
   return GC_ALIGNMENT;
diff --git a/src/bdw.c b/src/bdw.c
index 886e70718..f991437fd 100644
--- a/src/bdw.c
+++ b/src/bdw.c
@@ -65,7 +65,6 @@ struct gc_heap {
 
 struct gc_mutator {
   void *freelists[GC_INLINE_FREELIST_COUNT];
-  void *pointerless_freelists[GC_INLINE_FREELIST_COUNT];
   struct gc_heap *heap;
   struct gc_mutator_roots *roots;
   struct gc_mutator *next; // with heap lock
@@ -124,9 +123,6 @@ allocate_small(void **freelist, size_t idx, enum 
gc_inline_kind kind) {
   *freelist = *(void **)(head);
   *(void**)head = NULL;
 
-  if (kind == GC_INLINE_KIND_POINTERLESS)
-    memset(head, 0, gc_inline_freelist_object_size(idx));
-
   return head;
 }
 
@@ -134,41 +130,38 @@ void* gc_allocate_slow(struct gc_mutator *mut, size_t 
size,
                        enum gc_allocation_kind kind) {
   GC_ASSERT(size != 0);
   if (size <= gc_allocator_large_threshold()) {
-    size_t idx = gc_inline_bytes_to_freelist_index(size);
-    void **freelists;
-    enum gc_inline_kind freelist_kind;
     switch (kind) {
       case GC_ALLOCATION_TAGGED:
-      case GC_ALLOCATION_UNTAGGED_CONSERVATIVE:
+      case GC_ALLOCATION_UNTAGGED_CONSERVATIVE: {
+        size_t idx = gc_inline_bytes_to_freelist_index(size);
         return allocate_small(&mut->freelists[idx], idx, 
GC_INLINE_KIND_NORMAL);
+      }
       case GC_ALLOCATION_TAGGED_POINTERLESS:
       case GC_ALLOCATION_UNTAGGED_POINTERLESS:
-        return allocate_small(&mut->pointerless_freelists[idx], idx,
-                              GC_INLINE_KIND_POINTERLESS);
+        break;
       default:
         GC_CRASH();
     }
-  } else {
-    switch (kind) {
-      case GC_ALLOCATION_TAGGED:
-      case GC_ALLOCATION_UNTAGGED_CONSERVATIVE: {
-        void *ret = GC_malloc(size);
-        if (GC_LIKELY (ret != NULL))
-          return ret;
-        return __the_bdw_gc_heap->allocation_failure(__the_bdw_gc_heap, size);
-      }
-      case GC_ALLOCATION_TAGGED_POINTERLESS:
-      case GC_ALLOCATION_UNTAGGED_POINTERLESS: {
-        void *ret = GC_malloc_atomic(size);
-        if (GC_LIKELY (ret != NULL)) {
-          memset(ret, 0, size);
-          return ret;
-        }
-        return __the_bdw_gc_heap->allocation_failure(__the_bdw_gc_heap, size);
+  }
+  switch (kind) {
+    case GC_ALLOCATION_TAGGED:
+    case GC_ALLOCATION_UNTAGGED_CONSERVATIVE: {
+      void *ret = GC_malloc(size);
+      if (GC_LIKELY (ret != NULL))
+        return ret;
+      return __the_bdw_gc_heap->allocation_failure(__the_bdw_gc_heap, size);
+    }
+    case GC_ALLOCATION_TAGGED_POINTERLESS:
+    case GC_ALLOCATION_UNTAGGED_POINTERLESS: {
+      void *ret = GC_malloc_atomic(size);
+      if (GC_LIKELY (ret != NULL)) {
+        memset(ret, 0, size);
+        return ret;
       }
-      default:
-        GC_CRASH();
+      return __the_bdw_gc_heap->allocation_failure(__the_bdw_gc_heap, size);
     }
+    default:
+      GC_CRASH();
   }
 }
 
@@ -400,18 +393,7 @@ mark_mutator(GC_word *addr, struct GC_ms_entry 
*mark_stack_ptr,
     return state.mark_stack_ptr;
   }
 
-  for (int i = 0; i < GC_INLINE_FREELIST_COUNT; i++)
-    state.mark_stack_ptr = GC_MARK_AND_PUSH (mut->freelists[i],
-                                             state.mark_stack_ptr,
-                                             state.mark_stack_limit,
-                                             NULL);
-
-  for (int i = 0; i < GC_INLINE_FREELIST_COUNT; i++)
-    for (void *head = mut->pointerless_freelists[i]; head; head = 
*(void**)head)
-      state.mark_stack_ptr = GC_MARK_AND_PUSH (head,
-                                               state.mark_stack_ptr,
-                                               state.mark_stack_limit,
-                                               NULL);
+  memset(mut->freelists, 0, sizeof(void*) * GC_INLINE_FREELIST_COUNT);
 
   if (mut->roots)
     gc_trace_mutator_roots(mut->roots, bdw_mark_edge, mut->heap, &state);

Reply via email to