From a9e98b1c311df69d536f7df1ec5bda2be9555bde Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 18:23:33 +0900 Subject: [PATCH 1/9] small CSE optimize for irep --- src/vm.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/vm.c b/src/vm.c index c945e701..9f65958d 100644 --- a/src/vm.c +++ b/src/vm.c @@ -677,27 +677,28 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv) goto L_RET; } else { + struct pic_irep *irep = proc->u.irep; int i; pic_value rest; - if (ci->argc != proc->u.irep->argc) { - if (! (proc->u.irep->varg && ci->argc >= proc->u.irep->argc)) { - pic_errorf(pic, "wrong number of arguments (%d for %d%s)", ci->argc - 1, proc->u.irep->argc - 1, (proc->u.irep->varg ? "+" : "")); + if (ci->argc != irep->argc) { + if (! (irep->varg && ci->argc >= irep->argc)) { + pic_errorf(pic, "wrong number of arguments (%d for %d%s)", ci->argc - 1, irep->argc - 1, (irep->varg ? "+" : "")); } } /* prepare rest args */ - if (proc->u.irep->varg) { + if (irep->varg) { rest = pic_nil_value(); - for (i = 0; i < ci->argc - proc->u.irep->argc; ++i) { + for (i = 0; i < ci->argc - irep->argc; ++i) { pic_gc_protect(pic, v = POP()); rest = pic_cons(pic, v, rest); } PUSH(rest); } /* prepare local variable area */ - if (proc->u.irep->localc > 0) { - int l = proc->u.irep->localc; - if (proc->u.irep->varg) { + if (irep->localc > 0) { + int l = irep->localc; + if (irep->varg) { --l; } for (i = 0; i < l; ++i) { @@ -708,13 +709,13 @@ 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->up = proc->env; - ci->env->valuec = proc->u.irep->cv_num; + ci->env->valuec = irep->cv_num; ci->env->values = (pic_value *)pic_calloc(pic, ci->env->valuec, sizeof(pic_value)); for (i = 0; i < ci->env->valuec; ++i) { - ci->env->values[i] = ci->fp[proc->u.irep->cv_tbl[i]]; + ci->env->values[i] = ci->fp[irep->cv_tbl[i]]; } - pic->ip = proc->u.irep->code; + pic->ip = irep->code; pic_gc_arena_restore(pic, ai); JUMP; } From 510af57ce5c2ba6655fab6148130f32e350f87ca Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 18:29:14 +0900 Subject: [PATCH 2/9] explict type cast for return valus from pic_*allloc family is not mandatory --- src/codegen.c | 12 ++++++------ src/vm.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index b498fc1c..47bbc060 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1114,21 +1114,21 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo cxt->cv_num = 0; for (i = 0, c = pic_length(pic, closes); i < c; ++i) { i = cxt->cv_num++; - cxt->cv_tbl = (unsigned *)pic_realloc(pic, cxt->cv_tbl, sizeof(unsigned) * cxt->cv_num); + cxt->cv_tbl = pic_realloc(pic, cxt->cv_tbl, sizeof(unsigned) * cxt->cv_num); cxt->cv_tbl[i] = xh_get_int(vars, pic_sym(pic_list_ref(pic, closes, i)))->val; } xh_destroy(vars); - cxt->code = (pic_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->ccapa = PIC_ISEQ_SIZE; - cxt->irep = (struct pic_irep **)pic_calloc(pic, PIC_IREP_SIZE, sizeof(struct pic_irep *)); + cxt->irep = pic_calloc(pic, PIC_IREP_SIZE, sizeof(struct pic_irep *)); cxt->ilen = 0; cxt->icapa = PIC_IREP_SIZE; - cxt->pool = (pic_value *)pic_calloc(pic, PIC_POOL_SIZE, sizeof(pic_value)); + cxt->pool = pic_calloc(pic, PIC_POOL_SIZE, sizeof(pic_value)); cxt->plen = 0; cxt->pcapa = PIC_POOL_SIZE; @@ -1230,7 +1230,7 @@ codegen(codegen_state *state, pic_value obj) if (cxt->ilen >= cxt->icapa) { cxt->icapa *= 2; - cxt->irep = (struct pic_irep **)pic_realloc(pic, cxt->irep, sizeof(struct pic_irep *) * cxt->icapa); + cxt->irep = pic_realloc(pic, cxt->irep, sizeof(struct pic_irep *) * cxt->icapa); } k = cxt->ilen++; cxt->code[cxt->clen].insn = OP_LAMBDA; @@ -1303,7 +1303,7 @@ codegen(codegen_state *state, pic_value obj) default: if (cxt->plen >= cxt->pcapa) { cxt->pcapa *= 2; - cxt->pool = (pic_value *)pic_realloc(pic, cxt->pool, sizeof(pic_value) * cxt->pcapa); + cxt->pool = pic_realloc(pic, cxt->pool, sizeof(pic_value) * cxt->pcapa); } pidx = cxt->plen++; cxt->pool[pidx] = obj; diff --git a/src/vm.c b/src/vm.c index 9f65958d..8507aa50 100644 --- a/src/vm.c +++ b/src/vm.c @@ -710,7 +710,7 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value argv) ci->env = (struct pic_env *)pic_obj_alloc(pic, sizeof(struct pic_env), PIC_TT_ENV); ci->env->up = proc->env; ci->env->valuec = irep->cv_num; - ci->env->values = (pic_value *)pic_calloc(pic, ci->env->valuec, sizeof(pic_value)); + 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]]; } From 046fae1adb87b0f1023c4697869d56cf702af45e Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 18:41:46 +0900 Subject: [PATCH 3/9] grammer error fix --- src/codegen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/codegen.c b/src/codegen.c index 47bbc060..b40d1904 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1018,7 +1018,7 @@ pic_resolve(pic_state *pic, pic_value obj) typedef struct codegen_context { bool varg; - /* rest args variable is counted by localc */ + /* rest args variable is counted as a local */ int argc, localc; /* closed variable table */ unsigned *cv_tbl, cv_num; From 5a56f57782b25fbe0778a84478351f584db197f5 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 18:46:57 +0900 Subject: [PATCH 4/9] hold local variables information in codegen_context --- src/codegen.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index b40d1904..a7e17293 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1019,7 +1019,7 @@ pic_resolve(pic_state *pic, pic_value obj) typedef struct codegen_context { bool varg; /* rest args variable is counted as a local */ - int argc, localc; + xvect args, locals; /* closed variable table */ unsigned *cv_tbl, cv_num; /* actual bit code sequence */ @@ -1091,22 +1091,31 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo { pic_state *pic = state->pic; codegen_context *cxt; - int i, c; + size_t i, c; xhash *vars; + pic_value var; cxt = (codegen_context *)pic_alloc(pic, sizeof(codegen_context)); cxt->up = state->cxt; - cxt->argc = pic_length(pic, args) + 1; - cxt->localc = pic_length(pic, locals); cxt->varg = varg; + xv_init(&cxt->args, sizeof(pic_sym)); + xv_init(&cxt->locals, sizeof(pic_sym)); + + pic_for_each (var, args) { + xv_push(&cxt->args, &pic_sym(var)); + } + pic_for_each (var, locals) { + xv_push(&cxt->locals, &pic_sym(var)); + } + /* number local variables */ vars = xh_new_int(); - for (i = 1; i < cxt->argc; ++i) { - xh_put_int(vars, pic_sym(pic_list_ref(pic, args, i - 1)), i); + for (i = 0; i < cxt->args.size; ++i) { + xh_put_int(vars, pic_sym(pic_list_ref(pic, args, i)), i + 1); } - for (i = 0; i < cxt->localc; ++i) { - xh_put_int(vars, pic_sym(pic_list_ref(pic, locals, i)), cxt->argc + i); + for (i = 0; i < cxt->locals.size; ++i) { + xh_put_int(vars, pic_sym(pic_list_ref(pic, locals, i)), i + 1 + cxt->args.size); } /* closed variables */ @@ -1145,8 +1154,8 @@ pop_codegen_context(codegen_state *state) /* create irep */ irep = (struct pic_irep *)pic_obj_alloc(pic, sizeof(struct pic_irep), PIC_TT_IREP); irep->varg = state->cxt->varg; - irep->argc = state->cxt->argc; - irep->localc = state->cxt->localc; + irep->argc = state->cxt->args.size + 1; + irep->localc = state->cxt->locals.size; irep->cv_tbl = state->cxt->cv_tbl; irep->cv_num = state->cxt->cv_num; irep->code = pic_realloc(pic, state->cxt->code, sizeof(pic_code) * state->cxt->clen); @@ -1156,6 +1165,10 @@ pop_codegen_context(codegen_state *state) irep->pool = pic_realloc(pic, state->cxt->pool, sizeof(pic_value) * state->cxt->plen); irep->plen = state->cxt->plen; + /* finalize */ + xv_destroy(&cxt->args); + xv_destroy(&cxt->locals); + /* destroy context */ cxt = cxt->up; pic_free(pic, state->cxt); From cb2f9fece35370559779e48261f2695b98540643 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 18:58:25 +0900 Subject: [PATCH 5/9] separate cv table creation --- src/codegen.c | 64 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index a7e17293..69746458 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1019,7 +1019,7 @@ pic_resolve(pic_state *pic, pic_value obj) typedef struct codegen_context { bool varg; /* rest args variable is counted as a local */ - xvect args, locals; + xvect args, locals, captures; /* closed variable table */ unsigned *cv_tbl, cv_num; /* actual bit code sequence */ @@ -1087,12 +1087,45 @@ destroy_codegen_state(codegen_state *state) } static void -push_codegen_context(codegen_state *state, pic_value args, pic_value locals, bool varg, pic_value closes) +create_cv_table(pic_state *pic, codegen_context *cxt) +{ + size_t i; + xhash *vars; + pic_sym *var; + size_t offset; + + vars = xh_new_int(); + + /* number local variables */ + offset = 1; + for (i = 0; i < cxt->args.size; ++i) { + var = xv_get(&cxt->args, i); + xh_put_int(vars, *var, i + offset); + } + offset += i; + for (i = 0; i < cxt->locals.size; ++i) { + var = xv_get(&cxt->locals, i); + xh_put_int(vars, *var, i + offset); + } + + /* closed variables */ + cxt->cv_tbl = NULL; + cxt->cv_num = 0; + for (i = 0; i < cxt->captures.size; ++i) { + var = xv_get(&cxt->captures, i); + i = cxt->cv_num++; + cxt->cv_tbl = pic_realloc(pic, cxt->cv_tbl, sizeof(unsigned) * cxt->cv_num); + cxt->cv_tbl[i] = xh_get_int(vars, *var)->val; + } + + xh_destroy(vars); +} + +static void +push_codegen_context(codegen_state *state, pic_value args, pic_value locals, bool varg, pic_value captures) { pic_state *pic = state->pic; codegen_context *cxt; - size_t i, c; - xhash *vars; pic_value var; cxt = (codegen_context *)pic_alloc(pic, sizeof(codegen_context)); @@ -1101,6 +1134,7 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo xv_init(&cxt->args, sizeof(pic_sym)); xv_init(&cxt->locals, sizeof(pic_sym)); + xv_init(&cxt->captures, sizeof(pic_sym)); pic_for_each (var, args) { xv_push(&cxt->args, &pic_sym(var)); @@ -1108,26 +1142,11 @@ push_codegen_context(codegen_state *state, pic_value args, pic_value locals, boo pic_for_each (var, locals) { xv_push(&cxt->locals, &pic_sym(var)); } - - /* number local variables */ - vars = xh_new_int(); - for (i = 0; i < cxt->args.size; ++i) { - xh_put_int(vars, pic_sym(pic_list_ref(pic, args, i)), i + 1); - } - for (i = 0; i < cxt->locals.size; ++i) { - xh_put_int(vars, pic_sym(pic_list_ref(pic, locals, i)), i + 1 + cxt->args.size); + pic_for_each (var, captures) { + xv_push(&cxt->captures, &pic_sym(var)); } - /* closed variables */ - cxt->cv_tbl = NULL; - cxt->cv_num = 0; - for (i = 0, c = pic_length(pic, closes); i < c; ++i) { - i = cxt->cv_num++; - cxt->cv_tbl = pic_realloc(pic, cxt->cv_tbl, sizeof(unsigned) * cxt->cv_num); - cxt->cv_tbl[i] = xh_get_int(vars, pic_sym(pic_list_ref(pic, closes, i)))->val; - } - - xh_destroy(vars); + create_cv_table(pic, cxt); cxt->code = pic_calloc(pic, PIC_ISEQ_SIZE, sizeof(pic_code)); cxt->clen = 0; @@ -1168,6 +1187,7 @@ pop_codegen_context(codegen_state *state) /* finalize */ xv_destroy(&cxt->args); xv_destroy(&cxt->locals); + xv_destroy(&cxt->captures); /* destroy context */ cxt = cxt->up; From bdcf8a4bcb23014d8e5e4f3bac3f778761fd84ae Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 19:03:20 +0900 Subject: [PATCH 6/9] change ugly implementation; don't call realloc for each puching! --- src/codegen.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 69746458..09ae52ee 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1109,12 +1109,10 @@ create_cv_table(pic_state *pic, codegen_context *cxt) } /* closed variables */ - cxt->cv_tbl = NULL; - cxt->cv_num = 0; + cxt->cv_num = cxt->captures.size; + cxt->cv_tbl = pic_calloc(pic, cxt->cv_num, sizeof(unsigned)); for (i = 0; i < cxt->captures.size; ++i) { var = xv_get(&cxt->captures, i); - i = cxt->cv_num++; - cxt->cv_tbl = pic_realloc(pic, cxt->cv_tbl, sizeof(unsigned) * cxt->cv_num); cxt->cv_tbl[i] = xh_get_int(vars, *var)->val; } From 12852b062828ca7740e39028c4d13fab13124d9c Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 19:13:07 +0900 Subject: [PATCH 7/9] s/cv_num/capturec/g --- include/picrin/irep.h | 10 +++++----- src/codegen.c | 20 +++++++++----------- src/vm.c | 2 +- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/include/picrin/irep.h b/include/picrin/irep.h index 22968e41..36607c3a 100644 --- a/include/picrin/irep.h +++ b/include/picrin/irep.h @@ -61,8 +61,8 @@ struct pic_code { struct pic_irep { PIC_OBJECT_HEADER pic_code *code; - int argc, localc; - unsigned *cv_tbl, cv_num; + int argc, localc, capturec; + unsigned *cv_tbl; bool varg; struct pic_irep **irep; pic_value *pool; @@ -188,9 +188,9 @@ pic_dump_irep(struct pic_irep *irep) unsigned i; printf("## irep %p\n", (void *)irep); - printf("[clen = %zd, argc = %d, localc = %d]\n", irep->clen, irep->argc, irep->localc); - printf(":: cv_num = %d\n", irep->cv_num); - for (i = 0; i < irep->cv_num; ++i) { + 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) { diff --git a/src/codegen.c b/src/codegen.c index 09ae52ee..9bb7f3dc 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -774,9 +774,8 @@ pic_analyze(pic_state *pic, pic_value obj) typedef struct resolver_scope { int depth; bool varg; - int argc, localc; + int argc, localc, capturec; xhash *cvs, *lvs; - unsigned cv_num; struct resolver_scope *up; } resolver_scope; @@ -818,11 +817,11 @@ destroy_resolver_state(resolver_state *state) } static void -push_resolver_scope(resolver_state *state, pic_value args, pic_value locals, bool varg, pic_value closes) +push_resolver_scope(resolver_state *state, pic_value args, pic_value locals, bool varg, pic_value captures) { pic_state *pic = state->pic; resolver_scope *scope; - int i, c; + int i; scope = (resolver_scope *)pic_alloc(pic, sizeof(resolver_scope)); scope->up = state->scope; @@ -831,6 +830,7 @@ push_resolver_scope(resolver_state *state, pic_value args, pic_value locals, boo scope->cvs = xh_new_int(); scope->argc = pic_length(pic, args) + 1; scope->localc = pic_length(pic, locals); + scope->capturec = pic_length(pic, captures); scope->varg = varg; /* arguments */ @@ -844,9 +844,8 @@ push_resolver_scope(resolver_state *state, pic_value args, pic_value locals, boo } /* closed variables */ - scope->cv_num = 0; - for (i = 0, c = pic_length(pic, closes); i < c; ++i) { - xh_put_int(scope->cvs, pic_sym(pic_list_ref(pic, closes, i)), scope->cv_num++); + for (i = 0; i < scope->capturec; ++i) { + xh_put_int(scope->cvs, pic_sym(pic_list_ref(pic, captures, i)), i); } state->scope = scope; @@ -1021,7 +1020,7 @@ typedef struct codegen_context { /* rest args variable is counted as a local */ xvect args, locals, captures; /* closed variable table */ - unsigned *cv_tbl, cv_num; + unsigned *cv_tbl; /* actual bit code sequence */ pic_code *code; size_t clen, ccapa; @@ -1109,8 +1108,7 @@ create_cv_table(pic_state *pic, codegen_context *cxt) } /* closed variables */ - cxt->cv_num = cxt->captures.size; - cxt->cv_tbl = pic_calloc(pic, cxt->cv_num, sizeof(unsigned)); + 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(vars, *var)->val; @@ -1173,8 +1171,8 @@ pop_codegen_context(codegen_state *state) irep->varg = state->cxt->varg; 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->cv_num = state->cxt->cv_num; 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/vm.c b/src/vm.c index 8507aa50..079b35c0 100644 --- a/src/vm.c +++ b/src/vm.c @@ -709,7 +709,7 @@ 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->up = proc->env; - ci->env->valuec = irep->cv_num; + 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]]; From ac4e46783c940a7f04a160670eef6ae4873e5698 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 19:13:46 +0900 Subject: [PATCH 8/9] remove unused property --- src/codegen.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/codegen.c b/src/codegen.c index 9bb7f3dc..6cb1db1b 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1044,7 +1044,6 @@ typedef struct codegen_state { pic_sym sGREF, sCREF, sLREF; pic_sym sCALL, sTAILCALL, sRETURN; pic_sym sCALL_WITH_VALUES, sTAILCALL_WITH_VALUES; - unsigned *cv_tbl, cv_num; } codegen_state; static void push_codegen_context(codegen_state *, pic_value, pic_value, bool, pic_value); From d8ab5cadd1fce0e92012e37bcbf1e98a40835b23 Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Sat, 22 Mar 2014 19:19:49 +0900 Subject: [PATCH 9/9] cleanup. rename local variable. --- src/codegen.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/codegen.c b/src/codegen.c index 6cb1db1b..10aeeda7 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -1088,32 +1088,32 @@ static void create_cv_table(pic_state *pic, codegen_context *cxt) { size_t i; - xhash *vars; + xhash *regs; pic_sym *var; size_t offset; - vars = xh_new_int(); + regs = xh_new_int(); /* number local variables */ offset = 1; for (i = 0; i < cxt->args.size; ++i) { var = xv_get(&cxt->args, i); - xh_put_int(vars, *var, i + offset); + xh_put_int(regs, *var, i + offset); } offset += i; for (i = 0; i < cxt->locals.size; ++i) { var = xv_get(&cxt->locals, i); - xh_put_int(vars, *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) { var = xv_get(&cxt->captures, i); - cxt->cv_tbl[i] = xh_get_int(vars, *var)->val; + cxt->cv_tbl[i] = xh_get_int(regs, *var)->val; } - xh_destroy(vars); + xh_destroy(regs); } static void