Remove EvalState::mkAttrs()

This commit is contained in:
Eelco Dolstra 2022-01-04 20:29:17 +01:00
parent 17daec0b83
commit 2b4c944823
6 changed files with 52 additions and 42 deletions

View file

@ -7,6 +7,7 @@
namespace nix {
/* Allocate a new array of attributes for an attribute set with a specific
capacity. The space is implicitly reserved after the Bindings
structure. */
@ -16,15 +17,9 @@ Bindings * EvalState::allocBindings(size_t capacity)
return &emptyBindings;
if (capacity > std::numeric_limits<Bindings::size_t>::max())
throw Error("attribute set of size %d is too big", capacity);
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
}
void EvalState::mkAttrs(Value & v, size_t capacity)
{
v.mkAttrs(allocBindings(capacity));
nrAttrsets++;
nrAttrsInAttrsets += capacity;
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
}
@ -67,9 +62,7 @@ void Bindings::sort()
Value & Value::mkAttrs(BindingsBuilder & bindings)
{
clearValue();
internalType = tAttrs;
attrs = bindings.finish();
mkAttrs(bindings.finish());
return *this;
}

View file

@ -118,13 +118,14 @@ public:
call finish(), which sorts the bindings. */
class BindingsBuilder
{
EvalState & state;
Bindings * bindings;
public:
EvalState & state;
BindingsBuilder(EvalState & state, Bindings * bindings)
: state(state), bindings(bindings)
: bindings(bindings), state(state)
{ }
void insert(Symbol name, Value * value, ptr<Pos> pos = ptr(&noPos))
@ -146,6 +147,11 @@ public:
bindings->sort();
return bindings;
}
Bindings * alreadySorted()
{
return bindings;
}
};
}

View file

@ -145,7 +145,7 @@ void printValue(std::ostream & str, std::set<const Value *> & active, const Valu
str << v.fpoint;
break;
default:
throw Error("invalid value");
abort();
}
active.erase(&v);
@ -1065,8 +1065,8 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v)
void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
{
state.mkAttrs(v, attrs.size() + dynamicAttrs.size());
Env *dynamicEnv = &env;
v.mkAttrs(state.buildBindings(attrs.size() + dynamicAttrs.size()).finish());
auto dynamicEnv = &env;
if (recursive) {
/* Create a new environment that contains the attributes in
@ -1592,7 +1592,7 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
if (v1.attrs->size() == 0) { v = v2; return; }
if (v2.attrs->size() == 0) { v = v1; return; }
state.mkAttrs(v, v1.attrs->size() + v2.attrs->size());
auto attrs = state.buildBindings(v1.attrs->size() + v2.attrs->size());
/* Merge the sets, preferring values from the second set. Make
sure to keep the resulting vector in sorted order. */
@ -1601,17 +1601,19 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
while (i != v1.attrs->end() && j != v2.attrs->end()) {
if (i->name == j->name) {
v.attrs->push_back(*j);
attrs.insert(*j);
++i; ++j;
}
else if (i->name < j->name)
v.attrs->push_back(*i++);
attrs.insert(*i++);
else
v.attrs->push_back(*j++);
attrs.insert(*j++);
}
while (i != v1.attrs->end()) v.attrs->push_back(*i++);
while (j != v2.attrs->end()) v.attrs->push_back(*j++);
while (i != v1.attrs->end()) attrs.insert(*i++);
while (j != v2.attrs->end()) attrs.insert(*j++);
v.mkAttrs(attrs.alreadySorted());
state.nrOpUpdateValuesCopied += v.attrs->size();
}

View file

@ -347,7 +347,6 @@ public:
}
void mkList(Value & v, size_t length);
void mkAttrs(Value & v, size_t capacity);
void mkThunk_(Value & v, Expr * expr);
void mkPos(Value & v, ptr<Pos> pos);
@ -400,6 +399,8 @@ private:
friend struct ExprSelect;
friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v);
friend void prim_match(EvalState & state, const Pos & pos, Value * * args, Value & v);
friend struct Value;
};

View file

