summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-11-16 07:16:40 -0800
committerKaz Kylheku <kaz@kylheku.com>2018-11-16 07:16:40 -0800
commitedc808bf0ccba62aee1a5e49ae31baebdfc1c9a5 (patch)
tree9ae7e258eaa3681f7fcfe23a31753977a7fa6bb6
parent7ad10f417a5be78a7dec3b436ba6c37580b92340 (diff)
downloadtxr-edc808bf0ccba62aee1a5e49ae31baebdfc1c9a5.tar.gz
txr-edc808bf0ccba62aee1a5e49ae31baebdfc1c9a5.tar.bz2
txr-edc808bf0ccba62aee1a5e49ae31baebdfc1c9a5.zip
vm: provide special case call entry points.
* lib.c (funcall, funcall1, funcall2, funcall3, funcall4): Use vm_funcall, vm_funcall1, vm_funcall2, vm_funcall3, and vm_funcall4, respectively instead of the general vm_execute_closure. Also, missing argument count check added in funcall. * vm.c (vm_funcall_common): New macro. (vm_funcall, vm_funcall1, vm_funcall2, vm_funcall3, vm_funcall4): New functions. * vm.h (vm_funcall, vm_funcall1, vm_funcall2, vm_funcall3, vm_funcall4): Declared.
-rw-r--r--lib.c21
-rw-r--r--vm.c100
-rw-r--r--vm.h5
3 files changed, 112 insertions, 14 deletions
diff --git a/lib.c b/lib.c
index 3d17a562..69712f00 100644
--- a/lib.c
+++ b/lib.c
@@ -6439,8 +6439,9 @@ val funcall(val fun)
switch (fun->f.functype) {
case FVM:
{
- args_decl(args, ARGS_MIN);
- return vm_execute_closure(fun, args);
+ if (fun->f.fixparam != 0)
+ break;
+ return vm_funcall(fun);
}
case F0:
return fun->f.f.f0(fun->f.env);
@@ -6490,11 +6491,9 @@ val funcall1(val fun, val arg)
switch (fun->f.functype) {
case FVM:
{
- args_decl(args, ARGS_MIN);
if (fun->f.fixparam != 1)
break;
- args_add(args, arg);
- return vm_execute_closure(fun, args);
+ return vm_funcall1(fun, z(arg));
}
case F1:
return fun->f.f.f1(fun->f.env, z(arg));
@@ -6550,11 +6549,9 @@ val funcall2(val fun, val arg1, val arg2)
switch (fun->f.functype) {
case FVM:
{
- args_decl(args, ARGS_MIN);
if (fun->f.fixparam != 2)
break;
- args_add2(args, arg1, arg2);
- return vm_execute_closure(fun, args);
+ return vm_funcall2(fun, z(arg1), z(arg2));
}
case F2:
return fun->f.f.f2(fun->f.env, z(arg1), z(arg2));
@@ -6616,11 +6613,9 @@ val funcall3(val fun, val arg1, val arg2, val arg3)
switch (fun->f.functype) {
case FVM:
{
- args_decl(args, ARGS_MIN);
if (fun->f.fixparam != 3)
break;
- args_add3(args, arg1, arg2, arg3);
- return vm_execute_closure(fun, args);
+ return vm_funcall3(fun, z(arg1), z(arg2), z(arg3));
}
case F3:
return fun->f.f.f3(fun->f.env, z(arg1), z(arg2), z(arg3));
@@ -6688,11 +6683,9 @@ val funcall4(val fun, val arg1, val arg2, val arg3, val arg4)
switch (fun->f.functype) {
case FVM:
{
- args_decl(args, ARGS_MIN);
if (fun->f.fixparam != 4)
break;
- args_add4(args, arg1, arg2, arg3, arg4);
- return vm_execute_closure(fun, args);
+ return vm_funcall4(fun, z(arg1), z(arg2), z(arg3), z(arg4));
}
case F4:
return fun->f.f.f4(fun->f.env, z(arg1), z(arg2), z(arg3), z(arg4));
diff --git a/vm.c b/vm.c
index 8664b804..4413faef 100644
--- a/vm.c
+++ b/vm.c
@@ -1196,6 +1196,106 @@ val vm_execute_closure(val fun, struct args *args)
return vm_execute(&vm);
}
+#define vm_funcall_common \
+ val closure = fun->f.env; \
+ val desc = fun->f.f.vm_desc; \
+ struct vm_desc *vd = vm_desc_struct(self, desc); \
+ struct vm_closure *vc = coerce(struct vm_closure *, closure->co.handle); \
+ struct vm vm; \
+ val *frame = coerce(val *, alloca(sizeof *frame * vd->frsz)); \
+ struct vm_env *dspl = coerce(struct vm_env *, frame + vd->nreg); \
+ vm_reset(&vm, vd, dspl, vc->nlvl - 1, vc->ip); \
+ vm.dspl = coerce(struct vm_env *, frame + vd->nreg); \
+ frame[0] = nil; \
+ vm.dspl[0].mem = frame; \
+ vm.dspl[0].vec = nil; \
+ vm.dspl[1].mem = vd->data; \
+ vm.dspl[1].vec = vd->datavec; \
+ memcpy(vm.dspl + 2, vc->dspl + 2, (vc->nlvl - 2) * sizeof *vm.dspl); \
+ if (vc->frsz != 0) { \
+ vm.lev++; \
+ vm.dspl[vm.lev].mem = coerce(val *, zalloca(vc->frsz * sizeof (val *))); \
+ vm.dspl[vm.lev].vec = num_fast(vc->frsz); \
+ }
+
+val vm_funcall(val fun)
+{
+ val self = lit("vm-funcall");
+ vm_funcall_common;
+
+ return vm_execute(&vm);
+}
+
+val vm_funcall1(val fun, val arg)
+{
+ val self = lit("vm-funcall1");
+ vm_funcall_common;
+
+ {
+ vm_word_t argw = vm.code[vm.ip++];
+ unsigned areg = vm_arg_operand_lo(argw);
+ vm_set(dspl, areg, arg);
+ }
+
+ return vm_execute(&vm);
+}
+
+val vm_funcall2(val fun, val arg1, val arg2)
+{
+ val self = lit("vm-funcall2");
+ vm_funcall_common;
+
+ {
+ vm_word_t arg12w = vm.code[vm.ip++];
+ unsigned a1reg = vm_arg_operand_lo(arg12w);
+ unsigned a2reg = vm_arg_operand_hi(arg12w);
+ vm_set(dspl, a1reg, arg1);
+ vm_set(dspl, a2reg, arg2);
+ }
+
+ return vm_execute(&vm);
+}
+
+val vm_funcall3(val fun, val arg1, val arg2, val arg3)
+{
+ val self = lit("vm-funcall3");
+ vm_funcall_common;
+
+ {
+ vm_word_t arg12w = vm.code[vm.ip++];
+ vm_word_t arg34w = vm.code[vm.ip++];
+ unsigned a1reg = vm_arg_operand_lo(arg12w);
+ unsigned a2reg = vm_arg_operand_hi(arg12w);
+ unsigned a3reg = vm_arg_operand_lo(arg34w);
+ vm_set(dspl, a1reg, arg1);
+ vm_set(dspl, a2reg, arg2);
+ vm_set(dspl, a3reg, arg3);
+ }
+
+ return vm_execute(&vm);
+}
+
+val vm_funcall4(val fun, val arg1, val arg2, val arg3, val arg4)
+{
+ val self = lit("vm-funcall4");
+ vm_funcall_common;
+
+ {
+ vm_word_t arg12w = vm.code[vm.ip++];
+ vm_word_t arg34w = vm.code[vm.ip++];
+ unsigned a1reg = vm_arg_operand_lo(arg12w);
+ unsigned a2reg = vm_arg_operand_hi(arg12w);
+ unsigned a3reg = vm_arg_operand_lo(arg34w);
+ unsigned a4reg = vm_arg_operand_hi(arg34w);
+ vm_set(dspl, a1reg, arg1);
+ vm_set(dspl, a2reg, arg2);
+ vm_set(dspl, a3reg, arg3);
+ vm_set(dspl, a4reg, arg4);
+ }
+
+ return vm_execute(&vm);
+}
+
static val vm_closure_desc(val closure)
{
val self = lit("vm-closure-desc");
diff --git a/vm.h b/vm.h
index e39b115f..9fbaab76 100644
--- a/vm.h
+++ b/vm.h
@@ -32,5 +32,10 @@ val vm_make_desc(val nlevels, val nregs, val bytecode,
val vm_execute_toplevel(val desc);
val vm_copy_closure(val closure);
val vm_execute_closure(val fun, struct args *);
+val vm_funcall(val fun);
+val vm_funcall1(val fun, val arg);
+val vm_funcall2(val fun, val arg1, val arg2);
+val vm_funcall3(val fun, val arg1, val arg2, val arg3);
+val vm_funcall4(val fun, val arg1, val arg2, val arg3, val arg4);
void vm_invalidate_binding(val sym);
void vm_init(void);