From 0bfa58ff53eebfa25b20b6e7c8c6fb94270224c9 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Tue, 3 Dec 2024 20:38:41 +0100 Subject: [PATCH] libexpr: move runtime caches to new struct Change-Id: Ic5492853d39eaffdf03d961b3e69c93c4a75ae33 --- lix/libexpr/eval.cc | 23 ++++++++++++++--------- lix/libexpr/eval.hh | 35 +++++++++++++++++++---------------- lix/libexpr/flake/flake.cc | 8 ++++---- lix/libexpr/primops.cc | 25 ++++++++++++++++--------- 4 files changed, 53 insertions(+), 38 deletions(-) diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 2acbdf97d..faa9ece46 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -290,7 +290,6 @@ EvalState::EvalState( , repair(NoRepair) , store(store) , buildStore(buildStore ? buildStore : store) - , regexCache(makeRegexCache()) { countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; @@ -911,19 +910,24 @@ Value * ExprPath::maybeThunk(EvalState & state, Env & env) } +struct CachedEvalFile +{ + Value result; + explicit CachedEvalFile(Value result): result(result) {} +}; + void EvalState::evalFile(const SourcePath & path_, Value & v) { auto path = checkSourcePath(path_); - FileEvalCache::iterator i; - if ((i = fileEvalCache.find(path)) != fileEvalCache.end()) { - v = i->second; + if (auto i = caches.fileEval.find(path); i != caches.fileEval.end()) { + v = i->second->result; return; } auto resolvedPath = resolveExprPath(path); - if ((i = fileEvalCache.find(resolvedPath)) != fileEvalCache.end()) { - v = i->second; + if (auto i = caches.fileEval.find(resolvedPath); i != caches.fileEval.end()) { + v = i->second->result; return; } @@ -946,14 +950,15 @@ void EvalState::evalFile(const SourcePath & path_, Value & v) throw; } - fileEvalCache[resolvedPath] = v; - if (path != resolvedPath) fileEvalCache[path] = v; + auto cache = std::allocate_shared(TraceableAllocator(), v); + caches.fileEval[resolvedPath] = cache; + if (path != resolvedPath) caches.fileEval[path] = cache; } void EvalState::resetFileCache() { - fileEvalCache.clear(); + caches.fileEval.clear(); } diff --git a/lix/libexpr/eval.hh b/lix/libexpr/eval.hh index ffc4015d7..304284e33 100644 --- a/lix/libexpr/eval.hh +++ b/lix/libexpr/eval.hh @@ -130,8 +130,6 @@ void initLibExpr(); struct RegexCache; -std::shared_ptr makeRegexCache(); - struct DebugTrace { std::shared_ptr pos; const Expr & expr; @@ -326,6 +324,24 @@ public: std::optional getDoc(Value & v); }; +struct CachedEvalFile; + +struct EvalRuntimeCaches +{ + RootValue vCallFlake; + RootValue vImportedDrvToDerivation; + + /** + * Cache used by prim_match() and other regex functions. + */ + std::shared_ptr regexes; + + /** + * A cache from path names to values for evalFile(). + */ + std::map> fileEval; +}; + class EvalState { @@ -336,6 +352,7 @@ public: PosTable positions; const StaticSymbols s; EvalMemory mem; + EvalRuntimeCaches caches; private: SearchPath searchPath; @@ -365,9 +382,6 @@ public: */ const ref buildStore; - RootValue vCallFlake = nullptr; - RootValue vImportedDrvToDerivation = nullptr; - std::unique_ptr debug; template @@ -383,12 +397,6 @@ private: paths. */ std::map srcToStore; - /** - * A cache from path names to values. - */ - using FileEvalCache = GcMap; - FileEvalCache fileEvalCache; - std::map> searchPathResolved; /** @@ -396,11 +404,6 @@ private: */ std::unordered_map resolvedPaths; - /** - * Cache used by prim_match(). - */ - std::shared_ptr regexCache; - public: EvalState( diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index 81efa3329..202a05ace 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -791,14 +791,14 @@ void callFlake(EvalState & state, vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir); - if (!state.vCallFlake) { - state.vCallFlake = allocRootValue(state.mem.allocValue()); + if (!state.caches.vCallFlake) { + state.caches.vCallFlake = allocRootValue(state.mem.allocValue()); state.eval(state.parseExprFromString( #include "call-flake.nix.gen.hh" - , CanonPath::root), **state.vCallFlake); + , CanonPath::root), **state.caches.vCallFlake); } - state.callFunction(**state.vCallFlake, *vLocks, *vTmp1, noPos); + state.callFunction(**state.caches.vCallFlake, *vLocks, *vTmp1, noPos); state.callFunction(*vTmp1, *vRootSrc, *vTmp2, noPos); state.callFunction(*vTmp2, *vRootSubdir, vRes, noPos); } diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 7b9ea06cc..614ec1f26 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -206,15 +206,19 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v auto w = state.mem.allocValue(); w->mkAttrs(attrs); - if (!state.vImportedDrvToDerivation) { - state.vImportedDrvToDerivation = allocRootValue(state.mem.allocValue()); + if (!state.caches.vImportedDrvToDerivation) { + state.caches.vImportedDrvToDerivation = allocRootValue(state.mem.allocValue()); state.eval(state.parseExprFromString( #include "imported-drv-to-derivation.nix.gen.hh" - , CanonPath::root), **state.vImportedDrvToDerivation); + , CanonPath::root), **state.caches.vImportedDrvToDerivation); } - state.forceFunction(**state.vImportedDrvToDerivation, pos, "while evaluating imported-drv-to-derivation.nix.gen.hh"); - v.mkApp(*state.vImportedDrvToDerivation, w); + state.forceFunction( + **state.caches.vImportedDrvToDerivation, + pos, + "while evaluating imported-drv-to-derivation.nix.gen.hh" + ); + v.mkApp(*state.caches.vImportedDrvToDerivation, w); state.forceAttrs(v, pos, "while calling imported-drv-to-derivation.nix.gen.hh"); } @@ -2543,9 +2547,12 @@ struct RegexCache } }; -std::shared_ptr makeRegexCache() +static RegexCache & regexCacheOf(EvalState & state) { - return std::make_shared(); + if (!state.caches.regexes) { + state.caches.regexes = std::make_shared(); + } + return *state.caches.regexes; } void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) @@ -2554,7 +2561,7 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) try { - auto regex = state.regexCache->get(re); + auto regex = regexCacheOf(state).get(re); NixStringContext context; const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.match"); @@ -2596,7 +2603,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) try { - auto regex = state.regexCache->get(re); + auto regex = regexCacheOf(state).get(re); NixStringContext context; const auto str = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.split");