diff --git a/contrib/03.callcc/callcc.c b/contrib/03.callcc/callcc.c index 4020849c..4019df18 100644 --- a/contrib/03.callcc/callcc.c +++ b/contrib/03.callcc/callcc.c @@ -3,6 +3,8 @@ struct pic_cont { jmp_buf jmp; + pic_jmpbuf *prev_jmp; + struct pic_winder *wind; char *stk_pos, *stk_ptr; @@ -115,6 +117,8 @@ save_cont(pic_state *pic, struct pic_cont **c) cont = *c = pic_malloc(pic, sizeof(struct pic_cont)); + cont->prev_jmp = pic->jmp; + cont->wind = pic->wind; cont->stk_len = native_stack_length(pic, &pos); @@ -170,6 +174,8 @@ restore_cont(pic_state *pic, struct pic_cont *cont) if (&v > cont->stk_pos + cont->stk_len) native_stack_extend(pic, cont); } + pic->jmp = cont->prev_jmp; + pic->wind = cont->wind; pic->stbase = pic_realloc(pic, pic->stbase, sizeof(pic_value) * cont->st_len); diff --git a/extlib/benz/cont.c b/extlib/benz/cont.c index 90cccc60..e9891cf9 100644 --- a/extlib/benz/cont.c +++ b/extlib/benz/cont.c @@ -51,7 +51,8 @@ pic_dynamic_wind(pic_state *pic, struct pic_proc *in, struct pic_proc *thunk, st void pic_save_point(pic_state *pic, struct pic_escape *escape) { - escape->valid = true; + escape->jmp.prev = pic->jmp; + pic->jmp = &escape->jmp; /* save runtime context */ escape->wind = pic->wind; @@ -67,7 +68,14 @@ pic_save_point(pic_state *pic, struct pic_escape *escape) void pic_load_point(pic_state *pic, struct pic_escape *escape) { - if (! escape->valid) { + pic_jmpbuf *jmp; + + for (jmp = pic->jmp; jmp != NULL; jmp = jmp->prev) { + if (jmp == &escape->jmp) { + break; + } + } + if (jmp == NULL) { pic_errorf(pic, "calling dead escape continuation"); } @@ -80,8 +88,6 @@ pic_load_point(pic_state *pic, struct pic_escape *escape) pic->xp = pic->xpbase + escape->xp_offset; pic->arena_idx = escape->arena_idx; pic->ip = escape->ip; - - escape->valid = false; } static pic_value @@ -98,7 +104,7 @@ escape_call(pic_state *pic) pic_load_point(pic, e->data); - PIC_LONGJMP(pic, (void *)((struct pic_escape *)e->data)->jmp, 1); + PIC_LONGJMP(pic, (void *)((struct pic_escape *)e->data)->jmp.buf, 1); PIC_UNREACHABLE(); } @@ -127,7 +133,9 @@ pic_escape(pic_state *pic, struct pic_proc *proc) pic_save_point(pic, escape); - if (PIC_SETJMP(pic, (void *)escape->jmp)) { + if (PIC_SETJMP(pic, (void *)escape->jmp.buf)) { + pic->jmp = pic->jmp->prev; + return pic_values_by_list(pic, escape->results); } else { @@ -135,7 +143,7 @@ pic_escape(pic_state *pic, struct pic_proc *proc) val = pic_apply1(pic, proc, pic_obj_value(pic_make_econt(pic, escape))); - escape->valid = false; + pic->jmp = pic->jmp->prev; return val; } diff --git a/extlib/benz/error.c b/extlib/benz/error.c index 73370cd8..d9684386 100644 --- a/extlib/benz/error.c +++ b/extlib/benz/error.c @@ -105,19 +105,7 @@ pic_push_try(pic_state *pic, struct pic_proc *cont) void pic_pop_try(pic_state *pic) { - pic_value cont, escape; - - assert(pic->xp > pic->xpbase); - - cont = pic_attr_ref(pic, pic_obj_value(*--pic->xp), "@@escape"); - - assert(pic_proc_p(cont)); - - escape = pic_attr_ref(pic, cont, "@@escape"); - - assert(pic_data_p(escape)); - - ((struct pic_escape *)pic_data_ptr(escape)->data)->valid = false; + --pic->xp; } struct pic_error * diff --git a/extlib/benz/include/picrin.h b/extlib/benz/include/picrin.h index 46da1afe..faf3b29f 100644 --- a/extlib/benz/include/picrin.h +++ b/extlib/benz/include/picrin.h @@ -48,6 +48,11 @@ extern "C" { typedef struct pic_code pic_code; +typedef struct pic_jmpbuf { + PIC_JMPBUF buf; + struct pic_jmpbuf *prev; +} pic_jmpbuf; + struct pic_winder { struct pic_proc *in; struct pic_proc *out; @@ -73,6 +78,7 @@ typedef struct { pic_allocf allocf; + pic_jmpbuf *jmp; struct pic_winder *wind; pic_value *sp; diff --git a/extlib/benz/include/picrin/config.h b/extlib/benz/include/picrin/config.h index a0274422..4b98679d 100644 --- a/extlib/benz/include/picrin/config.h +++ b/extlib/benz/include/picrin/config.h @@ -21,7 +21,7 @@ /* #define PIC_NONE_IS_FALSE 1 */ /** custom setjmp/longjmp */ -/* #define PIC_JMPBUF_SIZE sizeof(jmp_buf) */ +/* #define PIC_JMPBUF jmp_buf */ /* #define PIC_SETJMP(pic, buf) setjmp(buf) */ /* #define PIC_LONGJMP(pic, buf, val) longjmp((buf), (val)) */ @@ -100,9 +100,9 @@ # define PIC_NONE_IS_FALSE 1 #endif -#ifndef PIC_JMPBUF_SIZE +#ifndef PIC_JMPBUF # include -# define PIC_JMPBUF_SIZE sizeof(jmp_buf) +# define PIC_JMPBUF jmp_buf #endif #ifndef PIC_SETJMP diff --git a/extlib/benz/include/picrin/cont.h b/extlib/benz/include/picrin/cont.h index 72fda5b2..b3002577 100644 --- a/extlib/benz/include/picrin/cont.h +++ b/extlib/benz/include/picrin/cont.h @@ -10,9 +10,7 @@ extern "C" { #endif struct pic_escape { - char jmp[PIC_JMPBUF_SIZE]; - - bool valid; + pic_jmpbuf jmp; struct pic_winder *wind; diff --git a/extlib/benz/include/picrin/error.h b/extlib/benz/include/picrin/error.h index 617f29f8..e7aaf920 100644 --- a/extlib/benz/include/picrin/error.h +++ b/extlib/benz/include/picrin/error.h @@ -32,13 +32,15 @@ struct pic_error *pic_make_error(pic_state *, pic_sym *, const char *, pic_list) do { \ struct pic_escape *escape = pic_malloc(pic, sizeof(struct pic_escape)); \ pic_save_point(pic, escape); \ - if (PIC_SETJMP(pic, (void *)escape->jmp) == 0) { \ + if (PIC_SETJMP(pic, (void *)escape->jmp.buf) == 0) { \ do { \ pic_push_try(pic, pic_make_econt(pic, escape)); #define pic_catch_(label) \ pic_pop_try(pic); \ } while (0); \ + pic->jmp = pic->jmp->prev; \ } else { \ + pic->jmp = pic->jmp->prev; \ goto label; \ } \ } while (0); \ diff --git a/extlib/benz/state.c b/extlib/benz/state.c index 521b9a0d..13a17e09 100644 --- a/extlib/benz/state.c +++ b/extlib/benz/state.c @@ -156,6 +156,9 @@ pic_open(int argc, char *argv[], char **envp, pic_allocf allocf) /* turn off GC */ pic->gc_enable = false; + /* jmp */ + pic->jmp = NULL; + /* root block */ pic->wind = NULL;