manage ireps using reference count

This commit is contained in:
Yuichi Nishiwaki 2016-02-05 00:30:11 +09:00
parent 6488e315d3
commit 64788af4b9
7 changed files with 83 additions and 28 deletions

View File

@ -694,7 +694,8 @@ codegen_context_destroy(pic_state *pic, codegen_context *cxt)
struct pic_irep *irep; struct pic_irep *irep;
/* create irep */ /* create irep */
irep = (struct pic_irep *)pic_obj_alloc(pic, sizeof(struct pic_irep), PIC_TT_IREP); irep = pic_malloc(pic, sizeof(struct pic_irep));
irep->refc = 1;
irep->varg = cxt->rest != NULL; irep->varg = cxt->rest != NULL;
irep->argc = (int)cxt->args->len + 1; irep->argc = (int)cxt->args->len + 1;
irep->localc = (int)cxt->locals->len; irep->localc = (int)cxt->locals->len;
@ -705,6 +706,11 @@ codegen_context_destroy(pic_state *pic, codegen_context *cxt)
irep->pool = pic_realloc(pic, cxt->pool, sizeof(pic_value) * cxt->plen); irep->pool = pic_realloc(pic, cxt->pool, sizeof(pic_value) * cxt->plen);
irep->plen = cxt->plen; irep->plen = cxt->plen;
irep->list.next = pic->ireps.next;
irep->list.prev = &pic->ireps;
irep->list.next->prev = &irep->list;
irep->list.prev->next = &irep->list;
return irep; return irep;
} }
@ -1086,6 +1092,7 @@ struct pic_proc *
pic_compile(pic_state *pic, pic_value obj, struct pic_env *env) pic_compile(pic_state *pic, pic_value obj, struct pic_env *env)
{ {
struct pic_irep *irep; struct pic_irep *irep;
struct pic_proc *proc;
size_t ai = pic_gc_arena_preserve(pic); size_t ai = pic_gc_arena_preserve(pic);
#if DEBUG #if DEBUG
@ -1143,7 +1150,9 @@ pic_compile(pic_state *pic, pic_value obj, struct pic_env *env)
puts(""); puts("");
#endif #endif
SAVE(pic, ai, pic_obj_value(irep)); proc = pic_make_proc_irep(pic, irep, NULL);
return pic_make_proc_irep(pic, irep, NULL); pic_irep_decref(pic, irep);
return proc;
} }

View File

