libexpr: move runtime caches to new struct

Change-Id: Ic5492853d39eaffdf03d961b3e69c93c4a75ae33
This commit is contained in:
eldritch horrors 2024-12-03 20:38:41 +01:00
parent 2e5780ebc8
commit 0bfa58ff53
4 changed files with 53 additions and 38 deletions

View file

@ -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<CachedEvalFile>(TraceableAllocator<CachedEvalFile>(), v);
caches.fileEval[resolvedPath] = cache;
if (path != resolvedPath) caches.fileEval[path] = cache;
}
void EvalState::resetFileCache()
{
fileEvalCache.clear();
caches.fileEval.clear();
}

View file

@ -130,8 +130,6 @@ void initLibExpr();
struct RegexCache;
std::shared_ptr<RegexCache> makeRegexCache();
struct DebugTrace {
std::shared_ptr<Pos> pos;
const Expr & expr;
@ -326,6 +324,24 @@ public:
std::optional<Doc> getDoc(Value & v);
};
struct CachedEvalFile;
struct EvalRuntimeCaches
{
RootValue vCallFlake;
RootValue vImportedDrvToDerivation;
/**
* Cache used by prim_match() and other regex functions.
*/
std::shared_ptr<RegexCache> regexes;
/**
* A cache from path names to values for evalFile().
*/
std::map<SourcePath, std::shared_ptr<CachedEvalFile>> 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<Store> buildStore;
RootValue vCallFlake = nullptr;
RootValue vImportedDrvToDerivation = nullptr;
std::unique_ptr<DebugState> debug;
template<class T, typename... Args>
@ -383,12 +397,6 @@ private:
paths. */
std::map<SourcePath, StorePath> srcToStore;
/**
* A cache from path names to values.
*/
using FileEvalCache = GcMap<SourcePath, Value>;
FileEvalCache fileEvalCache;
std::map<std::string, std::optional<std::string>> searchPathResolved;
/**
@ -396,11 +404,6 @@ private:
*/
std::unordered_map<Path, SourcePath> resolvedPaths;
/**
* Cache used by prim_match().
*/
std::shared_ptr<RegexCache> regexCache;
public:
EvalState(

View file

@ -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);
}

View file

@ -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<RegexCache> makeRegexCache()
static RegexCache & regexCacheOf(EvalState & state)
{
return std::make_shared<RegexCache>();
if (!state.caches.regexes) {
state.caches.regexes = std::make_shared<RegexCache>();
}
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");