summaryrefslogtreecommitdiffstats
path: root/vm.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-11-16 07:14:41 -0800
committerKaz Kylheku <kaz@kylheku.com>2018-11-16 07:14:41 -0800
commit7ad10f417a5be78a7dec3b436ba6c37580b92340 (patch)
treeaf6ef6cc211daa4c3067a8e64219518ed5e41ec3 /vm.c
parentb901452571285988ea4b3367c64642d2e8e0a580 (diff)
downloadtxr-7ad10f417a5be78a7dec3b436ba6c37580b92340.tar.gz
txr-7ad10f417a5be78a7dec3b436ba6c37580b92340.tar.bz2
txr-7ad10f417a5be78a7dec3b436ba6c37580b92340.zip
vm: use faster funcall functions in vm_gcall.
* vm.c (vm_gcall): For the 0 to 4 argument cases, use funcall, funcall1, ..., funcall4 instead of generic_funcall.
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c73
1 files changed, 58 insertions, 15 deletions
diff --git a/vm.c b/vm.c
index 9322cba8..8664b804 100644
--- a/vm.c
+++ b/vm.c
@@ -545,28 +545,71 @@ NOINLINE static void vm_gcall(struct vm *vm, vm_word_t insn)
unsigned nargs = vm_insn_extra(insn);
unsigned dest = vm_insn_operand(insn);
vm_word_t argw = vm->code[vm->ip++];
- unsigned fun = vm_arg_operand_lo(argw);
+ unsigned funidx = vm_arg_operand_lo(argw);
+ val fun = deref(vm_stab(vm, funidx, lookup_fun, lit("function")));
val result;
- args_decl (args, max(nargs, ARGS_MIN));
-
- if (nargs--) {
- args_add(args, vm_getz(vm->dspl, vm_arg_operand_hi(argw)));
- while (nargs >= 2) {
- nargs -= 2;
- argw = vm->code[vm->ip++];
- args_add(args, vm_getz(vm->dspl, vm_arg_operand_lo(argw)));
- args_add(args, vm_getz(vm->dspl, vm_arg_operand_hi(argw)));
+ switch (nargs) {
+ case 0:
+ result = funcall(fun);
+ break;
+ case 1:
+ {
+ val arg1 = vm_getz(vm->dspl, vm_arg_operand_hi(argw));
+ result = funcall1(fun, z(arg1));
+ }
+ break;
+ case 2:
+ {
+ vm_word_t argx = vm->code[vm->ip++];
+ val arg1 = vm_getz(vm->dspl, vm_arg_operand_hi(argw));
+ val arg2 = vm_getz(vm->dspl, vm_arg_operand_lo(argx));
+ result = funcall2(fun, z(arg1), z(arg2));
}
+ break;
+ case 3:
+ {
+ vm_word_t argx = vm->code[vm->ip++];
+ val arg1 = vm_getz(vm->dspl, vm_arg_operand_hi(argw));
+ val arg2 = vm_getz(vm->dspl, vm_arg_operand_lo(argx));
+ val arg3 = vm_getz(vm->dspl, vm_arg_operand_hi(argx));
+ result = funcall3(fun, z(arg1), z(arg2), z(arg3));
+ }
+ break;
+ case 4:
+ {
+ vm_word_t argx = vm->code[vm->ip++];
+ vm_word_t argy = vm->code[vm->ip++];
+ val arg1 = vm_getz(vm->dspl, vm_arg_operand_hi(argw));
+ val arg2 = vm_getz(vm->dspl, vm_arg_operand_lo(argx));
+ val arg3 = vm_getz(vm->dspl, vm_arg_operand_hi(argx));
+ val arg4 = vm_getz(vm->dspl, vm_arg_operand_lo(argy));
+ result = funcall4(fun, z(arg1), z(arg2), z(arg3), z(arg4));
+ }
+ break;
+ default:
+ {
+ args_decl (args, max(nargs, ARGS_MIN));
+ args_add(args, vm_getz(vm->dspl, vm_arg_operand_hi(argw)));
+ nargs--;
- if (nargs) {
- argw = vm->code[vm->ip++];
- args_add(args, vm_getz(vm->dspl, vm_arg_operand_lo(argw)));
+ while (nargs >= 2) {
+ nargs -= 2;
+ argw = vm->code[vm->ip++];
+ args_add(args, vm_getz(vm->dspl, vm_arg_operand_lo(argw)));
+ args_add(args, vm_getz(vm->dspl, vm_arg_operand_hi(argw)));
+ }
+
+ if (nargs) {
+ argw = vm->code[vm->ip++];
+ args_add(args, vm_getz(vm->dspl, vm_arg_operand_lo(argw)));
+ }
+
+ result = generic_funcall(fun, args);
}
+ break;
}
- result = generic_funcall(deref(vm_stab(vm, fun, lookup_fun,
- lit("function"))), args);
vm_set(vm->dspl, dest, result);
}