[bugfix] don't compare continuation objects by pointers. They may be

reused when it reenters the same stack position.
This commit is contained in:
Yuichi Nishiwaki 2015-06-23 03:12:17 +09:00
parent aae1b8792a
commit 777ba0ff6a
4 changed files with 26 additions and 19 deletions

View File

@ -61,6 +61,7 @@ pic_save_point(pic_state *pic, struct pic_cont *cont)
cont->ptable = pic->ptable; cont->ptable = pic->ptable;
cont->prev = pic->cc; cont->prev = pic->cc;
cont->results = pic_undef_value(); cont->results = pic_undef_value();
cont->id = pic->ccnt++;
pic->cc = cont; pic->cc = cont;
} }
@ -68,17 +69,6 @@ pic_save_point(pic_state *pic, struct pic_cont *cont)
void void
pic_load_point(pic_state *pic, struct pic_cont *cont) pic_load_point(pic_state *pic, struct pic_cont *cont)
{ {
struct pic_cont *cc;
for (cc = pic->cc; cc != NULL; cc = cc->prev) {
if (cc == cont) {
break;
}
}
if (cc == NULL) {
pic_errorf(pic, "calling dead escape continuation");
}
pic_wind(pic, pic->cp, cont->cp); pic_wind(pic, pic->cp, cont->cp);
/* load runtime context */ /* load runtime context */
@ -94,18 +84,32 @@ pic_load_point(pic_state *pic, struct pic_cont *cont)
static pic_value static pic_value
cont_call(pic_state *pic) cont_call(pic_state *pic)
{ {
struct pic_proc *self = pic_get_proc(pic);
size_t argc; size_t argc;
pic_value *argv; pic_value *argv;
struct pic_data *e; int id;
struct pic_cont *cc, *cont;
pic_get_args(pic, "*", &argc, &argv); pic_get_args(pic, "*", &argc, &argv);
e = pic_data_ptr(pic_proc_env_ref(pic, pic_get_proc(pic), "escape")); id = pic_int(pic_proc_env_ref(pic, self, "id"));
((struct pic_cont *)e->data)->results = pic_list_by_array(pic, argc, argv);
pic_load_point(pic, e->data); /* check if continuation is alive */
for (cc = pic->cc; cc != NULL; cc = cc->prev) {
if (cc->id == id) {
break;
}
}
if (cc == NULL) {
pic_errorf(pic, "calling dead escape continuation");
}
PIC_LONGJMP(pic, ((struct pic_cont *)e->data)->jmp, 1); cont = pic_data_ptr(pic_proc_env_ref(pic, self, "escape"))->data;
cont->results = pic_list_by_array(pic, argc, argv);
pic_load_point(pic, cont);
PIC_LONGJMP(pic, cont->jmp, 1);
PIC_UNREACHABLE(); PIC_UNREACHABLE();
} }
@ -123,6 +127,7 @@ pic_make_cont(pic_state *pic, struct pic_cont *cont)
/* save the escape continuation in proc */ /* save the escape continuation in proc */
pic_proc_env_set(pic, c, "escape", pic_obj_value(e)); pic_proc_env_set(pic, c, "escape", pic_obj_value(e));
pic_proc_env_set(pic, c, "id", pic_int_value(cont->id));
return c; return c;
} }

View File

@ -73,8 +73,9 @@ struct pic_state {
pic_allocf allocf; pic_allocf allocf;
struct pic_cont *cc;
pic_checkpoint *cp; pic_checkpoint *cp;
struct pic_cont *cc;
int ccnt;
pic_value *sp; pic_value *sp;
pic_value *stbase, *stend; pic_value *stbase, *stend;

View File

@ -12,14 +12,14 @@ extern "C" {
struct pic_cont { struct pic_cont {
PIC_JMPBUF jmp; PIC_JMPBUF jmp;
pic_checkpoint *cp; int id;
pic_checkpoint *cp;
ptrdiff_t sp_offset; ptrdiff_t sp_offset;
ptrdiff_t ci_offset; ptrdiff_t ci_offset;
ptrdiff_t xp_offset; ptrdiff_t xp_offset;
size_t arena_idx; size_t arena_idx;
pic_value ptable; pic_value ptable;
pic_code *ip; pic_code *ip;
pic_value results; pic_value results;

View File

@ -174,6 +174,7 @@ pic_open(int argc, char *argv[], char **envp, pic_allocf allocf)
/* continuation chain */ /* continuation chain */
pic->cc = NULL; pic->cc = NULL;
pic->ccnt = 0;
/* root block */ /* root block */
pic->cp = NULL; pic->cp = NULL;