diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-11-16 07:16:40 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-11-16 07:16:40 -0800 |
commit | edc808bf0ccba62aee1a5e49ae31baebdfc1c9a5 (patch) | |
tree | 9ae7e258eaa3681f7fcfe23a31753977a7fa6bb6 | |
parent | 7ad10f417a5be78a7dec3b436ba6c37580b92340 (diff) | |
download | txr-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.c | 21 | ||||
-rw-r--r-- | vm.c | 100 | ||||
-rw-r--r-- | vm.h | 5 |
3 files changed, 112 insertions, 14 deletions
@@ -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)); @@ -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"); @@ -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); |