about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2012-02-04T13·50+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2012-02-04T13·50+0000
commitf491ae97d472bfd6305a8f3e8c58fac1fdc443a4 (patch)
treee78fed9caf2450915214144f20dd976202d7d1a3 /src
parent2bda12ef3b2b1d9a0fc59324d723e3fa883ab223 (diff)
* Inline some functions and get rid of the indirection through
  EvalState::eval().  This gives a 12% speedup on ‘nix-instantiate
  /etc/nixos/nixos/ -A system --readonly-mode’ (from 1.01s to 0.89s).

Diffstat (limited to 'src')
-rw-r--r--src/libexpr/Makefile.am2
-rw-r--r--src/libexpr/eval-inline.hh61
-rw-r--r--src/libexpr/eval.cc131
-rw-r--r--src/libexpr/eval.hh13
-rw-r--r--src/libexpr/get-drvs.cc1
-rw-r--r--src/libexpr/primops.cc1
-rw-r--r--src/nix-instantiate/nix-instantiate.cc1
7 files changed, 94 insertions, 116 deletions
diff --git a/src/libexpr/Makefile.am b/src/libexpr/Makefile.am
index 9ca4b2448557..3e7e7e856a55 100644
--- a/src/libexpr/Makefile.am
+++ b/src/libexpr/Makefile.am
@@ -6,7 +6,7 @@ libexpr_la_SOURCES = \
  names.cc
 
 pkginclude_HEADERS = \
- nixexpr.hh eval.hh lexer-tab.hh parser-tab.hh \
+ nixexpr.hh eval.hh eval-inline.hh lexer-tab.hh parser-tab.hh \
  get-drvs.hh attr-path.hh value-to-xml.hh common-opts.hh \
  names.hh symbol-table.hh value.hh
 
diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
new file mode 100644
index 000000000000..6026a7d11015
--- /dev/null
+++ b/src/libexpr/eval-inline.hh
@@ -0,0 +1,61 @@
+#ifndef __EVAL_INLINE_H
+#define __EVAL_INLINE_H
+
+#include "eval.hh"
+
+#define LocalNoInline(f) static f __attribute__((noinline)); f
+#define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f
+
+namespace nix {
+
+
+LocalNoInlineNoReturn(void throwEvalError(const char * s))
+{
+    throw EvalError(s);
+}
+
+LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2))
+{
+    throw TypeError(format(s) % s2);
+}
+
+
+void EvalState::forceValue(Value & v)
+{
+    if (v.type == tThunk) {
+        ValueType saved = v.type;
+        try {
+            v.type = tBlackhole;
+            //checkInterrupt();
+            v.thunk.expr->eval(*this, *v.thunk.env, v);
+        } catch (Error & e) {
+            v.type = saved;
+            throw;
+        }
+    }
+    else if (v.type == tApp)
+        callFunction(*v.app.left, *v.app.right, v);
+    else if (v.type == tBlackhole)
+        throwEvalError("infinite recursion encountered");
+}
+
+
+inline void EvalState::forceAttrs(Value & v)
+{
+    forceValue(v);
+    if (v.type != tAttrs)
+        throwTypeError("value is %1% while an attribute set was expected", showType(v));
+}
+
+
+inline void EvalState::forceList(Value & v)
+{
+    forceValue(v);
+    if (v.type != tList)
+        throwTypeError("value is %1% while a list was expected", showType(v));
+}
+
+
+}
+
+#endif /* !__EVAL_INLINE_H */
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index fa31a85a06fd..6ce65e3e1162 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -4,6 +4,7 @@
 #include "store-api.hh"
 #include "derivations.hh"
 #include "globals.hh"
+#include "eval-inline.hh"
 
 #include <cstring>
 #include <unistd.h>
@@ -27,10 +28,6 @@
 #endif
 
 
