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

View file

@ -118,13 +118,14 @@ public:
call finish(), which sorts the bindings. */ call finish(), which sorts the bindings. */
class BindingsBuilder class BindingsBuilder
{ {
EvalState & state;
Bindings * bindings; Bindings * bindings;
public: public:
EvalState & state;
BindingsBuilder(EvalState & state, Bindings * bindings) BindingsBuilder(EvalState & state, Bindings * bindings)
: state(state), bindings(bindings) : bindings(bindings), state(state)
{ } { }
void insert(Symbol name, Value * value, ptr<Pos> pos = ptr(&noPos)) void insert(Symbol name, Value * value, ptr<Pos> pos = ptr(&noPos))
@ -146,6 +147,11 @@ public:
bindings->sort(); bindings->sort();
return bindings; 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; str << v.fpoint;
break; break;
default: default:
throw Error("invalid value"); abort();
} }
active.erase(&v); 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) void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
{ {
state.mkAttrs(v, attrs.size() + dynamicAttrs.size()); v.mkAttrs(state.buildBindings(attrs.size() + dynamicAttrs.size()).finish());
Env *dynamicEnv = &env; auto dynamicEnv = &env;
if (recursive) { if (recursive) {
/* Create a new environment that contains the attributes in /* 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 (v1.attrs->size() == 0) { v = v2; return; }
if (v2.attrs->size() == 0) { v = v1; 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 /* Merge the sets, preferring values from the second set. Make
sure to keep the resulting vector in sorted order. */ 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()) { while (i != v1.attrs->end() && j != v2.attrs->end()) {
if (i->name == j->name) { if (i->name == j->name) {
v.attrs->push_back(*j); attrs.insert(*j);
++i; ++j; ++i; ++j;
} }
else if (i->name < j->name) else if (i->name < j->name)
v.attrs->push_back(*i++); attrs.insert(*i++);
else else
v.attrs->push_back(*j++); attrs.insert(*j++);
} }
while (i != v1.attrs->end()) v.attrs->push_back(*i++); while (i != v1.attrs->end()) attrs.insert(*i++);
while (j != v2.attrs->end()) v.attrs->push_back(*j++); while (j != v2.attrs->end()) attrs.insert(*j++);
v.mkAttrs(attrs.alreadySorted());
state.nrOpUpdateValuesCopied += v.attrs->size(); state.nrOpUpdateValuesCopied += v.attrs->size();
} }

View file

@ -347,7 +347,6 @@ public:
} }
void mkList(Value & v, size_t length); void mkList(Value & v, size_t length);
void mkAttrs(Value & v, size_t capacity);
void mkThunk_(Value & v, Expr * expr); void mkThunk_(Value & v, Expr * expr);
void mkPos(Value & v, ptr<Pos> pos); void mkPos(Value & v, ptr<Pos> pos);
@ -400,6 +399,8 @@ private:
friend struct ExprSelect; friend struct ExprSelect;
friend void prim_getAttr(EvalState & state, const Pos & pos, Value * * args, Value & v); 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 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; ValueMap attrs;
std::unique_ptr<JSONState> resolve(EvalState & state) override std::unique_ptr<JSONState> resolve(EvalState & state) override
{ {
Value & v = parent->value(state); auto attrs2 = state.buildBindings(attrs.size());
state.mkAttrs(v, attrs.size());
for (auto & i : attrs) 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); return std::move(parent);
} }
void add() override { v = nullptr; } 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 /* 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 to sort v.attrs because it's a subset of an already sorted
vector. */ vector. */
state.mkAttrs(v, args[0]->attrs->size()); auto attrs = state.buildBindings(args[0]->attrs->size());
for (auto & i : *args[0]->attrs) { for (auto & i : *args[0]->attrs) {
if (!names.count(i.name)) if (!names.count(i.name))
v.attrs->push_back(i); attrs.insert(i);
} }
v.mkAttrs(attrs.alreadySorted());
} }
static RegisterPrimOp primop_removeAttrs({ 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[0], pos);
state.forceAttrs(*args[1], 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) { for (auto & i : *args[0]->attrs) {
Bindings::iterator j = args[1]->attrs->find(i.name); Bindings::iterator j = args[1]->attrs->find(i.name);
if (j != args[1]->attrs->end()) if (j != args[1]->attrs->end())
v.attrs->push_back(*j); attrs.insert(*j);
} }
v.mkAttrs(attrs.alreadySorted());
} }
static RegisterPrimOp primop_intersectAttrs({ static RegisterPrimOp primop_intersectAttrs({
@ -2429,7 +2432,7 @@ static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args
{ {
state.forceValue(*args[0], pos); state.forceValue(*args[0], pos);
if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) { if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) {
state.mkAttrs(v, 0); v.mkAttrs(&state.emptyBindings);
return; return;
} }
if (!args[0]->isLambda()) 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()) { if (!args[0]->lambda.fun->hasFormals()) {
state.mkAttrs(v, 0); v.mkAttrs(&state.emptyBindings);
return; return;
} }
@ -2472,15 +2475,17 @@ static void prim_mapAttrs(EvalState & state, const Pos & pos, Value * * args, Va
{ {
state.forceAttrs(*args[1], pos); 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) { for (auto & i : *args[1]->attrs) {
Value * vName = state.allocValue(); Value * vName = state.allocValue();
Value * vFun2 = state.allocValue(); Value * vFun2 = state.allocValue();
vName->mkString(i.name); vName->mkString(i.name);
vFun2->mkApp(args[0], vName); 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({ 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) { for (auto & [sym, elem] : attrsSeen) {
Value * list = state.allocAttr(v, sym); auto & list = attrs.alloc(sym);
state.mkList(*list, elem.first); state.mkList(list, elem.first);
elem.second = list->listElems(); elem.second = list.listElems();
} }
v.mkAttrs(attrs.alreadySorted());
for (unsigned int n = 0; n < listSize; ++n) { for (unsigned int n = 0; n < listSize; ++n) {
Value * vElem = listElems[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); vector->second.push_back(vElem);
} }
state.mkAttrs(v, attrs.size()); auto attrs2 = state.buildBindings(attrs.size());
for (auto & i : attrs) { for (auto & i : attrs) {
Value * list = state.allocAttr(v, i.first); auto & list = attrs2.alloc(i.first);
auto size = i.second.size(); auto size = i.second.size();
state.mkList(*list, size); state.mkList(list, size);
memcpy(list->listElems(), i.second.data(), sizeof(Value *) * size); memcpy(list.listElems(), i.second.data(), sizeof(Value *) * size);
} }
v.mkAttrs(attrs2.alreadySorted());
} }
static RegisterPrimOp primop_groupBy({ static RegisterPrimOp primop_groupBy({
@ -3829,7 +3837,7 @@ void EvalState::createBaseEnv()
Value v; Value v;
/* `builtins' must be first! */ /* `builtins' must be first! */
mkAttrs(v, 128); v.mkAttrs(buildBindings(128).finish());
addConstant("builtins", v); addConstant("builtins", v);
v.mkBool(true); v.mkBool(true);