about summary refs log tree commit diff
path: root/src/libexpr/primops.cc
diff options
context:
space:
mode:
authorvolth <volth@webmaster.ms>2018-07-05T12·37+0000
committerGitHub <noreply@github.com>2018-07-05T12·37+0000
commit841747b0e6d9c391c13159aaeee44599f9508868 (patch)
treec75f0ffe06841ec6045c948a40c5c6cdbfcba67e /src/libexpr/primops.cc
parentee218f99cac96bfd48aeb8fa17c271bcc2515ab1 (diff)
prim_concatMap: allocate intermediate list on stack
Diffstat (limited to 'src/libexpr/primops.cc')
-rw-r--r--src/libexpr/primops.cc22
1 files changed, 15 insertions, 7 deletions
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index aea2a34354..9b47519701 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1651,22 +1651,30 @@ static void prim_concatMap(EvalState & state, const Pos & pos, Value * * args, V
 {
     state.forceFunction(*args[0], pos);
     state.forceList(*args[1], pos);
-    auto len = args[1]->listSize();
+    auto nrLists = args[1]->listSize();
 
-    Value vList;
-    state.mkList(vList, len);
+    Value lists[nrLists];
+    size_t len = 0;
 
-    for (unsigned int n = 0; n < len; ++n) {
+    for (unsigned int n = 0; n < nrLists; ++n) {
         Value * vElem = args[1]->listElems()[n];
         state.forceValue(*vElem);
-        state.callFunction(*args[0], *vElem, *(vList.listElems()[n] = state.allocValue()), pos);
+        state.callFunction(*args[0], *vElem, lists[n], pos);
+        state.forceList(lists[n], pos);
+        len += lists[n].listSize();
     }
 
-    state.concatLists(v, len, vList.listElems(), pos);
+    state.mkList(v, len);
+    auto out = v.listElems();
+    for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
+        auto l = lists[n].listSize();
+        if (l)
+            memcpy(out + pos, lists[n].listElems(), l * sizeof(Value *));
+        pos += l;
+    }
 }
 
 
-
 /*************************************************************
  * Integer arithmetic
  *************************************************************/