diff options
Diffstat (limited to 'libguile/continuations.c')
-rw-r--r-- | libguile/continuations.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/libguile/continuations.c b/libguile/continuations.c index d9912783d..fe7618f5e 100644 --- a/libguile/continuations.c +++ b/libguile/continuations.c @@ -24,6 +24,7 @@ #include "libguile/_scm.h" +#include <assert.h> #include <string.h> #include <stdio.h> @@ -33,7 +34,7 @@ #include "libguile/stackchk.h" #include "libguile/smob.h" #include "libguile/ports.h" -#include "libguile/dynwind.h" +#include "libguile/dynstack.h" #include "libguile/eval.h" #include "libguile/vm.h" #include "libguile/instructions.h" @@ -52,7 +53,6 @@ static scm_t_bits tc16_continuation; #define SCM_SET_CONTINUATION_LENGTH(x, n)\ (SCM_CONTREGS (x)->num_stack_items = (n)) #define SCM_JMPBUF(x) ((SCM_CONTREGS (x))->jmpbuf) -#define SCM_DYNENV(x) ((SCM_CONTREGS (x))->dynenv) #define SCM_CONTINUATION_ROOT(x) ((SCM_CONTREGS (x))->root) #define SCM_DFRAME(x) ((SCM_CONTREGS (x))->dframe) @@ -173,14 +173,25 @@ continuation_print (SCM obj, SCM port, scm_print_state *state SCM_UNUSED) { scm_t_contregs *continuation = SCM_CONTREGS (obj); - scm_puts ("#<continuation ", port); + scm_puts_unlocked ("#<continuation ", port); scm_intprint (continuation->num_stack_items, 10, port); - scm_puts (" @ ", port); + scm_puts_unlocked (" @ ", port); scm_uintprint (SCM_SMOB_DATA_1 (obj), 16, port); - scm_putc ('>', port); + scm_putc_unlocked ('>', port); return 1; } +/* 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. + */ + +#if defined (sparc) || defined (__sparc__) || defined (__sparc) +# define SCM_FLUSH_REGISTER_WINDOWS asm("ta 3") +#else +# define SCM_FLUSH_REGISTER_WINDOWS /* empty */ +#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). */ @@ -200,7 +211,6 @@ scm_i_make_continuation (int *first, SCM vm, SCM vm_cont) + (stack_size - 1) * sizeof (SCM_STACKITEM), "continuation"); continuation->num_stack_items = stack_size; - continuation->dynenv = scm_i_dynwinds (); continuation->root = thread->continuation_root; src = thread->continuation_base; #if ! SCM_STACK_GROWS_UP @@ -323,33 +333,25 @@ grow_stack (SCM cont) * own frame are overwritten. Thus, memcpy can be used for best performance. */ -typedef struct { - scm_t_contregs *continuation; - SCM_STACKITEM *dst; -} copy_stack_data; - -static void -copy_stack (void *data) -{ - copy_stack_data *d = (copy_stack_data *)data; - memcpy (d->dst, d->continuation->stack, - sizeof (SCM_STACKITEM) * d->continuation->num_stack_items); -#ifdef __ia64__ - SCM_I_CURRENT_THREAD->pending_rbs_continuation = d->continuation; -#endif -} - static void copy_stack_and_call (scm_t_contregs *continuation, SCM_STACKITEM * dst) { - long delta; - copy_stack_data data; + scm_t_dynstack *dynstack; + scm_t_bits *joint; + scm_i_thread *thread = SCM_I_CURRENT_THREAD; + + dynstack = SCM_VM_CONT_DATA (continuation->vm_cont)->dynstack; + + joint = scm_dynstack_unwind_fork (&thread->dynstack, dynstack); + + memcpy (dst, continuation->stack, + sizeof (SCM_STACKITEM) * continuation->num_stack_items); +#ifdef __ia64__ + thread->pending_rbs_continuation = continuation; +#endif - delta = scm_ilength (scm_i_dynwinds ()) - scm_ilength (continuation->dynenv); - data.continuation = continuation; - data.dst = dst; - scm_i_dowinds (continuation->dynenv, delta, copy_stack, &data); + scm_dynstack_wind (&thread->dynstack, joint); SCM_I_LONGJMP (continuation->jmpbuf, 1); } @@ -486,7 +488,7 @@ print_exception_and_backtrace (SCM port, SCM tag, SCM args) if (should_print_backtrace (tag, stack)) { - scm_puts ("Backtrace:\n", port); + scm_puts_unlocked ("Backtrace:\n", port); scm_display_backtrace_with_highlights (stack, port, SCM_BOOL_F, SCM_BOOL_F, SCM_EOL); @@ -531,7 +533,7 @@ pre_unwind_handler (void *error_port, SCM tag, SCM args) { /* Print the exception unless TAG is `quit'. */ if (!scm_is_eq (tag, scm_from_latin1_symbol ("quit"))) - print_exception_and_backtrace (PTR2SCM (error_port), tag, args); + print_exception_and_backtrace (SCM_PACK_POINTER (error_port), tag, args); return SCM_UNSPECIFIED; } @@ -545,7 +547,7 @@ scm_c_with_continuation_barrier (void *(*func) (void *), void *data) scm_i_with_continuation_barrier (c_body, &c_data, c_handler, &c_data, pre_unwind_handler, - SCM2PTR (scm_current_error_port ())); + SCM_UNPACK_POINTER (scm_current_error_port ())); return c_data.result; } @@ -589,7 +591,7 @@ SCM_DEFINE (scm_with_continuation_barrier, "with-continuation-barrier", 1,0,0, return scm_i_with_continuation_barrier (scm_body, &scm_data, scm_handler, &scm_data, pre_unwind_handler, - SCM2PTR (scm_current_error_port ())); + SCM_UNPACK_POINTER (scm_current_error_port ())); } #undef FUNC_NAME |