1
Fork 0
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:
Andy Wingo 2018-06-26 11:25:07 +02:00
parent 185d19dfb1
commit 51e35158ba
5 changed files with 19 additions and 49 deletions

View file

@ -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)

View file

@ -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;

View file

@ -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. */

View file

@ -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))

View file

@ -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(&registers)
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