-#define LocalNoInline(f) static f __attribute__((noinline)); f
-#define LocalNoInlineNoReturn(f) static f __attribute__((noinline, noreturn)); f
-
-
 namespace nix {
 
 
@@ -227,11 +224,6 @@ void EvalState::addPrimOp(const string & name,
    evaluator.  So here are some helper functions for throwing
    exceptions. */
 
-LocalNoInlineNoReturn(void throwEvalError(const char * s))
-{
-    throw EvalError(s);
-}
-
 LocalNoInlineNoReturn(void throwEvalError(const char * s, const string & s2))
 {
     throw EvalError(format(s) % s2);
@@ -247,11 +239,6 @@ LocalNoInlineNoReturn(void throwTypeError(const char * s))
     throw TypeError(s);
 }
 
-LocalNoInlineNoReturn(void throwTypeError(const char * s, const string & s2))
-{
-    throw TypeError(format(s) % s2);
-}
-
 LocalNoInlineNoReturn(void throwTypeError(const char * s, const Pos & pos, const string & s2))
 {
     throw TypeError(format(s) % pos % s2);
@@ -309,7 +296,7 @@ void mkPath(Value & v, const char * s)
 }
 
 
-Value * EvalState::lookupVar(Env * env, const VarRef & var)
+inline Value * EvalState::lookupVar(Env * env, const VarRef & var)
 {
     for (unsigned int l = var.level; l; --l, env = env->up) ;
     
@@ -435,7 +422,6 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env)
 }
 
 
-
 void EvalState::evalFile(const Path & path, Value & v)
 {
     FileEvalCache::iterator i = fileEvalCache.find(path);
@@ -454,61 +440,25 @@ void EvalState::evalFile(const Path & path, Value & v)
 }
 
 
-struct RecursionCounter
-{
-    EvalState & state;
-    RecursionCounter(EvalState & state) : state(state)
-    {
-        state.recursionDepth++;
-        if (state.recursionDepth > state.maxRecursionDepth)
-            state.maxRecursionDepth = state.recursionDepth;
-    }
-    ~RecursionCounter()
-    {
-        state.recursionDepth--;
-    }
-};
-
-
-void EvalState::eval(Env & env, Expr * e, Value & v)
-{
-    /* When changing this function, make sure that you don't cause a
-       (large) increase in stack consumption! */
-
-    /* !!! Disable this eventually. */
-    RecursionCounter r(*this);
-    char x;
-    if (&x < deepestStack) deepestStack = &x;
-    
-    //debug(format("eval: %1%") % *e);
-
-    checkInterrupt();
-
-    nrEvaluated++;
-
-    e->eval(*this, env, v);
-}
-
-
 void EvalState::eval(Expr * e, Value & v)
 {
-    eval(baseEnv, e, v);
+    e->eval(*this, baseEnv, v);
 }
 
 
-bool EvalState::evalBool(Env & env, Expr * e)
+inline bool EvalState::evalBool(Env & env, Expr * e)
 {
     Value v;
-    eval(env, e, v);
+    e->eval(*this, env, v);
     if (v.type != tBool)
         throwTypeError("value is %1% while a Boolean was expected", showType(v));
     return v.boolean;
 }
 
 
-void EvalState::evalAttrs(Env & env, Expr * e, Value & v)
+inline void EvalState::evalAttrs(Env & env, Expr * e, Value & v)
 {
-    eval(env, e, v);
+    e->eval(*this, env, v);
     if (v.type != tAttrs)
         throwTypeError("value is %1% while an attribute set was expected", showType(v));
 }
@@ -622,7 +572,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
         else
             env2.values[displ++] = i->second.e->maybeThunk(state, env2);
 
-    state.eval(env2, body, v);
+    body->eval(state, env2, v);
 }
 
 
@@ -650,7 +600,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
     Pos * pos = 0;
     Value * vAttrs = &vTmp;
 
