wingo pushed a commit to branch wip-whippet in repository guile. commit d560676572eb83736ae265ba41213936f7fb9c26 Author: Andy Wingo <wi...@pobox.com> AuthorDate: Thu May 15 15:15:28 2025 +0200
Wire loader DT_GUILE_GC_ROOT sections to Whippet API * libguile/loader.c (add_roots): (scm_trace_loader_conservative_roots): (process_dynamic_segment): Use Whippet API to register roots. * libguile/trace.h (struct gc_heap_roots): Define here. * libguile/whippet-embedder.h (gc_trace_mutator_conservative_roots): (gc_trace_heap_conservative_roots): Add definitions. --- libguile/gc.c | 6 ++++++ libguile/loader.c | 42 ++++++++++++++++++++++++++++++++++++++++-- libguile/trace.h | 10 ++++++++++ libguile/whippet-embedder.h | 25 +++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/libguile/gc.c b/libguile/gc.c index 42c93cfc3..289adf3f1 100644 --- a/libguile/gc.c +++ b/libguile/gc.c @@ -53,6 +53,7 @@ #include "strings.h" #include "struct.h" #include "symbols.h" +#include "trace.h" #include "vectors.h" #include "gc.h" @@ -634,6 +635,7 @@ scm_gc_unregister_roots (SCM *b, unsigned long n) +static struct gc_heap_roots heap_roots; struct gc_mutator * scm_storage_prehistory (struct gc_stack_addr base) @@ -661,6 +663,10 @@ scm_storage_prehistory (struct gc_stack_addr base) abort (); } + // We need to set roots so that scm_trace_loader_conservative_roots + // gets called. + gc_heap_set_roots(the_gc_heap, &heap_roots); + /* Sanity check. */ if (!GC_is_visible (&scm_protects)) abort (); diff --git a/libguile/loader.c b/libguile/loader.c index 09bd166ec..bd91601b6 100644 --- a/libguile/loader.c +++ b/libguile/loader.c @@ -37,18 +37,19 @@ #include <sys/mman.h> #endif -#include "bdw-gc.h" #include "boolean.h" #include "bytevectors.h" #include "elf.h" #include "eval.h" #include "extensions.h" #include "gsubr.h" +#include "gc-internal.h" #include "list.h" #include "pairs.h" #include "programs.h" #include "strings.h" #include "threads.h" +#include "trace.h" #include "version.h" #include "loader.h" @@ -93,6 +94,43 @@ #define ELFDATA ELFDATA2LSB #endif +static scm_i_pthread_mutex_t roots_lock = SCM_I_PTHREAD_MUTEX_INITIALIZER; +static size_t roots_count = 0; +static size_t roots_capacity = 0; +struct loader_roots { uintptr_t lo, hi; }; +static struct loader_roots *roots; + +static void +add_roots(char *lo, char *hi) +{ + scm_i_pthread_mutex_lock (&roots_lock); + if (roots_count == roots_capacity) + { + roots_capacity = roots_capacity * 2 + 128; + size_t elt_size = sizeof(*roots); + struct loader_roots *new_roots = calloc (roots_capacity, elt_size); + // Leak the old roots; we're still O(n) as all previous root + // arrays sum to less than the new roots_capacity. + memcpy (new_roots, roots, roots_count * elt_size); + roots = new_roots; + } + roots[roots_count++] = (struct loader_roots){ (uintptr_t)lo, (uintptr_t)hi }; + scm_i_pthread_mutex_unlock (&roots_lock); +} + +void +scm_trace_loader_conservative_roots (void (*trace_range)(uintptr_t lo, + uintptr_t hi, + int possibly_interior, + struct gc_heap *heap, + void *trace_data), + struct gc_heap *heap, + void *trace_data) +{ + for (size_t i = 0; i < roots_count; i++) + trace_range(roots[i].lo, roots[i].hi, 0, heap, trace_data); +} + /* The page size. */ static size_t page_size; @@ -345,7 +383,7 @@ process_dynamic_segment (char *base, Elf_Phdr *dyn_phdr, } if (gc_root) - GC_add_roots (gc_root, gc_root + gc_root_size); + add_roots (gc_root, gc_root + gc_root_size); *init_out = init ? pointer_to_procedure (bytecode_kind, init) : SCM_BOOL_F; *entry_out = pointer_to_procedure (bytecode_kind, entry); diff --git a/libguile/trace.h b/libguile/trace.h index e05050470..d2705c112 100644 --- a/libguile/trace.h +++ b/libguile/trace.h @@ -29,6 +29,7 @@ struct scm_thread; struct scm_vm; struct gc_heap; +struct gc_heap_roots { int unused; }; SCM_INTERNAL void scm_trace_thread_mutator_roots (struct scm_thread *thread, @@ -52,5 +53,14 @@ SCM_INTERNAL void scm_trace_vm (struct scm_vm *vp, struct gc_heap *heap, void *trace_data); +SCM_INTERNAL void +scm_trace_loader_conservative_roots (void (*trace_range)(uintptr_t lo, + uintptr_t hi, + int possibly_interior, + struct gc_heap *heap, + void *trace_data), + struct gc_heap *heap, + void *trace_data); + #endif /* SCM_THREADS_INTERNAL_H */ diff --git a/libguile/whippet-embedder.h b/libguile/whippet-embedder.h index aa82eb4f1..82e177936 100644 --- a/libguile/whippet-embedder.h +++ b/libguile/whippet-embedder.h @@ -109,6 +109,31 @@ static inline void gc_trace_heap_roots (struct gc_heap_roots *roots, void *trace_data) { } +static inline void +gc_trace_mutator_conservative_roots (struct gc_mutator_roots *roots, + void (*trace_range) (uintptr_t lo, + uintptr_t hi, + int possibly_interior, + struct gc_heap *heap, + void *trace_data), + struct gc_heap *heap, + void *trace_data) { + /* FIXME: thread stack? Currently traced via the precise + gc_trace_mutator_roots. */ +} + +static inline void +gc_trace_heap_conservative_roots (struct gc_heap_roots *roots, + void (*trace_range) (uintptr_t lo, + uintptr_t hi, + int possibly_interior, + struct gc_heap *heap, + void *trace_data), + struct gc_heap *heap, + void *trace_data) { + scm_trace_loader_conservative_roots(trace_range, heap, trace_data); +} + static inline SCM scm_from_gc_ref (struct gc_ref ref) { return SCM_PACK (gc_ref_value (ref)); }