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

commit 2dab407ec156edd90d64663e1abae284a0578e10
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Fri Apr 18 15:08:01 2025 +0200

    Expose definition of gc_stack_addr, rework API
---
 api/gc-api.h            | 10 +++-------
 api/gc-stack-addr.h     | 36 ++++++++++++++++++++++++++++++++++++
 benchmarks/ephemerons.c |  5 +++--
 benchmarks/finalizers.c |  5 +++--
 benchmarks/mt-gcbench.c |  5 +++--
 benchmarks/quads.c      |  3 ++-
 embed.am                |  1 +
 src/bdw.c               | 10 +++++++---
 src/gc-stack.c          | 35 ++++++++++++++++-------------------
 src/gc-stack.h          |  7 ++-----
 src/mmc.c               |  5 ++---
 src/pcc.c               |  4 ++--
 src/semi.c              |  4 ++--
 13 files changed, 82 insertions(+), 48 deletions(-)

diff --git a/api/gc-api.h b/api/gc-api.h
index 78d8b2bdb..603b38030 100644
--- a/api/gc-api.h
+++ b/api/gc-api.h
@@ -11,6 +11,7 @@
 #include "gc-inline.h"
 #include "gc-options.h"
 #include "gc-ref.h"
+#include "gc-stack-addr.h"
 #include "gc-visibility.h"
 
 #include <stdatomic.h>
@@ -20,13 +21,8 @@
 struct gc_heap;
 struct gc_mutator;
 
-struct gc_stack_addr;
-GC_API_ void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr *,
-                                                 void *),
-                                      void *data) GC_NEVER_INLINE;
-
 GC_API_ int gc_init(const struct gc_options *options,
-                    struct gc_stack_addr *base, struct gc_heap **heap,
+                    struct gc_stack_addr base, struct gc_heap **heap,
                     struct gc_mutator **mutator,
                     struct gc_event_listener event_listener,
                     void *event_listener_data);
@@ -50,7 +46,7 @@ struct gc_extern_space;
 GC_API_ void gc_heap_set_extern_space(struct gc_heap *heap,
                                       struct gc_extern_space *space);
 
-GC_API_ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *base,
+GC_API_ struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base,
                                               struct gc_heap *heap);
 GC_API_ void gc_finish_for_thread(struct gc_mutator *mut);
 GC_API_ void* gc_call_without_gc(struct gc_mutator *mut, void* (*f)(void*),
diff --git a/api/gc-stack-addr.h b/api/gc-stack-addr.h
new file mode 100644
index 000000000..62c089432
--- /dev/null
+++ b/api/gc-stack-addr.h
@@ -0,0 +1,36 @@
+#ifndef GC_STACK_ADDR_H
+#define GC_STACK_ADDR_H
+
+#include "gc-assert.h"
+#include "gc-visibility.h"
+
+struct gc_stack_addr {
+  uintptr_t addr;
+};
+
+static inline struct gc_stack_addr gc_empty_stack_addr (void) {
+  return (struct gc_stack_addr){ 0 };
+};
+
+static inline int gc_stack_addr_is_empty (struct gc_stack_addr addr) {
+  return addr.addr == 0;
+};
+
+static inline char* gc_stack_addr_as_pointer (struct gc_stack_addr addr) {
+  GC_ASSERT(!gc_stack_addr_is_empty(addr));
+  return (char*)addr.addr;
+};
+
+static inline struct gc_stack_addr gc_stack_addr (uintptr_t addr) {
+  GC_ASSERT(addr);
+  return (struct gc_stack_addr){ addr };
+};
+
+GC_API_ void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr,
+                                                 void *),
+                                      void *data) GC_NEVER_INLINE;
+
+GC_API_ int gc_stack_addr_is_colder(struct gc_stack_addr a,
+                                    struct gc_stack_addr b);
+
+#endif // GC_STACK_ADDR_H
diff --git a/benchmarks/ephemerons.c b/benchmarks/ephemerons.c
index 2262bd5c9..c74db9d43 100644
--- a/benchmarks/ephemerons.c
+++ b/benchmarks/ephemerons.c
@@ -56,7 +56,7 @@ struct call_with_gc_data {
   void* (*f)(struct thread *);
   struct gc_heap *heap;
 };
