From 6f809194d7448c4ad50174bed9ba2419e2114352 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 3 Sep 2013 12:56:33 +0200 Subject: [PATCH] Get rid of the parse tree cache Since we already cache files in normal form (fileEvalCache), caching parse trees is redundant. Note that getting rid of this cache doesn't actually save much memory at the moment, because parse trees are currently not freed / GC'ed. --- src/libexpr/eval.cc | 30 +++++++++++++++----------- src/libexpr/eval.hh | 12 +++++------ src/libexpr/parser.y | 16 ++++++-------- src/libexpr/primops.cc | 5 ++--- src/nix-env/nix-env.cc | 4 ++-- src/nix-instantiate/nix-instantiate.cc | 2 +- 6 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 6ac07eed6c..50f36ce4e9 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -440,26 +440,30 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env) void EvalState::evalFile(const Path & path, Value & v) { - FileEvalCache::iterator i = fileEvalCache.find(path); - if (i == fileEvalCache.end()) { - startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path); - Expr * e = parseExprFromFile(path); - try { - eval(e, v); - } catch (Error & e) { - addErrorPrefix(e, "while evaluating the file `%1%':\n", path); - throw; - } - fileEvalCache[path] = v; - } else + Path path2 = resolveExprPath(path); + + FileEvalCache::iterator i = fileEvalCache.find(path2); + if (i != fileEvalCache.end()) { v = i->second; + return; + } + + startNest(nest, lvlTalkative, format("evaluating file `%1%'") % path2); + Expr * e = parseExprFromFile(path2); + try { + eval(e, v); + } catch (Error & e) { + addErrorPrefix(e, "while evaluating the file `%1%':\n", path2); + throw; + } + fileEvalCache[path2] = v; + //if (path != path2) fileEvalCache[path2] = v; } void EvalState::resetFileCache() { fileEvalCache.clear(); - parseTrees.clear(); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 98ac0bdb45..29c8341dfb 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -103,9 +103,6 @@ public: private: SrcToStore srcToStore; - /* A cache from path names to parse trees. */ - std::map parseTrees; - /* A cache from path names to values. */ #if HAVE_BOEHMGC typedef std::map, gc_allocator > > FileEvalCache; @@ -125,9 +122,8 @@ public: void addToSearchPath(const string & s); - /* Parse a Nix expression from the specified file. If `path' - refers to a directory, then "/default.nix" is appended. */ - Expr * parseExprFromFile(Path path); + /* Parse a Nix expression from the specified file. */ + Expr * parseExprFromFile(const Path & path); /* Parse a Nix expression from the specified string. */ Expr * parseExprFromString(const string & s, const Path & basePath, StaticEnv & staticEnv); @@ -278,4 +274,8 @@ private: string showType(const Value & v); +/* If `path' refers to a directory, then append "/default.nix". */ +Path resolveExprPath(Path path); + + } diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 623ac641cc..c63043c4d1 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -505,7 +505,7 @@ Expr * EvalState::parse(const char * text, } -Expr * EvalState::parseExprFromFile(Path path) +Path resolveExprPath(Path path) { assert(path[0] == '/'); @@ -523,15 +523,13 @@ Expr * EvalState::parseExprFromFile(Path path) if (S_ISDIR(st.st_mode)) path = canonPath(path + "/default.nix"); - /* Read and parse the input file, unless it's already in the parse - tree cache. */ - Expr * e = parseTrees[path]; - if (!e) { - e = parse(readFile(path).c_str(), path, dirOf(path), staticBaseEnv); - parseTrees[path] = e; - } + return path; +} - return e; + +Expr * EvalState::parseExprFromFile(const Path & path) +{ + return parse(readFile(path).c_str(), path, dirOf(path), staticBaseEnv); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index bcaa51dd63..a216fa7abd 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -82,8 +82,7 @@ static void prim_import(EvalState & state, Value * * args, Value & v) } w.attrs->sort(); Value fun; - state.mkThunk_(fun, - state.parseExprFromFile(state.findFile("nix/imported-drv-to-derivation.nix"))); + state.evalFile(state.findFile("nix/imported-drv-to-derivation.nix"), fun); state.forceFunction(fun); mkApp(v, fun, w); state.forceAttrs(v); @@ -1263,7 +1262,7 @@ void EvalState::createBaseEnv() /* Add a wrapper around the derivation primop that computes the `drvPath' and `outPath' attributes lazily. */ - mkThunk_(v, parseExprFromFile(findFile("nix/derivation.nix"))); + evalFile(findFile("nix/derivation.nix"), v); addConstant("derivation", v); /* Now that we've added all primops, sort the `builtins' attribute diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 9ed3eccf39..1cb1ec4833 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -131,7 +131,7 @@ static void getAllExprs(EvalState & state, if (hasSuffix(attrName, ".nix")) attrName = string(attrName, 0, attrName.size() - 4); attrs.attrs[state.symbols.create(attrName)] = - ExprAttrs::AttrDef(state.parseExprFromFile(absPath(path2)), noPos); + ExprAttrs::AttrDef(state.parseExprFromFile(resolveExprPath(absPath(path2))), noPos); } else /* `path2' is a directory (with no default.nix in it); @@ -143,7 +143,7 @@ static void getAllExprs(EvalState & state, static Expr * loadSourceExpr(EvalState & state, const Path & path) { - if (isNixExpr(path)) return state.parseExprFromFile(absPath(path)); + if (isNixExpr(path)) return state.parseExprFromFile(resolveExprPath(absPath(path))); /* The path is a directory. Put the Nix expressions in the directory in an attribute set, with the file name of each diff --git a/src/nix-instantiate/nix-instantiate.cc b/src/nix-instantiate/nix-instantiate.cc index 53cd711895..69fedb2a6a 100644 --- a/src/nix-instantiate/nix-instantiate.cc +++ b/src/nix-instantiate/nix-instantiate.cc @@ -160,7 +160,7 @@ void run(Strings args) files.push_back("./default.nix"); foreach (Strings::iterator, i, files) { - Expr * e = state.parseExprFromFile(lookupFileArg(state, *i)); + Expr * e = state.parseExprFromFile(resolveExprPath(lookupFileArg(state, *i))); processExpr(state, attrPaths, parseOnly, strict, autoArgs, evalOnly, xmlOutput, xmlOutputSourceLocation, e); }