-    state.eval(env, e, vTmp);
+    e->eval(state, env, vTmp);
 
     try {
         
@@ -662,7 +612,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
                 if (vAttrs->type != tAttrs ||
                     (j = vAttrs->attrs->find(*i)) == vAttrs->attrs->end())
                 {
-                    state.eval(env, def, v);
+                    def->eval(state, env, v);
                     return;
                 }
             } else {
@@ -692,7 +642,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v)
     Value vTmp;
     Value * vAttrs = &vTmp;
 
-    state.eval(env, e, vTmp);
+    e->eval(state, env, vTmp);
 
     foreach (AttrPath::const_iterator, i, attrPath) {
         state.forceValue(*vAttrs);
@@ -722,7 +672,7 @@ void ExprLambda::eval(EvalState & state, Env & env, Value & v)
 void ExprApp::eval(EvalState & state, Env & env, Value & v)
 {
     Value vFun;
-    state.eval(env, e1, vFun);
+    e1->eval(state, env, vFun);
     state.callFunction(vFun, *(e2->maybeThunk(state, env)), v);
 }
 
@@ -814,7 +764,7 @@ void EvalState::callFunction(Value & fun, Value & arg, Value & v)
     }
 
     try {
-        eval(env2, fun.lambda.fun->body, v);
+        fun.lambda.fun->body->eval(*this, env2, v);
     } catch (Error & e) {
         addErrorPrefix(e, "while evaluating the function at %1%:\n", fun.lambda.fun->pos);
         throw;
@@ -857,13 +807,13 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
     env2.values[0] = state.allocValue();
     state.evalAttrs(env, attrs, *env2.values[0]);
 
-    state.eval(env2, body, v);
+    body->eval(state, env2, v);
 }
 
 
 void ExprIf::eval(EvalState & state, Env & env, Value & v)
 {
-    state.eval(env, state.evalBool(env, cond) ? then : else_, v);
+    (state.evalBool(env, cond) ? then : else_)->eval(state, env, v);
 }
 
     
@@ -871,7 +821,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v)
 {
     if (!state.evalBool(env, cond))
         throwAssertionError("assertion failed at %1%", pos);
-    state.eval(env, body, v);
+    body->eval(state, env, v);
 }
 
     
@@ -883,16 +833,16 @@ void ExprOpNot::eval(EvalState & state, Env & env, Value & v)
 
 void ExprOpEq::eval(EvalState & state, Env & env, Value & v)
 {
-    Value v1; state.eval(env, e1, v1);
-    Value v2; state.eval(env, e2, v2);
+    Value v1; e1->eval(state, env, v1);
+    Value v2; e2->eval(state, env, v2);
     mkBool(v, state.eqValues(v1, v2));
 }
 
 
 void ExprOpNEq::eval(EvalState & state, Env & env, Value & v)
 {
-    Value v1; state.eval(env, e1, v1);
-    Value v2; state.eval(env, e2, v2);
+    Value v1; e1->eval(state, env, v1);
+    Value v2; e2->eval(state, env, v2);
     mkBool(v, !state.eqValues(v1, v2));
 }
 
