From a8de062bcbfa96ea4e1a99e9b10ed6323066f02b Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 6 Apr 2014 13:36:02 +0900 Subject: [PATCH 1/4] rename backtrace.c to debug.c --- src/{backtrace.c => debug.c} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{backtrace.c => debug.c} (100%) diff --git a/src/backtrace.c b/src/debug.c similarity index 100% rename from src/backtrace.c rename to src/debug.c From 920524dc40301469f30952f5de21b4be51de713f Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 6 Apr 2014 14:00:45 +0900 Subject: [PATCH 2/4] add pic_print_backtrace function --- include/picrin.h | 1 + src/debug.c | 49 ++++++++++++++++++++++++++++++++---------------- tools/main.c | 2 +- 3 files changed, 35 insertions(+), 17 deletions(-) diff --git a/include/picrin.h b/include/picrin.h index bac8032b..fa84f59b 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -187,6 +187,7 @@ noreturn void pic_abort(pic_state *, const char *); noreturn void pic_errorf(pic_state *, const char *, ...); void pic_warnf(pic_state *, const char *, ...); pic_str *pic_get_backtrace(pic_state *); +void pic_print_backtrace(pic_state *, struct pic_error *); /* obsoleted */ noreturn static inline void pic_error(pic_state *pic, const char *msg) diff --git a/src/debug.c b/src/debug.c index ba06d30a..63bc88a0 100644 --- a/src/debug.c +++ b/src/debug.c @@ -14,11 +14,38 @@ pic_get_backtrace(pic_state *pic) pic_callinfo *ci; pic_str *trace; + trace = pic_str_new(pic, NULL, 0); + + for (ci = pic->ci; ci != pic->cibase; --ci) { + struct pic_proc *proc = pic_proc_ptr(ci->fp[0]); + + trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, " at ")); + trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, pic_symbol_name(pic, pic_proc_name(proc)))); + + if (pic_proc_func_p(proc)) { + trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, " (native function)\n")); + } else if (pic_proc_irep_p(proc)) { + trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, " (unknown location)\n")); /* TODO */ + } + } + + pic_gc_arena_restore(pic, ai); + pic_gc_protect(pic, pic_obj_value(trace)); + + return trace; +} + +void +pic_print_backtrace(pic_state *pic, struct pic_error *e) +{ + int ai = pic_gc_arena_preserve(pic); + pic_str *trace; + assert(pic->err != NULL); trace = pic_str_new(pic, NULL, 0); - switch (pic->err->type) { + switch (e->type) { case PIC_ERROR_OTHER: trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, "error: ")); break; @@ -33,25 +60,15 @@ pic_get_backtrace(pic_state *pic) break; } - trace = pic_strcat(pic, trace, pic->err->msg); + trace = pic_strcat(pic, trace, e->msg); /* TODO: print error irritants */ - for (ci = pic->ci; ci != pic->cibase; --ci) { - struct pic_proc *proc = pic_proc_ptr(ci->fp[0]); + trace = pic_strcat(pic, trace, pic_str_new(pic, "\n", 1)); + trace = pic_strcat(pic, trace, pic_get_backtrace(pic)); - trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, "\n at ")); - trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, pic_symbol_name(pic, pic_proc_name(proc)))); - - if (pic_proc_func_p(proc)) { - trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, " (native function)")); - } else if (pic_proc_irep_p(proc)) { - trace = pic_strcat(pic, trace, pic_str_new_cstr(pic, " (unknown location)")); /* TODO */ - } - } + /* print! */ + printf("%s", pic_str_cstr(trace)); pic_gc_arena_restore(pic, ai); - pic_gc_protect(pic, pic_obj_value(trace)); - - return trace; } diff --git a/tools/main.c b/tools/main.c index 3b82de4d..c65582f5 100644 --- a/tools/main.c +++ b/tools/main.c @@ -142,7 +142,7 @@ repl(pic_state *pic) } } pic_catch { - printf("%s\n", pic_str_cstr(pic_get_backtrace(pic))); + pic_print_backtrace(pic, pic->err); pic->err = NULL; code[0] = '\0'; } From 5893dd5b5c1c51e8fe45c93c7330642a2e198394 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 6 Apr 2014 14:02:21 +0900 Subject: [PATCH 3/4] save stacktrace in error objects --- include/picrin/error.h | 1 + src/debug.c | 2 +- src/error.c | 3 +++ src/gc.c | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/include/picrin/error.h b/include/picrin/error.h index cebc85e1..1c62294f 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -41,6 +41,7 @@ struct pic_error { } type; struct pic_string *msg; pic_value irrs; + pic_str *stack; }; #define pic_error_p(v) (pic_type(v) == PIC_TT_ERROR) diff --git a/src/debug.c b/src/debug.c index 63bc88a0..7ce89fc0 100644 --- a/src/debug.c +++ b/src/debug.c @@ -65,7 +65,7 @@ pic_print_backtrace(pic_state *pic, struct pic_error *e) /* TODO: print error irritants */ trace = pic_strcat(pic, trace, pic_str_new(pic, "\n", 1)); - trace = pic_strcat(pic, trace, pic_get_backtrace(pic)); + trace = pic_strcat(pic, trace, e->stack); /* print! */ printf("%s", pic_str_cstr(trace)); diff --git a/src/error.c b/src/error.c index 227c80f3..2c319b79 100644 --- a/src/error.c +++ b/src/error.c @@ -96,6 +96,7 @@ pic_errorf(pic_state *pic, const char *fmt, ...) e->type = PIC_ERROR_OTHER; e->msg = pic_str_ptr(pic_car(pic, err_line)); e->irrs = pic_cdr(pic, err_line); + e->stack = pic_get_backtrace(pic); pic_throw(pic, e); } @@ -133,6 +134,7 @@ pic_error_raise(pic_state *pic) e->type = PIC_ERROR_RAISED; e->msg = pic_str_new_cstr(pic, "object is raised"); e->irrs = pic_list1(pic, v); + e->stack = pic_get_backtrace(pic); pic_throw(pic, e); } @@ -151,6 +153,7 @@ pic_error_error(pic_state *pic) e->type = PIC_ERROR_OTHER; e->msg = str; e->irrs = pic_list_by_array(pic, argc, argv); + e->stack = pic_get_backtrace(pic); pic_throw(pic, e); } diff --git a/src/gc.c b/src/gc.c index 81906f66..fd48833e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -391,6 +391,7 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) struct pic_error *err = (struct pic_error *)obj; gc_mark_object(pic,(struct pic_object *)err->msg); gc_mark(pic, err->irrs); + gc_mark_object(pic, (struct pic_object *)err->stack); break; } case PIC_TT_STRING: { From f5a4047e28f037ed46c2d5ddadac8f6178342fbb Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 6 Apr 2014 14:02:50 +0900 Subject: [PATCH 4/4] unwind picrin VM registers when pic_pop_try is called --- include/picrin/error.h | 3 +++ src/error.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/include/picrin/error.h b/include/picrin/error.h index 1c62294f..024d5d29 100644 --- a/include/picrin/error.h +++ b/include/picrin/error.h @@ -11,6 +11,9 @@ extern "C" { struct pic_jmpbuf { jmp_buf here; + pic_callinfo *ci; + pic_value *sp; + pic_code *ip; jmp_buf *prev_jmp; struct pic_jmpbuf *prev; }; diff --git a/src/error.c b/src/error.c index 2c319b79..c4d02cf2 100644 --- a/src/error.c +++ b/src/error.c @@ -41,6 +41,10 @@ pic_push_try(pic_state *pic) try_jmp = pic_alloc(pic, sizeof(struct pic_jmpbuf)); + try_jmp->ci = pic->ci; + try_jmp->sp = pic->sp; + try_jmp->ip = pic->ip; + try_jmp->prev_jmp = pic->jmp; pic->jmp = &try_jmp->here; @@ -55,6 +59,10 @@ pic_pop_try(pic_state *pic) assert(pic->jmp == &pic->try_jmps->here); + pic->ci = pic->try_jmps->ci; + pic->sp = pic->try_jmps->sp; + pic->ip = pic->try_jmps->ip; + pic->jmp = pic->try_jmps->prev_jmp; prev = pic->try_jmps->prev;