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

commit 08e6633f93803300e6700247f9a698ee423596dc
Author: Andy Wingo <wi...@igalia.com>
AuthorDate: Thu May 15 14:46:34 2025 +0200

    Add embedder API to provide heap and mutator conservative roots
---
 api/gc-embedder-api.h           | 19 +++++++++++++++++++
 benchmarks/simple-gc-embedder.h | 20 ++++++++++++++++++++
 src/bdw.c                       | 23 +++++++++++++++++++++--
 src/mmc.c                       | 19 +++++++++++++++++--
 src/root.h                      | 16 ++++++++++++++++
 5 files changed, 93 insertions(+), 4 deletions(-)

diff --git a/api/gc-embedder-api.h b/api/gc-embedder-api.h
index c1b272a51..28a0fb6de 100644
--- a/api/gc-embedder-api.h
+++ b/api/gc-embedder-api.h
@@ -50,6 +50,25 @@ GC_EMBEDDER_API inline void gc_trace_heap_roots(struct 
gc_heap_roots *roots,
                                                 struct gc_heap *heap,
                                                 void *trace_data);
 
+GC_EMBEDDER_API inline void
+gc_trace_mutator_conservative_roots(struct gc_mutator_roots *roots,
+                                    void (*trace_range)(uintptr_t start,
+                                                        uintptr_t end,
+                                                        int possibly_interior,
+                                                        struct gc_heap *heap,
+                                                        void *data),
+                                    struct gc_heap *heap,
+                                    void *data);
+GC_EMBEDDER_API inline void
+gc_trace_heap_conservative_roots(struct gc_heap_roots *roots,
+                                 void (*trace_range)(uintptr_t start,
+                                                     uintptr_t end,
+                                                     int possibly_interior,
+                                                     struct gc_heap *heap,
+                                                     void *data),
+                                 struct gc_heap *heap,
+                                 void *data);
+
 GC_EMBEDDER_API inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref 
ref);
 GC_EMBEDDER_API inline void gc_object_forward_nonatomic(struct gc_ref ref,
                                                         struct gc_ref new_ref);
diff --git a/benchmarks/simple-gc-embedder.h b/benchmarks/simple-gc-embedder.h
index 904d2c740..6f329573b 100644
--- a/benchmarks/simple-gc-embedder.h
+++ b/benchmarks/simple-gc-embedder.h
@@ -92,6 +92,26 @@ static inline void gc_trace_heap_roots(struct gc_heap_roots 
*roots,
     visit_roots(roots->roots, trace_edge, heap, trace_data);
 }
 
+static inline void
+gc_trace_mutator_conservative_roots(struct gc_mutator_roots *roots,
+                                    void (*trace_range)(uintptr_t start,
+                                                        uintptr_t end,
+                                                        int possibly_interior,
+                                                        struct gc_heap *heap,
+                                                        void *data),
+                                    struct gc_heap *heap,
+                                    void *data) {}
+
+static inline void
+gc_trace_heap_conservative_roots(struct gc_heap_roots *roots,
+                                 void (*trace_range)(uintptr_t start,
+                                                     uintptr_t end,
+                                                     int possibly_interior,
+                                                     struct gc_heap *heap,
+                                                     void *data),
+                                 struct gc_heap *heap,
+                                 void *data) {}
+
 static inline uintptr_t gc_object_forwarded_nonatomic(struct gc_ref ref) {
   uintptr_t tag = *tag_word(ref);
   return (tag & gcobj_not_forwarded_bit) ? 0 : tag;
diff --git a/src/bdw.c b/src/bdw.c
index 8419df46e..fa06f7256 100644
--- a/src/bdw.c
+++ b/src/bdw.c
@@ -228,6 +228,20 @@ static void bdw_mark_edge(struct gc_edge edge, struct 
gc_heap *heap,
                                             NULL);
 }
 
+static void bdw_mark_range(uintptr_t lo, uintptr_t hi, int possibly_interior,
+                           struct gc_heap *heap, void *visit_data) {
+  struct bdw_mark_state *state = visit_data;
+
+  GC_ASSERT_EQ (lo, align_up (lo, sizeof(void*)));
+  GC_ASSERT_EQ (hi, align_up (hi, sizeof(void*)));
+
+  for (void **walk = (void**)lo, **end = (void**)hi; walk < end; walk++)
+    state->mark_stack_ptr = GC_MARK_AND_PUSH (*walk,
+                                              state->mark_stack_ptr,
+                                              state->mark_stack_limit,
+                                              NULL);
+}
+
 static int heap_gc_kind;
 static int mutator_gc_kind;
 static int ephemeron_gc_kind;
