diff --git a/src/cont.c b/src/cont.c index df2d8a6b..a5740aa0 100644 --- a/src/cont.c +++ b/src/cont.c @@ -164,9 +164,12 @@ native_stack_extend(pic_state *pic, struct pic_cont *cont) noreturn static void restore_cont(pic_state *pic, struct pic_cont *cont) { + void pic_vm_tear_off(pic_state *); char v; struct pic_cont *tmp = cont; + pic_vm_tear_off(pic); /* tear off */ + if (&v < pic->native_stack_start) { if (&v > cont->stk_pos) native_stack_extend(pic, cont); } diff --git a/src/error.c b/src/error.c index b5ed169e..fb2d63f7 100644 --- a/src/error.c +++ b/src/error.c @@ -91,11 +91,16 @@ error_new(pic_state *pic, short type, pic_str *msg, pic_value irrs) noreturn void pic_throw_error(pic_state *pic, struct pic_error *e) { + void pic_vm_tear_off(pic_state *); + + pic_vm_tear_off(pic); /* tear off */ + pic->err = e; if (! pic->jmp) { puts(pic_errmsg(pic)); abort(); } + longjmp(*pic->jmp, 1); } diff --git a/src/vm.c b/src/vm.c index 39e0d6f8..2ab80a1e 100644 --- a/src/vm.c +++ b/src/vm.c @@ -503,12 +503,28 @@ vm_tear_off(pic_state *pic) assert(pic->ci->env != NULL); env = pic->ci->env; + + if (env->regs == env->storage) { + return; /* is torn off */ + } for (i = 0; i < env->regc; ++i) { env->storage[i] = env->regs[i]; } env->regs = env->storage; } +void +pic_vm_tear_off(pic_state *pic) +{ + pic_callinfo *ci; + + for (ci = pic->ci; ci > pic->cibase; ci--) { + if (pic->ci->env != NULL) { + vm_tear_off(pic); + } + } +} + pic_value pic_apply0(pic_state *pic, struct pic_proc *proc) {