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 /vm.c | |
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.
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 100 |
1 files changed, 100 insertions, 0 deletions
@@ -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"); |