@@ -380,8 +394,10 @@ mark_heap(GC_word *addr, struct GC_ms_entry 
*mark_stack_ptr,
   if (heap != __the_bdw_gc_heap)
     return state.mark_stack_ptr;
 
-  if (heap->roots)
+  if (heap->roots) {
+    gc_trace_heap_conservative_roots(heap->roots, bdw_mark_range, heap, 
&state);
     gc_trace_heap_roots(heap->roots, bdw_mark_edge, heap, &state);
+  }
 
   gc_visit_finalizer_roots(heap->finalizer_state, bdw_mark_edge, heap, &state);
 
@@ -415,8 +431,11 @@ mark_mutator(GC_word *addr, struct GC_ms_entry 
*mark_stack_ptr,
 
   memset(mut->freelists, 0, sizeof(void*) * GC_INLINE_FREELIST_COUNT);
 
-  if (mut->roots)
+  if (mut->roots) {
+    gc_trace_mutator_conservative_roots(mut->roots, bdw_mark_range,
+                                        mut->heap, &state);
     gc_trace_mutator_roots(mut->roots, bdw_mark_edge, mut->heap, &state);
+  }
 
   state.mark_stack_ptr = GC_MARK_AND_PUSH (mut->next,
                                            state.mark_stack_ptr,
diff --git a/src/mmc.c b/src/mmc.c
index ab0b9f54a..4e79675cc 100644
--- a/src/mmc.c
+++ b/src/mmc.c
@@ -328,7 +328,8 @@ load_conservative_ref(uintptr_t addr) {
 
 static inline void
 trace_conservative_edges(uintptr_t low, uintptr_t high, int possibly_interior,
-                         struct gc_heap *heap, struct gc_trace_worker *worker) 
{
+                         struct gc_heap *heap, void *data) {
+  struct gc_trace_worker *worker = data;
   GC_ASSERT(low == align_down(low, sizeof(uintptr_t)));
   GC_ASSERT(high == align_down(high, sizeof(uintptr_t)));
   for (uintptr_t addr = low; addr < high; addr += sizeof(uintptr_t))
@@ -402,6 +403,14 @@ trace_root(struct gc_root root, struct gc_heap *heap,
     gc_field_set_visit_edge_buffer(&heap->remembered_set, root.edge_buffer,
                                    trace_remembered_edge, heap, worker);
     break;
+  case GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS:
+    gc_trace_heap_conservative_roots(root.heap->roots, 
trace_conservative_edges,
+                                     heap, worker);
+    break;
+  case GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS:
+    gc_trace_mutator_conservative_roots(root.mutator->roots,
+                                        trace_conservative_edges, heap, 
worker);
+    break;
   default:
     GC_CRASH();
   }
@@ -639,9 +648,13 @@ enqueue_mutator_conservative_roots(struct gc_heap *heap) {
     int possibly_interior = gc_mutator_conservative_roots_may_be_interior();
     for (struct gc_mutator *mut = heap->mutators;
          mut;
-         mut = mut->next)
+         mut = mut->next) {
       gc_stack_visit(&mut->stack, enqueue_conservative_roots, heap,
                      &possibly_interior);
+      if (mut->roots)
+        gc_tracer_add_root(&heap->tracer,
+                           gc_root_mutator_conservative_roots(mut));
+    }
     return 1;
   }
   return 0;
@@ -653,6 +666,8 @@ enqueue_global_conservative_roots(struct gc_heap *heap) {
     int possibly_interior = 0;
     gc_platform_visit_global_conservative_roots
       (enqueue_conservative_roots, heap, &possibly_interior);
+    if (heap->roots)
+      gc_tracer_add_root(&heap->tracer, gc_root_heap_conservative_roots(heap));
     return 1;
   }
   return 0;
diff --git a/src/root.h b/src/root.h
index 4fc705e61..597e8d840 100644
--- a/src/root.h
+++ b/src/root.h
@@ -18,6 +18,8 @@ enum gc_root_kind {
   GC_ROOT_KIND_RESOLVED_EPHEMERONS,
   GC_ROOT_KIND_EDGE,
   GC_ROOT_KIND_EDGE_BUFFER,
+  GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS,
+  GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS,
 };
 
 struct gc_root {
@@ -78,4 +80,18 @@ gc_root_edge_buffer(struct gc_edge_buffer *buf) {
   return ret;
 }
 
+static inline struct gc_root
+gc_root_heap_conservative_roots(struct gc_heap* heap) {
+  struct gc_root ret = { GC_ROOT_KIND_HEAP_CONSERVATIVE_ROOTS };
+  ret.heap = heap;
+  return ret;
+}
+
+static inline struct gc_root
+gc_root_mutator_conservative_roots(struct gc_mutator* mutator) {
+  struct gc_root ret = { GC_ROOT_KIND_MUTATOR_CONSERVATIVE_ROOTS };
+  ret.mutator = mutator;
+  return ret;
+}
+
 #endif // ROOT_H

Reply via email to