diff --git a/cont.c b/cont.c index 8fba3c78..563332aa 100644 --- a/cont.c +++ b/cont.c @@ -131,14 +131,19 @@ save_cont(pic_state *pic, struct pic_cont **c) cont->sp_offset = pic->sp - pic->stbase; cont->st_len = pic->stend - pic->stbase; - cont->st_ptr = (pic_value *)pic_alloc(pic, sizeof(pic_value) * cont->st_len); + cont->st_ptr = pic_alloc(pic, sizeof(pic_value) * cont->st_len); memcpy(cont->st_ptr, pic->stbase, sizeof(pic_value) * cont->st_len); cont->ci_offset = pic->ci - pic->cibase; cont->ci_len = pic->ciend - pic->cibase; - cont->ci_ptr = (pic_callinfo *)pic_alloc(pic, sizeof(pic_callinfo) * cont->ci_len); + cont->ci_ptr = pic_alloc(pic, sizeof(pic_callinfo) * cont->ci_len); memcpy(cont->ci_ptr, pic->cibase, sizeof(pic_callinfo) * cont->ci_len); + cont->xp_offset = pic->xp - pic->xpbase; + cont->xp_len = pic->xpend - pic->xpbase; + cont->xp_ptr = pic_alloc(pic, sizeof(struct pic_proc *) * cont->xp_len); + memcpy(cont->xp_ptr, pic->xpbase, sizeof(struct pic_proc *) * cont->xp_len); + cont->ip = pic->ip; cont->arena_idx = pic->arena_idx; @@ -146,11 +151,6 @@ save_cont(pic_state *pic, struct pic_cont **c) cont->arena = (struct pic_object **)pic_alloc(pic, sizeof(struct pic_object *) * pic->arena_size); memcpy(cont->arena, pic->arena, sizeof(struct pic_object *) * pic->arena_size); - cont->try_jmp_idx = pic->try_jmp_idx; - cont->try_jmp_size = pic->try_jmp_size; - cont->try_jmps = pic_alloc(pic, sizeof(struct pic_jmpbuf) * pic->try_jmp_size); - memcpy(cont->try_jmps, pic->try_jmps, sizeof(struct pic_jmpbuf) * pic->try_jmp_size); - cont->results = pic_undef_value(); } @@ -178,16 +178,21 @@ restore_cont(pic_state *pic, struct pic_cont *cont) pic->wind = cont->wind; - pic->stbase = (pic_value *)pic_realloc(pic, pic->stbase, sizeof(pic_value) * cont->st_len); + pic->stbase = pic_realloc(pic, pic->stbase, sizeof(pic_value) * cont->st_len); memcpy(pic->stbase, cont->st_ptr, sizeof(pic_value) * cont->st_len); pic->sp = pic->stbase + cont->sp_offset; pic->stend = pic->stbase + cont->st_len; - pic->cibase = (pic_callinfo *)pic_realloc(pic, pic->cibase, sizeof(pic_callinfo) * cont->ci_len); + pic->cibase = pic_realloc(pic, pic->cibase, sizeof(pic_callinfo) * cont->ci_len); memcpy(pic->cibase, cont->ci_ptr, sizeof(pic_callinfo) * cont->ci_len); pic->ci = pic->cibase + cont->ci_offset; pic->ciend = pic->cibase + cont->ci_len; + pic->xpbase = pic_realloc(pic, pic->xpbase, sizeof(struct pic_proc *) * cont->xp_len); + memcpy(pic->xpbase, cont->xp_ptr, sizeof(struct pic_proc *) * cont->xp_len); + pic->xp = pic->xpbase + cont->xp_offset; + pic->xpend = pic->xpbase + cont->xp_len; + pic->ip = cont->ip; pic->arena = (struct pic_object **)pic_realloc(pic, pic->arena, sizeof(struct pic_object *) * cont->arena_size); @@ -195,11 +200,6 @@ restore_cont(pic_state *pic, struct pic_cont *cont) pic->arena_size = cont->arena_size; pic->arena_idx = cont->arena_idx; - pic->try_jmps = pic_realloc(pic, pic->try_jmps, sizeof(struct pic_jmpbuf) * cont->try_jmp_size); - memcpy(pic->try_jmps, cont->try_jmps, sizeof(struct pic_jmpbuf) * cont->try_jmp_size); - pic->try_jmp_size = cont->try_jmp_size; - pic->try_jmp_idx = cont->try_jmp_idx; - memcpy(cont->stk_pos, cont->stk_ptr, cont->stk_len); longjmp(tmp->jmp, 1); diff --git a/error.c b/error.c index 4eb34157..8023c0be 100644 --- a/error.c +++ b/error.c @@ -89,7 +89,7 @@ static pic_value native_push_try(pic_state *pic) { struct pic_proc *cont, *handler; - struct pic_jmpbuf *try_jmp; + size_t xp_len, xp_offset; pic_get_args(pic, "l", &cont); @@ -97,13 +97,15 @@ native_push_try(pic_state *pic) pic_attr_set(pic, handler, "@@escape", pic_obj_value(cont)); - if (pic->try_jmp_idx >= pic->try_jmp_size) { - pic->try_jmp_size *= 2; - pic->try_jmps = pic_realloc(pic, pic->try_jmps, sizeof(struct pic_jmpbuf) * pic->try_jmp_size); + if (pic->xp >= pic->xpend) { + xp_len = (pic->xpend - pic->xpbase) * 2; + xp_offset = pic->xp - pic->xpbase; + pic->xpbase = pic_realloc(pic, pic->xpbase, sizeof(struct pic_proc *) * xp_len); + pic->xp = pic->xpbase + xp_offset; + pic->xpend = pic->xpbase + xp_len; } - try_jmp = pic->try_jmps + pic->try_jmp_idx++; - try_jmp->handler = handler; + *pic->xp++ = handler; return pic_true_value(); } @@ -121,7 +123,7 @@ pic_push_try(pic_state *pic) void pic_pop_try(pic_state *pic) { - --pic->try_jmp_idx; + --pic->xp; } struct pic_error * @@ -147,19 +149,17 @@ pic_raise_continuable(pic_state *pic, pic_value err) struct pic_proc *handler; pic_value v; - if (pic->try_jmp_idx == 0) { + if (pic->xp == pic->xpbase) { pic_panic(pic, "no exception handler registered"); } - handler = pic->try_jmps[pic->try_jmp_idx - 1].handler; + handler = *--pic->xp; pic_gc_protect(pic, pic_obj_value(handler)); - pic->try_jmp_idx--; + v = pic_apply1(pic, handler, err); - v = pic_apply1(pic, pic->try_jmps[pic->try_jmp_idx].handler, err); - - pic->try_jmps[pic->try_jmp_idx++].handler = handler; + *pic->xp++ = handler; return v; } @@ -197,19 +197,23 @@ pic_error_with_exception_handler(pic_state *pic) { struct pic_proc *handler, *thunk; pic_value val; + size_t xp_len, xp_offset; pic_get_args(pic, "ll", &handler, &thunk); - if (pic->try_jmp_idx >= pic->try_jmp_size) { - pic->try_jmp_size *= 2; - pic->try_jmps = pic_realloc(pic, pic->try_jmps, sizeof(struct pic_jmpbuf) * pic->try_jmp_size); + if (pic->xp >= pic->xpend) { + xp_len = (pic->xpend - pic->xpbase) * 2; + xp_offset = pic->xp - pic->xpbase; + pic->xpbase = pic_realloc(pic, pic->xpbase, sizeof(struct pic_proc *) * xp_len); + pic->xp = pic->xpbase + xp_offset; + pic->xpend = pic->xpbase + xp_len; } - pic->try_jmps[pic->try_jmp_idx++].handler = handler; + *pic->xp++ = handler; val = pic_apply0(pic, thunk); - pic->try_jmp_idx--; + --pic->xp; return val; } diff --git a/gc.c b/gc.c index 15304788..7ac019ff 100644 --- a/gc.c +++ b/gc.c @@ -416,6 +416,7 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) struct pic_cont *cont = (struct pic_cont *)obj; pic_value *stack; pic_callinfo *ci; + struct pic_proc **xhandler; size_t i; /* winder */ @@ -433,18 +434,16 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) } } + /* exception handlers */ + for (xhandler = cont->xp_ptr; xhandler != cont->xp_ptr + cont->xp_offset; ++xhandler) { + gc_mark_object(pic, (struct pic_object *)*xhandler); + } + /* arena */ for (i = 0; i < (size_t)cont->arena_idx; ++i) { gc_mark_object(pic, cont->arena[i]); } - /* error handlers */ - for (i = 0; i < cont->try_jmp_idx; ++i) { - if (cont->try_jmps[i].handler) { - gc_mark_object(pic, (struct pic_object *)cont->try_jmps[i].handler); - } - } - /* result values */ gc_mark(pic, cont->results); break; @@ -562,7 +561,8 @@ gc_mark_phase(pic_state *pic) { pic_value *stack; pic_callinfo *ci; - size_t i, j; + struct pic_proc **xhandler; + size_t j; xh_entry *it; /* winder */ @@ -582,8 +582,10 @@ gc_mark_phase(pic_state *pic) } } - /* error object */ - gc_mark(pic, pic->err); + /* exception handlers */ + for (xhandler = pic->xpbase; xhandler != pic->xp; ++xhandler) { + gc_mark_object(pic, (struct pic_object *)*xhandler); + } /* arena */ for (j = 0; j < pic->arena_idx; ++j) { @@ -600,13 +602,10 @@ gc_mark_phase(pic_state *pic) gc_mark_object(pic, xh_val(it, struct pic_object *)); } - /* error handlers */ - for (i = 0; i < pic->try_jmp_idx; ++i) { - if (pic->try_jmps[i].handler) { - gc_mark_object(pic, (struct pic_object *)pic->try_jmps[i].handler); - } - } + /* error object */ + gc_mark(pic, pic->err); + /* features */ gc_mark(pic, pic->features); /* readers */ @@ -669,8 +668,8 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) pic_free(pic, cont->stk_ptr); pic_free(pic, cont->st_ptr); pic_free(pic, cont->ci_ptr); + pic_free(pic, cont->xp_ptr); pic_free(pic, cont->arena); - pic_free(pic, cont->try_jmps); break; } case PIC_TT_SENV: { diff --git a/include/picrin.h b/include/picrin.h index 17a159dd..b00e451d 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -75,6 +75,9 @@ typedef struct { pic_callinfo *ci; pic_callinfo *cibase, *ciend; + struct pic_proc **xp; + struct pic_proc **xpbase, **xpend; + pic_code *ip; struct pic_lib *lib; @@ -111,16 +114,14 @@ typedef struct { struct pic_reader *reader; - pic_value err; - struct pic_jmpbuf *try_jmps; - size_t try_jmp_size, try_jmp_idx; - struct pic_heap *heap; struct pic_object **arena; size_t arena_size, arena_idx; struct pic_port *xSTDIN, *xSTDOUT, *xSTDERR; + pic_value err; + char *native_stack_start; } pic_state; diff --git a/include/picrin/cont.h b/include/picrin/cont.h index 740a1175..503651f1 100644 --- a/include/picrin/cont.h +++ b/include/picrin/cont.h @@ -24,15 +24,15 @@ struct pic_cont { pic_callinfo *ci_ptr; size_t ci_offset, ci_len; + struct pic_proc **xp_ptr; + size_t xp_offset, xp_len; + pic_code *ip; struct pic_object **arena; size_t arena_size; int arena_idx; - struct pic_jmpbuf *try_jmps; - size_t try_jmp_idx, try_jmp_size; - pic_value results; }; diff --git a/include/picrin/error.h b/include/picrin/error.h index 8686d3ff..0549c69d 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -9,15 +9,6 @@ extern "C" { #endif -struct pic_jmpbuf { - jmp_buf here; - struct pic_proc *handler; - ptrdiff_t ci_offset; - ptrdiff_t sp_offset; - pic_code *ip; - jmp_buf *prev_jmp; -}; - /* do not return from try block! */ #define pic_try \ diff --git a/state.c b/state.c index e75876a2..e61aef44 100644 --- a/state.c +++ b/state.c @@ -42,6 +42,10 @@ pic_open(int argc, char *argv[], char **envp) pic->cibase = pic->ci = calloc(PIC_STACK_SIZE, sizeof(pic_callinfo)); pic->ciend = pic->cibase + PIC_STACK_SIZE; + /* exception handler */ + pic->xpbase = pic->xp = calloc(PIC_RESCUE_SIZE, sizeof(struct pic_proc *)); + pic->xpend = pic->xpbase + PIC_RESCUE_SIZE; + /* memory heap */ pic->heap = pic_heap_open(); @@ -70,11 +74,8 @@ pic_open(int argc, char *argv[], char **envp) pic->reader->trie = pic_make_trie(pic); xh_init_int(&pic->reader->labels, sizeof(pic_value)); - /* error handling */ + /* raised error object */ pic->err = pic_undef_value(); - pic->try_jmps = calloc(PIC_RESCUE_SIZE, sizeof(struct pic_jmpbuf)); - pic->try_jmp_idx = 0; - pic->try_jmp_size = PIC_RESCUE_SIZE; /* standard ports */ pic->xSTDIN = NULL; @@ -191,6 +192,7 @@ pic_close(pic_state *pic) /* clear out root objects */ pic->sp = pic->stbase; pic->ci = pic->cibase; + pic->xp = pic->xpbase; pic->arena_idx = 0; pic->err = pic_undef_value(); xh_clear(&pic->macros); @@ -206,6 +208,7 @@ pic_close(pic_state *pic) /* free runtime context */ free(pic->stbase); free(pic->cibase); + free(pic->xpbase); /* free reader struct */ xh_destroy(&pic->reader->labels); @@ -213,7 +216,6 @@ pic_close(pic_state *pic) free(pic->reader); /* free global stacks */ - free(pic->try_jmps); xh_destroy(&pic->syms); xh_destroy(&pic->globals); xh_destroy(&pic->macros);