@ -32,7 +32,6 @@ struct pic_object {
struct pic_env env; struct pic_env env;
struct pic_proc proc; struct pic_proc proc;
struct pic_context cxt; struct pic_context cxt;
struct pic_irep irep;
struct pic_port port; struct pic_port port;
struct pic_error err; struct pic_error err;
struct pic_lib lib; struct pic_lib lib;
@ -300,7 +299,6 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
} }
case PIC_TT_PROC: { case PIC_TT_PROC: {
if (pic_proc_irep_p(&obj->u.proc)) { if (pic_proc_irep_p(&obj->u.proc)) {
gc_mark_object(pic, (struct pic_object *)obj->u.proc.u.i.irep);
if (obj->u.proc.u.i.cxt) { if (obj->u.proc.u.i.cxt) {
LOOP(obj->u.proc.u.i.cxt); LOOP(obj->u.proc.u.i.cxt);
} }
@ -360,17 +358,6 @@ gc_mark_object(pic_state *pic, struct pic_object *obj)
LOOP(obj->u.lib.exports); LOOP(obj->u.lib.exports);
break; break;
} }
case PIC_TT_IREP: {
size_t i;
for (i = 0; i < obj->u.irep.ilen; ++i) {
gc_mark_object(pic, (struct pic_object *)obj->u.irep.irep[i]);
}
for (i = 0; i < obj->u.irep.plen; ++i) {
gc_mark(pic, obj->u.irep.pool[i]);
}
break;
}
case PIC_TT_DATA: { case PIC_TT_DATA: {
if (obj->u.data.type->mark) { if (obj->u.data.type->mark) {
obj->u.data.type->mark(pic, obj->u.data.data, gc_mark); obj->u.data.type->mark(pic, obj->u.data.data, gc_mark);
@ -441,6 +428,7 @@ gc_mark_phase(pic_state *pic)
pic_value *stack; pic_value *stack;
pic_callinfo *ci; pic_callinfo *ci;
struct pic_proc **xhandler; struct pic_proc **xhandler;
struct pic_list *list;
size_t j; size_t j;
assert(pic->heap->regs == NULL); assert(pic->heap->regs == NULL);
@ -472,6 +460,14 @@ gc_mark_phase(pic_state *pic)
gc_mark_object(pic, (struct pic_object *)pic->arena[j]); gc_mark_object(pic, (struct pic_object *)pic->arena[j]);
} }
/* ireps */
for (list = pic->ireps.next; list != &pic->ireps; list = list->next) {
struct pic_irep *irep = (struct pic_irep *)list;
for (j = 0; j < irep->plen; ++j) {
gc_mark(pic, irep->pool[j]);
}
}
/* mark reserved symbols */ /* mark reserved symbols */
M(sQUOTE); M(sQUASIQUOTE); M(sUNQUOTE); M(sUNQUOTE_SPLICING); M(sQUOTE); M(sQUASIQUOTE); M(sUNQUOTE); M(sUNQUOTE_SPLICING);
M(sSYNTAX_QUOTE); M(sSYNTAX_QUASIQUOTE); M(sSYNTAX_UNQUOTE); M(sSYNTAX_UNQUOTE_SPLICING); M(sSYNTAX_QUOTE); M(sSYNTAX_QUASIQUOTE); M(sSYNTAX_UNQUOTE); M(sSYNTAX_UNQUOTE_SPLICING);
@ -564,12 +560,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
kh_destroy(env, &obj->u.env.map); kh_destroy(env, &obj->u.env.map);
break; break;
} }
case PIC_TT_IREP: {
pic_free(pic, obj->u.irep.code);
pic_free(pic, obj->u.irep.irep);
pic_free(pic, obj->u.irep.pool);
break;
}
case PIC_TT_DATA: { case PIC_TT_DATA: {
if (obj->u.data.type->dtor) { if (obj->u.data.type->dtor) {
obj->u.data.type->dtor(pic, obj->u.data.data); obj->u.data.type->dtor(pic, obj->u.data.data);
@ -588,10 +578,15 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
kh_destroy(reg, &obj->u.reg.hash); kh_destroy(reg, &obj->u.reg.hash);
break; break;
} }
case PIC_TT_PROC: {
if (pic_proc_irep_p(&obj->u.proc)) {
pic_irep_decref(pic, obj->u.proc.u.i.irep);
}
break;
}
case PIC_TT_PAIR: case PIC_TT_PAIR:
case PIC_TT_CXT: case PIC_TT_CXT:
case PIC_TT_PROC:
case PIC_TT_PORT: case PIC_TT_PORT:
case PIC_TT_ERROR: case PIC_TT_ERROR:
case PIC_TT_ID: case PIC_TT_ID:

View File

@ -121,6 +121,7 @@ struct pic_state {
struct pic_reg *globals; struct pic_reg *globals;
struct pic_reg *macros; struct pic_reg *macros;
pic_value libs; pic_value libs;
struct pic_list ireps; /* chain */
pic_reader reader; pic_reader reader;
xFILE files[XOPEN_MAX]; xFILE files[XOPEN_MAX];

View File

@ -20,16 +20,25 @@ typedef struct {
} u; } u;
} pic_code; } pic_code;
struct pic_list {
struct pic_list *prev, *next;
};
struct pic_irep { struct pic_irep {
PIC_OBJECT_HEADER struct pic_list list;
int refc;
pic_code *code; pic_code *code;
int argc, localc, capturec; int argc, localc, capturec;
bool varg; bool varg;
struct pic_irep **irep; struct pic_irep **irep;
size_t ilen;
pic_value *pool; pic_value *pool;
size_t ilen, plen; size_t plen;
}; };
void pic_irep_incref(pic_state *, struct pic_irep *);
void pic_irep_decref(pic_state *, struct pic_irep *);
pic_sym *pic_resolve(pic_state *, pic_value, struct pic_env *); pic_sym *pic_resolve(pic_state *, pic_value, struct pic_env *);
pic_value pic_expand(pic_state *, pic_value, struct pic_env *); pic_value pic_expand(pic_state *, pic_value, struct pic_env *);
pic_value pic_analyze(pic_state *, pic_value); pic_value pic_analyze(pic_state *, pic_value);

View File

@ -158,7 +158,6 @@ enum pic_tt {
PIC_TT_RECORD, PIC_TT_RECORD,
PIC_TT_BOX, PIC_TT_BOX,
PIC_TT_CXT, PIC_TT_CXT,
PIC_TT_IREP,
PIC_TT_CP PIC_TT_CP
}; };
@ -305,8 +304,6 @@ pic_type_repr(enum pic_tt tt)
return "env"; return "env";
case PIC_TT_LIB: case PIC_TT_LIB:
return "lib"; return "lib";
case PIC_TT_IREP:
return "irep";
case PIC_TT_DATA: case PIC_TT_DATA:
return "data"; return "data";
case PIC_TT_DICT: case PIC_TT_DICT:

View File

@ -4,6 +4,33 @@
#include "picrin.h" #include "picrin.h"
void
pic_irep_incref(pic_state PIC_UNUSED(*pic), struct pic_irep *irep)
{
irep->refc++;
}
void
pic_irep_decref(pic_state *pic, struct pic_irep *irep)
{
size_t i;
if (--irep->refc == 0) {
pic_free(pic, irep->code);
pic_free(pic, irep->pool);
/* unchain before decref children ireps */
irep->list.prev->next = irep->list.next;
irep->list.next->prev = irep->list.prev;
for (i = 0; i < irep->ilen; ++i) {
pic_irep_decref(pic, irep->irep[i]);
}
pic_free(pic, irep->irep);
pic_free(pic, irep);
}
}
struct pic_proc * struct pic_proc *
pic_make_proc(pic_state *pic, pic_func_t func) pic_make_proc(pic_state *pic, pic_func_t func)
{ {
@ -25,6 +52,7 @@ pic_make_proc_irep(pic_state *pic, struct pic_irep *irep, struct pic_context *cx
proc->tag = PIC_PROC_TAG_IREP; proc->tag = PIC_PROC_TAG_IREP;
proc->u.i.irep = irep; proc->u.i.irep = irep;
proc->u.i.cxt = cxt; proc->u.i.cxt = cxt;
pic_irep_incref(pic, irep);
return proc; return proc;
} }

View File

@ -316,6 +316,10 @@ pic_open(pic_allocf allocf, void *userdata)
pic->libs = pic_nil_value(); pic->libs = pic_nil_value();
pic->lib = NULL; pic->lib = NULL;
/* ireps */
pic->ireps.next = &pic->ireps;
pic->ireps.prev = &pic->ireps;
/* raised error object */ /* raised error object */
pic->err = pic_invalid_value(); pic->err = pic_invalid_value();
@ -478,6 +482,18 @@ pic_close(pic_state *pic)
/* free all heap objects */ /* free all heap objects */
pic_gc_run(pic); pic_gc_run(pic);
#if 0
{
/* FIXME */
int i = 0;
struct pic_list *list;
for (list = pic->ireps.next; list != &pic->ireps; list = list->next) {
i++;
}
printf("%d\n", i);
}
#endif
/* flush all xfiles */ /* flush all xfiles */
xfflush(pic, NULL); xfflush(pic, NULL);