@@ -954,9 +904,9 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
 
 void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
 {
-    Value v1; state.eval(env, e1, v1);
+    Value v1; e1->eval(state, env, v1);
     state.forceList(v1);
-    Value v2; state.eval(env, e2, v2);
+    Value v2; e2->eval(state, env, v2);
     state.forceList(v2);
     state.mkList(v, v1.list.length + v2.list.length);
     for (unsigned int n = 0; n < v1.list.length; ++n)
@@ -975,7 +925,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
     Value vStr;
 
     foreach (vector<Expr *>::iterator, i, *es) {
-        state.eval(env, *i, vStr);
+        (*i)->eval(state, env, vStr);
 
         /* If the first element is a path, then the result will also
            be a path, we don't copy anything (yet - that's done later,
@@ -999,25 +949,6 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
 }
 
 
-void EvalState::forceValue(Value & v)
-{
-    if (v.type == tThunk) {
-        ValueType saved = v.type;
-        try {
-            v.type = tBlackhole;
-            eval(*v.thunk.env, v.thunk.expr, v);
-        } catch (Error & e) {
-            v.type = saved;
-            throw;
-        }
-    }
-    else if (v.type == tApp)
-        callFunction(*v.app.left, *v.app.right, v);
-    else if (v.type == tBlackhole)
-        throwEvalError("infinite recursion encountered");
-}
-
-
 void EvalState::strictForceValue(Value & v)
 {
     forceValue(v);
@@ -1052,22 +983,6 @@ bool EvalState::forceBool(Value & v)
 }
 
 
-void EvalState::forceAttrs(Value & v)
-{
-    forceValue(v);
-    if (v.type != tAttrs)
-        throwTypeError("value is %1% while an attribute set was expected", showType(v));
-}
-
-
-void EvalState::forceList(Value & v)
-{
-    forceValue(v);
-    if (v.type != tList)
-        throwTypeError("value is %1% while a list was expected", showType(v));
-}
-
-
 void EvalState::forceFunction(Value & v)
 {
     forceValue(v);
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index 91004fe4ca39..c4ba170e8cc7 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -138,18 +138,17 @@ public:
     /* Evaluate an expression to normal form, storing the result in
        value `v'. */
     void eval(Expr * e, Value & v);
-    void eval(Env & env, Expr * e, Value & v);
 
     /* Evaluation the expression, then verify that it has the expected
        type. */
-    bool evalBool(Env & env, Expr * e);
-    void evalAttrs(Env & env, Expr * e, Value & v);
+    inline bool evalBool(Env & env, Expr * e);
+    inline void evalAttrs(Env & env, Expr * e, Value & v);
 
     /* If `v' is a thunk, enter it and overwrite `v' with the result
        of the evaluation of the thunk.  If `v' is a delayed function
        application, call the function and overwrite `v' with the
        result.  Otherwise, this is a no-op. */
-    void forceValue(Value & v);
+    inline void forceValue(Value & v);
 
     /* Force a value, then recursively force list elements and
        attributes. */
@@ -158,8 +157,8 @@ public:
     /* Force `v', and then verify that it has the expected type. */
     int forceInt(Value & v);
     bool forceBool(Value & v);
-    void forceAttrs(Value & v);
-    void forceList(Value & v);
+    inline void forceAttrs(Value & v);
+    inline void forceList(Value & v);
     void forceFunction(Value & v); // either lambda or primop
     string forceString(Value & v);
     string forceString(Value & v, PathSet & context);
@@ -203,7 +202,7 @@ private:
     void addPrimOp(const string & name,
         unsigned int arity, PrimOpFun primOp);
 
-    Value * lookupVar(Env * env, const VarRef & var);
+    inline Value * lookupVar(Env * env, const VarRef & var);
     
     friend class ExprVar;
     friend class ExprAttrs;
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index a28a705d22d1..6670d0636a1f 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -1,5 +1,6 @@
 #include "get-drvs.hh"
 #include "util.hh"
+#include "eval-inline.hh"
 
 
 namespace nix {
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index bdf8dddca8b9..4a171a2aeb4f 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -6,6 +6,7 @@
 #include "archive.hh"
 #include "value-to-xml.hh"
 #include "names.hh"
+#include "eval-inline.hh"
 
 #include <sys/types.h>
 #include <sys/stat.h>
diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc
index 93aa50943450..8f3a290f3a6a 100644
--- a/src/nix-instantiate/nix-instantiate.cc
+++ b/src/nix-instantiate/nix-instantiate.cc
@@ -1,6 +1,7 @@
 #include "globals.hh"
 #include "shared.hh"
 #include "eval.hh"
+#include "eval-inline.hh"
 #include "get-drvs.hh"
 #include "attr-path.hh"
 #include "value-to-xml.hh"