* When allocating an attribute set, reserve enough space for all

elements.  This prevents the vector from having to resize itself.
This commit is contained in:
Eelco Dolstra 2010-10-24 20:09:37 +00:00
parent e0b7fb8f27
commit 43535499f3
4 changed files with 21 additions and 28 deletions

View file

@ -340,11 +340,12 @@ void EvalState::mkList(Value & v, unsigned int length)
} }
void EvalState::mkAttrs(Value & v) void EvalState::mkAttrs(Value & v, unsigned int expected)
{ {
clearValue(v); clearValue(v);
v.type = tAttrs; v.type = tAttrs;
v.attrs = NEW Bindings; v.attrs = NEW Bindings;
v.attrs->reserve(expected);
nrAttrsets++; nrAttrsets++;
} }
@ -391,13 +392,6 @@ Value * EvalState::maybeThunk(Env & env, Expr * expr)
} }
void EvalState::cloneAttrs(Value & src, Value & dst)
{
mkAttrs(dst);
*dst.attrs = *src.attrs;
}
void EvalState::evalFile(const Path & path, Value & v) void EvalState::evalFile(const Path & path, Value & v)
{ {
startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path);
@ -504,7 +498,7 @@ 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); // !!! reserve size state.mkAttrs(v, attrs.size());
if (recursive) { if (recursive) {
/* Create a new environment that contains the attributes in /* Create a new environment that contains the attributes in
@ -758,7 +752,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
} }
Value actualArgs; Value actualArgs;
mkAttrs(actualArgs); mkAttrs(actualArgs, fun.lambda.fun->formals->formals.size());
foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) { foreach (Formals::Formals_::iterator, i, fun.lambda.fun->formals->formals) {
Bindings::iterator j = args.find(i->name); Bindings::iterator j = args.find(i->name);
@ -852,7 +846,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); state.mkAttrs(v, v1.attrs->size() + v2.attrs->size());
/* Merge the attribute sets, preferring values from the second /* Merge the attribute sets, preferring values from the second
set. Make sure to keep the resulting vector in sorted set. Make sure to keep the resulting vector in sorted

View file

@ -319,13 +319,11 @@ public:
Value * allocAttr(Value & vAttrs, const Symbol & name); Value * allocAttr(Value & vAttrs, const Symbol & name);
void mkList(Value & v, unsigned int length); void mkList(Value & v, unsigned int length);
void mkAttrs(Value & v); void mkAttrs(Value & v, unsigned int expected);
void mkThunk_(Value & v, Expr * expr); void mkThunk_(Value & v, Expr * expr);
Value * maybeThunk(Env & env, Expr * expr); Value * maybeThunk(Env & env, Expr * expr);
void cloneAttrs(Value & src, Value & dst);
/* Print statistics. */ /* Print statistics. */
void printStats(); void printStats();

View file

@ -206,7 +206,7 @@ static void prim_addErrorContext(EvalState & state, Value * * args, Value & v)
* else => {success=false; value=false;} */ * else => {success=false; value=false;} */
static void prim_tryEval(EvalState & state, Value * * args, Value & v) static void prim_tryEval(EvalState & state, Value * * args, Value & v)
{ {
state.mkAttrs(v); state.mkAttrs(v, 2);
try { try {
state.forceValue(*args[0]); state.forceValue(*args[0]);
v.attrs->push_back(Attr(state.symbols.create("value"), args[0])); v.attrs->push_back(Attr(state.symbols.create("value"), args[0]));
@ -484,7 +484,7 @@ static void prim_derivationStrict(EvalState & state, Value * * args, Value & v)
state.drvHashes[drvPath] = hashDerivationModulo(state, drv); state.drvHashes[drvPath] = hashDerivationModulo(state, drv);
/* !!! assumes a single output */ /* !!! assumes a single output */
state.mkAttrs(v); state.mkAttrs(v, 2);
mkString(*state.allocAttr(v, state.sOutPath), outPath, singleton<PathSet>(drvPath)); mkString(*state.allocAttr(v, state.sOutPath), outPath, singleton<PathSet>(drvPath));
mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath)); mkString(*state.allocAttr(v, state.sDrvPath), drvPath, singleton<PathSet>("=" + drvPath));
v.attrs->sort(); v.attrs->sort();
@ -745,7 +745,7 @@ static void prim_removeAttrs(EvalState & state, Value * * args, Value & v)
/* 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); state.mkAttrs(v, args[0]->attrs->size());
foreach (Bindings::iterator, i, *args[0]->attrs) { foreach (Bindings::iterator, i, *args[0]->attrs) {
if (names.find(i->name) == names.end()) if (names.find(i->name) == names.end())
v.attrs->push_back(*i); v.attrs->push_back(*i);
@ -761,7 +761,7 @@ static void prim_listToAttrs(EvalState & state, Value * * args, Value & v)
{ {
state.forceList(*args[0]); state.forceList(*args[0]);
state.mkAttrs(v); state.mkAttrs(v, args[0]->list.length);
std::set<Symbol> seen; std::set<Symbol> seen;
@ -798,7 +798,7 @@ static void prim_intersectAttrs(EvalState & state, Value * * args, Value & v)
state.forceAttrs(*args[0]); state.forceAttrs(*args[0]);
state.forceAttrs(*args[1]); state.forceAttrs(*args[1]);
state.mkAttrs(v); state.mkAttrs(v, std::min(args[0]->attrs->size(), args[1]->attrs->size()));
foreach (Bindings::iterator, i, *args[0]->attrs) { foreach (Bindings::iterator, i, *args[0]->attrs) {
Bindings::iterator j = args[1]->attrs->find(i->name); Bindings::iterator j = args[1]->attrs->find(i->name);
@ -827,14 +827,15 @@ static void prim_functionArgs(EvalState & state, Value * * args, Value & v)
if (args[0]->type != tLambda) if (args[0]->type != tLambda)
throw TypeError("`functionArgs' requires a function"); throw TypeError("`functionArgs' requires a function");
state.mkAttrs(v); if (!args[0]->lambda.fun->matchAttrs) {
state.mkAttrs(v, 0);
if (!args[0]->lambda.fun->matchAttrs) return; return;
}
state.mkAttrs(v, args[0]->lambda.fun->formals->formals.size());
foreach (Formals::Formals_::iterator, i, args[0]->lambda.fun->formals->formals) foreach (Formals::Formals_::iterator, i, args[0]->lambda.fun->formals->formals)
// !!! should optimise booleans (allocate only once) // !!! should optimise booleans (allocate only once)
mkBool(*state.allocAttr(v, i->name), i->def); mkBool(*state.allocAttr(v, i->name), i->def);
v.attrs->sort(); v.attrs->sort();
} }
@ -1015,7 +1016,7 @@ static void prim_parseDrvName(EvalState & state, Value * * args, Value & v)
{ {
string name = state.forceStringNoCtx(*args[0]); string name = state.forceStringNoCtx(*args[0]);
DrvName parsed(name); DrvName parsed(name);
state.mkAttrs(v); state.mkAttrs(v, 2);
mkString(*state.allocAttr(v, state.sName), parsed.name); mkString(*state.allocAttr(v, state.sName), parsed.name);
mkString(*state.allocAttr(v, state.symbols.create("version")), parsed.version); mkString(*state.allocAttr(v, state.symbols.create("version")), parsed.version);
v.attrs->sort(); v.attrs->sort();
@ -1043,7 +1044,7 @@ void EvalState::createBaseEnv()
Value v; Value v;
/* `builtins' must be first! */ /* `builtins' must be first! */
mkAttrs(v); mkAttrs(v, 128);
addConstant("builtins", v); addConstant("builtins", v);
mkBool(v, true); mkBool(v, true);

View file

@ -61,7 +61,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
Value & v(*state.allocValue()); Value & v(*state.allocValue());
manifest.list.elems[n++] = &v; manifest.list.elems[n++] = &v;
state.mkAttrs(v); state.mkAttrs(v, 8);
mkString(*state.allocAttr(v, state.sType), "derivation"); mkString(*state.allocAttr(v, state.sType), "derivation");
mkString(*state.allocAttr(v, state.sName), i->name); mkString(*state.allocAttr(v, state.sName), i->name);
@ -71,7 +71,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state)); mkString(*state.allocAttr(v, state.sDrvPath), i->queryDrvPath(state));
Value & vMeta = *state.allocAttr(v, state.sMeta); Value & vMeta = *state.allocAttr(v, state.sMeta);
state.mkAttrs(vMeta); state.mkAttrs(vMeta, 16);
MetaInfo meta = i->queryMetaInfo(state); MetaInfo meta = i->queryMetaInfo(state);
@ -118,7 +118,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Construct a Nix expression that calls the user environment /* Construct a Nix expression that calls the user environment
builder with the manifest as argument. */ builder with the manifest as argument. */
Value args, topLevel; Value args, topLevel;
state.mkAttrs(args); state.mkAttrs(args, 3);
mkString(*state.allocAttr(args, state.sSystem), thisSystem); mkString(*state.allocAttr(args, state.sSystem), thisSystem);
mkString(*state.allocAttr(args, state.symbols.create("manifest")), mkString(*state.allocAttr(args, state.symbols.create("manifest")),
manifestFile, singleton<PathSet>(manifestFile)); manifestFile, singleton<PathSet>(manifestFile));