summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-03-19 22:07:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2018-03-19 22:07:34 -0700
commit839b4c4bb701d33d69ba06fbdfe8c9fac4e91ecc (patch)
tree2ecd4cb89328822ff1997ff82aff15be0fc72e33
parent5699fa66ff753922e103f956e0da2721b193897c (diff)
downloadtxr-839b4c4bb701d33d69ba06fbdfe8c9fac4e91ecc.tar.gz
txr-839b4c4bb701d33d69ba06fbdfe8c9fac4e91ecc.tar.bz2
txr-839b4c4bb701d33d69ba06fbdfe8c9fac4e91ecc.zip
vm: support deferred resolution of ftab bindings.
This allows a virtual machine's funvec to refer to functions that are not yet defined. We resolve all the ones that are defined when the virtual machine description is constructed. The others are resolved at vm execution time when accessed. * vm.c (vm_make_desc): When filling ftab with resolved function bindings, check that lookup_fun has returned nil; in that case, initialize the binding location to zero, instead of blowing up calling cdr_l(nil). (vm_ftab): New static function. Implements the null check and late resolution. (vm_gcall, vm_gapply): Acces ftab through vm_ftab instead of open-coded expression.
-rw-r--r--vm.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/vm.c b/vm.c
index 17efa503..9c9c8525 100644
--- a/vm.c
+++ b/vm.c
@@ -160,7 +160,7 @@ val vm_make_desc(val nlevels, val nregs, val bytecode,
for (i = 0; i < fvl; i++) {
struct vm_ftent *fe = &ftab[i];
fe->fb = lookup_fun(nil, vecref(funvec, num_fast(i)));
- fe->fbloc = cdr_l(fe->fb);
+ fe->fbloc = if3(fe->fb, cdr_l(fe->fb), nulloc);
}
return desc;
@@ -420,6 +420,23 @@ static void vm_apply(struct vm *vm, vm_word_t insn)
vm_set(vm->dspl, dest, result);
}
+static loc vm_ftab(struct vm *vm, unsigned fun)
+{
+ struct vm_desc *vd = vm->vd;
+ struct vm_ftent *fe = &vd->ftab[fun];
+ loc fbloc = fe->fbloc;
+
+ if (!nullocp(fbloc))
+ return fbloc;
+
+ if (nilp(fe->fb = lookup_fun(nil, vecref(vd->funvec, num_fast(fun)))))
+ eval_error(vd->bytecode,
+ lit("function ~s is not defined"),
+ vecref(vd->funvec, num(fun)), nao);
+ gc_mutated(vd->self);
+ return (fe->fbloc = cdr_l(fe->fb));
+}
+
static void vm_gcall(struct vm *vm, vm_word_t insn)
{
unsigned nargs = vm_insn_extra(insn);
@@ -445,7 +462,7 @@ static void vm_gcall(struct vm *vm, vm_word_t insn)
}
}
- result = generic_funcall(deref(vm->vd->ftab[fun].fbloc), args);
+ result = generic_funcall(deref(vm_ftab(vm, fun)), args);
vm_set(vm->dspl, dest, result);
}
@@ -474,8 +491,7 @@ static void vm_gapply(struct vm *vm, vm_word_t insn)
}
}
- result = apply_intrinsic(deref(vm->vd->ftab[fun].fbloc),
- args_get_list(args));
+ result = apply_intrinsic(deref(vm_ftab(vm, fun)), args_get_list(args));
vm_set(vm->dspl, dest, result);
}