mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Refactor continuation capture in VM
* libguile/continuations.h: * libguile/continuations.c (scm_i_make_continuation): Refactor to expect registers to already be captured. * libguile/scm.h (scm_i_thread): Add forward decl. * libguile/threads.h (struct scm_i_thread): Just fill in the struct type. * libguile/vm-engine.c (call/cc); Use the registers already captured before entering the VM.
This commit is contained in:
parent
185d19dfb1
commit
51e35158ba
5 changed files with 19 additions and 49 deletions
|
@ -166,18 +166,12 @@ restore_auxiliary_stack (scm_i_thread *thread, scm_t_contregs *continuation)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* this may return more than once: the first time with the escape
|
|
||||||
procedure, then subsequently with SCM_UNDEFINED (the vals already having been
|
|
||||||
placed on the VM stack). */
|
|
||||||
#define FUNC_NAME "scm_i_make_continuation"
|
|
||||||
SCM
|
SCM
|
||||||
scm_i_make_continuation (int *first, struct scm_vm *vp, SCM vm_cont)
|
scm_i_make_continuation (jmp_buf *registers, scm_i_thread *thread, SCM vm_cont)
|
||||||
{
|
{
|
||||||
scm_i_thread *thread = SCM_I_CURRENT_THREAD;
|
|
||||||
SCM cont;
|
SCM cont;
|
||||||
scm_t_contregs *continuation;
|
scm_t_contregs *continuation;
|
||||||
long stack_size;
|
long stack_size;
|
||||||
const void *saved_cookie;
|
|
||||||
SCM_STACKITEM * src;
|
SCM_STACKITEM * src;
|
||||||
|
|
||||||
SCM_FLUSH_REGISTER_WINDOWS;
|
SCM_FLUSH_REGISTER_WINDOWS;
|
||||||
|
@ -193,23 +187,14 @@ scm_i_make_continuation (int *first, struct scm_vm *vp, SCM vm_cont)
|
||||||
#endif
|
#endif
|
||||||
continuation->offset = continuation->stack - src;
|
continuation->offset = continuation->stack - src;
|
||||||
memcpy (continuation->stack, src, sizeof (SCM_STACKITEM) * stack_size);
|
memcpy (continuation->stack, src, sizeof (SCM_STACKITEM) * stack_size);
|
||||||
|
memcpy (continuation->jmpbuf, registers, sizeof (*registers));
|
||||||
continuation->vm_cont = vm_cont;
|
continuation->vm_cont = vm_cont;
|
||||||
saved_cookie = vp->resumable_prompt_cookie;
|
|
||||||
capture_auxiliary_stack (thread, continuation);
|
capture_auxiliary_stack (thread, continuation);
|
||||||
|
|
||||||
SCM_NEWSMOB (cont, tc16_continuation, continuation);
|
SCM_NEWSMOB (cont, tc16_continuation, continuation);
|
||||||
|
|
||||||
*first = !setjmp (continuation->jmpbuf);
|
return make_continuation_trampoline (cont);
|
||||||
if (*first)
|
|
||||||
return make_continuation_trampoline (cont);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vp->resumable_prompt_cookie = saved_cookie;
|
|
||||||
scm_gc_after_nonlocal_exit ();
|
|
||||||
return SCM_UNDEFINED;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#undef FUNC_NAME
|
|
||||||
|
|
||||||
int
|
int
|
||||||
scm_i_continuation_to_frame (SCM continuation, struct scm_frame *frame)
|
scm_i_continuation_to_frame (SCM continuation, struct scm_frame *frame)
|
||||||
|
|
|
@ -67,8 +67,8 @@ typedef struct
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SCM_INTERNAL SCM scm_i_make_continuation (int *first,
|
SCM_INTERNAL SCM scm_i_make_continuation (jmp_buf *registers,
|
||||||
struct scm_vm *vp,
|
scm_i_thread *thread,
|
||||||
SCM vm_cont);
|
SCM vm_cont);
|
||||||
SCM_INTERNAL void scm_i_reinstate_continuation (SCM cont) SCM_NORETURN;
|
SCM_INTERNAL void scm_i_reinstate_continuation (SCM cont) SCM_NORETURN;
|
||||||
|
|
||||||
|
|
|
@ -827,7 +827,7 @@ typedef int32_t scm_t_wchar;
|
||||||
struct scm_frame;
|
struct scm_frame;
|
||||||
struct scm_vm;
|
struct scm_vm;
|
||||||
union scm_vm_stack_element;
|
union scm_vm_stack_element;
|
||||||
|
typedef struct scm_i_thread scm_i_thread; /* FIXME: Rename. */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ SCM_API scm_t_bits scm_tc16_condvar;
|
||||||
|
|
||||||
struct scm_thread_wake_data;
|
struct scm_thread_wake_data;
|
||||||
|
|
||||||
typedef struct scm_i_thread {
|
struct scm_i_thread {
|
||||||
struct scm_i_thread *next_thread;
|
struct scm_i_thread *next_thread;
|
||||||
|
|
||||||
SCM handle;
|
SCM handle;
|
||||||
|
@ -105,7 +105,7 @@ typedef struct scm_i_thread {
|
||||||
struct scm_vm vm;
|
struct scm_vm vm;
|
||||||
SCM_STACKITEM *base;
|
SCM_STACKITEM *base;
|
||||||
jmp_buf regs;
|
jmp_buf regs;
|
||||||
} scm_i_thread;
|
};
|
||||||
|
|
||||||
#define SCM_I_IS_THREAD(x) SCM_SMOB_PREDICATE (scm_tc16_thread, x)
|
#define SCM_I_IS_THREAD(x) SCM_SMOB_PREDICATE (scm_tc16_thread, x)
|
||||||
#define SCM_I_THREAD_DATA(x) ((scm_i_thread *) SCM_SMOB_DATA (x))
|
#define SCM_I_THREAD_DATA(x) ((scm_i_thread *) SCM_SMOB_DATA (x))
|
||||||
|
|
|
@ -758,7 +758,6 @@ VM_NAME (scm_i_thread *thread, jmp_buf *registers, int resume)
|
||||||
{
|
{
|
||||||
SCM vm_cont, cont;
|
SCM vm_cont, cont;
|
||||||
scm_t_dynstack *dynstack;
|
scm_t_dynstack *dynstack;
|
||||||
int first;
|
|
||||||
|
|
||||||
SYNC_IP ();
|
SYNC_IP ();
|
||||||
dynstack = scm_dynstack_capture_all (&thread->dynstack);
|
dynstack = scm_dynstack_capture_all (&thread->dynstack);
|
||||||
|
@ -768,35 +767,21 @@ VM_NAME (scm_i_thread *thread, jmp_buf *registers, int resume)
|
||||||
SCM_FRAME_RETURN_ADDRESS (VP->fp),
|
SCM_FRAME_RETURN_ADDRESS (VP->fp),
|
||||||
dynstack,
|
dynstack,
|
||||||
0);
|
0);
|
||||||
/* FIXME: Seems silly to capture the registers here, when they are
|
cont = scm_i_make_continuation (registers, thread, vm_cont);
|
||||||
already captured in the registers local, which here we are
|
|
||||||
copying out to the heap; and likewise, the setjmp(®isters)
|
|
||||||
code already has the non-local return handler. But oh
|
|
||||||
well! */
|
|
||||||
cont = scm_i_make_continuation (&first, VP, vm_cont);
|
|
||||||
|
|
||||||
if (first)
|
RESET_FRAME (2);
|
||||||
{
|
|
||||||
RESET_FRAME (2);
|
|
||||||
|
|
||||||
SP_SET (1, SP_REF (0));
|
SP_SET (1, SP_REF (0));
|
||||||
SP_SET (0, cont);
|
SP_SET (0, cont);
|
||||||
|
|
||||||
if (SCM_LIKELY (SCM_PROGRAM_P (SP_REF (1))))
|
if (SCM_LIKELY (SCM_PROGRAM_P (SP_REF (1))))
|
||||||
ip = SCM_PROGRAM_CODE (SP_REF (1));
|
ip = SCM_PROGRAM_CODE (SP_REF (1));
|
||||||
else
|
|
||||||
ip = (uint32_t *) vm_apply_non_program_code;
|
|
||||||
|
|
||||||
APPLY_HOOK ();
|
|
||||||
|
|
||||||
NEXT (0);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
ip = (uint32_t *) vm_apply_non_program_code;
|
||||||
CACHE_REGISTER ();
|
|
||||||
ABORT_CONTINUATION_HOOK ();
|
APPLY_HOOK ();
|
||||||
NEXT (0);
|
|
||||||
}
|
NEXT (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* abort _:24
|
/* abort _:24
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue