Skip to content

Commit 9f6202e

Browse files
Radvendiixokdvium
authored andcommitted
libexpr: move eval memory allocation to own struct
Co-authored-by: eldritch horrors <[email protected]> https://git.lix.systems/lix-project/lix/commit/f5754dc90ae9b1207656d0e29ad2704d3ef1e554
1 parent 169a368 commit 9f6202e

File tree

25 files changed

+168
-132
lines changed

25 files changed

+168
-132
lines changed

src/libcmd/common-eval-args.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
155155
{
156156
auto res = state.buildBindings(autoArgs.size());
157157
for (auto & [name, arg] : autoArgs) {
158-
auto v = state.allocValue();
158+
auto v = state.mem.allocValue();
159159
std::visit(
160160
overloaded{
161161
[&](const AutoArgExpr & arg) {

src/libcmd/installables.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ ref<eval_cache::EvalCache> openEvalCache(EvalState & state, std::shared_ptr<flak
454454
if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0")
455455
throw Error("not everything is cached, but evaluation is not allowed");
456456

457-
auto vFlake = state.allocValue();
457+
auto vFlake = state.mem.allocValue();
458458
flake::callFlake(state, *lockedFlake, *vFlake);
459459

460460
state.forceAttrs(*vFlake, noPos, "while parsing cached flake data");
@@ -495,7 +495,7 @@ Installables SourceExprCommand::parseInstallables(ref<Store> store, std::vector<
495495
}
496496

497497
auto state = getEvalState();
498-
auto vFile = state->allocValue();
498+
auto vFile = state->mem.allocValue();
499499

500500
if (file == "-") {
501501
auto e = state->parseStdin();

src/libcmd/repl.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
697697
if (p != std::string::npos && p < line.size() && line[p + 1] != '='
698698
&& isVarName(name = removeWhitespace(line.substr(0, p)))) {
699699
Expr * e = parseString(line.substr(p + 1));
700-
Value & v(*state->allocValue());
700+
Value & v(*state->mem.allocValue());
701701
v.mkThunk(env, e);
702702
addVarToScope(state->symbols.create(name), v);
703703
} else {
@@ -760,7 +760,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
760760

761761
void NixRepl::initEnv()
762762
{
763-
env = &state->allocEnv(envSize);
763+
env = &state->mem.allocEnv(envSize);
764764
env->up = &state->baseEnv;
765765
displ = 0;
766766
staticEnv->vars.clear();

src/libexpr-c/nix_api_value.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ nix_value * nix_alloc_value(nix_c_context * context, EvalState * state)
160160
if (context)
161161
context->last_err_code = NIX_OK;
162162
try {
163-
nix_value * res = as_nix_value_ptr(state->state.allocValue());
163+
nix_value * res = as_nix_value_ptr(state->state.mem.allocValue());
164164
nix_gc_incref(nullptr, res);
165165
return res;
166166
}
@@ -605,7 +605,7 @@ nix_err nix_bindings_builder_insert(nix_c_context * context, BindingsBuilder * b
605605
context->last_err_code = NIX_OK;
606606
try {
607607
auto & v = check_value_not_null(value);
608-
nix::Symbol s = bb->builder.state.get().symbols.create(name);
608+
nix::Symbol s = bb->builder.symbols.get().create(name);
609609
bb->builder.insert(s, &v);
610610
}
611611
NIXC_CATCH_ERRS

src/libexpr-tests/derived-path.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ TEST_F(DerivedPathExpressionTest, force_init) {}
2222

2323
RC_GTEST_FIXTURE_PROP(DerivedPathExpressionTest, prop_opaque_path_round_trip, (const SingleDerivedPath::Opaque & o))
2424
{
25-
auto * v = state.allocValue();
25+
auto * v = state.mem.allocValue();
2626
state.mkStorePathString(o.path, *v);
2727
auto d = state.coerceToSingleDerivedPath(noPos, *v, "");
2828
RC_ASSERT(SingleDerivedPath{o} == d);
@@ -41,7 +41,7 @@ RC_GTEST_FIXTURE_PROP(
4141
ExperimentalFeatureSettings mockXpSettings;
4242
mockXpSettings.set("experimental-features", "ca-derivations dynamic-derivations");
4343

44-
auto * v = state.allocValue();
44+
auto * v = state.mem.allocValue();
4545
state.mkOutputString(*v, b, std::nullopt, mockXpSettings);
4646
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings);
4747
RC_ASSERT(SingleDerivedPath{b} == d);
@@ -55,7 +55,7 @@ RC_GTEST_FIXTURE_PROP(
5555
ExperimentalFeatureSettings mockXpSettings;
5656
mockXpSettings.set("experimental-features", "dynamic-derivations");
5757

58-
auto * v = state.allocValue();
58+
auto * v = state.mem.allocValue();
5959
state.mkOutputString(*v, b, outPath, mockXpSettings);
6060
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "", mockXpSettings);
6161
RC_ASSERT(SingleDerivedPath{b} == d);

src/libexpr/attr-path.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & au
5252
auto attrIndex = string2Int<unsigned int>(attr);
5353

5454
/* Evaluate the expression. */
55-
Value * vNew = state.allocValue();
55+
Value * vNew = state.mem.allocValue();
5656
state.autoCallFunction(autoArgs, *v, *vNew);
5757
v = vNew;
5858
state.forceValue(*v, noPos);

src/libexpr/attr-set.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,27 +10,27 @@ Bindings Bindings::emptyBindings;
1010
/* Allocate a new array of attributes for an attribute set with a specific
1111
capacity. The space is implicitly reserved after the Bindings
1212
structure. */
13-
Bindings * EvalState::allocBindings(size_t capacity)
13+
Bindings * EvalMemory::allocBindings(size_t capacity)
1414
{
1515
if (capacity == 0)
1616
return &Bindings::emptyBindings;
1717
if (capacity > std::numeric_limits<Bindings::size_type>::max())
1818
throw Error("attribute set of size %d is too big", capacity);
19-
nrAttrsets++;
20-
nrAttrsInAttrsets += capacity;
19+
stats.nrAttrsets++;
20+
stats.nrAttrsInAttrsets += capacity;
2121
return new (allocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings();
2222
}
2323

2424
Value & BindingsBuilder::alloc(Symbol name, PosIdx pos)
2525
{
26-
auto value = state.get().allocValue();
26+
auto value = mem.get().allocValue();
2727
bindings->push_back(Attr(name, value, pos));
2828
return *value;
2929
}
3030

3131
Value & BindingsBuilder::alloc(std::string_view name, PosIdx pos)
3232
{
33-
return alloc(state.get().symbols.create(name), pos);
33+
return alloc(symbols.get().create(name), pos);
3434
}
3535

3636
void Bindings::sort()

src/libexpr/eval.cc

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,15 @@ static Symbol getName(const AttrName & name, EvalState & state, Env & env)
193193

194194
static constexpr size_t BASE_ENV_SIZE = 128;
195195

196+
EvalMemory::EvalMemory()
197+
#if NIX_USE_BOEHMGC
198+
: valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
199+
, env1AllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
200+
#endif
201+
{
202+
assertGCInitialized();
203+
}
204+
196205
EvalState::EvalState(
197206
const LookupPath & lookupPathFromArguments,
198207
ref<Store> store,
@@ -269,23 +278,14 @@ EvalState::EvalState(
269278
, importResolutionCache(make_ref<decltype(importResolutionCache)::element_type>())
270279
, fileEvalCache(make_ref<decltype(fileEvalCache)::element_type>())
271280
, regexCache(makeRegexCache())
272-
#if NIX_USE_BOEHMGC
273-
, valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
274-
, env1AllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
275-
, baseEnvP(std::allocate_shared<Env *>(traceable_allocator<Env *>(), &allocEnv(BASE_ENV_SIZE)))
276-
, baseEnv(**baseEnvP)
277-
#else
278-
, baseEnv(allocEnv(BASE_ENV_SIZE))
279-
#endif
281+
, baseEnv(mem.allocEnv(BASE_ENV_SIZE))
280282
, staticBaseEnv{std::make_shared<StaticEnv>(nullptr, nullptr)}
281283
{
282284
corepkgsFS->setPathDisplay("<nix", ">");
283285
internalFS->setPathDisplay("«nix-internal»", "");
284286

285287
countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0";
286288

287-
assertGCInitialized();
288-
289289
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
290290

291291
/* Construct the Nix expression search path. */
@@ -418,7 +418,7 @@ void EvalState::checkURI(const std::string & uri)
418418

419419
Value * EvalState::addConstant(const std::string & name, Value & v, Constant info)
420420
{
421-
Value * v2 = allocValue();
421+
Value * v2 = mem.allocValue();
422422
*v2 = v;
423423
addConstant(name, v2, info);
424424
return v2;
@@ -484,7 +484,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
484484
the primop to a dummy value. */
485485
if (primOp.arity == 0) {
486486
primOp.arity = 1;
487-
auto vPrimOp = allocValue();
487+
auto vPrimOp = mem.allocValue();
488488
vPrimOp->mkPrimOp(new PrimOp(primOp));
489489
Value v;
490490
v.mkApp(vPrimOp, vPrimOp);
@@ -501,7 +501,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
501501
if (hasPrefix(primOp.name, "__"))
502502
primOp.name = primOp.name.substr(2);
503503

504-
Value * v = allocValue();
504+
Value * v = mem.allocValue();
505505
v->mkPrimOp(new PrimOp(primOp));
506506

507507
if (primOp.internal)
@@ -880,11 +880,10 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
880880
}
881881
}
882882

883-
ListBuilder::ListBuilder(EvalState & state, size_t size)
883+
ListBuilder::ListBuilder(size_t size)
884884
: size(size)
885885
, elems(size <= 2 ? inlineElems : (Value **) allocBytes(size * sizeof(Value *)))
886886
{
887-
state.nrListElems += size;
888887
}
889888

890889
Value * EvalState::getBool(bool b)
@@ -985,7 +984,7 @@ void EvalState::mkSingleDerivedPathString(const SingleDerivedPath & p, Value & v
985984

986985
Value * Expr::maybeThunk(EvalState & state, Env & env)
987986
{
988-
Value * v = state.allocValue();
987+
Value * v = state.mem.allocValue();
989988
mkThunk(*v, env, this);
990989
return v;
991990
}
@@ -1095,7 +1094,7 @@ void EvalState::evalFile(const SourcePath & path, Value & v, bool mustBeTrivial)
10951094
*resolvedPath,
10961095
nullptr,
10971096
[&](auto & i) {
1098-
vExpr = allocValue();
1097+
vExpr = mem.allocValue();
10991098
vExpr->mkThunk(&baseEnv, expr);
11001099
i.second = vExpr;
11011100
},
@@ -1178,7 +1177,7 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v)
11781177

11791178
Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up)
11801179
{
1181-
Env & inheritEnv = state.allocEnv(inheritFromExprs->size());
1180+
Env & inheritEnv = state.mem.allocEnv(inheritFromExprs->size());
11821181
inheritEnv.up = &up;
11831182

11841183
Displacement displ = 0;
@@ -1197,7 +1196,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
11971196
if (recursive) {
11981197
/* Create a new environment that contains the attributes in
11991198
this `rec'. */
1200-
Env & env2(state.allocEnv(attrs.size()));
1199+
Env & env2(state.mem.allocEnv(attrs.size()));
12011200
env2.up = &env;
12021201
dynamicEnv = &env2;
12031202
Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr;
@@ -1212,7 +1211,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
12121211
for (auto & i : attrs) {
12131212
Value * vAttr;
12141213
if (hasOverrides && i.second.kind != AttrDef::Kind::Inherited) {
1215-
vAttr = state.allocValue();
1214+
vAttr = state.mem.allocValue();
12161215
mkThunk(*vAttr, *i.second.chooseByKind(&env2, &env, inheritEnv), i.second.e);
12171216
} else
12181217
vAttr = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv));
@@ -1289,7 +1288,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
12891288
{
12901289
/* Create a new environment that contains the attributes in this
12911290
`let'. */
1292-
Env & env2(state.allocEnv(attrs->attrs.size()));
1291+
Env & env2(state.mem.allocEnv(attrs->attrs.size()));
12931292
env2.up = &env;
12941293

12951294
Env * inheritEnv = attrs->inheritFromExprs ? attrs->buildInheritFromEnv(state, env2) : nullptr;
@@ -1480,7 +1479,7 @@ void EvalState::callFunction(Value & fun, std::span<Value *> args, Value & vRes,
14801479
auto makeAppChain = [&]() {
14811480
vRes = vCur;
14821481
for (auto arg : args) {
1483-
auto fun2 = allocValue();
1482+
auto fun2 = mem.allocValue();
14841483
*fun2 = vRes;
14851484
vRes.mkPrimOpApp(fun2, arg);
14861485
}
@@ -1495,7 +1494,7 @@ void EvalState::callFunction(Value & fun, std::span<Value *> args, Value & vRes,
14951494
ExprLambda & lambda(*vCur.lambda().fun);
14961495

14971496
auto size = (!lambda.arg ? 0 : 1) + (lambda.hasFormals() ? lambda.formals->formals.size() : 0);
1498-
Env & env2(allocEnv(size));
1497+
Env & env2(mem.allocEnv(size));
14991498
env2.up = vCur.lambda().env;
15001499

15011500
Displacement displ = 0;
@@ -1678,7 +1677,7 @@ void EvalState::callFunction(Value & fun, std::span<Value *> args, Value & vRes,
16781677
/* 'vCur' may be allocated on the stack of the calling
16791678
function, but for functors we may keep a reference, so
16801679
heap-allocate a copy and use that instead. */
1681-
Value * args2[] = {allocValue(), args[0]};
1680+
Value * args2[] = {mem.allocValue(), args[0]};
16821681
*args2[0] = vCur;
16831682
try {
16841683
callFunction(*functor->value, args2, vCur, functor->pos);
@@ -1738,7 +1737,7 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res
17381737
if (fun.type() == nAttrs) {
17391738
auto found = fun.attrs()->get(s.functor);
17401739
if (found) {
1741-
Value * v = allocValue();
1740+
Value * v = mem.allocValue();
17421741
callFunction(*found->value, fun, *v, pos);
17431742
forceValue(*v, pos);
17441743
return autoCallFunction(args, *v, res);
@@ -1779,12 +1778,12 @@ values, or passed explicitly with '--arg' or '--argstr'. See
17791778
}
17801779
}
17811780

1782-
callFunction(fun, allocValue()->mkAttrs(attrs), res, pos);
1781+
callFunction(fun, mem.allocValue()->mkAttrs(attrs), res, pos);
17831782
}
17841783

17851784
void ExprWith::eval(EvalState & state, Env & env, Value & v)
17861785
{
1787-
Env & env2(state.allocEnv(1));
1786+
Env & env2(state.mem.allocEnv(1));
17881787
env2.up = &env;
17891788
env2.values[0] = attrs->maybeThunk(state, env);
17901789

@@ -2883,10 +2882,12 @@ void EvalState::printStatistics()
28832882
std::chrono::microseconds cpuTimeDuration = getCpuUserTime();
28842883
float cpuTime = std::chrono::duration_cast<std::chrono::duration<float>>(cpuTimeDuration).count();
28852884

2886-
uint64_t bEnvs = nrEnvs * sizeof(Env) + nrValuesInEnvs * sizeof(Value *);
2887-
uint64_t bLists = nrListElems * sizeof(Value *);
2888-
uint64_t bValues = nrValues * sizeof(Value);
2889-
uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr);
2885+
auto memstats = mem.getStats();
2886+
2887+
uint64_t bEnvs = memstats.nrEnvs * sizeof(Env) + memstats.nrValuesInEnvs * sizeof(Value *);
2888+
uint64_t bLists = memstats.nrListElems * sizeof(Value *);
2889+
uint64_t bValues = memstats.nrValues * sizeof(Value);
2890+
uint64_t bAttrsets = memstats.nrAttrsets * sizeof(Bindings) + memstats.nrAttrsInAttrsets * sizeof(Attr);
28902891

28912892
#if NIX_USE_BOEHMGC
28922893
GC_word heapSize, totalBytes;
@@ -2912,28 +2913,28 @@ void EvalState::printStatistics()
29122913
#endif
29132914
};
29142915
topObj["envs"] = {
2915-
{"number", nrEnvs},
2916-
{"elements", nrValuesInEnvs},
2916+
{"number", memstats.nrEnvs},
2917+
{"elements", memstats.nrValuesInEnvs},
29172918
{"bytes", bEnvs},
29182919
};
29192920
topObj["nrExprs"] = Expr::nrExprs;
29202921
topObj["list"] = {
2921-
{"elements", nrListElems},
2922+
{"elements", memstats.nrListElems},
29222923
{"bytes", bLists},
29232924
{"concats", nrListConcats},
29242925
};
29252926
topObj["values"] = {
2926-
{"number", nrValues},
2927+
{"number", memstats.nrValues},
29272928
{"bytes", bValues},
29282929
};
29292930
topObj["symbols"] = {
29302931
{"number", symbols.size()},
29312932
{"bytes", symbols.totalSize()},
29322933
};
29332934
topObj["sets"] = {
2934-
{"number", nrAttrsets},
2935+
{"number", memstats.nrAttrsets},
29352936
{"bytes", bAttrsets},
2936-
{"elements", nrAttrsInAttrsets},
2937+
{"elements", memstats.nrAttrsInAttrsets},
29372938
};
29382939
topObj["sizes"] = {
29392940
{"Env", sizeof(Env)},

0 commit comments

Comments
 (0)