diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2018-04-18 06:55:31 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2018-04-18 06:55:31 -0700 |
commit | ea0fa417084012b1c44d3325e8fa0dbd47106952 (patch) | |
tree | 98110d9f402317eb7012315aa65a026cf5782a56 /eval.c | |
parent | 4a73b8e0cc47b93563c3f4ad935552adb2756411 (diff) | |
download | txr-ea0fa417084012b1c44d3325e8fa0dbd47106952.tar.gz txr-ea0fa417084012b1c44d3325e8fa0dbd47106952.tar.bz2 txr-ea0fa417084012b1c44d3325e8fa0dbd47106952.zip |
apply: eliminate wasteful consing.
Now (pprof (apply '+ 1 2 3 4 5 '(6 7))) shows zero
bytes consed. Previously 176 (on 32 bit). This is
the same whether the expression is compiled or
interpreted.
* eval.c (applyv): Rewritten to efficiently manipulate the
args and call generic_funcall directly. The consing
funcction apply_intrinsic_frob_args is only used when
args contains a trailing list (args->list) and is only
used on that trailing list, not the entire arg list.
Also, changing the static function to external.
* eval.h (applyv): Declared.
* vm.c (vm_apply): Use applyv instead of wastefully
converting the arguments to a consed list and going through
apply_intrinsic.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 14 |
1 files changed, 12 insertions, 2 deletions
@@ -1142,9 +1142,19 @@ val apply_intrinsic(val fun, val args) return apply(fun, apply_intrinsic_frob_args(z(args))); } -static val applyv(val fun, struct args *args) +val applyv(val fun, struct args *args) { - return apply_intrinsic(fun, args_get_list(args)); + args_normalize_least(args, 1); + + if (!args->fill) + uw_throwf(error_s, lit("apply: trailing-args argument missing"), nao); + + if (!args->list) + args->list = z(args->arg[--args->fill]); + else + args->list = apply_intrinsic_frob_args(args->list); + + return generic_funcall(fun, args); } static loc term(loc head) |