Merge branch 'tearoff'

This commit is contained in:
Yuichi Nishiwaki 2014-03-23 12:26:03 +09:00
commit 25e5b51c1c
5 changed files with 48 additions and 31 deletions

View File

@ -62,7 +62,6 @@ struct pic_irep {
PIC_OBJECT_HEADER PIC_OBJECT_HEADER
pic_code *code; pic_code *code;
int argc, localc, capturec; int argc, localc, capturec;
unsigned *cv_tbl;
bool varg; bool varg;
struct pic_irep **irep; struct pic_irep **irep;
pic_value *pool; pic_value *pool;
@ -189,10 +188,6 @@ pic_dump_irep(struct pic_irep *irep)
printf("## irep %p\n", (void *)irep); printf("## irep %p\n", (void *)irep);
printf("[clen = %zd, argc = %d, localc = %d, capturec = %d]\n", irep->clen, irep->argc, irep->localc, irep->capturec); printf("[clen = %zd, argc = %d, localc = %d, capturec = %d]\n", irep->clen, irep->argc, irep->localc, irep->capturec);
printf(":: cv_tbl\n");
for (i = 0; i < (unsigned)irep->capturec; ++i) {
printf(": %d -> %d\n", irep->cv_tbl[i], i);
}
for (i = 0; i < irep->clen; ++i) { for (i = 0; i < irep->clen; ++i) {
printf("%02x ", i); printf("%02x ", i);
pic_dump_code(irep->code[i]); pic_dump_code(irep->code[i]);

View File

@ -20,6 +20,7 @@ struct pic_env {
pic_value *values; pic_value *values;
int valuec; int valuec;
struct pic_env *up; struct pic_env *up;
pic_value storage[];
}; };
struct pic_proc { struct pic_proc {

View File

@ -817,8 +817,6 @@ typedef struct codegen_context {
bool varg; bool varg;
/* rest args variable is counted as a local */ /* rest args variable is counted as a local */
xvect args, locals, captures; xvect args, locals, captures;
/* closed variable table */
unsigned *cv_tbl;
/* actual bit code sequence */ /* actual bit code sequence */
pic_code *code; pic_code *code;
size_t clen, ccapa; size_t clen, ccapa;
@ -883,16 +881,15 @@ destroy_codegen_state(codegen_state *state)
} }
static void static void
create_cv_table(pic_state *pic, codegen_context *cxt) create_activation(codegen_context *cxt)
{ {
size_t i; size_t i, n;
xhash *regs; xhash *regs;
pic_sym *var; pic_sym *var;
size_t offset; size_t offset;
regs = xh_new_int(); regs = xh_new_int();
/* number local variables */
offset = 1; offset = 1;
for (i = 0; i < cxt->args.size; ++i) { for (i = 0; i < cxt->args.size; ++i) {
var = xv_get(&cxt->args, i); var = xv_get(&cxt->args, i);
@ -904,11 +901,18 @@ create_cv_table(pic_state *pic, codegen_context *cxt)
xh_put_int(regs, *var, i + offset); xh_put_int(regs, *var, i + offset);
} }
/* closed variables */
cxt->cv_tbl = pic_calloc(pic, cxt->captures.size, sizeof(unsigned));
for (i = 0; i < cxt->captures.size; ++i) { for (i = 0; i < cxt->captures.size; ++i) {
var = xv_get(&cxt->captures, i); var = xv_get(&cxt->captures, i);
cxt->cv_tbl[i] = xh_get_int(regs, *var)->val; if ((n = xh_get_int(regs, *var)->val) <= cxt->args.size) {
/* copy arguments to capture variable area */
cxt->code[cxt->clen].insn = OP_LREF;
cxt->code[cxt->clen].u.i = n;
cxt->clen++;
} else {
/* otherwise, just extend the stack */
cxt->code[cxt->clen].insn = OP_PUSHNONE;
cxt->clen++;
}
} }
xh_destroy(regs); xh_destroy(regs);
@ -939,8 +943,6 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo
xv_push(&cxt->captures, &pic_sym(var)); xv_push(&cxt->captures, &pic_sym(var));
} }
create_cv_table(pic, cxt);
cxt->code = pic_calloc(pic, PIC_ISEQ_SIZE, sizeof(pic_code)); cxt->code = pic_calloc(pic, PIC_ISEQ_SIZE, sizeof(pic_code));
cxt->clen = 0; cxt->clen = 0;
cxt->ccapa = PIC_ISEQ_SIZE; cxt->ccapa = PIC_ISEQ_SIZE;
@ -954,6 +956,8 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo
cxt->pcapa = PIC_POOL_SIZE; cxt->pcapa = PIC_POOL_SIZE;
state->cxt = cxt; state->cxt = cxt;
create_activation(cxt);
} }
static struct pic_irep * static struct pic_irep *
@ -969,7 +973,6 @@ pop_codegen_context(codegen_state *state)
irep->argc = state->cxt->args.size + 1; irep->argc = state->cxt->args.size + 1;
irep->localc = state->cxt->locals.size; irep->localc = state->cxt->locals.size;
irep->capturec = state->cxt->captures.size; irep->capturec = state->cxt->captures.size;
irep->cv_tbl = state->cxt->cv_tbl;
irep->code = pic_realloc(pic, state->cxt->code, sizeof(pic_code) * state->cxt->clen); irep->code = pic_realloc(pic, state->cxt->code, sizeof(pic_code) * state->cxt->clen);
irep->clen = state->cxt->clen; irep->clen = state->cxt->clen;
irep->irep = pic_realloc(pic, state->cxt->irep, sizeof(struct pic_irep *) * state->cxt->ilen); irep->irep = pic_realloc(pic, state->cxt->irep, sizeof(struct pic_irep *) * state->cxt->ilen);
@ -1050,7 +1053,6 @@ codegen(codegen_state *state, pic_value obj)
pic_sym name; pic_sym name;
int depth; int depth;
CREF:
depth = pic_int(pic_list_ref(pic, obj, 1)); depth = pic_int(pic_list_ref(pic, obj, 1));
name = pic_sym(pic_list_ref(pic, obj, 2)); name = pic_sym(pic_list_ref(pic, obj, 2));
cxt->code[cxt->clen].insn = OP_CREF; cxt->code[cxt->clen].insn = OP_CREF;
@ -1060,11 +1062,14 @@ codegen(codegen_state *state, pic_value obj)
return; return;
} else if (sym == state->sLREF) { } else if (sym == state->sLREF) {
pic_sym name; pic_sym name;
int i;
name = pic_sym(pic_list_ref(pic, obj, 1)); name = pic_sym(pic_list_ref(pic, obj, 1));
if (index_capture(state, name, 0) != -1) { if ((i = index_capture(state, name, 0)) != -1) {
obj = pic_list3(pic, pic_sym_value(state->sCREF), pic_int_value(0), pic_sym_value(name)); cxt->code[cxt->clen].insn = OP_LREF;
goto CREF; cxt->code[cxt->clen].u.i = i + cxt->args.size + cxt->locals.size + 1;
cxt->clen++;
return;
} }
cxt->code[cxt->clen].insn = OP_LREF; cxt->code[cxt->clen].insn = OP_LREF;
cxt->code[cxt->clen].u.i = index_local(state, name); cxt->code[cxt->clen].u.i = index_local(state, name);
@ -1091,7 +1096,6 @@ codegen(codegen_state *state, pic_value obj)
pic_sym name; pic_sym name;
int depth; int depth;
CSET:
depth = pic_int(pic_list_ref(pic, var, 1)); depth = pic_int(pic_list_ref(pic, var, 1));
name = pic_sym(pic_list_ref(pic, var, 2)); name = pic_sym(pic_list_ref(pic, var, 2));
cxt->code[cxt->clen].insn = OP_CSET; cxt->code[cxt->clen].insn = OP_CSET;
@ -1104,11 +1108,16 @@ codegen(codegen_state *state, pic_value obj)
} }
else if (type == state->sLREF) { else if (type == state->sLREF) {
pic_sym name; pic_sym name;
int i;
name = pic_sym(pic_list_ref(pic, var, 1)); name = pic_sym(pic_list_ref(pic, var, 1));
if (index_capture(state, name, 0) != -1) { if ((i = index_capture(state, name, 0)) != -1) {
var = pic_list3(pic, pic_sym_value(state->sCREF), pic_int_value(0), pic_sym_value(name)); cxt->code[cxt->clen].insn = OP_LSET;
goto CSET; cxt->code[cxt->clen].u.i = i + cxt->args.size + cxt->locals.size + 1;
cxt->clen++;
cxt->code[cxt->clen].insn = OP_PUSHNONE;
cxt->clen++;
return;
} }
cxt->code[cxt->clen].insn = OP_LSET; cxt->code[cxt->clen].insn = OP_LSET;
cxt->code[cxt->clen].u.i = index_local(state, name); cxt->code[cxt->clen].u.i = index_local(state, name);

View File

@ -580,7 +580,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
break; break;
} }
case PIC_TT_ENV: { case PIC_TT_ENV: {
pic_free(pic, ((struct pic_env *)obj)->values);
break; break;
} }
case PIC_TT_PROC: { case PIC_TT_PROC: {
@ -635,7 +634,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
case PIC_TT_IREP: { case PIC_TT_IREP: {
struct pic_irep *irep = (struct pic_irep *)obj; struct pic_irep *irep = (struct pic_irep *)obj;
pic_free(pic, irep->code); pic_free(pic, irep->code);
pic_free(pic, irep->cv_tbl);
pic_free(pic, irep->irep); pic_free(pic, irep->irep);
pic_free(pic, irep->pool); pic_free(pic, irep->pool);
break; break;

View File

@ -424,6 +424,19 @@ pic_defvar(pic_state *pic, const char *name, pic_value init)
pic_define(pic, name, pic_obj_value(pic_wrap_var(pic, var))); pic_define(pic, name, pic_obj_value(pic_wrap_var(pic, var)));
} }
static void
vm_tear_off(pic_state *pic)
{
struct pic_env *env;
int i;
env = pic->ci->env;
for (i = 0; i < env->valuec; ++i) {
env->storage[i] = env->values[i];
}
env->values = env->storage;
}
pic_value pic_value
pic_apply_argv(pic_state *pic, struct pic_proc *proc, size_t argc, ...) pic_apply_argv(pic_state *pic, struct pic_proc *proc, size_t argc, ...)
{ {
@ -707,13 +720,10 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv)
} }
/* prepare env */ /* prepare env */
ci->env = (struct pic_env *)pic_obj_alloc(pic, sizeof(struct pic_env), PIC_TT_ENV); ci->env = (struct pic_env *)pic_obj_alloc(pic, offsetof(struct pic_env, storage) + sizeof(pic_value) * irep->capturec, PIC_TT_ENV);
ci->env->up = proc->env; ci->env->up = proc->env;
ci->env->valuec = irep->capturec; ci->env->valuec = irep->capturec;
ci->env->values = pic_calloc(pic, ci->env->valuec, sizeof(pic_value)); ci->env->values = ci->fp + irep->argc + irep->localc;
for (i = 0; i < ci->env->valuec; ++i) {
ci->env->values[i] = ci->fp[irep->cv_tbl[i]];
}
pic->ip = irep->code; pic->ip = irep->code;
pic_gc_arena_restore(pic, ai); pic_gc_arena_restore(pic, ai);
@ -725,6 +735,8 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv)
pic_value *argv; pic_value *argv;
pic_callinfo *ci; pic_callinfo *ci;
vm_tear_off(pic);
if (c.u.i == -1) { if (c.u.i == -1) {
pic->sp += pic->ci[1].retc - 1; pic->sp += pic->ci[1].retc - 1;
c.u.i = pic->ci[1].retc + 1; c.u.i = pic->ci[1].retc + 1;
@ -753,6 +765,8 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv)
goto L_STOP; goto L_STOP;
} }
vm_tear_off(pic);
pic->ci->retc = c.u.i; pic->ci->retc = c.u.i;
L_RET: L_RET: