do variable closing operation not in OP_CALL but in OP_RET
This commit is contained in:
parent
626ebefa65
commit
c9eb612561
|
@ -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 {
|
||||||
|
|
|
@ -885,7 +885,7 @@ destroy_codegen_state(codegen_state *state)
|
||||||
static void
|
static void
|
||||||
create_cv_table(pic_state *pic, codegen_context *cxt)
|
create_cv_table(pic_state *pic, 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;
|
||||||
|
@ -908,7 +908,17 @@ create_cv_table(pic_state *pic, codegen_context *cxt)
|
||||||
cxt->cv_tbl = pic_calloc(pic, cxt->captures.size, sizeof(unsigned));
|
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++;
|
||||||
|
}
|
||||||
|
cxt->cv_tbl[i] = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
xh_destroy(regs);
|
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));
|
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 +962,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_cv_table(pic, cxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct pic_irep *
|
static struct pic_irep *
|
||||||
|
|
1
src/gc.c
1
src/gc.c
|
@ -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: {
|
||||||
|
|
24
src/vm.c
24
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)));
|
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:
|
||||||
|
|
Loading…
Reference in New Issue