summaryrefslogtreecommitdiffstats
path: root/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/eval.c b/eval.c
index cd87c3a9..e6edb5a0 100644
--- a/eval.c
+++ b/eval.c
@@ -57,11 +57,18 @@
#include "filter.h"
#include "tree.h"
#include "vm.h"
+#include "buf.h"
#include "eval.h"
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
+#if CONFIG_SMALL_MEM
+#define MAP_ALLOCA_LIMIT 1024
+#else
+#define MAP_ALLOCA_LIMIT 4096
+#endif
+
typedef val (*opfun_t)(val, val);
struct c_var {
@@ -5776,9 +5783,13 @@ static val map_common(val self, val fun, varg lists,
return map_fn(fun, args_atz(lists, 0));
} else {
cnum i, idx, argc = args_count(lists, self);
+ int over_limit = (argc > MAP_ALLOCA_LIMIT);
val arg0 = args_at(lists, 0);
seq_iter_t *iter_array = coerce(seq_iter_t *,
- alloca(argc * sizeof *iter_array));
+ if3(over_limit,
+ chk_malloc(argc * sizeof *iter_array),
+ alloca(argc * sizeof *iter_array)));
+ val buf = if2(over_limit, make_owned_buf(one, coerce(mem_t *, iter_array)));
seq_build_t out = { 0 };
args_decl(args_fun, max(argc, ARGS_MIN));
@@ -5798,8 +5809,11 @@ static val map_common(val self, val fun, varg lists,
val elem;
seq_iter_t *iter = &iter_array[i];
- if (!seq_get(iter, &elem))
+ if (!seq_get(iter, &elem)) {
+ if (buf)
+ buf_free(buf);
return collect_fn != 0 ? seq_finish(&out) : nil;
+ }
args_fun->arg[i] = elem;
}