-static void* call_with_gc_inner(struct gc_stack_addr *addr, void *arg) {
+static void* call_with_gc_inner(struct gc_stack_addr addr, void *arg) {
   struct call_with_gc_data *data = arg;
   struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
   struct thread t = { mut, };
@@ -234,7 +234,8 @@ int main(int argc, char *argv[]) {
   struct gc_heap *heap;
   struct gc_mutator *mut;
   struct gc_basic_stats stats;
-  if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) {
+  if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut,
+               GC_BASIC_STATS, &stats)) {
     fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
             (size_t)heap_size);
     return 1;
diff --git a/benchmarks/finalizers.c b/benchmarks/finalizers.c
index 537307118..79a2660c3 100644
--- a/benchmarks/finalizers.c
+++ b/benchmarks/finalizers.c
@@ -56,7 +56,7 @@ struct call_with_gc_data {
   void* (*f)(struct thread *);
   struct gc_heap *heap;
 };
-static void* call_with_gc_inner(struct gc_stack_addr *addr, void *arg) {
+static void* call_with_gc_inner(struct gc_stack_addr addr, void *arg) {
   struct call_with_gc_data *data = arg;
   struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
   struct thread t = { mut, };
@@ -241,7 +241,8 @@ int main(int argc, char *argv[]) {
   struct gc_heap *heap;
   struct gc_mutator *mut;
   struct gc_basic_stats stats;
-  if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) {
+  if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut,
+               GC_BASIC_STATS, &stats)) {
     fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
             (size_t)heap_size);
     return 1;
diff --git a/benchmarks/mt-gcbench.c b/benchmarks/mt-gcbench.c
index 9b2521043..62fdc7154 100644
--- a/benchmarks/mt-gcbench.c
+++ b/benchmarks/mt-gcbench.c
@@ -258,7 +258,7 @@ struct call_with_gc_data {
   void* (*f)(struct thread *);
   struct gc_heap *heap;
 };
-static void* call_with_gc_inner(struct gc_stack_addr *addr, void *arg) {
+static void* call_with_gc_inner(struct gc_stack_addr addr, void *arg) {
   struct call_with_gc_data *data = arg;
   struct gc_mutator *mut = gc_init_for_thread(addr, data->heap);
   struct thread t = { mut, };
@@ -364,7 +364,8 @@ int main(int argc, char *argv[]) {
   struct gc_heap *heap;
   struct gc_mutator *mut;
   struct gc_basic_stats stats;
-  if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) {
+  if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut,
+               GC_BASIC_STATS, &stats)) {
     fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
             heap_size);
     return 1;
diff --git a/benchmarks/quads.c b/benchmarks/quads.c
index 6fa19f452..51bcca870 100644
--- a/benchmarks/quads.c
+++ b/benchmarks/quads.c
@@ -135,7 +135,8 @@ int main(int argc, char *argv[]) {
   struct gc_heap *heap;
   struct gc_mutator *mut;
   struct gc_basic_stats stats;
-  if (!gc_init(options, NULL, &heap, &mut, GC_BASIC_STATS, &stats)) {
+  if (!gc_init(options, gc_empty_stack_addr(), &heap, &mut,
+               GC_BASIC_STATS, &stats)) {
     fprintf(stderr, "Failed to initialize GC with heap size %zu bytes\n",
             heap_size);
     return 1;
diff --git a/embed.am b/embed.am
index d59dbd06f..57423b515 100644
--- a/embed.am
+++ b/embed.am
@@ -67,6 +67,7 @@ libwhippet_la_SOURCES = \
   %D%/api/gc-null-event-listener.h \
   %D%/api/gc-options.h \
   %D%/api/gc-ref.h \
+  %D%/api/gc-stack-addr.h \
   %D%/api/gc-tracepoint.h \
   %D%/api/gc-visibility.h \
   %D%/api/mmc-attrs.h \
diff --git a/src/bdw.c b/src/bdw.c
index 2fcc02e37..83a157d61 100644
--- a/src/bdw.c
+++ b/src/bdw.c
@@ -490,6 +490,10 @@ static void on_collection_event(GC_EventType event) {
     // Sloppily attribute finalizers and eager reclamation to
     // ephemerons.
     HEAP_EVENT(ephemerons_traced);
+    // FIXME: This overestimates the live data size, as blocks that have at
+    // least one live object will be lazily swept, and free space discovered in
+    // those objects will be added to GC_bytes_found, which would need to be
+    // subtracted from this value.
     HEAP_EVENT(live_data_size, GC_get_heap_size() - GC_get_free_bytes());
     break;
   case GC_EVENT_END:
@@ -517,7 +521,7 @@ uint64_t gc_allocation_counter(struct gc_heap *heap) {
   return GC_get_total_bytes();
 }
 
-int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
+int gc_init(const struct gc_options *options, struct gc_stack_addr stack_base,
             struct gc_heap **heap, struct gc_mutator **mutator,
             struct gc_event_listener event_listener,
             void *event_listener_data) {
@@ -613,9 +617,9 @@ int gc_init(const struct gc_options *options, struct 
gc_stack_addr *stack_base,
   return 1;
 }
 
-struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *stack_base,
+struct gc_mutator* gc_init_for_thread(struct gc_stack_addr stack_base,
                                       struct gc_heap *heap) {
-  struct GC_stack_base base = { stack_base };
+  struct GC_stack_base base = { gc_stack_addr_as_pointer (stack_base) };
   GC_register_my_thread(&base);
   return add_mutator(heap);
 }
diff --git a/src/gc-stack.c b/src/gc-stack.c
index 318f5757f..e4e170505 100644
--- a/src/gc-stack.c
+++ b/src/gc-stack.c
@@ -26,40 +26,37 @@ static uintptr_t current_thread_hot_stack_addr(void) {
 // FIXME: check platform stack growth direction.
 #define HOTTER_THAN <=
 
-static void capture_current_thread_hot_stack_addr(struct gc_stack_addr *addr) {
-  addr->addr = current_thread_hot_stack_addr();
+static struct gc_stack_addr capture_current_thread_hot_stack_addr(void) {
+  return gc_stack_addr(current_thread_hot_stack_addr());
 }
 
-static void capture_current_thread_cold_stack_addr(struct gc_stack_addr *addr) 
{
-  addr->addr = gc_platform_current_thread_stack_base();
+static struct gc_stack_addr capture_current_thread_cold_stack_addr(void) {
+  return gc_stack_addr(gc_platform_current_thread_stack_base());
 }
 
-void gc_stack_init(struct gc_stack *stack, struct gc_stack_addr *base) {
-  if (base)
-    stack->cold = *base;
-  else
-    capture_current_thread_cold_stack_addr(&stack->cold);
-  stack->hot = stack->cold;
+void gc_stack_init(struct gc_stack *stack, struct gc_stack_addr base) {
+  if (gc_stack_addr_is_empty (base))
+    base = capture_current_thread_cold_stack_addr();
+  stack->cold = stack->hot = base;
 }
 
 void gc_stack_capture_hot(struct gc_stack *stack) {
-  capture_current_thread_hot_stack_addr(&stack->hot);
+  stack->hot = capture_current_thread_hot_stack_addr();
   setjmp(stack->registers);
   GC_ASSERT(stack->hot.addr HOTTER_THAN stack->cold.addr);
 }
 
-static void* call_with_stack(void* (*)(struct gc_stack_addr*, void*),
-                             struct gc_stack_addr*, void*) GC_NEVER_INLINE;
-static void* call_with_stack(void* (*f)(struct gc_stack_addr *, void *),
-                             struct gc_stack_addr *addr, void *arg) {
+static void* call_with_stack(void* (*)(struct gc_stack_addr, void*),
+                             struct gc_stack_addr, void*) GC_NEVER_INLINE;
+static void* call_with_stack(void* (*f)(struct gc_stack_addr, void *),
+                             struct gc_stack_addr addr, void *arg) {
   return f(addr, arg);
 }
-void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr *base,
+void* gc_call_with_stack_addr(void* (*f)(struct gc_stack_addr base,
                                          void *arg),
                               void *arg) {
-  struct gc_stack_addr base;
-  capture_current_thread_hot_stack_addr(&base);
-  return call_with_stack(f, &base, arg);
+  struct gc_stack_addr base = capture_current_thread_hot_stack_addr();
+  return call_with_stack(f, base, arg);
 }
 
 void gc_stack_visit(struct gc_stack *stack,
diff --git a/src/gc-stack.h b/src/gc-stack.h
index 15df9df6d..b075f5a57 100644
--- a/src/gc-stack.h
+++ b/src/gc-stack.h
@@ -6,12 +6,9 @@
 #endif
 
 #include "gc-inline.h"
+#include "gc-stack-addr.h"
 #include <setjmp.h>
 
-struct gc_stack_addr {
-  uintptr_t addr;
-};
-
 struct gc_stack {
   struct gc_stack_addr cold;
   struct gc_stack_addr hot;
@@ -21,7 +18,7 @@ struct gc_stack {
 struct gc_heap;
 
 GC_INTERNAL void gc_stack_init(struct gc_stack *stack,
-                               struct gc_stack_addr *base);
+                               struct gc_stack_addr base);
 GC_INTERNAL void gc_stack_capture_hot(struct gc_stack *stack);
 GC_INTERNAL void gc_stack_visit(struct gc_stack *stack,
                                 void (*visit)(uintptr_t low, uintptr_t high,
diff --git a/src/mmc.c b/src/mmc.c
index 661b7084b..d2bc4df9d 100644
--- a/src/mmc.c
+++ b/src/mmc.c
@@ -1148,7 +1148,7 @@ heap_init(struct gc_heap *heap, const struct gc_options 
*options) {
 }
 
 int
-gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
+gc_init(const struct gc_options *options, struct gc_stack_addr stack_base,
         struct gc_heap **heap, struct gc_mutator **mut,
         struct gc_event_listener event_listener,
         void *event_listener_data) {
@@ -1217,8 +1217,7 @@ gc_init(const struct gc_options *options, struct 
gc_stack_addr *stack_base,
 }
 
 struct gc_mutator*
-gc_init_for_thread(struct gc_stack_addr *stack_base,
-                                      struct gc_heap *heap) {
+gc_init_for_thread(struct gc_stack_addr stack_base, struct gc_heap *heap) {
   struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator));
   if (!ret)
     GC_CRASH();
diff --git a/src/pcc.c b/src/pcc.c
index ca8be1c11..0b137f56b 100644
--- a/src/pcc.c
+++ b/src/pcc.c
@@ -1218,7 +1218,7 @@ static int heap_init(struct gc_heap *heap, const struct 
gc_options *options) {
   return 1;
 }
 
-int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
+int gc_init(const struct gc_options *options, struct gc_stack_addr stack_base,
             struct gc_heap **heap, struct gc_mutator **mut,
             struct gc_event_listener event_listener,
             void *event_listener_data) {
@@ -1294,7 +1294,7 @@ int gc_init(const struct gc_options *options, struct 
gc_stack_addr *stack_base,
   return 1;
 }
 
-struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *stack_base,
+struct gc_mutator* gc_init_for_thread(struct gc_stack_addr stack_base,
                                       struct gc_heap *heap) {
   struct gc_mutator *ret = calloc(1, sizeof(struct gc_mutator));
   if (!ret)
diff --git a/src/semi.c b/src/semi.c
index 6f902534d..a4ee85f39 100644
--- a/src/semi.c
+++ b/src/semi.c
@@ -670,7 +670,7 @@ int gc_options_parse_and_set(struct gc_options *options, 
int option,
   return gc_common_options_parse_and_set(&options->common, option, value);
 }
 
-int gc_init(const struct gc_options *options, struct gc_stack_addr *stack_base,
+int gc_init(const struct gc_options *options, struct gc_stack_addr stack_base,
             struct gc_heap **heap, struct gc_mutator **mut,
             struct gc_event_listener event_listener,
             void *event_listener_data) {
@@ -722,7 +722,7 @@ void gc_heap_set_extern_space(struct gc_heap *heap,
   heap->extern_space = space;
 }
 
-struct gc_mutator* gc_init_for_thread(struct gc_stack_addr *base,
+struct gc_mutator* gc_init_for_thread(struct gc_stack_addr base,
                                       struct gc_heap *heap) {
   fprintf(stderr,
           "Semispace copying collector not appropriate for multithreaded 
use.\n");

Reply via email to