@ -37,10 +37,10 @@ class JSONSax : nlohmann::json_sax<json> {
ValueMap attrs;
std::unique_ptr<JSONState> resolve(EvalState & state) override
{
Value & v = parent->value(state);
state.mkAttrs(v, attrs.size());
auto attrs2 = state.buildBindings(attrs.size());
for (auto & i : attrs)
v.attrs->push_back(Attr(i.first, i.second));
attrs2.insert(i.first, i.second);
parent->value(state).mkAttrs(attrs2.alreadySorted());
return std::move(parent);
}
void add() override { v = nullptr; }

View file

@ -2274,11 +2274,12 @@ static void prim_removeAttrs(EvalState & state, const Pos & pos, Value * * args,
/* Copy all attributes not in that set. Note that we don't need
to sort v.attrs because it's a subset of an already sorted
vector. */
state.mkAttrs(v, args[0]->attrs->size());
auto attrs = state.buildBindings(args[0]->attrs->size());
for (auto & i : *args[0]->attrs) {
if (!names.count(i.name))
v.attrs->push_back(i);
attrs.insert(i);
}
v.mkAttrs(attrs.alreadySorted());
}
static RegisterPrimOp primop_removeAttrs({
@ -2369,13 +2370,15 @@ static void prim_intersectAttrs(EvalState & state, const Pos & pos, Value * * ar
state.forceAttrs(*args[0], pos);
state.forceAttrs(*args[1], pos);
state.mkAttrs(v, std::min(args[0]->attrs->size(), args[1]->attrs->size()));
auto attrs = state.buildBindings(std::min(args[0]->attrs->size(), args[1]->attrs->size()));
for (auto & i : *args[0]->attrs) {
Bindings::iterator j = args[1]->attrs->find(i.name);
if (j != args[1]->attrs->end())
v.attrs->push_back(*j);
attrs.insert(*j);
}
v.mkAttrs(attrs.alreadySorted());
}
static RegisterPrimOp primop_intersectAttrs({
@ -2429,7 +2432,7 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
{
state.forceValue(*args[0], pos);
if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) {
state.mkAttrs(v, 0);
v.mkAttrs(&state.emptyBindings);
return;
}
if (!args[0]->isLambda())
@ -2439,7 +2442,7 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
});
if (!args[0]->lambda.fun->hasFormals()) {
state.mkAttrs(v, 0);
v.mkAttrs(&state.emptyBindings);
return;
}
@ -2472,15 +2475,17 @@ static void prim_mapAttrs(EvalState & state, const Pos & pos, Value * * args, Va
{
state.forceAttrs(*args[1], pos);
state.mkAttrs(v, args[1]->attrs->size());
auto attrs = state.buildBindings(args[1]->attrs->size());
for (auto & i : *args[1]->attrs) {
Value * vName = state.allocValue();
Value * vFun2 = state.allocValue();
vName->mkString(i.name);
vFun2->mkApp(args[0], vName);
state.allocAttr(v, i.name)->mkApp(vFun2, i.value);
attrs.alloc(i.name).mkApp(vFun2, i.value);
}
v.mkAttrs(attrs.alreadySorted());
}
static RegisterPrimOp primop_mapAttrs({
@ -2526,12 +2531,13 @@ static void prim_zipAttrsWith(EvalState & state, const Pos & pos, Value * * args
}
}
state.mkAttrs(v, attrsSeen.size());
auto attrs = state.buildBindings(attrsSeen.size());
for (auto & [sym, elem] : attrsSeen) {
Value * list = state.allocAttr(v, sym);
state.mkList(*list, elem.first);
elem.second = list->listElems();
auto & list = attrs.alloc(sym);
state.mkList(list, elem.first);
elem.second = list.listElems();
}
v.mkAttrs(attrs.alreadySorted());
for (unsigned int n = 0; n < listSize; ++n) {
Value * vElem = listElems[n];
@ -3054,14 +3060,16 @@ static void prim_groupBy(EvalState & state, const Pos & pos, Value * * args, Val
vector->second.push_back(vElem);
}
state.mkAttrs(v, attrs.size());
auto attrs2 = state.buildBindings(attrs.size());
for (auto & i : attrs) {
Value * list = state.allocAttr(v, i.first);
auto & list = attrs2.alloc(i.first);
auto size = i.second.size();
state.mkList(*list, size);
memcpy(list->listElems(), i.second.data(), sizeof(Value *) * size);
state.mkList(list, size);
memcpy(list.listElems(), i.second.data(), sizeof(Value *) * size);
}
v.mkAttrs(attrs2.alreadySorted());
}
static RegisterPrimOp primop_groupBy({
@ -3829,7 +3837,7 @@ void EvalState::createBaseEnv()
Value v;
/* `builtins' must be first! */
mkAttrs(v, 128);
v.mkAttrs(buildBindings(128).finish());
addConstant("builtins", v);
v.mkBool(true);