diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-11-16 07:14:41 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-11-16 07:14:41 -0800 |
commit | 7ad10f417a5be78a7dec3b436ba6c37580b92340 (patch) | |
tree | af6ef6cc211daa4c3067a8e64219518ed5e41ec3 /vm.c | |
parent | b901452571285988ea4b3367c64642d2e8e0a580 (diff) | |
download | txr-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.c | 73 |
1 files changed, 58 insertions, 15 deletions
@@ -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); } |