From ee2a4b92f597e7215689ebcc35ffb558e55a7dea Mon Sep 17 00:00:00 2001 From: Yuichi Nishiwaki Date: Wed, 26 Aug 2015 21:52:20 +0900 Subject: [PATCH] more efficient arguments processing in pic_apply --- extlib/benz/include/picrin.h | 3 +- extlib/benz/pair.c | 4 +- extlib/benz/string.c | 4 +- extlib/benz/vector.c | 4 +- extlib/benz/vm.c | 100 +++++++++++++++++++++++------------ 5 files changed, 75 insertions(+), 40 deletions(-) diff --git a/extlib/benz/include/picrin.h b/extlib/benz/include/picrin.h index 9bec5fc4..3ab6f421 100644 --- a/extlib/benz/include/picrin.h +++ b/extlib/benz/include/picrin.h @@ -198,13 +198,14 @@ pic_value pic_funcall1(pic_state *pic, struct pic_lib *, const char *, pic_value pic_value pic_funcall2(pic_state *pic, struct pic_lib *, const char *, pic_value, pic_value); pic_value pic_funcall3(pic_state *pic, struct pic_lib *, const char *, pic_value, pic_value, pic_value); -pic_value pic_apply(pic_state *, struct pic_proc *, pic_value); +pic_value pic_apply(pic_state *, struct pic_proc *, int, pic_value *); pic_value pic_apply0(pic_state *, struct pic_proc *); pic_value pic_apply1(pic_state *, struct pic_proc *, pic_value); pic_value pic_apply2(pic_state *, struct pic_proc *, pic_value, pic_value); pic_value pic_apply3(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value); pic_value pic_apply4(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value, pic_value); pic_value pic_apply5(pic_state *, struct pic_proc *, pic_value, pic_value, pic_value, pic_value, pic_value); +pic_value pic_apply_list(pic_state *, struct pic_proc *, pic_value); pic_value pic_apply_trampoline(pic_state *, struct pic_proc *, int, pic_value *); pic_value pic_apply_trampoline_list(pic_state *, struct pic_proc *, pic_value); pic_value pic_eval(pic_state *, pic_value, struct pic_env *); diff --git a/extlib/benz/pair.c b/extlib/benz/pair.c index 99d954a7..6bb698c7 100644 --- a/extlib/benz/pair.c +++ b/extlib/benz/pair.c @@ -661,7 +661,7 @@ pic_pair_map(pic_state *pic) if (i != argc) { break; } - pic_push(pic, pic_apply(pic, proc, pic_reverse(pic, arg)), ret); + pic_push(pic, pic_apply_list(pic, proc, pic_reverse(pic, arg)), ret); } while (1); return pic_reverse(pic, ret); @@ -689,7 +689,7 @@ pic_pair_for_each(pic_state *pic) if (i != argc) { break; } - pic_apply(pic, proc, pic_reverse(pic, arg)); + pic_apply_list(pic, proc, pic_reverse(pic, arg)); } while (1); return pic_undef_value(); diff --git a/extlib/benz/string.c b/extlib/benz/string.c index 71545c6a..de023afa 100644 --- a/extlib/benz/string.c +++ b/extlib/benz/string.c @@ -584,7 +584,7 @@ pic_str_string_map(pic_state *pic) for (j = 0; j < argc; ++j) { pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); } - val = pic_apply(pic, proc, vals); + val = pic_apply_list(pic, proc, vals); pic_assert_type(pic, val, char); buf[i] = pic_char(val); @@ -629,7 +629,7 @@ pic_str_string_for_each(pic_state *pic) for (j = 0; j < argc; ++j) { pic_push(pic, pic_char_value(pic_str_ref(pic, pic_str_ptr(argv[j]), i)), vals); } - pic_apply(pic, proc, vals); + pic_apply_list(pic, proc, vals); } return pic_undef_value(); diff --git a/extlib/benz/vector.c b/extlib/benz/vector.c index f7b2972a..c06d0023 100644 --- a/extlib/benz/vector.c +++ b/extlib/benz/vector.c @@ -240,7 +240,7 @@ pic_vec_vector_map(pic_state *pic) for (j = 0; j < argc; ++j) { pic_push(pic, pic_vec_ptr(argv[j])->data[i], vals); } - vec->data[i] = pic_apply(pic, proc, vals); + vec->data[i] = pic_apply_list(pic, proc, vals); } return pic_obj_value(vec); @@ -269,7 +269,7 @@ pic_vec_vector_for_each(pic_state *pic) for (j = 0; j < argc; ++j) { pic_push(pic, pic_vec_ptr(argv[j])->data[i], vals); } - pic_apply(pic, proc, vals); + pic_apply_list(pic, proc, vals); } return pic_undef_value(); diff --git a/extlib/benz/vm.c b/extlib/benz/vm.c index e19f3ebd..23b3f26e 100644 --- a/extlib/benz/vm.c +++ b/extlib/benz/vm.c @@ -520,11 +520,12 @@ pic_vm_tear_off(pic_state *pic) #endif pic_value -pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args) +pic_apply(pic_state *pic, struct pic_proc *proc, int argc, pic_value *argv) { pic_code c; size_t ai = pic_gc_arena_preserve(pic); pic_code boot[2]; + int i; #if PIC_DIRECT_THREADED_VM static const void *oplabels[] = { @@ -544,28 +545,19 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args) pic_callinfo *cibase; #endif - if (! pic_list_p(args)) { - pic_errorf(pic, "argv must be a proper list"); + PUSH(pic_obj_value(proc)); + + for (i = 0; i < argc; ++i) { + PUSH(argv[i]); } - else { - int argc, i; - argc = (int)pic_length(pic, args) + 1; + VM_BOOT_PRINT; - VM_BOOT_PRINT; - - PUSH(pic_obj_value(proc)); - for (i = 1; i < argc; ++i) { - PUSH(pic_car(pic, args)); - args = pic_cdr(pic, args); - } - - /* boot! */ - boot[0].insn = OP_CALL; - boot[0].u.i = argc; - boot[1].insn = OP_STOP; - pic->ip = boot; - } + /* boot! */ + boot[0].insn = OP_CALL; + boot[0].u.i = argc + 1; + boot[1].insn = OP_STOP; + pic->ip = boot; VM_LOOP { CASE(OP_NOP) { @@ -977,6 +969,24 @@ pic_apply(pic_state *pic, struct pic_proc *proc, pic_value args) } VM_LOOP_END; } +pic_value +pic_apply_list(pic_state *pic, struct pic_proc *proc, pic_value list) +{ + int n, i = 0; + pic_vec *args; + pic_value x, it; + + n = pic_length(pic, list); + + args = pic_make_vec(pic, n); + + pic_for_each (x, list, it) { + args->data[i++] = x; + } + + return pic_apply(pic, proc, n, args->data); +} + pic_value pic_apply_trampoline(pic_state *pic, struct pic_proc *proc, int argc, pic_value *args) { @@ -1021,40 +1031,58 @@ pic_apply_trampoline_list(pic_state *pic, struct pic_proc *proc, pic_value args) return pic_apply_trampoline(pic, proc, argc, argv->data); } +static pic_value +pic_va_apply(pic_state *pic, struct pic_proc *proc, int n, ...) +{ + pic_vec *args = pic_make_vec(pic, n); + va_list ap; + int i = 0; + + va_start(ap, n); + + while (i < n) { + args->data[i++] = va_arg(ap, pic_value); + } + + va_end(ap); + + return pic_apply(pic, proc, n, args->data); +} + pic_value pic_apply0(pic_state *pic, struct pic_proc *proc) { - return pic_apply(pic, proc, pic_nil_value()); + return pic_va_apply(pic, proc, 0); } pic_value pic_apply1(pic_state *pic, struct pic_proc *proc, pic_value arg1) { - return pic_apply(pic, proc, pic_list1(pic, arg1)); + return pic_va_apply(pic, proc, 1, arg1); } pic_value pic_apply2(pic_state *pic, struct pic_proc *proc, pic_value arg1, pic_value arg2) { - return pic_apply(pic, proc, pic_list2(pic, arg1, arg2)); + return pic_va_apply(pic, proc, 2, arg1, arg2); } pic_value pic_apply3(pic_state *pic, struct pic_proc *proc, pic_value arg1, pic_value arg2, pic_value arg3) { - return pic_apply(pic, proc, pic_list3(pic, arg1, arg2, arg3)); + return pic_va_apply(pic, proc, 3, arg1, arg2, arg3); } pic_value pic_apply4(pic_state *pic, struct pic_proc *proc, pic_value arg1, pic_value arg2, pic_value arg3, pic_value arg4) { - return pic_apply(pic, proc, pic_list4(pic, arg1, arg2, arg3, arg4)); + return pic_va_apply(pic, proc, 4, arg1, arg2, arg3, arg4); } pic_value pic_apply5(pic_state *pic, struct pic_proc *proc, pic_value arg1, pic_value arg2, pic_value arg3, pic_value arg4, pic_value arg5) { - return pic_apply(pic, proc, pic_list5(pic, arg1, arg2, arg3, arg4, arg5)); + return pic_va_apply(pic, proc, 5, arg1, arg2, arg3, arg4, arg5); } void @@ -1136,8 +1164,8 @@ pic_set(pic_state *pic, struct pic_lib *lib, const char *name, pic_value val) vm_gset(pic_vm_gref_slot(pic, uid), val); } -pic_value -pic_funcall(pic_state *pic, struct pic_lib *lib, const char *name, pic_value args) +static struct pic_proc * +pic_ref_proc(pic_state *pic, struct pic_lib *lib, const char *name) { pic_value proc; @@ -1145,29 +1173,35 @@ pic_funcall(pic_state *pic, struct pic_lib *lib, const char *name, pic_value arg pic_assert_type(pic, proc, proc); - return pic_apply(pic, pic_proc_ptr(proc), args); + return pic_proc_ptr(proc); +} + +pic_value +pic_funcall(pic_state *pic, struct pic_lib *lib, const char *name, pic_value args) +{ + return pic_apply_list(pic, pic_ref_proc(pic, lib, name), args); } pic_value pic_funcall0(pic_state *pic, struct pic_lib *lib, const char *name) { - return pic_funcall(pic, lib, name, pic_nil_value()); + return pic_apply0(pic, pic_ref_proc(pic, lib, name)); } pic_value pic_funcall1(pic_state *pic, struct pic_lib *lib, const char *name, pic_value arg0) { - return pic_funcall(pic, lib, name, pic_list1(pic, arg0)); + return pic_apply1(pic, pic_ref_proc(pic, lib, name), arg0); } pic_value pic_funcall2(pic_state *pic, struct pic_lib *lib, const char *name, pic_value arg0, pic_value arg1) { - return pic_funcall(pic, lib, name, pic_list2(pic, arg0, arg1)); + return pic_apply2(pic, pic_ref_proc(pic, lib, name), arg0, arg1); } pic_value pic_funcall3(pic_state *pic, struct pic_lib *lib, const char *name, pic_value arg0, pic_value arg1, pic_value arg2) { - return pic_funcall(pic, lib, name, pic_list3(pic, arg0, arg1, arg2)); + return pic_apply3(pic, pic_ref_proc(pic, lib, name), arg0, arg1, arg2); }