1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-07-05 17:20:18 +02:00

Capturing continuations pins conservative roots

* libguile/continuations.c (pin_conservative_roots): New helper.
(capture_auxiliary_stack):
(scm_i_make_continuation): Pin aux stack, jmpbuf, and stack items.
This commit is contained in:
Andy Wingo 2025-06-13 13:30:36 +02:00
parent 12da6739b1
commit 4e5a132f4f

View file

@ -38,6 +38,7 @@
#include "debug.h" #include "debug.h"
#include "dynstack.h" #include "dynstack.h"
#include "eval.h" #include "eval.h"
#include "gc-internal.h"
#include "gsubr.h" #include "gsubr.h"
#include "init.h" #include "init.h"
#include "instructions.h" #include "instructions.h"
@ -118,6 +119,23 @@ scm_i_print_continuation (SCM obj, SCM port, scm_print_state *state SCM_UNUSED)
return 1; 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 /* James Clark came up with this neat one instruction fix for
* continuations on the SPARC. It flushes the register windows so * continuations on the SPARC. It flushes the register windows so
* that all the state of the process is contained in the stack. * 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"); "continuation auxiliary stack");
memcpy (continuation->auxiliary_stack, thread->auxiliary_stack_base, memcpy (continuation->auxiliary_stack, thread->auxiliary_stack_base,
continuation->auxiliary_stack_size); continuation->auxiliary_stack_size);
pin_conservative_roots (thread,
continuation->auxiliary_stack,
continuation->auxiliary_stack_size);
#endif /* SCM_HAVE_AUXILIARY_STACK */ #endif /* SCM_HAVE_AUXILIARY_STACK */
} }
@ -183,6 +205,7 @@ scm_i_make_continuation (scm_thread *thread, struct scm_vm_cont *vm_cont)
"continuation"); "continuation");
continuation->tag = scm_tc16_continuation; continuation->tag = scm_tc16_continuation;
memcpy (continuation->jmpbuf, thread->vm.registers, sizeof (jmp_buf)); memcpy (continuation->jmpbuf, thread->vm.registers, sizeof (jmp_buf));
pin_conservative_roots (thread, continuation->jmpbuf, sizeof (jmp_buf));
capture_auxiliary_stack (thread, continuation); capture_auxiliary_stack (thread, continuation);
continuation->root = thread->continuation_root; continuation->root = thread->continuation_root;
continuation->vm_cont = vm_cont; 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); memcpy (continuation->stack, src, sizeof (SCM_STACKITEM) * stack_size);
continuation->offset = continuation->stack - src; continuation->offset = continuation->stack - src;
continuation->num_stack_items = stack_size; continuation->num_stack_items = stack_size;
pin_conservative_roots (thread, continuation->stack,
sizeof (SCM_STACKITEM) * stack_size);
return make_continuation_trampoline (continuation); return make_continuation_trampoline (continuation);
} }