diff --git a/libguile/continuations.c b/libguile/continuations.c index 2ea7d29fb..96ece0526 100644 --- a/libguile/continuations.c +++ b/libguile/continuations.c @@ -38,6 +38,7 @@ #include "debug.h" #include "dynstack.h" #include "eval.h" +#include "gc-internal.h" #include "gsubr.h" #include "init.h" #include "instructions.h" @@ -118,6 +119,23 @@ scm_i_print_continuation (SCM obj, SCM port, scm_print_state *state SCM_UNUSED) return 1; } +static void +pin_conservative_roots (scm_thread *thread, void *base, size_t size) +{ + struct gc_mutator *mut = thread->mutator; + struct gc_heap *heap = gc_mutator_heap (mut); + + size_t nwords = size / sizeof (scm_t_bits); + scm_t_bits *words = base; + for (size_t i = 0; i < nwords; i++) + { + struct gc_conservative_ref maybe_ref = gc_conservative_ref (words[i]); + struct gc_ref ref = gc_resolve_conservative_ref (heap, maybe_ref, 0); + if (!gc_ref_is_null (ref)) + gc_pin_object (mut, ref); + } +} + /* James Clark came up with this neat one instruction fix for * continuations on the SPARC. It flushes the register windows so * that all the state of the process is contained in the stack. @@ -160,6 +178,10 @@ capture_auxiliary_stack (scm_thread *thread, struct scm_continuation *continuati "continuation auxiliary stack"); memcpy (continuation->auxiliary_stack, thread->auxiliary_stack_base, continuation->auxiliary_stack_size); + + pin_conservative_roots (thread, + continuation->auxiliary_stack, + continuation->auxiliary_stack_size); #endif /* SCM_HAVE_AUXILIARY_STACK */ } @@ -183,6 +205,7 @@ scm_i_make_continuation (scm_thread *thread, struct scm_vm_cont *vm_cont) "continuation"); continuation->tag = scm_tc16_continuation; memcpy (continuation->jmpbuf, thread->vm.registers, sizeof (jmp_buf)); + pin_conservative_roots (thread, continuation->jmpbuf, sizeof (jmp_buf)); capture_auxiliary_stack (thread, continuation); continuation->root = thread->continuation_root; continuation->vm_cont = vm_cont; @@ -193,6 +216,8 @@ scm_i_make_continuation (scm_thread *thread, struct scm_vm_cont *vm_cont) memcpy (continuation->stack, src, sizeof (SCM_STACKITEM) * stack_size); continuation->offset = continuation->stack - src; continuation->num_stack_items = stack_size; + pin_conservative_roots (thread, continuation->stack, + sizeof (SCM_STACKITEM) * stack_size); return make_continuation_trampoline (continuation); }