about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2012-01-04T21·24+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2012-01-04T21·24+0000
commit35f2a6ba82419d48ed8ebce7b8c3e74e65ac74f2 (patch)
treeeae7ae96104e0d68de31efa9a31a9d75b8c05129
parentadaf64a99b0a882249e35768c3f4fe3de104cbb2 (diff)
* 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.

-rw-r--r--src/libexpr/eval.cc43
-rw-r--r--src/libexpr/eval.hh2
-rw-r--r--src/libexpr/nixexpr.hh2
3 files changed, 23 insertions, 24 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index bba14bc35491..3aa35b32760a 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -404,28 +404,27 @@ void EvalState::mkThunk_(Value & v, Expr * expr)
 }
 
 
-unsigned long nrAvoided = 0;
-
 /* Create a thunk for the delayed computation of the given expression
    in the given environment.  But if the expression is a variable,
    then look it up right away.  This significantly reduces the number
    of thunks allocated. */
-Value * EvalState::maybeThunk(Env & env, Expr * expr)
-{
-    ExprVar * var;
-    /* Ignore variables from `withs' because they can throw an
-       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 * Expr::maybeThunk(EvalState & state, Env & env)
+{
+    Value * v = state.allocValue();
+    mkThunk(*v, env, this);
+    return v;
+}
 
-    Value * v = allocValue();
-    mkThunk(*v, env, expr);
 
-    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);
 }
 
 
@@ -560,7 +559,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
                     vAttr = state.allocValue();
                     mkThunk(*vAttr, env2, i->second.e);
                 } else
-                    vAttr = state.maybeThunk(env2, i->second.e);
+                    vAttr = i->second.e->maybeThunk(state, env2);
                 env2.values[displ++] = vAttr;
                 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)
                 v.attrs->push_back(Attr(i->first, state.lookupVar(&env, i->second.var), &i->second.pos));
             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)
             env2.values[displ++] = state.lookupVar(&env, i->second.var);
         else
-            env2.values[displ++] = state.maybeThunk(env2, i->second.e);
+            env2.values[displ++] = i->second.e->maybeThunk(state, env2);
 
     state.eval(env2, body, v);
 }
@@ -623,7 +622,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v)
 {
     state.mkList(v, elems.size());
     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;
     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 (!i->def) throwTypeError("function at %1% called without required argument `%2%'",
                     fun.lambda.fun->pos, i->name);
-                env2.values[displ++] = maybeThunk(env2, i->def);
+                env2.values[displ++] = i->def->maybeThunk(*this, env2);
             } else {
                 attrsUsed++;
                 env2.values[displ++] = j->value;
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 694d4407b847..1db3453f395c 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -346,8 +346,6 @@ public:
     void mkAttrs(Value & v, unsigned int expected);
     void mkThunk_(Value & v, Expr * expr);
 
-    Value * maybeThunk(Env & env, Expr * expr);
-    
     /* Print statistics. */
     void printStats();
 
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 166289b29851..1c5cc07afe18 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -53,6 +53,7 @@ struct Expr
     virtual void show(std::ostream & str);
     virtual void bindVars(const StaticEnv & env);
     virtual void eval(EvalState & state, Env & env, Value & v);
+    virtual Value * maybeThunk(EvalState & state, Env & env);
 };
 
 std::ostream & operator << (std::ostream & str, Expr & e);
@@ -117,6 +118,7 @@ struct ExprVar : Expr
     VarRef info;
     ExprVar(const Symbol & name) : info(name) { };
     COMMON_METHODS
+    Value * maybeThunk(EvalState & state, Env & env);
 };
 
 struct ExprSelect : Expr