diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index 8814346d0..78e67a58c 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -144,7 +144,7 @@ static void getAllExprs(EvalState & state, continue; } /* Load the expression on demand. */ - auto vArg = state.allocValue(); + auto vArg = state.mem.allocValue(); vArg->mkString(path2.path.abs()); if (seen.size() == maxAttrs) throw Error("too many Nix expressions in directory '%1%'", path); @@ -695,7 +695,7 @@ static void opUpgrade(Globals & globals, Strings opFlags, Strings opArgs) static void setMetaFlag(EvalState & state, DrvInfo & drv, const std::string & name, const std::string & value) { - auto v = state.allocValue(); + auto v = state.mem.allocValue(); v->mkString(value); drv.setMeta(name, v); } diff --git a/lix/legacy/user-env.cc b/lix/legacy/user-env.cc index ad238622f..8fc279764 100644 --- a/lix/legacy/user-env.cc +++ b/lix/legacy/user-env.cc @@ -34,8 +34,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, /* Construct the whole top level derivation. */ StorePathSet references; - Value manifest; - state.mkList(manifest, elems.size()); + Value manifest = state.mem.newList(elems.size()); size_t n = 0; for (auto & i : elems) { /* Create a pseudo-derivation containing the name, system, @@ -58,9 +57,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, // Copy each output meant for installation. auto & vOutputs = attrs.alloc(state.s.outputs); - state.mkList(vOutputs, outputs.size()); + vOutputs = state.mem.newList(outputs.size()); for (const auto & [m, j] : enumerate(outputs)) { - (vOutputs.listElems()[m] = state.allocValue())->mkString(j.first); + (vOutputs.listElems()[m] = state.mem.allocValue())->mkString(j.first); auto outputAttrs = state.buildBindings(2); outputAttrs.alloc(state.s.outPath).mkString(state.store->printStorePath(*j.second)); attrs.alloc(j.first).mkAttrs(outputAttrs); @@ -83,7 +82,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems, attrs.alloc(state.s.meta).mkAttrs(meta); - (manifest.listElems()[n++] = state.allocValue())->mkAttrs(attrs); + (manifest.listElems()[n++] = state.mem.allocValue())->mkAttrs(attrs); if (drvPath) references.insert(*drvPath); } diff --git a/lix/libcmd/cmd-profiles.cc b/lix/libcmd/cmd-profiles.cc index a14940629..6995facee 100644 --- a/lix/libcmd/cmd-profiles.cc +++ b/lix/libcmd/cmd-profiles.cc @@ -21,7 +21,7 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv) if (pathExists(manifestFile)) { Value v; state.evalFile(CanonPath(manifestFile), v); - Bindings & bindings(*state.allocBindings(0)); + Bindings & bindings(*state.mem.allocBindings(0)); getDerivations(state, v, "", bindings, elems, false); } return elems; diff --git a/lix/libcmd/common-eval-args.cc b/lix/libcmd/common-eval-args.cc index 32866233e..c3d1bb114 100644 --- a/lix/libcmd/common-eval-args.cc +++ b/lix/libcmd/common-eval-args.cc @@ -175,7 +175,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state) { auto res = state.buildBindings(autoArgs.size()); for (auto & i : autoArgs) { - auto v = state.allocValue(); + auto v = state.mem.allocValue(); if (i.second[0] == 'E') state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), CanonPath::fromCwd())); else diff --git a/lix/libcmd/installable-flake.cc b/lix/libcmd/installable-flake.cc index 8a6e2b274..91b019b09 100644 --- a/lix/libcmd/installable-flake.cc +++ b/lix/libcmd/installable-flake.cc @@ -43,7 +43,7 @@ std::vector InstallableFlake::getActualAttrPaths() Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::LockedFlake & lockedFlake) { - auto vFlake = state.allocValue(); + auto vFlake = state.mem.allocValue(); callFlake(state, lockedFlake, *vFlake); diff --git a/lix/libcmd/installables.cc b/lix/libcmd/installables.cc index a353feb79..ab55c7cca 100644 --- a/lix/libcmd/installables.cc +++ b/lix/libcmd/installables.cc @@ -403,7 +403,7 @@ ref openEvalCache( if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0") throw Error("not everything is cached, but evaluation is not allowed"); - auto vFlake = state.allocValue(); + auto vFlake = state.mem.allocValue(); flake::callFlake(state, *lockedFlake, *vFlake); state.forceAttrs(*vFlake, noPos, "while parsing cached flake data"); @@ -438,7 +438,7 @@ Installables SourceExprCommand::parseInstallables( if (file) evalSettings.pureEval.override(false); auto state = getEvalState(); - auto vFile = state->allocValue(); + auto vFile = state->mem.allocValue(); if (file == "-") { auto & e = state->parseStdin(); diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index fdb890429..782175098 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -844,7 +844,7 @@ ProcessLineResult NixRepl::processLine(std::string line) isVarName(name = removeWhitespace(line.substr(0, p)))) { Expr & e = parseString(line.substr(p + 1)); - Value & v(*state.allocValue()); + Value & v(*state.mem.allocValue()); v.mkThunk(env, e); addVarToScope(state.symbols.create(name), v); } else { @@ -893,7 +893,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS) void NixRepl::initEnv() { - env = &state.allocEnv(envSize); + env = &state.mem.allocEnv(envSize); env->up = &state.baseEnv; displ = 0; staticEnv->vars.clear(); @@ -939,7 +939,7 @@ void NixRepl::loadReplOverlays() notice("Loading '%1%'...", Magenta("repl-overlays")); auto replInitFilesFunction = getReplOverlaysEvalFunction(); - Value &newAttrs(*state.allocValue()); + Value &newAttrs(*state.mem.allocValue()); SmallValueVector<3> args = {replInitInfo(), bindingsToAttrs(), replOverlays()}; state.callFunction( *replInitFilesFunction, @@ -964,7 +964,7 @@ Value * NixRepl::getReplOverlaysEvalFunction() } auto evalReplInitFilesPath = CanonPath::root + "repl-overlays.nix"; - *replOverlaysEvalFunction = state.allocValue(); + *replOverlaysEvalFunction = state.mem.allocValue(); auto code = #include "repl-overlays.nix.gen.hh" ; @@ -981,8 +981,8 @@ Value * NixRepl::getReplOverlaysEvalFunction() Value * NixRepl::replOverlays() { - Value * replInits(state.allocValue()); - state.mkList(*replInits, evalSettings.replOverlays.get().size()); + Value * replInits(state.mem.allocValue()); + *replInits = state.mem.newList(evalSettings.replOverlays.get().size()); Value ** replInitElems = replInits->listElems(); size_t i = 0; @@ -1024,11 +1024,11 @@ Value * NixRepl::replInitInfo() { auto builder = state.buildBindings(2); - Value * currentSystem(state.allocValue()); + Value * currentSystem(state.mem.allocValue()); currentSystem->mkString(evalSettings.getCurrentSystem()); builder.insert(state.symbols.create("currentSystem"), currentSystem); - Value * info(state.allocValue()); + Value * info(state.mem.allocValue()); info->mkAttrs(builder.finish()); return info; } @@ -1070,7 +1070,7 @@ Value * NixRepl::bindingsToAttrs() builder.insert(symbol, env->values[displacement]); } - Value * attrs(state.allocValue()); + Value * attrs(state.mem.allocValue()); attrs->mkAttrs(builder.finish()); return attrs; } @@ -1092,7 +1092,7 @@ void NixRepl::evalString(std::string s, Value & v) Value * NixRepl::evalFile(SourcePath & path) { auto & expr = state.parseExprFromFile(path, staticEnv); - Value * result(state.allocValue()); + Value * result(state.mem.allocValue()); expr.eval(state, *env, *result); state.forceValue(*result, result->determinePos(noPos)); return result; diff --git a/lix/libexpr/attr-path.cc b/lix/libexpr/attr-path.cc index bc2bc1558..23de3923b 100644 --- a/lix/libexpr/attr-path.cc +++ b/lix/libexpr/attr-path.cc @@ -54,7 +54,7 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin auto attrIndex = string2Int(attr); /* Evaluate the expression. */ - Value * vNew = state.allocValue(); + Value * vNew = state.mem.allocValue(); state.autoCallFunction(autoArgs, *v, *vNew); v = vNew; state.forceValue(*v, noPos); @@ -109,7 +109,7 @@ std::pair findPackageFilename(EvalState & state, Value & v { Value * v2; try { - auto dummyArgs = state.allocBindings(0); + auto dummyArgs = state.mem.allocBindings(0); v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v).first; } catch (Error &) { throw NoPositionInfo("package '%s' has no source location information", what); diff --git a/lix/libexpr/attr-set.cc b/lix/libexpr/attr-set.cc index 8097d4bbb..c6ebde076 100644 --- a/lix/libexpr/attr-set.cc +++ b/lix/libexpr/attr-set.cc @@ -13,21 +13,21 @@ Bindings Bindings::EMPTY{0}; /* Allocate a new array of attributes for an attribute set with a specific capacity. The space is implicitly reserved after the Bindings structure. */ -Bindings * EvalState::allocBindings(size_t capacity) +Bindings * EvalMemory::allocBindings(size_t capacity) { if (capacity == 0) return &Bindings::EMPTY; if (capacity > std::numeric_limits::max()) throw Error("attribute set of size %d is too big", capacity); - nrAttrsets++; - nrAttrsInAttrsets += capacity; + stats.nrAttrsets++; + stats.nrAttrsInAttrsets += capacity; return new (gcAllocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity); } Value & BindingsBuilder::alloc(Symbol name, PosIdx pos) { - auto value = state.allocValue(); + auto value = mem.allocValue(); bindings->push_back(Attr(name, value, pos)); return *value; } @@ -35,7 +35,7 @@ Value & BindingsBuilder::alloc(Symbol name, PosIdx pos) Value & BindingsBuilder::alloc(std::string_view name, PosIdx pos) { - return alloc(state.symbols.create(name), pos); + return alloc(symbols.create(name), pos); } diff --git a/lix/libexpr/attr-set.hh b/lix/libexpr/attr-set.hh index f25d1545e..f5ab8dad0 100644 --- a/lix/libexpr/attr-set.hh +++ b/lix/libexpr/attr-set.hh @@ -10,7 +10,7 @@ namespace nix { -class EvalState; +class EvalMemory; struct Value; /** @@ -117,7 +117,7 @@ public: return res; } - friend class EvalState; + friend class EvalMemory; }; /** @@ -128,15 +128,17 @@ public: class BindingsBuilder { Bindings * bindings; + EvalMemory & mem; + SymbolTable & symbols; public: // needed by std::back_inserter using value_type = Attr; - EvalState & state; - - BindingsBuilder(EvalState & state, Bindings * bindings) - : bindings(bindings), state(state) + BindingsBuilder(EvalMemory & mem, SymbolTable & symbols, Bindings * bindings) + : bindings(bindings) + , mem(mem) + , symbols(symbols) { } void insert(Symbol name, Value * value, PosIdx pos = noPos) diff --git a/lix/libexpr/eval-inline.hh b/lix/libexpr/eval-inline.hh index d29349362..07605f6b7 100644 --- a/lix/libexpr/eval-inline.hh +++ b/lix/libexpr/eval-inline.hh @@ -9,7 +9,7 @@ namespace nix { [[gnu::always_inline]] -Value * EvalState::allocValue() +Value * EvalMemory::allocValue() { #if HAVE_BOEHMGC /* We use the boehm batch allocator to speed up allocations of Values (of which there are many). @@ -30,16 +30,16 @@ Value * EvalState::allocValue() void * p = gcAllocBytes(sizeof(Value)); #endif - nrValues++; + stats.nrValues++; return static_cast(p); } [[gnu::always_inline]] -Env & EvalState::allocEnv(size_t size) +Env & EvalMemory::allocEnv(size_t size) { - nrEnvs++; - nrValuesInEnvs += size; + stats.nrEnvs++; + stats.nrValuesInEnvs += size; Env * env; diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 62d554c39..8539510a1 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -253,6 +253,15 @@ StaticSymbols::StaticSymbols(SymbolTable & symbols) { } +EvalMemory::EvalMemory() +#if HAVE_BOEHMGC + : valueAllocCache(std::allocate_shared(traceable_allocator(), nullptr)) + , env1AllocCache(std::allocate_shared(traceable_allocator(), nullptr)) +#endif +{ + assert(libexprInitialised); +} + EvalState::EvalState( const SearchPath & _searchPath, ref store, @@ -263,17 +272,11 @@ EvalState::EvalState( , store(store) , buildStore(buildStore ? buildStore : store) , regexCache(makeRegexCache()) -#if HAVE_BOEHMGC - , valueAllocCache(std::allocate_shared(traceable_allocator(), nullptr)) - , env1AllocCache(std::allocate_shared(traceable_allocator(), nullptr)) -#endif - , baseEnv(allocEnv(128)) + , baseEnv(mem.allocEnv(128)) , staticBaseEnv{std::make_shared(nullptr, nullptr)} { countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; - assert(libexprInitialised); - static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes"); /* Initialise the Nix expression search path. */ @@ -426,7 +429,7 @@ Path EvalState::toRealPath(const Path & path, const NixStringContext & context) Value * EvalState::addConstant(const std::string & name, const Value & v, Constant info) { - Value * v2 = allocValue(); + Value * v2 = mem.allocValue(); *v2 = v; addConstant(name, v2, info); return v2; @@ -475,7 +478,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp) the primop to a dummy value. */ if (primOp.arity == 0) { primOp.arity = 1; - auto vPrimOp = allocValue(); + auto vPrimOp = mem.allocValue(); vPrimOp->mkPrimOp(new PrimOp(primOp)); Value v; v.mkApp(vPrimOp, vPrimOp); @@ -489,7 +492,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp) if (primOp.name.starts_with("__")) primOp.name = primOp.name.substr(2); - Value * v = allocValue(); + Value * v = mem.allocValue(); v->mkPrimOp(new PrimOp(primOp)); staticBaseEnv->vars.emplace_back(envName, baseEnvDispl); baseEnv.values[baseEnvDispl++] = v; @@ -760,12 +763,14 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval) } } -void EvalState::mkList(Value & v, size_t size) +Value EvalMemory::newList(size_t size) { + Value v; v.mkList(size); if (size > 2) v.bigList.elems = gcAllocType(size); - nrListElems += size; + stats.nrListElems += size; + return v; } @@ -878,7 +883,7 @@ void EvalState::mkSingleDerivedPathString( of thunks allocated. */ Value * Expr::maybeThunk(EvalState & state, Env & env) { - Value * v = state.allocValue(); + Value * v = state.mem.allocValue(); mkThunk(*v, env, *this); return v; } @@ -1064,7 +1069,7 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v) Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up) { - Env & inheritEnv = state.allocEnv(inheritFromExprs->size()); + Env & inheritEnv = state.mem.allocEnv(inheritFromExprs->size()); inheritEnv.up = &up; Displacement displ = 0; @@ -1082,7 +1087,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) if (recursive) { /* Create a new environment that contains the attributes in this `rec'. */ - Env & env2(state.allocEnv(attrs.size())); + Env & env2(state.mem.allocEnv(attrs.size())); env2.up = &env; dynamicEnv = &env2; Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr; @@ -1097,7 +1102,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) for (auto & i : attrs) { Value * vAttr; if (hasOverrides && i.second.kind != AttrDef::Kind::Inherited) { - vAttr = state.allocValue(); + vAttr = state.mem.allocValue(); mkThunk(*vAttr, *i.second.chooseByKind(&env2, &env, inheritEnv), *i.second.e); } else vAttr = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv)); @@ -1116,7 +1121,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) if (hasOverrides) { Value * vOverrides = (*v.attrs)[overrides->second.displ].value; state.forceAttrs(*vOverrides, [&]() { return vOverrides->determinePos(noPos); }, "while evaluating the `__overrides` attribute"); - Bindings * newBnds = state.allocBindings(v.attrs->capacity() + vOverrides->attrs->size()); + Bindings * newBnds = state.mem.allocBindings(v.attrs->capacity() + vOverrides->attrs->size()); for (auto & i : *v.attrs) newBnds->push_back(i); for (auto & i : *vOverrides->attrs) { @@ -1169,7 +1174,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) { /* Create a new environment that contains the attributes in this `let'. */ - Env & env2(state.allocEnv(attrs->attrs.size())); + Env & env2(state.mem.allocEnv(attrs->attrs.size())); env2.up = &env; Env * inheritEnv = attrs->inheritFromExprs ? attrs->buildInheritFromEnv(state, env2) : nullptr; @@ -1203,7 +1208,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) void ExprList::eval(EvalState & state, Env & env, Value & v) { - state.mkList(v, elems.size()); + v = state.mem.newList(elems.size()); for (auto [n, v2] : enumerate(v.listItems())) const_cast(v2) = elems[n]->maybeThunk(state, env); } @@ -1511,7 +1516,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & { vRes = vCur; for (size_t i = 0; i < nrArgs; ++i) { - auto fun2 = allocValue(); + auto fun2 = mem.allocValue(); *fun2 = vRes; vRes.mkPrimOpApp(fun2, args[i]); } @@ -1528,7 +1533,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & auto size = (!lambda.arg ? 0 : 1) + (lambda.hasFormals() ? lambda.formals->formals.size() : 0); - Env & env2(allocEnv(size)); + Env & env2(mem.allocEnv(size)); env2.up = vCur.lambda.env; Displacement displ = 0; @@ -1699,7 +1704,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & /* 'vCur' may be allocated on the stack of the calling function, but for functors we may keep a reference, so heap-allocate a copy and use that instead. */ - Value * args2[] = {allocValue(), args[0]}; + Value * args2[] = {mem.allocValue(), args[0]}; *args2[0] = vCur; try { callFunction(*functor->value, 2, args2, vCur, functor->pos); @@ -1772,7 +1777,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res) if (fun.type() == nAttrs) { auto found = fun.attrs->find(s.functor); if (found != fun.attrs->end()) { - Value * v = allocValue(); + Value * v = mem.allocValue(); callFunction(*found->value, fun, *v, pos); forceValue(*v, pos); return autoCallFunction(args, *v, res); @@ -1809,13 +1814,13 @@ https://docs.lix.systems/manual/lix/stable/language/constructs.html#functions)", } } - callFunction(fun, allocValue()->mkAttrs(attrs), res, pos); + callFunction(fun, mem.allocValue()->mkAttrs(attrs), res, pos); } void ExprWith::eval(EvalState & state, Env & env, Value & v) { - Env & env2(state.allocEnv(1)); + Env & env2(state.mem.allocEnv(1)); env2.up = &env; env2.values[0] = attrs->maybeThunk(state, env); @@ -1946,7 +1951,7 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Po return; } - mkList(v, len); + v = mem.newList(len); auto out = v.listElems(); for (size_t n = 0, pos = 0; n < nrLists; ++n) { auto l = lists[n]->listSize(); @@ -2577,11 +2582,12 @@ void EvalState::printStatistics() struct rusage buf; getrusage(RUSAGE_SELF, &buf); float cpuTime = buf.ru_utime.tv_sec + ((float) buf.ru_utime.tv_usec / 1000000); + auto mem = this->mem.getStats(); - uint64_t bEnvs = nrEnvs * sizeof(Env) + nrValuesInEnvs * sizeof(Value *); - uint64_t bLists = nrListElems * sizeof(Value *); - uint64_t bValues = nrValues * sizeof(Value); - uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr); + uint64_t bEnvs = mem.nrEnvs * sizeof(Env) + mem.nrValuesInEnvs * sizeof(Value *); + uint64_t bLists = mem.nrListElems * sizeof(Value *); + uint64_t bValues = mem.nrValues * sizeof(Value); + uint64_t bAttrsets = mem.nrAttrsets * sizeof(Bindings) + mem.nrAttrsInAttrsets * sizeof(Attr); #if HAVE_BOEHMGC GC_word heapSize, totalBytes; @@ -2595,17 +2601,17 @@ void EvalState::printStatistics() json topObj = json::object(); topObj["cpuTime"] = cpuTime; topObj["envs"] = { - {"number", nrEnvs}, - {"elements", nrValuesInEnvs}, + {"number", mem.nrEnvs}, + {"elements", mem.nrValuesInEnvs}, {"bytes", bEnvs}, }; topObj["list"] = { - {"elements", nrListElems}, + {"elements", mem.nrListElems}, {"bytes", bLists}, {"concats", nrListConcats}, }; topObj["values"] = { - {"number", nrValues}, + {"number", mem.nrValues}, {"bytes", bValues}, }; topObj["symbols"] = { @@ -2613,9 +2619,9 @@ void EvalState::printStatistics() {"bytes", symbols.totalSize()}, }; topObj["sets"] = { - {"number", nrAttrsets}, + {"number", mem.nrAttrsets}, {"bytes", bAttrsets}, - {"elements", nrAttrsInAttrsets}, + {"elements", mem.nrAttrsInAttrsets}, }; topObj["sizes"] = { {"Env", sizeof(Env)}, diff --git a/lix/libexpr/eval.hh b/lix/libexpr/eval.hh index acc184b7b..55d3aa44f 100644 --- a/lix/libexpr/eval.hh +++ b/lix/libexpr/eval.hh @@ -227,6 +227,55 @@ struct StaticSymbols explicit StaticSymbols(SymbolTable & symbols); }; +class EvalMemory +{ +#if HAVE_BOEHMGC + /** + * Allocation cache for GC'd Value objects. + */ + std::shared_ptr valueAllocCache; + + /** + * Allocation cache for size-1 Env objects. + */ + std::shared_ptr env1AllocCache; +#endif + +public: + struct Statistics + { + unsigned long nrEnvs = 0; + unsigned long nrValuesInEnvs = 0; + unsigned long nrValues = 0; + unsigned long nrAttrsets = 0; + unsigned long nrAttrsInAttrsets = 0; + unsigned long nrListElems = 0; + }; + + EvalMemory(); + + EvalMemory(const EvalMemory &) = delete; + EvalMemory(EvalMemory &&) = delete; + EvalMemory & operator=(const EvalMemory &) = delete; + EvalMemory & operator=(EvalMemory &&) = delete; + + inline Value * allocValue(); + inline Env & allocEnv(size_t size); + + Bindings * allocBindings(size_t capacity); + Value newList(size_t length); + + BindingsBuilder buildBindings(SymbolTable & symbols, size_t capacity) + { + return BindingsBuilder(*this, symbols, allocBindings(capacity)); + } + + const Statistics getStats() const { return stats; } + +private: + Statistics stats; +}; + class EvalState { @@ -234,6 +283,7 @@ public: SymbolTable symbols; PosTable positions; const StaticSymbols s; + EvalMemory mem; /** * If set, force copying files to the Nix store even if they @@ -308,18 +358,6 @@ private: */ std::shared_ptr regexCache; -#if HAVE_BOEHMGC - /** - * Allocation cache for GC'd Value objects. - */ - std::shared_ptr valueAllocCache; - - /** - * Allocation cache for size-1 Env objects. - */ - std::shared_ptr env1AllocCache; -#endif - public: EvalState( @@ -638,20 +676,11 @@ public: */ void autoCallFunction(Bindings & args, Value & fun, Value & res); - /** - * Allocation primitives. - */ - inline Value * allocValue(); - inline Env & allocEnv(size_t size); - - Bindings * allocBindings(size_t capacity); - BindingsBuilder buildBindings(size_t capacity) { - return BindingsBuilder(*this, allocBindings(capacity)); + return mem.buildBindings(symbols, capacity); } - void mkList(Value & v, size_t length); void mkThunk_(Value & v, Expr & expr); void mkPos(Value & v, PosIdx pos); @@ -745,13 +774,7 @@ private: std::string mkSingleDerivedPathStringRaw( const SingleDerivedPath & p); - unsigned long nrEnvs = 0; - unsigned long nrValuesInEnvs = 0; - unsigned long nrValues = 0; - unsigned long nrListElems = 0; unsigned long nrLookups = 0; - unsigned long nrAttrsets = 0; - unsigned long nrAttrsInAttrsets = 0; unsigned long nrAvoided = 0; unsigned long nrOpUpdates = 0; unsigned long nrOpUpdateValuesCopied = 0; diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index b9b6139b3..c18252a90 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -765,11 +765,11 @@ void callFlake(EvalState & state, const LockedFlake & lockedFlake, Value & vRes) { - auto vLocks = state.allocValue(); - auto vRootSrc = state.allocValue(); - auto vRootSubdir = state.allocValue(); - auto vTmp1 = state.allocValue(); - auto vTmp2 = state.allocValue(); + auto vLocks = state.mem.allocValue(); + auto vRootSrc = state.mem.allocValue(); + auto vRootSubdir = state.mem.allocValue(); + auto vTmp1 = state.mem.allocValue(); + auto vTmp2 = state.mem.allocValue(); vLocks->mkString(lockedFlake.lockFile.to_string()); @@ -784,7 +784,7 @@ void callFlake(EvalState & state, vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir); if (!state.vCallFlake) { - state.vCallFlake = allocRootValue(state.allocValue()); + state.vCallFlake = allocRootValue(state.mem.allocValue()); state.eval(state.parseExprFromString( #include "call-flake.nix.gen.hh" , CanonPath::root), **state.vCallFlake); diff --git a/lix/libexpr/json-to-value.cc b/lix/libexpr/json-to-value.cc index 985c10155..f5ab9c186 100644 --- a/lix/libexpr/json-to-value.cc +++ b/lix/libexpr/json-to-value.cc @@ -28,7 +28,7 @@ class JSONSax : nlohmann::json_sax { Value & value(EvalState & state) { if (!v) - v = allocRootValue(state.allocValue()); + v = allocRootValue(state.mem.allocValue()); return **v; } virtual ~JSONState() {} @@ -59,7 +59,7 @@ class JSONSax : nlohmann::json_sax { std::unique_ptr resolve(EvalState & state) override { Value & v = parent->value(state); - state.mkList(v, values.size()); + v = state.mem.newList(values.size()); for (size_t n = 0; n < values.size(); ++n) { v.listElems()[n] = values[n]; } diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index c20c38722..c57745526 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -196,18 +196,18 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v }); attrs.alloc(state.s.name).mkString(drv.env["name"]); auto & outputsVal = attrs.alloc(state.s.outputs); - state.mkList(outputsVal, drv.outputs.size()); + outputsVal = state.mem.newList(drv.outputs.size()); for (const auto & [i, o] : enumerate(drv.outputs)) { mkOutputString(state, attrs, *storePath, o); - (outputsVal.listElems()[i] = state.allocValue())->mkString(o.first); + (outputsVal.listElems()[i] = state.mem.allocValue())->mkString(o.first); } - auto w = state.allocValue(); + auto w = state.mem.allocValue(); w->mkAttrs(attrs); if (!state.vImportedDrvToDerivation) { - state.vImportedDrvToDerivation = allocRootValue(state.allocValue()); + state.vImportedDrvToDerivation = allocRootValue(state.mem.allocValue()); state.eval(state.parseExprFromString( #include "imported-drv-to-derivation.nix.gen.hh" , CanonPath::root), **state.vImportedDrvToDerivation); @@ -230,7 +230,7 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v else { state.forceAttrs(*vScope, pos, "while evaluating the first argument passed to builtins.scopedImport"); - Env * env = &state.allocEnv(vScope->attrs->size()); + Env * env = &state.mem.allocEnv(vScope->attrs->size()); env->up = &state.baseEnv; auto staticEnv = std::make_shared(nullptr, state.staticBaseEnv.get(), vScope->attrs->size()); @@ -557,7 +557,7 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a } /* Create the result list. */ - state.mkList(v, res.size()); + v = state.mem.newList(res.size()); unsigned int n = 0; for (auto & i : res) v.listElems()[n++] = i; @@ -1372,7 +1372,7 @@ static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Va // Some filesystems or operating systems may not be able to return // detailed node info quickly in this case we produce a thunk to // query the file type lazily. - auto epath = state.allocValue(); + auto epath = state.mem.allocValue(); epath->mkPath(path + name); if (!readFileType) readFileType = &state.getBuiltin("readFileType"); @@ -1616,11 +1616,11 @@ static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args, { state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.attrNames"); - state.mkList(v, args[0]->attrs->size()); + v = state.mem.newList(args[0]->attrs->size()); size_t n = 0; for (auto & i : *args[0]->attrs) - (v.listElems()[n++] = state.allocValue())->mkString(state.symbols[i.name]); + (v.listElems()[n++] = state.mem.allocValue())->mkString(state.symbols[i.name]); std::sort(v.listElems(), v.listElems() + n, [](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; }); @@ -1632,7 +1632,7 @@ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args, { state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.attrValues"); - state.mkList(v, args[0]->attrs->size()); + v = state.mem.newList(args[0]->attrs->size()); // FIXME: this is incredibly evil, *why* // NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast) @@ -1723,7 +1723,7 @@ static struct LazyPosAcessors { void operator()(EvalState & state, const PosIdx pos, Value & line, Value & column) { - Value * posV = state.allocValue(); + Value * posV = state.mem.allocValue(); posV->mkInt(pos.id); line.mkApp(&lineOfPos, posV); column.mkApp(&columnOfPos, posV); @@ -1889,7 +1889,7 @@ static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, V res[found++] = i->value; } - state.mkList(v, found); + v = state.mem.newList(found); for (unsigned int n = 0; n < found; ++n) v.listElems()[n] = res[n]; } @@ -1924,8 +1924,8 @@ static void prim_mapAttrs(EvalState & state, const PosIdx pos, Value * * args, V auto attrs = state.buildBindings(args[1]->attrs->size()); for (auto & i : *args[1]->attrs) { - Value * vName = state.allocValue(); - Value * vFun2 = state.allocValue(); + Value * vName = state.mem.allocValue(); + Value * vFun2 = state.mem.allocValue(); vName->mkString(state.symbols[i.name]); vFun2->mkApp(args[0], vName); attrs.alloc(i.name).mkApp(vFun2, i.value); @@ -1960,7 +1960,7 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg auto attrs = state.buildBindings(attrsSeen.size()); for (auto & [sym, elem] : attrsSeen) { auto & list = attrs.alloc(sym); - state.mkList(list, elem.first); + list = state.mem.newList(elem.first); elem.second = list.listElems(); } v.mkAttrs(attrs.alreadySorted()); @@ -1972,11 +1972,11 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg } for (auto & attr : *v.attrs) { - auto name = state.allocValue(); + auto name = state.mem.allocValue(); name->mkString(state.symbols[attr.name]); - auto call1 = state.allocValue(); + auto call1 = state.mem.allocValue(); call1->mkApp(args[0], name); - auto call2 = state.allocValue(); + auto call2 = state.mem.allocValue(); call2->mkApp(call1, attr.value); attr.value = call2; } @@ -2029,7 +2029,7 @@ static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value if (args[0]->listSize() == 0) state.error("'tail' called on an empty list").atPos(pos).debugThrow(); - state.mkList(v, args[0]->listSize() - 1); + v = state.mem.newList(args[0]->listSize() - 1); for (unsigned int n = 0; n < v.listSize(); ++n) v.listElems()[n] = args[0]->listElems()[n + 1]; } @@ -2046,9 +2046,9 @@ static void prim_map(EvalState & state, const PosIdx pos, Value * * args, Value state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.map"); - state.mkList(v, args[1]->listSize()); + v = state.mem.newList(args[1]->listSize()); for (unsigned int n = 0; n < v.listSize(); ++n) - (v.listElems()[n] = state.allocValue())->mkApp( + (v.listElems()[n] = state.mem.allocValue())->mkApp( args[0], args[1]->listElems()[n]); } @@ -2082,7 +2082,7 @@ static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Val if (same) v = *args[1]; else { - state.mkList(v, k); + v = state.mem.newList(k); for (unsigned int n = 0; n < k; ++n) v.listElems()[n] = vs[n]; } } @@ -2126,7 +2126,7 @@ static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value * * args for (auto [n, elem] : enumerate(args[2]->listItems())) { Value * vs []{vCur, elem}; - vCur = n == args[2]->listSize() - 1 ? &v : state.allocValue(); + vCur = n == args[2]->listSize() - 1 ? &v : state.mem.allocValue(); state.callFunction(*args[0], 2, vs, *vCur, pos); } state.forceValue(v, pos); @@ -2182,11 +2182,11 @@ static void prim_genList(EvalState & state, const PosIdx pos, Value * * args, Va // as evaluating map without accessing any values makes little sense. state.forceFunction(*args[0], noPos, "while evaluating the first argument passed to builtins.genList"); - state.mkList(v, len); + v = state.mem.newList(len); for (size_t n = 0; n < len; ++n) { - auto arg = state.allocValue(); + auto arg = state.mem.allocValue(); arg->mkInt(n); - (v.listElems()[n] = state.allocValue())->mkApp(args[0], arg); + (v.listElems()[n] = state.mem.allocValue())->mkApp(args[0], arg); } } @@ -2205,7 +2205,7 @@ static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.sort"); - state.mkList(v, len); + v = state.mem.newList(len); for (unsigned int n = 0; n < len; ++n) { state.forceValue(*args[1]->listElems()[n], pos); v.listElems()[n] = args[1]->listElems()[n]; @@ -2258,13 +2258,13 @@ static void prim_partition(EvalState & state, const PosIdx pos, Value * * args, auto & vRight = attrs.alloc(state.s.right); auto rsize = right.size(); - state.mkList(vRight, rsize); + vRight = state.mem.newList(rsize); if (rsize) memcpy(vRight.listElems(), right.data(), sizeof(Value *) * rsize); auto & vWrong = attrs.alloc(state.s.wrong); auto wsize = wrong.size(); - state.mkList(vWrong, wsize); + vWrong = state.mem.newList(wsize); if (wsize) memcpy(vWrong.listElems(), wrong.data(), sizeof(Value *) * wsize); @@ -2292,7 +2292,7 @@ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Va for (auto & i : attrs) { auto & list = attrs2.alloc(i.first); auto size = i.second.size(); - state.mkList(list, size); + list = state.mem.newList(size); memcpy(list.listElems(), i.second.data(), sizeof(Value *) * size); } @@ -2316,7 +2316,7 @@ static void prim_concatMap(EvalState & state, const PosIdx pos, Value * * args, len += lists[n].listSize(); } - state.mkList(v, len); + v = state.mem.newList(len); auto out = v.listElems(); for (unsigned int n = 0, pos = 0; n < nrLists; ++n) { auto l = lists[n].listSize(); @@ -2565,12 +2565,12 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) // the first match is the whole string const size_t len = match.size() - 1; - state.mkList(v, len); + v = state.mem.newList(len); for (size_t i = 0; i < len; ++i) { if (!match[i+1].matched) - (v.listElems()[i] = state.allocValue())->mkNull(); + (v.listElems()[i] = state.mem.allocValue())->mkNull(); else - (v.listElems()[i] = state.allocValue())->mkString(match[i + 1].str()); + (v.listElems()[i] = state.mem.allocValue())->mkString(match[i + 1].str()); } } catch (std::regex_error & e) { @@ -2604,7 +2604,7 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) // Any matches results are surrounded by non-matching results. const size_t len = std::distance(begin, end); - state.mkList(v, 2 * len + 1); + v = state.mem.newList(2 * len + 1); size_t idx = 0; if (len == 0) { @@ -2617,24 +2617,24 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) auto match = *i; // Add a string for non-matched characters. - (v.listElems()[idx++] = state.allocValue())->mkString(match.prefix().str()); + (v.listElems()[idx++] = state.mem.allocValue())->mkString(match.prefix().str()); // Add a list for matched substrings. const size_t slen = match.size() - 1; - auto elem = v.listElems()[idx++] = state.allocValue(); + auto elem = v.listElems()[idx++] = state.mem.allocValue(); // Start at 1, beacause the first match is the whole string. - state.mkList(*elem, slen); + *elem = state.mem.newList(slen); for (size_t si = 0; si < slen; ++si) { if (!match[si + 1].matched) - (elem->listElems()[si] = state.allocValue())->mkNull(); + (elem->listElems()[si] = state.mem.allocValue())->mkNull(); else - (elem->listElems()[si] = state.allocValue())->mkString(match[si + 1].str()); + (elem->listElems()[si] = state.mem.allocValue())->mkString(match[si + 1].str()); } // Add a string for non-matched suffix characters. if (idx == 2 * len) - (v.listElems()[idx++] = state.allocValue())->mkString(match.suffix().str()); + (v.listElems()[idx++] = state.mem.allocValue())->mkString(match.suffix().str()); } assert(idx == 2 * len + 1); @@ -2764,9 +2764,9 @@ static void prim_splitVersion(EvalState & state, const PosIdx pos, Value * * arg break; components.emplace_back(component); } - state.mkList(v, components.size()); + v = state.mem.newList(components.size()); for (const auto & [n, component] : enumerate(components)) - (v.listElems()[n] = state.allocValue())->mkString(std::move(component)); + (v.listElems()[n] = state.mem.allocValue())->mkString(std::move(component)); } @@ -2788,13 +2788,13 @@ RegisterPrimOp::RegisterPrimOp(PrimOp && primOp) static Value getNixPath(EvalState & state, SearchPath & searchPath) { Value v; - state.mkList(v, searchPath.elements.size()); + v = state.mem.newList(searchPath.elements.size()); int n = 0; for (auto & i : searchPath.elements) { auto attrs = state.buildBindings(2); attrs.alloc("path").mkString(i.path.s); attrs.alloc("prefix").mkString(i.prefix.s); - (v.listElems()[n++] = state.allocValue())->mkAttrs(attrs); + (v.listElems()[n++] = state.mem.allocValue())->mkAttrs(attrs); } return v; } @@ -2835,7 +2835,7 @@ void EvalState::createBaseEnv() Null docs because it is documented separately. */ - auto vDerivation = allocValue(); + auto vDerivation = mem.allocValue(); addConstant("derivation", vDerivation, { .type = nFunction, }); diff --git a/lix/libexpr/primops/context.cc b/lix/libexpr/primops/context.cc index c4a33b4f6..9e8fe79e4 100644 --- a/lix/libexpr/primops/context.cc +++ b/lix/libexpr/primops/context.cc @@ -149,9 +149,9 @@ void prim_getContext(EvalState & state, const PosIdx pos, Value * * args, Value infoAttrs.alloc(sAllOutputs).mkBool(true); if (!info.second.outputs.empty()) { auto & outputsVal = infoAttrs.alloc(state.s.outputs); - state.mkList(outputsVal, info.second.outputs.size()); + outputsVal = state.mem.newList(info.second.outputs.size()); for (const auto & [i, output] : enumerate(info.second.outputs)) - (outputsVal.listElems()[i] = state.allocValue())->mkString(output); + (outputsVal.listElems()[i] = state.mem.allocValue())->mkString(output); } attrs.alloc(state.store->printStorePath(info.first)).mkAttrs(infoAttrs); } diff --git a/lix/libexpr/primops/fromTOML.cc b/lix/libexpr/primops/fromTOML.cc index f9c8f6fe0..83f9052c4 100644 --- a/lix/libexpr/primops/fromTOML.cc +++ b/lix/libexpr/primops/fromTOML.cc @@ -39,9 +39,9 @@ void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, Value & auto array = toml::get>(t); size_t size = array.size(); - state.mkList(v, size); + v = state.mem.newList(size); for (size_t i = 0; i < size; ++i) - visit(*(v.listElems()[i] = state.allocValue()), array[i]); + visit(*(v.listElems()[i] = state.mem.allocValue()), array[i]); } break;; case toml::value_t::boolean: diff --git a/lix/nix/bundle.cc b/lix/nix/bundle.cc index badcdd69c..2c012e3a8 100644 --- a/lix/nix/bundle.cc +++ b/lix/nix/bundle.cc @@ -90,7 +90,7 @@ struct CmdBundle : InstallableCommand lockFlags }; - auto vRes = evalState->allocValue(); + auto vRes = evalState->mem.allocValue(); evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos); if (!evalState->isDerivation(*vRes)) diff --git a/lix/nix/eval.cc b/lix/nix/eval.cc index d99382516..bbd866ddb 100644 --- a/lix/nix/eval.cc +++ b/lix/nix/eval.cc @@ -67,9 +67,9 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption NixStringContext context; if (apply) { - auto vApply = state->allocValue(); + auto vApply = state->mem.allocValue(); state->eval(state->parseExprFromString(*apply, CanonPath::fromCwd()), *vApply); - auto vRes = state->allocValue(); + auto vRes = state->mem.allocValue(); state->callFunction(*vApply, *v, *vRes, noPos); v = vRes; } diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 75a7fe6bf..1f581af41 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -520,7 +520,7 @@ struct CmdFlakeCheck : FlakeCommand try { Activity act(*logger, lvlInfo, actUnknown, fmt("checking NixOS configuration '%s'", attrPath)); - Bindings & bindings(*state->allocBindings(0)); + Bindings & bindings(*state->mem.allocBindings(0)); auto vToplevel = findAlongAttrPath(*state, "config.system.build.toplevel", bindings, v).first; state->forceValue(*vToplevel, pos); if (!state->isDerivation(*vToplevel)) @@ -582,7 +582,7 @@ struct CmdFlakeCheck : FlakeCommand { Activity act(*logger, lvlInfo, actUnknown, "evaluating flake"); - auto vFlake = state->allocValue(); + auto vFlake = state->mem.allocValue(); flake::callFlake(*state, flake, *vFlake); enumerateOutputs(*state, diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 2de7c0105..6047a8e17 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -256,12 +256,12 @@ static void showHelp(std::vector subcommand, NixArgs & toplevel) evalSettings.pureEval.override(false); EvalState state({}, openStore("dummy://")); - auto vGenerateManpage = state.allocValue(); + auto vGenerateManpage = state.mem.allocValue(); state.eval(state.parseExprFromString( #include "generate-manpage.nix.gen.hh" , CanonPath::root), *vGenerateManpage); - auto vUtils = state.allocValue(); + auto vUtils = state.mem.allocValue(); state.cacheFile( CanonPath("/utils.nix"), CanonPath("/utils.nix"), &state.parseExprFromString( @@ -269,10 +269,10 @@ static void showHelp(std::vector subcommand, NixArgs & toplevel) , CanonPath::root), *vUtils); - auto vDump = state.allocValue(); + auto vDump = state.mem.allocValue(); vDump->mkString(toplevel.dumpCli()); - auto vRes = state.allocValue(); + auto vRes = state.mem.allocValue(); state.callFunction(*vGenerateManpage, state.getBuiltin("false"), *vRes, noPos); state.callFunction(*vRes, *vDump, *vRes, noPos); diff --git a/lix/nix/repl.cc b/lix/nix/repl.cc index 8e37ccbf7..01458b883 100644 --- a/lix/nix/repl.cc +++ b/lix/nix/repl.cc @@ -75,7 +75,7 @@ struct CmdRepl : RawInstallablesCommand auto what = installable.what(); state->forceValue(*val, pos); auto autoArgs = getAutoArgs(*state); - auto valPost = state->allocValue(); + auto valPost = state->mem.allocValue(); state->autoCallFunction(*autoArgs, *val, *valPost); state->forceValue(*valPost, pos); values.push_back( {valPost, what }); diff --git a/lix/nix/upgrade-nix.cc b/lix/nix/upgrade-nix.cc index 85d34732a..789926048 100644 --- a/lix/nix/upgrade-nix.cc +++ b/lix/nix/upgrade-nix.cc @@ -289,9 +289,9 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand auto data = content->drain(); auto state = std::make_unique(SearchPath{}, store); - auto v = state->allocValue(); + auto v = state->mem.allocValue(); state->eval(state->parseExprFromString(data, CanonPath("/no-such-path")), *v); - Bindings & bindings(*state->allocBindings(0)); + Bindings & bindings(*state->mem.allocBindings(0)); auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; return store->parseStorePath(state->forceString(*v2, noPos, "while evaluating the path tho latest nix version")); diff --git a/tests/unit/libexpr/derived-path.cc b/tests/unit/libexpr/derived-path.cc index d5fc6f201..6bc6a59e4 100644 --- a/tests/unit/libexpr/derived-path.cc +++ b/tests/unit/libexpr/derived-path.cc @@ -25,7 +25,7 @@ RC_GTEST_FIXTURE_PROP( prop_opaque_path_round_trip, (const SingleDerivedPath::Opaque & o)) { - auto * v = state.allocValue(); + auto * v = state.mem.allocValue(); state.mkStorePathString(o.path, *v); auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); RC_ASSERT(SingleDerivedPath { o } == d); @@ -46,7 +46,7 @@ RC_GTEST_FIXTURE_PROP( ExperimentalFeatureSettings mockXpSettings; mockXpSettings.set("experimental-features", "ca-derivations"); - auto * v = state.allocValue(); + auto * v = state.mem.allocValue(); state.mkOutputString(*v, b, std::nullopt, mockXpSettings); auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); RC_ASSERT(SingleDerivedPath { b } == d); @@ -57,7 +57,7 @@ RC_GTEST_FIXTURE_PROP( prop_derived_path_built_out_path_round_trip, (const SingleDerivedPath::Built & b, const StorePath & outPath)) { - auto * v = state.allocValue(); + auto * v = state.mem.allocValue(); state.mkOutputString(*v, b, outPath); auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); RC_ASSERT(SingleDerivedPath { b } == d); diff --git a/tests/unit/libexpr/value/print.cc b/tests/unit/libexpr/value/print.cc index 5331057d2..35f9f085a 100644 --- a/tests/unit/libexpr/value/print.cc +++ b/tests/unit/libexpr/value/print.cc @@ -61,7 +61,7 @@ TEST_F(ValuePrintingTests, tAttrs) Value vTwo; vTwo.mkInt(2); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("one"), &vOne); builder.insert(state.symbols.create("two"), &vTwo); @@ -79,8 +79,7 @@ TEST_F(ValuePrintingTests, tList) Value vTwo; vTwo.mkInt(2); - Value vList; - state.mkList(vList, 5); + Value vList = state.mem.newList(5); vList.bigList.elems[0] = &vOne; vList.bigList.elems[1] = &vTwo; vList.bigList.size = 3; @@ -202,16 +201,16 @@ TEST_F(ValuePrintingTests, depthAttrs) Value vTwo; vTwo.mkInt(2); - BindingsBuilder builderEmpty(state, state.allocBindings(0)); + BindingsBuilder builderEmpty = state.buildBindings(0); Value vAttrsEmpty; vAttrsEmpty.mkAttrs(builderEmpty.finish()); - BindingsBuilder builderNested(state, state.allocBindings(1)); + BindingsBuilder builderNested = state.buildBindings(1); builderNested.insert(state.symbols.create("zero"), &vZero); Value vAttrsNested; vAttrsNested.mkAttrs(builderNested.finish()); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("one"), &vOne); builder.insert(state.symbols.create("two"), &vTwo); builder.insert(state.symbols.create("empty"), &vAttrsEmpty); @@ -220,7 +219,7 @@ TEST_F(ValuePrintingTests, depthAttrs) Value vAttrs; vAttrs.mkAttrs(builder.finish()); - BindingsBuilder builder2(state, state.allocBindings(10)); + BindingsBuilder builder2 = state.buildBindings(10); builder2.insert(state.symbols.create("one"), &vOne); builder2.insert(state.symbols.create("two"), &vTwo); builder2.insert(state.symbols.create("nested"), &vAttrs); @@ -242,14 +241,14 @@ TEST_F(ValuePrintingTests, depthList) Value vTwo; vTwo.mkInt(2); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("one"), &vOne); builder.insert(state.symbols.create("two"), &vTwo); Value vAttrs; vAttrs.mkAttrs(builder.finish()); - BindingsBuilder builder2(state, state.allocBindings(10)); + BindingsBuilder builder2 = state.buildBindings(10); builder2.insert(state.symbols.create("one"), &vOne); builder2.insert(state.symbols.create("two"), &vTwo); builder2.insert(state.symbols.create("nested"), &vAttrs); @@ -257,8 +256,7 @@ TEST_F(ValuePrintingTests, depthList) Value vNested; vNested.mkAttrs(builder2.finish()); - Value vList; - state.mkList(vList, 5); + Value vList = state.mem.newList(5); vList.bigList.elems[0] = &vOne; vList.bigList.elems[1] = &vTwo; vList.bigList.elems[2] = &vNested; @@ -306,7 +304,7 @@ TEST_F(ValuePrintingTests, attrsTypeFirst) Value vApple; vApple.mkString("apple"); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("type"), &vType); builder.insert(state.symbols.create("apple"), &vApple); @@ -417,7 +415,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrs) Value vTwo; vTwo.mkInt(2); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("one"), &vOne); builder.insert(state.symbols.create("two"), &vTwo); @@ -436,7 +434,7 @@ TEST_F(ValuePrintingTests, ansiColorsDerivation) Value vDerivation; vDerivation.mkString("derivation"); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.s.type, &vDerivation); Value vAttrs; @@ -487,7 +485,7 @@ TEST_F(ValuePrintingTests, ansiColorsDerivationError) Value vDerivation; vDerivation.mkString("derivation"); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.s.type, &vDerivation); builder.insert(state.s.drvPath, &vError); @@ -546,8 +544,7 @@ TEST_F(ValuePrintingTests, ansiColorsList) Value vTwo; vTwo.mkInt(2); - Value vList; - state.mkList(vList, 5); + Value vList = state.mem.newList(5); vList.bigList.elems[0] = &vOne; vList.bigList.elems[1] = &vTwo; vList.bigList.size = 3; @@ -653,13 +650,13 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated) Value vZero; vZero.mkInt(0); - BindingsBuilder innerBuilder(state, state.allocBindings(1)); + BindingsBuilder innerBuilder = state.buildBindings(1); innerBuilder.insert(state.symbols.create("x"), &vZero); Value vInner; vInner.mkAttrs(innerBuilder.finish()); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("a"), &vInner); builder.insert(state.symbols.create("b"), &vInner); @@ -678,14 +675,13 @@ TEST_F(ValuePrintingTests, ansiColorsListRepeated) Value vZero; vZero.mkInt(0); - BindingsBuilder innerBuilder(state, state.allocBindings(1)); + BindingsBuilder innerBuilder = state.buildBindings(1); innerBuilder.insert(state.symbols.create("x"), &vZero); Value vInner; vInner.mkAttrs(innerBuilder.finish()); - Value vList; - state.mkList(vList, 3); + Value vList = state.mem.newList(3); vList.bigList.elems[0] = &vInner; vList.bigList.elems[1] = &vInner; vList.bigList.size = 2; @@ -702,14 +698,13 @@ TEST_F(ValuePrintingTests, listRepeated) Value vZero; vZero.mkInt(0); - BindingsBuilder innerBuilder(state, state.allocBindings(1)); + BindingsBuilder innerBuilder = state.buildBindings(1); innerBuilder.insert(state.symbols.create("x"), &vZero); Value vInner; vInner.mkAttrs(innerBuilder.finish()); - Value vList; - state.mkList(vList, 3); + Value vList = state.mem.newList(3); vList.bigList.elems[0] = &vInner; vList.bigList.elems[1] = &vInner; vList.bigList.size = 2; @@ -730,7 +725,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided) Value vTwo; vTwo.mkInt(2); - BindingsBuilder builder(state, state.allocBindings(10)); + BindingsBuilder builder = state.buildBindings(10); builder.insert(state.symbols.create("one"), &vOne); builder.insert(state.symbols.create("two"), &vTwo); @@ -760,16 +755,13 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided) TEST_F(ValuePrintingTests, ansiColorsListElided) { - BindingsBuilder emptyBuilder(state, state.allocBindings(1)); - Value vOne; vOne.mkInt(1); Value vTwo; vTwo.mkInt(2); - Value vList; - state.mkList(vList, 4); + Value vList = state.mem.newList(4); vList.bigList.elems[0] = &vOne; vList.bigList.elems[1] = &vTwo; vList.bigList.size = 2;