diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-05-17 00:42:48 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-05-17 00:42:48 -0700 |
commit | ecbe8288afad8b2e181b50a69ca6920426f38824 (patch) | |
tree | ba09a9c38b46c81a356cd7055e127e2b49a35f03 | |
parent | e0e208751fe416209c52cff822ba0aa9c7ce66b9 (diff) | |
download | txr-ecbe8288afad8b2e181b50a69ca6920426f38824.tar.gz txr-ecbe8288afad8b2e181b50a69ca6920426f38824.tar.bz2 txr-ecbe8288afad8b2e181b50a69ca6920426f38824.zip |
vm: handle cases in CALL like in GCALL.
* vm.c (vm_call): Specially handle the cases of 0
to 4 arguments, avoiding the general loop and
invocation of generic_funcall. This gets us about
a 1% improvement in recompiling the standard
libarry (touch stdlib/*.tl; make).
-rw-r--r-- | vm.c | 72 |
1 files changed, 58 insertions, 14 deletions
@@ -467,27 +467,71 @@ NOINLINE static void vm_call(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 = vm_getz(vm->dspl, funidx); val result; - args_decl (args, max(nargs, ARGS_MIN)); - - if (nargs--) { - args_add(args, vm_get(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(vm_getz(vm->dspl, fun), args); vm_set(vm->dspl, dest, result); } |