From c9eb61256110df932e56019e46556ca719c8010d Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 20:03:05 +0900 Subject: [PATCH 1/4] do variable closing operation not in OP_CALL but in OP_RET --- include/picrin/proc.h | 1 + src/codegen.c | 18 ++++++++++++++---- src/gc.c | 1 - src/vm.c | 24 +++++++++++++++++++----- 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/include/picrin/proc.h b/include/picrin/proc.h index 0b937537..34c12654 100644 --- a/include/picrin/proc.h +++ b/include/picrin/proc.h @@ -20,6 +20,7 @@ struct pic_env { pic_value *values; int valuec; struct pic_env *up; + pic_value storage[]; }; struct pic_proc { diff --git a/src/codegen.c b/src/codegen.c index 9946fa4b..4de20f75 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -885,7 +885,7 @@ destroy_codegen_state(codegen_state *state) static void create_cv_table(pic_state *pic, codegen_context *cxt) { - size_t i; + size_t i, n; xhash *regs; pic_sym *var; size_t offset; @@ -908,7 +908,17 @@ create_cv_table(pic_state *pic, codegen_context *cxt) cxt->cv_tbl = pic_calloc(pic, cxt->captures.size, sizeof(unsigned)); for (i = 0; i < cxt->captures.size; ++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++; + } + cxt->cv_tbl[i] = n; } xh_destroy(regs); @@ -939,8 +949,6 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo xv_push(&cxt->captures, &pic_sym(var)); } - create_cv_table(pic, cxt); - cxt->code = pic_calloc(pic, PIC_ISEQ_SIZE, sizeof(pic_code)); cxt->clen = 0; cxt->ccapa = PIC_ISEQ_SIZE; @@ -954,6 +962,8 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo cxt->pcapa = PIC_POOL_SIZE; state->cxt = cxt; + + create_cv_table(pic, cxt); } static struct pic_irep * diff --git a/src/gc.c b/src/gc.c index ec830474..6681b793 100644 --- a/src/gc.c +++ b/src/gc.c @@ -580,7 +580,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) break; } case PIC_TT_ENV: { - pic_free(pic, ((struct pic_env *)obj)->values); break; } case PIC_TT_PROC: { diff --git a/src/vm.c b/src/vm.c index 079b35c0..ca3a11b8 100644 --- a/src/vm.c +++ b/src/vm.c @@ -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))); } +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_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 */ - 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->valuec = irep->capturec; - ci->env->values = pic_calloc(pic, ci->env->valuec, sizeof(pic_value)); - for (i = 0; i < ci->env->valuec; ++i) { - ci->env->values[i] = ci->fp[irep->cv_tbl[i]]; - } + ci->env->values = ci->fp + irep->argc + irep->localc; pic->ip = irep->code; 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_callinfo *ci; + vm_tear_off(pic); + if (c.u.i == -1) { pic->sp += 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; } + vm_tear_off(pic); + pic->ci->retc = c.u.i; L_RET: From cac31845d03808acf285112c7aadd416bc48f060 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 20:06:20 +0900 Subject: [PATCH 2/4] cv_tbl is no longer used --- include/picrin/irep.h | 5 ----- src/codegen.c | 5 ----- src/gc.c | 1 - 3 files changed, 11 deletions(-) diff --git a/include/picrin/irep.h b/include/picrin/irep.h index 36607c3a..de0b8e80 100644 --- a/include/picrin/irep.h +++ b/include/picrin/irep.h @@ -62,7 +62,6 @@ struct pic_irep { PIC_OBJECT_HEADER pic_code *code; int argc, localc, capturec; - unsigned *cv_tbl; bool varg; struct pic_irep **irep; pic_value *pool; @@ -189,10 +188,6 @@ pic_dump_irep(struct pic_irep *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(":: 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) { printf("%02x ", i); pic_dump_code(irep->code[i]); diff --git a/src/codegen.c b/src/codegen.c index 4de20f75..bc022512 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -817,8 +817,6 @@ typedef struct codegen_context { bool varg; /* rest args variable is counted as a local */ xvect args, locals, captures; - /* closed variable table */ - unsigned *cv_tbl; /* actual bit code sequence */ pic_code *code; size_t clen, ccapa; @@ -905,7 +903,6 @@ create_cv_table(pic_state *pic, codegen_context *cxt) } /* closed variables */ - cxt->cv_tbl = pic_calloc(pic, cxt->captures.size, sizeof(unsigned)); for (i = 0; i < cxt->captures.size; ++i) { var = xv_get(&cxt->captures, i); if ((n = xh_get_int(regs, *var)->val) <= cxt->args.size) { @@ -918,7 +915,6 @@ create_cv_table(pic_state *pic, codegen_context *cxt) cxt->code[cxt->clen].insn = OP_PUSHNONE; cxt->clen++; } - cxt->cv_tbl[i] = n; } xh_destroy(regs); @@ -979,7 +975,6 @@ pop_codegen_context(codegen_state *state) irep->argc = state->cxt->args.size + 1; irep->localc = state->cxt->locals.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->clen = state->cxt->clen; irep->irep = pic_realloc(pic, state->cxt->irep, sizeof(struct pic_irep *) * state->cxt->ilen); diff --git a/src/gc.c b/src/gc.c index 6681b793..424ea87c 100644 --- a/src/gc.c +++ b/src/gc.c @@ -634,7 +634,6 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj) case PIC_TT_IREP: { struct pic_irep *irep = (struct pic_irep *)obj; pic_free(pic, irep->code); - pic_free(pic, irep->cv_tbl); pic_free(pic, irep->irep); pic_free(pic, irep->pool); break; From 1b6f1db1c0611e0f6deb1447f9136ba0c42e55a3 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 20:36:50 +0900 Subject: [PATCH 3/4] s/create_cv_table/create_activation/g --- src/codegen.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index bc022512..a91c790e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -881,7 +881,7 @@ destroy_codegen_state(codegen_state *state) } static void -create_cv_table(pic_state *pic, codegen_context *cxt) +create_activation(codegen_context *cxt) { size_t i, n; xhash *regs; @@ -890,7 +890,6 @@ create_cv_table(pic_state *pic, codegen_context *cxt) regs = xh_new_int(); - /* number local variables */ offset = 1; for (i = 0; i < cxt->args.size; ++i) { var = xv_get(&cxt->args, i); @@ -902,7 +901,6 @@ create_cv_table(pic_state *pic, codegen_context *cxt) xh_put_int(regs, *var, i + offset); } - /* closed variables */ for (i = 0; i < cxt->captures.size; ++i) { var = xv_get(&cxt->captures, i); if ((n = xh_get_int(regs, *var)->val) <= cxt->args.size) { @@ -959,7 +957,7 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo state->cxt = cxt; - create_cv_table(pic, cxt); + create_activation(cxt); } static struct pic_irep * From 4a1809a9c5eb3325bf39fb93fdacfa7862a4b8ae Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sun, 23 Mar 2014 12:18:41 +0900 Subject: [PATCH 4/4] get access to captured local variables with OP_LREF/OP_LSET --- src/codegen.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index a91c790e..26b68e2e 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1053,7 +1053,6 @@ codegen(codegen_state *state, pic_value obj) pic_sym name; int depth; - CREF: depth = pic_int(pic_list_ref(pic, obj, 1)); name = pic_sym(pic_list_ref(pic, obj, 2)); cxt->code[cxt->clen].insn = OP_CREF; @@ -1063,11 +1062,14 @@ codegen(codegen_state *state, pic_value obj) return; } else if (sym == state->sLREF) { pic_sym name; + int i; name = pic_sym(pic_list_ref(pic, obj, 1)); - if (index_capture(state, name, 0) != -1) { - obj = pic_list3(pic, pic_sym_value(state->sCREF), pic_int_value(0), pic_sym_value(name)); - goto CREF; + if ((i = index_capture(state, name, 0)) != -1) { + cxt->code[cxt->clen].insn = OP_LREF; + 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].u.i = index_local(state, name); @@ -1094,7 +1096,6 @@ codegen(codegen_state *state, pic_value obj) pic_sym name; int depth; - CSET: depth = pic_int(pic_list_ref(pic, var, 1)); name = pic_sym(pic_list_ref(pic, var, 2)); cxt->code[cxt->clen].insn = OP_CSET; @@ -1107,11 +1108,16 @@ codegen(codegen_state *state, pic_value obj) } else if (type == state->sLREF) { pic_sym name; + int i; name = pic_sym(pic_list_ref(pic, var, 1)); - if (index_capture(state, name, 0) != -1) { - var = pic_list3(pic, pic_sym_value(state->sCREF), pic_int_value(0), pic_sym_value(name)); - goto CSET; + if ((i = index_capture(state, name, 0)) != -1) { + cxt->code[cxt->clen].insn = OP_LSET; + 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].u.i = index_local(state, name);