From b4c3f4fb730335d091becb0f62419fa0db4ab301 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 17 Sep 2014 15:09:15 +0900 Subject: [PATCH 01/10] pic_block -> pic_winder --- cont.c | 26 ++++++++++++-------------- gc.c | 41 +++++++++++++++++++---------------------- include/picrin.h | 9 ++++++++- include/picrin/cont.h | 9 +-------- include/picrin/value.h | 3 --- state.c | 18 +++++++++--------- 6 files changed, 49 insertions(+), 57 deletions(-) diff --git a/cont.c b/cont.c index 695e39b0..c542399d 100644 --- a/cont.c +++ b/cont.c @@ -121,7 +121,7 @@ save_cont(pic_state *pic, struct pic_cont **c) cont = *c = (struct pic_cont *)pic_obj_alloc(pic, sizeof(struct pic_cont), PIC_TT_CONT); - cont->blk = pic->blk; + cont->wind = pic->wind; cont->stk_len = native_stack_length(pic, &pos); cont->stk_pos = pos; @@ -168,7 +168,6 @@ restore_cont(pic_state *pic, struct pic_cont *cont) { char v; struct pic_cont *tmp = cont; - struct pic_block *blk; if (&v < pic->native_stack_start) { if (&v > cont->stk_pos) native_stack_extend(pic, cont); @@ -177,8 +176,7 @@ restore_cont(pic_state *pic, struct pic_cont *cont) if (&v > cont->stk_pos + cont->stk_len) native_stack_extend(pic, cont); } - blk = pic->blk; - pic->blk = cont->blk; + pic->wind = cont->wind; pic->stbase = (pic_value *)pic_realloc(pic, pic->stbase, sizeof(pic_value) * cont->st_len); memcpy(pic->stbase, cont->st_ptr, sizeof(pic_value) * cont->st_len); @@ -208,7 +206,7 @@ restore_cont(pic_state *pic, struct pic_cont *cont) } static void -walk_to_block(pic_state *pic, struct pic_block *here, struct pic_block *there) +walk_to_block(pic_state *pic, struct pic_winder *here, struct pic_winder *there) { if (here == there) return; @@ -226,23 +224,23 @@ walk_to_block(pic_state *pic, struct pic_block *here, struct pic_block *there) static pic_value pic_dynamic_wind(pic_state *pic, struct pic_proc *in, struct pic_proc *thunk, struct pic_proc *out) { - struct pic_block *here; + struct pic_winder *here; pic_value val; if (in != NULL) { pic_apply0(pic, in); /* enter */ } - here = pic->blk; - pic->blk = (struct pic_block *)pic_obj_alloc(pic, sizeof(struct pic_block), PIC_TT_BLK); - pic->blk->prev = here; - pic->blk->depth = here->depth + 1; - pic->blk->in = in; - pic->blk->out = out; + here = pic->wind; + pic->wind = pic_alloc(pic, sizeof(struct pic_winder)); + pic->wind->prev = here; + pic->wind->depth = here->depth + 1; + pic->wind->in = in; + pic->wind->out = out; val = pic_apply0(pic, thunk); - pic->blk = here; + pic->wind = here; if (out != NULL) { pic_apply0(pic, out); /* exit */ @@ -266,7 +264,7 @@ cont_call(pic_state *pic) cont->results = pic_list_by_array(pic, argc, argv); /* execute guard handlers */ - walk_to_block(pic, pic->blk, cont->blk); + walk_to_block(pic, pic->wind, cont->wind); restore_cont(pic, cont); } diff --git a/gc.c b/gc.c index 38be3150..15304788 100644 --- a/gc.c +++ b/gc.c @@ -333,6 +333,20 @@ gc_unmark(union header *p) p->s.mark = PIC_GC_UNMARK; } +static void +gc_mark_winder(pic_state *pic, struct pic_winder *wind) +{ + if (wind->prev) { + gc_mark_object(pic, (struct pic_object *)wind->prev); + } + if (wind->in) { + gc_mark_object(pic, (struct pic_object *)wind->in); + } + if (wind->out) { + gc_mark_object(pic, (struct pic_object *)wind->out); + } +} + static void gc_mark_object(pic_state *pic, struct pic_object *obj) { @@ -404,8 +418,8 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) pic_callinfo *ci; size_t i; - /* block */ - gc_mark_object(pic, (struct pic_object *)cont->blk); + /* winder */ + gc_mark_winder(pic, cont->wind); /* stack */ for (stack = cont->st_ptr; stack != cont->st_ptr + cont->sp_offset; ++stack) { @@ -504,20 +518,6 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) } break; } - case PIC_TT_BLK: { - struct pic_block *blk = (struct pic_block *)obj; - - if (blk->prev) { - gc_mark_object(pic, (struct pic_object *)blk->prev); - } - if (blk->in) { - gc_mark_object(pic, (struct pic_object *)blk->in); - } - if (blk->out) { - gc_mark_object(pic, (struct pic_object *)blk->out); - } - break; - } case PIC_TT_NIL: case PIC_TT_BOOL: case PIC_TT_FLOAT: @@ -565,9 +565,9 @@ gc_mark_phase(pic_state *pic) size_t i, j; xh_entry *it; - /* block */ - if (pic->blk) { - gc_mark_object(pic, (struct pic_object *)pic->blk); + /* winder */ + if (pic->wind) { + gc_mark_winder(pic, pic->wind); } /* stack */ @@ -709,9 +709,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) xh_destroy(&rec->hash); break; } - case PIC_TT_BLK: { - break; - } case PIC_TT_NIL: case PIC_TT_BOOL: case PIC_TT_FLOAT: diff --git a/include/picrin.h b/include/picrin.h index 3df0c538..5bec9eb0 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -46,6 +46,13 @@ extern "C" { typedef struct pic_code pic_code; +struct pic_winder { + struct pic_proc *in; + struct pic_proc *out; + int depth; + struct pic_winder *prev; +}; + typedef struct { int argc, retc; pic_code *ip; @@ -60,7 +67,7 @@ typedef struct { int argc; char **argv, **envp; - struct pic_block *blk; + struct pic_winder *wind; pic_value *sp; pic_value *stbase, *stend; diff --git a/include/picrin/cont.h b/include/picrin/cont.h index eeabb798..587a46d1 100644 --- a/include/picrin/cont.h +++ b/include/picrin/cont.h @@ -9,18 +9,11 @@ extern "C" { #endif -struct pic_block { - PIC_OBJECT_HEADER - struct pic_block *prev; - int depth; - struct pic_proc *in, *out; -}; - struct pic_cont { PIC_OBJECT_HEADER jmp_buf jmp; - struct pic_block *blk; + struct pic_winder *wind; char *stk_pos, *stk_ptr; ptrdiff_t stk_len; diff --git a/include/picrin/value.h b/include/picrin/value.h index 6a211dc1..453e645a 100644 --- a/include/picrin/value.h +++ b/include/picrin/value.h @@ -125,7 +125,6 @@ enum pic_tt { PIC_TT_DATA, PIC_TT_DICT, PIC_TT_RECORD, - PIC_TT_BLK, }; #define PIC_OBJECT_HEADER \ @@ -274,8 +273,6 @@ pic_type_repr(enum pic_tt tt) return "dict"; case PIC_TT_RECORD: return "record"; - case PIC_TT_BLK: - return "block"; } UNREACHABLE(); } diff --git a/state.c b/state.c index b88f40a1..df9ba02c 100644 --- a/state.c +++ b/state.c @@ -27,7 +27,7 @@ pic_open(int argc, char *argv[], char **envp) pic = malloc(sizeof(pic_state)); /* root block */ - pic->blk = NULL; + pic->wind = NULL; /* command line */ pic->argc = argc; @@ -153,10 +153,10 @@ pic_open(int argc, char *argv[], char **envp) pic_gc_arena_restore(pic, ai); /* root block */ - pic->blk = (struct pic_block *)pic_obj_alloc(pic, sizeof(struct pic_block), PIC_TT_BLK); - pic->blk->prev = NULL; - pic->blk->depth = 0; - pic->blk->in = pic->blk->out = NULL; + pic->wind = pic_alloc(pic, sizeof(struct pic_winder)); + pic->wind->prev = NULL; + pic->wind->depth = 0; + pic->wind->in = pic->wind->out = NULL; /* init readers */ pic_init_reader(pic); @@ -182,11 +182,11 @@ pic_close(pic_state *pic) xh_entry *it; /* invoke exit handlers */ - while (pic->blk) { - if (pic->blk->out) { - pic_apply0(pic, pic->blk->out); + while (pic->wind) { + if (pic->wind->out) { + pic_apply0(pic, pic->wind->out); } - pic->blk = pic->blk->prev; + pic->wind = pic->wind->prev; } /* clear out root objects */ From 836c60797970b6b320b9cfc7f41c096e7df557f3 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 17 Sep 2014 15:26:42 +0900 Subject: [PATCH 02/10] s/walk_to_block/pic_wind/g --- cont.c | 10 +++++----- include/picrin/cont.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cont.c b/cont.c index c542399d..8fba3c78 100644 --- a/cont.c +++ b/cont.c @@ -205,19 +205,19 @@ restore_cont(pic_state *pic, struct pic_cont *cont) longjmp(tmp->jmp, 1); } -static void -walk_to_block(pic_state *pic, struct pic_winder *here, struct pic_winder *there) +void +pic_wind(pic_state *pic, struct pic_winder *here, struct pic_winder *there) { if (here == there) return; if (here->depth < there->depth) { - walk_to_block(pic, here, there->prev); + pic_wind(pic, here, there->prev); pic_apply0(pic, there->in); } else { pic_apply0(pic, there->out); - walk_to_block(pic, here->prev, there); + pic_wind(pic, here->prev, there); } } @@ -264,7 +264,7 @@ cont_call(pic_state *pic) cont->results = pic_list_by_array(pic, argc, argv); /* execute guard handlers */ - walk_to_block(pic, pic->wind, cont->wind); + pic_wind(pic, pic->wind, cont->wind); restore_cont(pic, cont); } diff --git a/include/picrin/cont.h b/include/picrin/cont.h index 587a46d1..740a1175 100644 --- a/include/picrin/cont.h +++ b/include/picrin/cont.h @@ -47,6 +47,7 @@ pic_value pic_values_by_list(pic_state *, pic_value); size_t pic_receive(pic_state *, size_t, pic_value *); pic_value pic_callcc(pic_state *, struct pic_proc *); +void pic_wind(pic_state *, struct pic_winder *, struct pic_winder *); #if defined(__cplusplus) } From a17e79a1606d84042cf2ce9950b488459a518049 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 17 Sep 2014 21:58:51 +0900 Subject: [PATCH 03/10] add pic_raise_continuable --- error.c | 98 +++++++++++++++++++++++------------------- include/picrin/error.h | 1 + 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/error.c b/error.c index bc618630..feaefa92 100644 --- a/error.c +++ b/error.c @@ -33,6 +33,39 @@ pic_warnf(pic_state *pic, const char *fmt, ...) fprintf(stderr, "warn: %s\n", pic_str_cstr(pic_str_ptr(pic_car(pic, err_line)))); } +void +pic_errorf(pic_state *pic, const char *fmt, ...) +{ + va_list ap; + pic_value err_line, irrs; + const char *msg; + + va_start(ap, fmt); + err_line = pic_xvformat(pic, fmt, ap); + va_end(ap); + + msg = pic_str_cstr(pic_str_ptr(pic_car(pic, err_line))); + irrs = pic_cdr(pic, err_line); + + pic_error(pic, msg, irrs); +} + +const char * +pic_errmsg(pic_state *pic) +{ + pic_str *str; + + assert(! pic_undef_p(pic->err)); + + if (! pic_error_p(pic->err)) { + str = pic_format(pic, "~s", pic->err); + } else { + str = pic_error_ptr(pic->err)->msg; + } + + return pic_str_cstr(str); +} + void pic_push_try(pic_state *pic, struct pic_proc *handler) { @@ -88,6 +121,25 @@ pic_make_error(pic_state *pic, pic_sym type, const char *msg, pic_value irrs) return e; } +pic_value +pic_raise_continuable(pic_state *pic, pic_value err) +{ + pic_value v; + + if (pic->try_jmp_idx == 0) { + pic_errorf(pic, "no exception handler registered"); + } + if (pic->try_jmps[pic->try_jmp_idx - 1].handler == NULL) { + pic_errorf(pic, "uncontinuable exception handler is on top"); + } + else { + pic->try_jmp_idx--; + v = pic_apply1(pic, pic->try_jmps[pic->try_jmp_idx].handler, err); + ++pic->try_jmp_idx; + } + return v; +} + noreturn void pic_raise(pic_state *pic, pic_value err) { @@ -120,39 +172,6 @@ pic_error(pic_state *pic, const char *msg, pic_value irrs) pic_throw(pic, pic_intern_cstr(pic, ""), msg, irrs); } -const char * -pic_errmsg(pic_state *pic) -{ - pic_str *str; - - assert(! pic_undef_p(pic->err)); - - if (! pic_error_p(pic->err)) { - str = pic_format(pic, "~s", pic->err); - } else { - str = pic_error_ptr(pic->err)->msg; - } - - return pic_str_cstr(str); -} - -void -pic_errorf(pic_state *pic, const char *fmt, ...) -{ - va_list ap; - pic_value err_line, irrs; - const char *msg; - - va_start(ap, fmt); - err_line = pic_xvformat(pic, fmt, ap); - va_end(ap); - - msg = pic_str_cstr(pic_str_ptr(pic_car(pic, err_line))); - irrs = pic_cdr(pic, err_line); - - pic_error(pic, msg, irrs); -} - static pic_value pic_error_with_exception_handler(pic_state *pic) { @@ -193,18 +212,7 @@ pic_error_raise_continuable(pic_state *pic) pic_get_args(pic, "o", &v); - if (pic->try_jmp_idx == 0) { - pic_errorf(pic, "no exception handler registered"); - } - if (pic->try_jmps[pic->try_jmp_idx - 1].handler == NULL) { - pic_errorf(pic, "uncontinuable exception handler is on top"); - } - else { - pic->try_jmp_idx--; - v = pic_apply1(pic, pic->try_jmps[pic->try_jmp_idx].handler, v); - ++pic->try_jmp_idx; - } - return v; + return pic_raise_continuable(pic, v); } noreturn static pic_value diff --git a/include/picrin/error.h b/include/picrin/error.h index 1b96f3ee..9541ab55 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -34,6 +34,7 @@ struct pic_jmpbuf { void pic_push_try(pic_state *, struct pic_proc *); void pic_pop_try(pic_state *); +pic_value pic_raise_continuable(pic_state *, pic_value); noreturn void pic_raise(pic_state *, pic_value); noreturn void pic_throw(pic_state *, pic_sym, const char *, pic_list); noreturn void pic_error(pic_state *, const char *, pic_list); From d33d0eee8588f99e8931013e052d14cfead1f640 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 17 Sep 2014 22:13:00 +0900 Subject: [PATCH 04/10] inline pic_try/pic_catch in with_exception_handler --- error.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/error.c b/error.c index feaefa92..10a778d7 100644 --- a/error.c +++ b/error.c @@ -180,10 +180,16 @@ pic_error_with_exception_handler(pic_state *pic) pic_get_args(pic, "ll", &handler, &thunk); - pic_try_with_handler(handler) { + pic_push_try(pic, handler); + if (setjmp(*pic->jmp) == 0) { + val = pic_apply0(pic, thunk); + + pic_pop_try(pic); } - pic_catch { + else { + pic_pop_try(pic); + pic_value e = pic->err; pic->err = pic_undef_value(); From de92aab1946e39d20cf86bdb0dca0bd21203495d Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 17 Sep 2014 22:21:31 +0900 Subject: [PATCH 05/10] with-exception-handler don't need to catch the continuation! --- error.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/error.c b/error.c index 10a778d7..84cdb64d 100644 --- a/error.c +++ b/error.c @@ -143,6 +143,21 @@ pic_raise_continuable(pic_state *pic, pic_value err) noreturn void pic_raise(pic_state *pic, pic_value err) { + if (pic->try_jmps[pic->try_jmp_idx - 1].handler != NULL) { + struct pic_proc *handler; + pic_value val; + + handler = pic->try_jmps[pic->try_jmp_idx - 1].handler; + + pic_pop_try(pic); + + pic_gc_protect(pic, pic_obj_value(handler)); + + val = pic_apply1(pic, handler, err); + + pic_errorf(pic, "error handler returned with ~s on error ~s", val, err); + } + void pic_vm_tear_off(pic_state *); pic_vm_tear_off(pic); /* tear off */ @@ -181,23 +196,11 @@ pic_error_with_exception_handler(pic_state *pic) pic_get_args(pic, "ll", &handler, &thunk); pic_push_try(pic, handler); - if (setjmp(*pic->jmp) == 0) { - val = pic_apply0(pic, thunk); + val = pic_apply0(pic, thunk); - pic_pop_try(pic); - } - else { - pic_pop_try(pic); + pic_pop_try(pic); - pic_value e = pic->err; - - pic->err = pic_undef_value(); - - val = pic_apply1(pic, handler, e); - - pic_errorf(pic, "error handler returned with ~s on error ~s", val, e); - } return val; } From 6a8a7d93e7bda66feade30a7d126a474c5e70fe5 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 17 Sep 2014 22:34:51 +0900 Subject: [PATCH 06/10] use raise-continuable in raise procedure --- error.c | 58 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/error.c b/error.c index 84cdb64d..2e7ec4d5 100644 --- a/error.c +++ b/error.c @@ -129,46 +129,46 @@ pic_raise_continuable(pic_state *pic, pic_value err) if (pic->try_jmp_idx == 0) { pic_errorf(pic, "no exception handler registered"); } + if (pic->try_jmps[pic->try_jmp_idx - 1].handler == NULL) { - pic_errorf(pic, "uncontinuable exception handler is on top"); - } - else { - pic->try_jmp_idx--; - v = pic_apply1(pic, pic->try_jmps[pic->try_jmp_idx].handler, err); - ++pic->try_jmp_idx; + void pic_vm_tear_off(pic_state *); + + pic_vm_tear_off(pic); /* tear off */ + + pic->err = err; + if (! pic->jmp) { + puts(pic_errmsg(pic)); + pic_panic(pic, "no handler found on stack"); + } + + longjmp(*pic->jmp, 1); } + + struct pic_proc *handler; + + handler = pic->try_jmps[pic->try_jmp_idx - 1].handler; + + pic_gc_protect(pic, pic_obj_value(handler)); + + pic->try_jmp_idx--; + + v = pic_apply1(pic, pic->try_jmps[pic->try_jmp_idx].handler, err); + + pic->try_jmp_idx++; + return v; } noreturn void pic_raise(pic_state *pic, pic_value err) { - if (pic->try_jmps[pic->try_jmp_idx - 1].handler != NULL) { - struct pic_proc *handler; - pic_value val; + pic_value val; - handler = pic->try_jmps[pic->try_jmp_idx - 1].handler; + val = pic_raise_continuable(pic, err); - pic_pop_try(pic); + pic_pop_try(pic); - pic_gc_protect(pic, pic_obj_value(handler)); - - val = pic_apply1(pic, handler, err); - - pic_errorf(pic, "error handler returned with ~s on error ~s", val, err); - } - - void pic_vm_tear_off(pic_state *); - - pic_vm_tear_off(pic); /* tear off */ - - pic->err = err; - if (! pic->jmp) { - puts(pic_errmsg(pic)); - pic_panic(pic, "no handler found on stack"); - } - - longjmp(*pic->jmp, 1); + pic_errorf(pic, "error handler returned with ~s on error ~s", val, err); } noreturn void From 46c1d0f2a77e1b8c46634fe586db043089fbff56 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 18 Sep 2014 14:12:18 +0900 Subject: [PATCH 07/10] use call/cc in exception handler implementation --- error.c | 88 +++++++++++++++++++++++------------------- include/picrin.h | 1 - include/picrin/error.h | 7 +--- state.c | 1 - 4 files changed, 51 insertions(+), 46 deletions(-) diff --git a/error.c b/error.c index 2e7ec4d5..4eb34157 100644 --- a/error.c +++ b/error.c @@ -8,6 +8,8 @@ #include "picrin.h" #include "picrin/pair.h" +#include "picrin/proc.h" +#include "picrin/cont.h" #include "picrin/string.h" #include "picrin/error.h" @@ -66,42 +68,60 @@ pic_errmsg(pic_state *pic) return pic_str_cstr(str); } -void -pic_push_try(pic_state *pic, struct pic_proc *handler) +static pic_value +native_exception_handler(pic_state *pic) { + pic_value err; + struct pic_proc *cont; + + pic_get_args(pic, "o", &err); + + pic->err = err; + + cont = pic_proc_ptr(pic_attr_ref(pic, pic_get_proc(pic), "@@escape")); + + pic_apply1(pic, cont, pic_false_value()); + + UNREACHABLE(); +} + +static pic_value +native_push_try(pic_state *pic) +{ + struct pic_proc *cont, *handler; struct pic_jmpbuf *try_jmp; + pic_get_args(pic, "l", &cont); + + handler = pic_make_proc(pic, native_exception_handler, "(native-exception-handler)"); + + 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); } try_jmp = pic->try_jmps + pic->try_jmp_idx++; - try_jmp->handler = handler; - try_jmp->ci_offset = pic->ci - pic->cibase; - try_jmp->sp_offset = pic->sp - pic->stbase; - try_jmp->ip = pic->ip; + return pic_true_value(); +} - try_jmp->prev_jmp = pic->jmp; - pic->jmp = &try_jmp->here; +bool +pic_push_try(pic_state *pic) +{ + pic_value val; + + val = pic_callcc(pic, pic_make_proc(pic, native_push_try, "(native-push-try)")); + + return pic_test(val); } void pic_pop_try(pic_state *pic) { - struct pic_jmpbuf *try_jmp; - - try_jmp = pic->try_jmps + --pic->try_jmp_idx; - - /* assert(pic->jmp == &try_jmp->here); */ - - pic->ci = try_jmp->ci_offset + pic->cibase; - pic->sp = try_jmp->sp_offset + pic->stbase; - pic->ip = try_jmp->ip; - - pic->jmp = try_jmp->prev_jmp; + --pic->try_jmp_idx; } struct pic_error * @@ -124,28 +144,13 @@ pic_make_error(pic_state *pic, pic_sym type, const char *msg, pic_value irrs) pic_value pic_raise_continuable(pic_state *pic, pic_value err) { + struct pic_proc *handler; pic_value v; if (pic->try_jmp_idx == 0) { - pic_errorf(pic, "no exception handler registered"); + pic_panic(pic, "no exception handler registered"); } - if (pic->try_jmps[pic->try_jmp_idx - 1].handler == NULL) { - void pic_vm_tear_off(pic_state *); - - pic_vm_tear_off(pic); /* tear off */ - - pic->err = err; - if (! pic->jmp) { - puts(pic_errmsg(pic)); - pic_panic(pic, "no handler found on stack"); - } - - longjmp(*pic->jmp, 1); - } - - struct pic_proc *handler; - handler = pic->try_jmps[pic->try_jmp_idx - 1].handler; pic_gc_protect(pic, pic_obj_value(handler)); @@ -154,7 +159,7 @@ pic_raise_continuable(pic_state *pic, pic_value err) v = pic_apply1(pic, pic->try_jmps[pic->try_jmp_idx].handler, err); - pic->try_jmp_idx++; + pic->try_jmps[pic->try_jmp_idx++].handler = handler; return v; } @@ -195,11 +200,16 @@ pic_error_with_exception_handler(pic_state *pic) pic_get_args(pic, "ll", &handler, &thunk); - pic_push_try(pic, handler); + 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); + } + + pic->try_jmps[pic->try_jmp_idx++].handler = handler; val = pic_apply0(pic, thunk); - pic_pop_try(pic); + pic->try_jmp_idx--; return val; } diff --git a/include/picrin.h b/include/picrin.h index 5bec9eb0..17a159dd 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -111,7 +111,6 @@ typedef struct { struct pic_reader *reader; - jmp_buf *jmp; pic_value err; struct pic_jmpbuf *try_jmps; size_t try_jmp_size, try_jmp_idx; diff --git a/include/picrin/error.h b/include/picrin/error.h index 9541ab55..8686d3ff 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -21,17 +21,14 @@ struct pic_jmpbuf { /* do not return from try block! */ #define pic_try \ - pic_try_with_handler(NULL) -#define pic_try_with_handler(handler) \ - pic_push_try(pic, handler); \ - if (setjmp(*pic->jmp) == 0) \ + if (pic_push_try(pic)) \ do #define pic_catch \ while (pic_pop_try(pic), 0); \ else \ if (pic_pop_try(pic), 1) -void pic_push_try(pic_state *, struct pic_proc *); +bool pic_push_try(pic_state *); void pic_pop_try(pic_state *); pic_value pic_raise_continuable(pic_state *, pic_value); diff --git a/state.c b/state.c index df9ba02c..e75876a2 100644 --- a/state.c +++ b/state.c @@ -71,7 +71,6 @@ pic_open(int argc, char *argv[], char **envp) xh_init_int(&pic->reader->labels, sizeof(pic_value)); /* error handling */ - pic->jmp = NULL; pic->err = pic_undef_value(); pic->try_jmps = calloc(PIC_RESCUE_SIZE, sizeof(struct pic_jmpbuf)); pic->try_jmp_idx = 0; From b0b1b77c6528d17b45e9bd52d9eb2af3fccbda35 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 18 Sep 2014 14:14:09 +0900 Subject: [PATCH 08/10] [bugfix] don't refer to env storage when accessing non-captured variable --- vm.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/vm.c b/vm.c index 609c702f..92af1ce7 100644 --- a/vm.c +++ b/vm.c @@ -755,20 +755,28 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv) } CASE(OP_LREF) { pic_callinfo *ci = pic->ci; + struct pic_irep *irep; if (ci->env != NULL && ci->env->regs == ci->env->storage) { - PUSH(ci->env->regs[c.u.i - (ci->regs - ci->fp)]); - NEXT; + irep = pic_get_proc(pic)->u.irep; + if (c.u.i >= irep->argc + irep->localc) { + PUSH(ci->env->regs[c.u.i - (ci->regs - ci->fp)]); + NEXT; + } } PUSH(pic->ci->fp[c.u.i]); NEXT; } CASE(OP_LSET) { pic_callinfo *ci = pic->ci; + struct pic_irep *irep; if (ci->env != NULL && ci->env->regs == ci->env->storage) { - ci->env->regs[c.u.i - (ci->regs - ci->fp)] = POP(); - NEXT; + irep = pic_get_proc(pic)->u.irep; + if (c.u.i >= irep->argc + irep->localc) { + ci->env->regs[c.u.i - (ci->regs - ci->fp)] = POP(); + NEXT; + } } pic->ci->fp[c.u.i] = POP(); NEXT; From 978c51bb2629483dc7fce2a91aa32ea80e5f7a15 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 18 Sep 2014 14:50:01 +0900 Subject: [PATCH 09/10] compact struct pic_jmpbuf --- cont.c | 28 ++++++++++++++-------------- error.c | 40 ++++++++++++++++++++++------------------ gc.c | 33 ++++++++++++++++----------------- include/picrin.h | 9 +++++---- include/picrin/cont.h | 6 +++--- include/picrin/error.h | 9 --------- state.c | 12 +++++++----- 7 files changed, 67 insertions(+), 70 deletions(-) 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); From 7a8144bbf7bc355f689aee1e1fae175caf436858 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Thu, 18 Sep 2014 14:50:58 +0900 Subject: [PATCH 10/10] cosmetic change --- include/picrin/error.h | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/include/picrin/error.h b/include/picrin/error.h index 0549c69d..5be65502 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -9,6 +9,19 @@ extern "C" { #endif +struct pic_error { + PIC_OBJECT_HEADER + pic_sym type; + pic_str *msg; + pic_value irrs; + pic_str *stack; +}; + +#define pic_error_p(v) (pic_type(v) == PIC_TT_ERROR) +#define pic_error_ptr(v) ((struct pic_error *)pic_ptr(v)) + +struct pic_error *pic_make_error(pic_state *, pic_sym, const char *, pic_list); + /* do not return from try block! */ #define pic_try \ @@ -27,19 +40,6 @@ noreturn void pic_raise(pic_state *, pic_value); noreturn void pic_throw(pic_state *, pic_sym, const char *, pic_list); noreturn void pic_error(pic_state *, const char *, pic_list); -struct pic_error { - PIC_OBJECT_HEADER - pic_sym type; - pic_str *msg; - pic_value irrs; - pic_str *stack; -}; - -#define pic_error_p(v) (pic_type(v) == PIC_TT_ERROR) -#define pic_error_ptr(v) ((struct pic_error *)pic_ptr(v)) - -struct pic_error *pic_make_error(pic_state *, pic_sym, const char *, pic_list); - #if defined(__cplusplus) } #endif