diff options
Diffstat (limited to 'libguile/loader.c')
-rw-r--r-- | libguile/loader.c | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/libguile/loader.c b/libguile/loader.c index 09bd166ec..fd2a04609 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); |