From 50879dd7b6195a9029601b7ee928f22a9602f060 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Fri, 25 Jul 2014 14:41:56 +0900 Subject: [PATCH] Allocate pic_blocks in picrin's gc pool; reference count may cause problems --- include/picrin.h | 9 +-------- include/picrin/cont.h | 37 ++++++++----------------------------- include/picrin/value.h | 5 ++++- src/codegen.c | 1 + src/cont.c | 14 ++++---------- src/gc.c | 36 +++++++++++++++++++++--------------- src/macro.c | 1 + src/state.c | 23 +++++++++++++++-------- src/system.c | 2 +- 9 files changed, 56 insertions(+), 72 deletions(-) diff --git a/include/picrin.h b/include/picrin.h index ca043c09..b4036cb5 100644 --- a/include/picrin.h +++ b/include/picrin.h @@ -57,18 +57,11 @@ typedef struct { struct pic_env *up; } pic_callinfo; -typedef struct pic_block { - struct pic_block *prev; - int depth; - struct pic_proc *in, *out; - unsigned refcnt; -} pic_block; - typedef struct { int argc; char **argv, **envp; - pic_block *blk; + struct pic_block *blk; pic_value *sp; pic_value *stbase, *stend; diff --git a/include/picrin/cont.h b/include/picrin/cont.h index b33b6755..0a0da9f1 100644 --- a/include/picrin/cont.h +++ b/include/picrin/cont.h @@ -9,11 +9,18 @@ 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; - pic_block *blk; + struct pic_block *blk; char *stk_pos, *stk_ptr; ptrdiff_t stk_len; @@ -36,34 +43,6 @@ struct pic_cont { pic_value results; }; -#define PIC_BLK_INCREF(pic,blk) do { \ - (blk)->refcnt++; \ - } while (0) - -#define PIC_BLK_DECREF(pic,blk) do { \ - pic_block *_a = (blk), *_b; \ - while (_a) { \ - if (! --_a->refcnt) { \ - _b = _a->prev; \ - pic_free((pic), _a); \ - _a = _b; \ - } else { \ - break; \ - } \ - } \ - } while (0) - -#define PIC_BLK_EXIT(pic) do { \ - pic_block *_a; \ - while (pic->blk) { \ - if (pic->blk->out) \ - pic_apply0(pic, pic->blk->out); \ - _a = pic->blk->prev; \ - PIC_BLK_DECREF(pic, pic->blk); \ - pic->blk = _a; \ - } \ - } while (0) - pic_value pic_values0(pic_state *); pic_value pic_values1(pic_state *, pic_value); pic_value pic_values2(pic_state *, pic_value, pic_value); diff --git a/include/picrin/value.h b/include/picrin/value.h index 283bac28..023902a3 100644 --- a/include/picrin/value.h +++ b/include/picrin/value.h @@ -115,7 +115,8 @@ enum pic_tt { PIC_TT_VAR, PIC_TT_IREP, PIC_TT_DATA, - PIC_TT_DICT + PIC_TT_DICT, + PIC_TT_BLK, }; #define PIC_OBJECT_HEADER \ @@ -268,6 +269,8 @@ pic_type_repr(enum pic_tt tt) return "data"; case PIC_TT_DICT: return "dict"; + case PIC_TT_BLK: + return "block"; } UNREACHABLE(); } diff --git a/src/codegen.c b/src/codegen.c index a5c35eb8..8f8d9aed 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -831,6 +831,7 @@ analyze_node(analyze_state *state, pic_value obj, bool tailpos) case PIC_TT_IREP: case PIC_TT_DATA: case PIC_TT_DICT: + case PIC_TT_BLK: pic_errorf(pic, "invalid expression given: ~s", obj); } UNREACHABLE(); diff --git a/src/cont.c b/src/cont.c index bfda7310..30d26568 100644 --- a/src/cont.c +++ b/src/cont.c @@ -119,7 +119,6 @@ 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; - PIC_BLK_INCREF(pic, cont->blk); cont->stk_len = native_stack_length(pic, &pos); cont->stk_pos = pos; @@ -167,7 +166,7 @@ restore_cont(pic_state *pic, struct pic_cont *cont) void pic_vm_tear_off(pic_state *); char v; struct pic_cont *tmp = cont; - pic_block *blk; + struct pic_block *blk; pic_vm_tear_off(pic); /* tear off */ @@ -180,8 +179,6 @@ restore_cont(pic_state *pic, struct pic_cont *cont) blk = pic->blk; pic->blk = cont->blk; - PIC_BLK_INCREF(pic, pic->blk); - PIC_BLK_DECREF(pic, blk); 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); @@ -211,7 +208,7 @@ restore_cont(pic_state *pic, struct pic_cont *cont) } static void -walk_to_block(pic_state *pic, pic_block *here, pic_block *there) +walk_to_block(pic_state *pic, struct pic_block *here, struct pic_block *there) { if (here == there) return; @@ -229,7 +226,7 @@ walk_to_block(pic_state *pic, pic_block *here, pic_block *there) static pic_value pic_dynamic_wind(pic_state *pic, struct pic_proc *in, struct pic_proc *thunk, struct pic_proc *out) { - pic_block *here; + struct pic_block *here; pic_value val; if (in != NULL) { @@ -237,17 +234,14 @@ pic_dynamic_wind(pic_state *pic, struct pic_proc *in, struct pic_proc *thunk, st } here = pic->blk; - pic->blk = (pic_block *)pic_alloc(pic, sizeof(pic_block)); + 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; - pic->blk->refcnt = 1; - PIC_BLK_INCREF(pic, here); val = pic_apply0(pic, thunk); - PIC_BLK_DECREF(pic, pic->blk); pic->blk = here; if (out != NULL) { diff --git a/src/gc.c b/src/gc.c index 1ea3986e..4e3c82ff 100644 --- a/src/gc.c +++ b/src/gc.c @@ -322,18 +322,6 @@ gc_free(pic_state *pic, union header *bp) static void gc_mark(pic_state *, pic_value); static void gc_mark_object(pic_state *pic, struct pic_object *obj); -static void -gc_mark_block(pic_state *pic, pic_block *blk) -{ - while (blk) { - if (blk->in) - gc_mark_object(pic, (struct pic_object *)blk->in); - if (blk->out) - gc_mark_object(pic, (struct pic_object *)blk->out); - blk = blk->prev; - } -} - static bool gc_is_marked(union header *p) { @@ -418,7 +406,7 @@ gc_mark_object(pic_state *pic, struct pic_object *obj) int i; /* block */ - gc_mark_block(pic, cont->blk); + gc_mark_object(pic, (struct pic_object *)cont->blk); /* stack */ for (stack = cont->st_ptr; stack != cont->st_ptr + cont->sp_offset; ++stack) { @@ -506,6 +494,20 @@ 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: @@ -539,7 +541,9 @@ gc_mark_phase(pic_state *pic) xh_iter it; /* block */ - gc_mark_block(pic, pic->blk); + if (pic->blk) { + gc_mark_object(pic, (struct pic_object *)pic->blk); + } /* stack */ for (stack = pic->stbase; stack != pic->sp; ++stack) { @@ -622,7 +626,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) pic_free(pic, cont->ci_ptr); pic_free(pic, cont->arena); pic_free(pic, cont->try_jmps); - PIC_BLK_DECREF(pic, cont->blk); break; } case PIC_TT_SENV: { @@ -659,6 +662,9 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) xh_destroy(&dict->hash); break; } + case PIC_TT_BLK: { + break; + } case PIC_TT_NIL: case PIC_TT_BOOL: case PIC_TT_FLOAT: diff --git a/src/macro.c b/src/macro.c index 597eb57f..a31173de 100644 --- a/src/macro.c +++ b/src/macro.c @@ -416,6 +416,7 @@ macroexpand_node(pic_state *pic, pic_value expr, struct pic_senv *senv) case PIC_TT_IREP: case PIC_TT_DATA: case PIC_TT_DICT: + case PIC_TT_BLK: pic_errorf(pic, "unexpected value type: ~s", expr); } UNREACHABLE(); diff --git a/src/state.c b/src/state.c index cdae3901..518d2ea4 100644 --- a/src/state.c +++ b/src/state.c @@ -23,18 +23,14 @@ pic_open(int argc, char *argv[], char **envp) pic = (pic_state *)malloc(sizeof(pic_state)); + /* root block */ + pic->blk = NULL; + /* command line */ pic->argc = argc; pic->argv = argv; pic->envp = envp; - /* root block */ - pic->blk = (pic_block *)malloc(sizeof(pic_block)); - pic->blk->prev = NULL; - pic->blk->depth = 0; - pic->blk->in = pic->blk->out = NULL; - pic->blk->refcnt = 1; - /* prepare VM stack */ pic->stbase = pic->sp = (pic_value *)calloc(PIC_STACK_SIZE, sizeof(pic_value)); pic->stend = pic->stbase + PIC_STACK_SIZE; @@ -135,6 +131,12 @@ pic_open(int argc, char *argv[], char **envp) register_renamed_symbol(pic, rEXPORT, "export"); 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_init_core(pic); /* set library */ @@ -150,7 +152,12 @@ pic_close(pic_state *pic) xh_iter it; /* invoke exit handlers */ - PIC_BLK_EXIT(pic); + while (pic->blk) { + if (pic->blk->out) { + pic_apply0(pic, pic->blk->out); + } + pic->blk = pic->blk->prev; + } /* clear out root objects */ pic->sp = pic->stbase; diff --git a/src/system.c b/src/system.c index 73b27262..633d4a94 100644 --- a/src/system.c +++ b/src/system.c @@ -47,7 +47,7 @@ pic_system_exit(pic_state *pic) } } - PIC_BLK_EXIT(pic); + pic_close(pic); exit(status); }