summaryrefslogtreecommitdiffstats
path: root/vm.c
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
commit50b3b8a020217910041ece4f380cc97ed6845ae9 (patch)
tree2ecd4cb89328822ff1997ff82aff15be0fc72e33 /vm.c
parentf0b797d9b99951d9b08bd0c0bddff283401703ec (diff)
downloadtxr-50b3b8a020217910041ece4f380cc97ed6845ae9.tar.gz
txr-50b3b8a020217910041ece4f380cc97ed6845ae9.tar.bz2
txr-50b3b8a020217910041ece4f380cc97ed6845ae9.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.
Diffstat (limited to 'vm.c')
-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);
}