1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-11 08:10:21 +02:00

Partial continuations are RTL stubs

* libguile/control.c: Implement partial continuations as RTL programs.

* libguile/programs.c (scm_i_rtl_program_minimum_arity): Add partial
  continuation case.

* libguile/vm-engine.c (compose-continuation): Fix to look for vm_cont
  from the free variables.

* libguile/vm-i-system.c (abort): Poison continuations captured in the
  stack VM, as the can't be rewound by the RTL stubs.
This commit is contained in:
Andy Wingo 2013-10-18 19:33:50 +02:00
parent d6fbf0c00e
commit d76de8716d
4 changed files with 24 additions and 70 deletions

View file

@ -24,7 +24,7 @@
#include "libguile/_scm.h" #include "libguile/_scm.h"
#include "libguile/control.h" #include "libguile/control.h"
#include "libguile/objcodes.h" #include "libguile/programs.h"
#include "libguile/instructions.h" #include "libguile/instructions.h"
#include "libguile/vm.h" #include "libguile/vm.h"
@ -57,69 +57,25 @@ scm_i_prompt_pop_abort_args_x (SCM vm)
} }
#ifdef WORDS_BIGENDIAN static const scm_t_uint32 compose_continuation_code[] =
#define OBJCODE_HEADER(main,meta) 0, 0, 0, main, 0, 0, 0, meta+8 {
#define META_HEADER(meta) 0, 0, 0, meta, 0, 0, 0, 0 SCM_PACK_RTL_24 (scm_rtl_op_compose_continuation, 0)
#else };
#define OBJCODE_HEADER(main,meta) main, 0, 0, 0, meta+8, 0, 0, 0
#define META_HEADER(meta) meta, 0, 0, 0, 0, 0, 0, 0
#endif
#define OBJCODE_TAG SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_STATIC, 0)
#if defined (SCM_ALIGNED)
#define SCM_DECLARE_STATIC_ALIGNED_ARRAY(type, sym) \
static const type sym[]
#define SCM_STATIC_ALIGNED_ARRAY(alignment, type, sym) \
static SCM_ALIGNED (alignment) const type sym[]
#define SCM_STATIC_OBJCODE(sym) \
SCM_DECLARE_STATIC_ALIGNED_ARRAY (scm_t_uint8, sym##__bytecode); \
SCM_STATIC_ALIGNED_ARRAY (8, scm_t_cell, sym##__cells) = { \
{ SCM_PACK (OBJCODE_TAG), SCM_PACK (sym##__bytecode) }, \
{ SCM_BOOL_F, SCM_PACK (0) } \
}; \
static const SCM sym = SCM_PACK (sym##__cells); \
SCM_STATIC_ALIGNED_ARRAY (8, scm_t_uint8, sym##__bytecode)
#else
#define SCM_STATIC_OBJCODE(sym) \
static SCM sym; \
static scm_t_uint8 *sym##_bytecode; \
SCM_SNARF_INIT(sym##_bytecode = scm_gc_malloc_pointerless (sizeof(sym##_bytecode__unaligned), "partial continuation stub"); \
memcpy (sym##_bytecode, sym##_bytecode__unaligned, sizeof(sym##_bytecode__unaligned));) \
SCM_SNARF_INIT(sym = scm_double_cell (OBJCODE_TAG, \
(scm_t_bits)sym##_bytecode, \
SCM_UNPACK (SCM_BOOL_F), \
0);) \
static const scm_t_uint8 sym##_bytecode__unaligned[]
#endif
SCM_STATIC_OBJCODE (cont_objcode) = { static SCM
/* Like in continuations.c, but with partial-cont-call. */ make_partial_continuation (SCM vm_cont)
OBJCODE_HEADER (8, 19), {
/* leave args on the stack */ scm_t_bits nfree = 1;
/* 0 */ scm_op_object_ref, 0, /* push scm_vm_cont object */ scm_t_bits flags = SCM_F_PROGRAM_IS_PARTIAL_CONTINUATION;
/* 2 */ scm_op_partial_cont_call, /* and go! */ SCM ret;
/* 3 */ scm_op_nop,
/* 4 */ scm_op_nop, scm_op_nop, scm_op_nop, scm_op_nop, /* pad to 8 bytes */
/* 8 */
/* We could put some meta-info to say that this proc is a continuation. Not sure ret = scm_words (scm_tc7_rtl_program | (nfree << 16) | flags, nfree + 2);
how to do that, though. */ SCM_SET_CELL_WORD_1 (ret, compose_continuation_code);
META_HEADER (19), SCM_RTL_PROGRAM_FREE_VARIABLE_SET (ret, 0, vm_cont);
/* 0 */ scm_op_make_eol, /* bindings */
/* 1 */ scm_op_make_eol, /* sources */
/* 2 */ scm_op_make_int8, 0, scm_op_make_int8, 3, /* arity: from ip 0 to ip 3 */
/* 6 */ scm_op_make_int8_0, /* the arity is 0 required args */
/* 7 */ scm_op_make_int8_0, /* 0 optionals */
/* 8 */ scm_op_make_true, /* and a rest arg */
/* 9 */ scm_op_list, 0, 5, /* make a list of those 5 vals */
/* 12 */ scm_op_list, 0, 1, /* and the arities will be a list of that one list */
/* 15 */ scm_op_list, 0, 3, /* pack bindings, sources, and arities into list */
/* 18 */ scm_op_return /* and return */
/* 19 */
};
return ret;
}
static SCM static SCM
reify_partial_continuation (SCM vm, reify_partial_continuation (SCM vm,
@ -128,7 +84,7 @@ reify_partial_continuation (SCM vm,
scm_t_dynstack *dynstack, scm_t_dynstack *dynstack,
scm_i_jmp_buf *current_registers) scm_i_jmp_buf *current_registers)
{ {
SCM vm_cont, ret; SCM vm_cont;
scm_t_uint32 flags; scm_t_uint32 flags;
flags = SCM_F_VM_CONT_PARTIAL; flags = SCM_F_VM_CONT_PARTIAL;
@ -155,12 +111,7 @@ reify_partial_continuation (SCM vm,
dynstack, dynstack,
flags); flags);
ret = scm_make_program (cont_objcode, return make_partial_continuation (vm_cont);
scm_c_make_vector (1, vm_cont),
SCM_BOOL_F);
SCM_SET_CELL_WORD_0 (ret,
SCM_CELL_WORD_0 (ret) | SCM_F_PROGRAM_IS_PARTIAL_CONTINUATION);
return ret;
} }
void void

View file

@ -527,7 +527,8 @@ scm_i_rtl_program_minimum_arity (SCM program, int *req, int *opt, int *rest)
if (SCM_PROGRAM_IS_FOREIGN (program)) if (SCM_PROGRAM_IS_FOREIGN (program))
return scm_i_foreign_arity (program, req, opt, rest); return scm_i_foreign_arity (program, req, opt, rest);
if (SCM_PROGRAM_IS_CONTINUATION (program)) if (SCM_PROGRAM_IS_CONTINUATION (program)
|| SCM_PROGRAM_IS_PARTIAL_CONTINUATION (program))
{ {
*req = *opt = 0; *req = *opt = 0;
*rest = 1; *rest = 1;

View file

@ -1273,7 +1273,7 @@ RTL_VM_NAME (SCM vm, SCM program, SCM *argv, size_t nargs_)
scm_t_uint32 cont_idx; scm_t_uint32 cont_idx;
SCM_UNPACK_RTL_24 (op, cont_idx); SCM_UNPACK_RTL_24 (op, cont_idx);
vmcont = LOCAL_REF (cont_idx); vmcont = SCM_RTL_PROGRAM_FREE_VARIABLE_REF (LOCAL_REF (0), cont_idx);
SYNC_IP (); SYNC_IP ();
VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont), VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont),

View file

@ -1482,7 +1482,9 @@ VM_DEFINE_INSTRUCTION (89, abort, "abort", 1, -1, -1)
tail = sp[0]; tail = sp[0];
stack_args = sp - n; stack_args = sp - n;
tag = sp[-(n + 1)]; tag = sp[-(n + 1)];
vm_abort (vm, tag, n, stack_args, tail, sp - (n + 2), &registers); /* Partial continuations are now RTL programs, and therefore not
resumable. Pass NULL as registers to indicate that fact. */
vm_abort (vm, tag, n, stack_args, tail, sp - (n + 2), NULL);
/* vm_abort should not return */ /* vm_abort should not return */
abort (); abort ();
} }