libexpr: Push Values onto vectors instead of default constructing
ahead of time Rather than creating fixed size vectors of default constructed Values before assigning to those elements, reserve the desired capacity and then push created values onto the vector. This avoids default constructing any Values. Part of fixing #744 Change-Id: I36eff4275a893b181eaf3ce145b1ee446a6a6964
This commit is contained in:
@@ -429,12 +429,12 @@ Value ExprConcatStrings::eval(EvalState & state, Env & env)
|
||||
};
|
||||
|
||||
// List of returned strings. References to these Values must NOT be persisted.
|
||||
SmallTemporaryValueVector<conservativeStackReservation> values(es.size());
|
||||
Value * vTmpP = values.data();
|
||||
SmallTemporaryValueVector<conservativeStackReservation> values;
|
||||
values.reserve(es.size());
|
||||
|
||||
for (auto & [i_pos, i] : es) {
|
||||
Value & vTmp = *vTmpP++;
|
||||
vTmp = i->eval(state, env);
|
||||
values.push_back(i->eval(state, env));
|
||||
Value & vTmp = values.back();
|
||||
|
||||
/* If the first element is a path, then the result will also
|
||||
be a path, we don't copy anything (yet - that's done later,
|
||||
@@ -715,9 +715,10 @@ Value ExprCall::eval(EvalState & state, Env & env)
|
||||
// 5: under 10
|
||||
// This excluded attrset lambdas (`{...}:`). Contributions of mixed lambdas appears insignificant at ~150
|
||||
// total.
|
||||
SmallValueVector<4> vArgs(args.size());
|
||||
SmallValueVector<4> vArgs;
|
||||
vArgs.reserve(args.size());
|
||||
for (size_t i = 0; i < args.size(); ++i) {
|
||||
vArgs[i] = args[i]->maybeThunk(state, env);
|
||||
vArgs.push_back(args[i]->maybeThunk(state, env));
|
||||
}
|
||||
|
||||
return state.callFunction(vFun, vArgs, pos);
|
||||
|
||||
+21
-18
@@ -2109,8 +2109,8 @@ static void prim_catAttrs(EvalState & state, Value * * args, Value & v)
|
||||
auto attrName = state.ctx.symbols.create(state.forceStringNoCtx(*args[0], noPos, "while evaluating the first argument passed to builtins.catAttrs"));
|
||||
state.forceList(*args[1], noPos, "while evaluating the second argument passed to builtins.catAttrs");
|
||||
|
||||
SmallValueVector<nonRecursiveStackReservation> res(args[1]->listSize());
|
||||
size_t found = 0;
|
||||
SmallValueVector<nonRecursiveStackReservation> res;
|
||||
res.reserve(args[1]->listSize());
|
||||
|
||||
for (auto & v2 : args[1]->listItems()) {
|
||||
state.forceAttrs(
|
||||
@@ -2120,15 +2120,13 @@ static void prim_catAttrs(EvalState & state, Value * * args, Value & v)
|
||||
);
|
||||
auto i = v2.attrs()->get(attrName);
|
||||
if (i) {
|
||||
res[found++] = i->value;
|
||||
res.push_back(i->value);
|
||||
}
|
||||
}
|
||||
|
||||
auto result = state.ctx.mem.newList(found);
|
||||
auto result = state.ctx.mem.newList(res.size());
|
||||
std::copy(res.cbegin(), res.cend(), result->elems);
|
||||
v = {NewValueAs::list, result};
|
||||
for (size_t n = 0; n < found; ++n) {
|
||||
result->elems[n] = res[n];
|
||||
}
|
||||
}
|
||||
|
||||
static void prim_functionArgs(EvalState & state, Value * * args, Value & v)
|
||||
@@ -2310,26 +2308,30 @@ static void prim_filter(EvalState & state, Value * * args, Value & v)
|
||||
state.forceFunction(*args[0], noPos, "while evaluating the first argument passed to builtins.filter");
|
||||
|
||||
auto len = args[1]->listSize();
|
||||
SmallValueVector<nonRecursiveStackReservation> vs(len);
|
||||
size_t k = 0;
|
||||
SmallValueVector<nonRecursiveStackReservation> vs;
|
||||
vs.reserve(len);
|
||||
|
||||
bool same = true;
|
||||
for (size_t n = 0; n < len; ++n) {
|
||||
Value res = state.callFunction(*args[0], args[1]->listElems()[n], noPos);
|
||||
if (state.forceBool(res, noPos, "while evaluating the return value of the filtering function passed to builtins.filter"))
|
||||
vs[k++] = args[1]->listElems()[n];
|
||||
else
|
||||
if (state.forceBool(
|
||||
res,
|
||||
noPos,
|
||||
"while evaluating the return value of the filtering function passed to builtins.filter"
|
||||
))
|
||||
{
|
||||
vs.push_back(args[1]->listElems()[n]);
|
||||
} else {
|
||||
same = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (same)
|
||||
v = *args[1];
|
||||
else {
|
||||
auto result = state.ctx.mem.newList(k);
|
||||
auto result = state.ctx.mem.newList(vs.size());
|
||||
v = {NewValueAs::list, result};
|
||||
for (unsigned int n = 0; n < k; ++n) {
|
||||
result->elems[n] = vs[n];
|
||||
}
|
||||
std::copy(vs.cbegin(), vs.cend(), result->elems);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2570,12 +2572,13 @@ static void prim_concatMap(EvalState & state, Value * * args, Value & v)
|
||||
auto nrLists = args[1]->listSize();
|
||||
|
||||
// List of returned lists before concatenation. References to these Values must NOT be persisted.
|
||||
SmallTemporaryValueVector<conservativeStackReservation> lists(nrLists);
|
||||
SmallTemporaryValueVector<conservativeStackReservation> lists;
|
||||
lists.reserve(nrLists);
|
||||
size_t len = 0;
|
||||
|
||||
for (size_t n = 0; n < nrLists; ++n) {
|
||||
Value & vElem = args[1]->listElems()[n];
|
||||
lists[n] = state.callFunction(*args[0], vElem, noPos);
|
||||
lists.push_back(state.callFunction(*args[0], vElem, noPos));
|
||||
state.forceList(lists[n], noPos, "while evaluating the return value of the function passed to builtins.concatMap");
|
||||
len += lists[n].listSize();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user