* Don't use dynamic_cast, it's very slow. "nix-instantiate
/etc/nixos/nixos -A system" spent about 10% of its time in dynamic_cast.
This commit is contained in:
parent
adaf64a99b
commit
35f2a6ba82
|
@ -404,31 +404,30 @@ void EvalState::mkThunk_(Value & v, Expr * expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned long nrAvoided = 0;
|
|
||||||
|
|
||||||
/* Create a thunk for the delayed computation of the given expression
|
/* Create a thunk for the delayed computation of the given expression
|
||||||
in the given environment. But if the expression is a variable,
|
in the given environment. But if the expression is a variable,
|
||||||
then look it up right away. This significantly reduces the number
|
then look it up right away. This significantly reduces the number
|
||||||
of thunks allocated. */
|
of thunks allocated. */
|
||||||
Value * EvalState::maybeThunk(Env & env, Expr * expr)
|
Value * Expr::maybeThunk(EvalState & state, Env & env)
|
||||||
{
|
{
|
||||||
ExprVar * var;
|
Value * v = state.allocValue();
|
||||||
/* Ignore variables from `withs' because they can throw an
|
mkThunk(*v, env, this);
|
||||||
exception. */
|
|
||||||
if ((var = dynamic_cast<ExprVar *>(expr))) {
|
|
||||||
Value * v = lookupVar(&env, var->info);
|
|
||||||
/* The value might not be initialised in the environment yet.
|
|
||||||
In that case, ignore it. */
|
|
||||||
if (v) { nrAvoided++; return v; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Value * v = allocValue();
|
|
||||||
mkThunk(*v, env, expr);
|
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned long nrAvoided = 0;
|
||||||
|
|
||||||
|
Value * ExprVar::maybeThunk(EvalState & state, Env & env)
|
||||||
|
{
|
||||||
|
Value * v = state.lookupVar(&env, info);
|
||||||
|
/* The value might not be initialised in the environment yet.
|
||||||
|
In that case, ignore it. */
|
||||||
|
if (v) { nrAvoided++; return v; }
|
||||||
|
return Expr::maybeThunk(state, env);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EvalState::evalFile(const Path & path, Value & v)
|
void EvalState::evalFile(const Path & path, Value & v)
|
||||||
{
|
{
|
||||||
FileEvalCache::iterator i = fileEvalCache.find(path);
|
FileEvalCache::iterator i = fileEvalCache.find(path);
|
||||||
|
@ -560,7 +559,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
vAttr = state.allocValue();
|
vAttr = state.allocValue();
|
||||||
mkThunk(*vAttr, env2, i->second.e);
|
mkThunk(*vAttr, env2, i->second.e);
|
||||||
} else
|
} else
|
||||||
vAttr = state.maybeThunk(env2, i->second.e);
|
vAttr = i->second.e->maybeThunk(state, env2);
|
||||||
env2.values[displ++] = vAttr;
|
env2.values[displ++] = vAttr;
|
||||||
v.attrs->push_back(Attr(i->first, vAttr, &i->second.pos));
|
v.attrs->push_back(Attr(i->first, vAttr, &i->second.pos));
|
||||||
}
|
}
|
||||||
|
@ -593,7 +592,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
||||||
if (i->second.inherited)
|
if (i->second.inherited)
|
||||||
v.attrs->push_back(Attr(i->first, state.lookupVar(&env, i->second.var), &i->second.pos));
|
v.attrs->push_back(Attr(i->first, state.lookupVar(&env, i->second.var), &i->second.pos));
|
||||||
else
|
else
|
||||||
v.attrs->push_back(Attr(i->first, state.maybeThunk(env, i->second.e), &i->second.pos));
|
v.attrs->push_back(Attr(i->first, i->second.e->maybeThunk(state, env), &i->second.pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +612,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||||
if (i->second.inherited)
|
if (i->second.inherited)
|
||||||
env2.values[displ++] = state.lookupVar(&env, i->second.var);
|
env2.values[displ++] = state.lookupVar(&env, i->second.var);
|
||||||
else
|
else
|
||||||
env2.values[displ++] = state.maybeThunk(env2, i->second.e);
|
env2.values[displ++] = i->second.e->maybeThunk(state, env2);
|
||||||
|
|
||||||
state.eval(env2, body, v);
|
state.eval(env2, body, v);
|
||||||
}
|
}
|
||||||
|
@ -623,7 +622,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
state.mkList(v, elems.size());
|
state.mkList(v, elems.size());
|
||||||
for (unsigned int n = 0; n < v.list.length; ++n)
|
for (unsigned int n = 0; n < v.list.length; ++n)
|
||||||
v.list.elems[n] = state.maybeThunk(env, elems[n]);
|
v.list.elems[n] = elems[n]->maybeThunk(state, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -716,7 +715,7 @@ void ExprApp::eval(EvalState & state, Env & env, Value & v)
|
||||||
{
|
{
|
||||||
Value vFun;
|
Value vFun;
|
||||||
state.eval(env, e1, vFun);
|
state.eval(env, e1, vFun);
|
||||||
state.callFunction(vFun, *state.maybeThunk(env, e2), v);
|
state.callFunction(vFun, *(e2->maybeThunk(state, env)), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -791,7 +790,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
|
||||||
if (j == arg.attrs->end()) {
|
if (j == arg.attrs->end()) {
|
||||||
if (!i->def) throwTypeError("function at %1% called without required argument `%2%'",
|
if (!i->def) throwTypeError("function at %1% called without required argument `%2%'",
|
||||||
fun.lambda.fun->pos, i->name);
|
fun.lambda.fun->pos, i->name);
|
||||||
env2.values[displ++] = maybeThunk(env2, i->def);
|
env2.values[displ++] = i->def->maybeThunk(*this, env2);
|
||||||
} else {
|
} else {
|
||||||
attrsUsed++;
|
attrsUsed++;
|
||||||
env2.values[displ++] = j->value;
|
env2.values[displ++] = j->value;
|
||||||
|
|
|
@ -346,8 +346,6 @@ public:
|
||||||
void mkAttrs(Value & v, unsigned int expected);
|
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);
|
|
||||||
|
|
||||||
/* Print statistics. */
|
/* Print statistics. */
|
||||||
void printStats();
|
void printStats();
|
||||||
|
|
||||||
|
|
|
@ -53,6 +53,7 @@ struct Expr
|
||||||
virtual void show(std::ostream & str);
|
virtual void show(std::ostream & str);
|
||||||
virtual void bindVars(const StaticEnv & env);
|
virtual void bindVars(const StaticEnv & env);
|
||||||
virtual void eval(EvalState & state, Env & env, Value & v);
|
virtual void eval(EvalState & state, Env & env, Value & v);
|
||||||
|
virtual Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream & operator << (std::ostream & str, Expr & e);
|
std::ostream & operator << (std::ostream & str, Expr & e);
|
||||||
|
@ -117,6 +118,7 @@ struct ExprVar : Expr
|
||||||
VarRef info;
|
VarRef info;
|
||||||
ExprVar(const Symbol & name) : info(name) { };
|
ExprVar(const Symbol & name) : info(name) { };
|
||||||
COMMON_METHODS
|
COMMON_METHODS
|
||||||
|
Value * maybeThunk(EvalState & state, Env & env);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExprSelect : Expr
|
struct ExprSelect : Expr
|
||||||
|
|
Loading…
Reference in a new issue