libexpr: move eval memory allocation to own struct

Change-Id: I9d472c9606fe66fdc1cb7cb9dcf6d1b6b46c6686
This commit is contained in:
eldritch horrors 2024-11-27 02:09:08 +01:00
parent cb8262e11c
commit f5754dc90a
26 changed files with 229 additions and 207 deletions

View file

@ -144,7 +144,7 @@ static void getAllExprs(EvalState & state,
continue; continue;
} }
/* Load the expression on demand. */ /* Load the expression on demand. */
auto vArg = state.allocValue(); auto vArg = state.mem.allocValue();
vArg->mkString(path2.path.abs()); vArg->mkString(path2.path.abs());
if (seen.size() == maxAttrs) if (seen.size() == maxAttrs)
throw Error("too many Nix expressions in directory '%1%'", path); 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, static void setMetaFlag(EvalState & state, DrvInfo & drv,
const std::string & name, const std::string & value) const std::string & name, const std::string & value)
{ {
auto v = state.allocValue(); auto v = state.mem.allocValue();
v->mkString(value); v->mkString(value);
drv.setMeta(name, v); drv.setMeta(name, v);
} }

View file

@ -34,8 +34,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
/* Construct the whole top level derivation. */ /* Construct the whole top level derivation. */
StorePathSet references; StorePathSet references;
Value manifest; Value manifest = state.mem.newList(elems.size());
state.mkList(manifest, elems.size());
size_t n = 0; size_t n = 0;
for (auto & i : elems) { for (auto & i : elems) {
/* Create a pseudo-derivation containing the name, system, /* Create a pseudo-derivation containing the name, system,
@ -58,9 +57,9 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
// Copy each output meant for installation. // Copy each output meant for installation.
auto & vOutputs = attrs.alloc(state.s.outputs); 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)) { 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); auto outputAttrs = state.buildBindings(2);
outputAttrs.alloc(state.s.outPath).mkString(state.store->printStorePath(*j.second)); outputAttrs.alloc(state.s.outPath).mkString(state.store->printStorePath(*j.second));
attrs.alloc(j.first).mkAttrs(outputAttrs); attrs.alloc(j.first).mkAttrs(outputAttrs);
@ -83,7 +82,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
attrs.alloc(state.s.meta).mkAttrs(meta); 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); if (drvPath) references.insert(*drvPath);
} }

View file

@ -21,7 +21,7 @@ DrvInfos queryInstalled(EvalState & state, const Path & userEnv)
if (pathExists(manifestFile)) { if (pathExists(manifestFile)) {
Value v; Value v;
state.evalFile(CanonPath(manifestFile), v); state.evalFile(CanonPath(manifestFile), v);
Bindings & bindings(*state.allocBindings(0)); Bindings & bindings(*state.mem.allocBindings(0));
getDerivations(state, v, "", bindings, elems, false); getDerivations(state, v, "", bindings, elems, false);
} }
return elems; return elems;

View file

@ -175,7 +175,7 @@ Bindings * MixEvalArgs::getAutoArgs(EvalState & state)
{ {
auto res = state.buildBindings(autoArgs.size()); auto res = state.buildBindings(autoArgs.size());
for (auto & i : autoArgs) { for (auto & i : autoArgs) {
auto v = state.allocValue(); auto v = state.mem.allocValue();
if (i.second[0] == 'E') if (i.second[0] == 'E')
state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), CanonPath::fromCwd())); state.mkThunk_(*v, state.parseExprFromString(i.second.substr(1), CanonPath::fromCwd()));
else else

View file

@ -43,7 +43,7 @@ std::vector<std::string> InstallableFlake::getActualAttrPaths()
Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::LockedFlake & lockedFlake) Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::LockedFlake & lockedFlake)
{ {
auto vFlake = state.allocValue(); auto vFlake = state.mem.allocValue();
callFlake(state, lockedFlake, *vFlake); callFlake(state, lockedFlake, *vFlake);

View file

@ -403,7 +403,7 @@ ref<eval_cache::EvalCache> openEvalCache(
if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0") if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0")
throw Error("not everything is cached, but evaluation is not allowed"); 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); flake::callFlake(state, *lockedFlake, *vFlake);
state.forceAttrs(*vFlake, noPos, "while parsing cached flake data"); state.forceAttrs(*vFlake, noPos, "while parsing cached flake data");
@ -438,7 +438,7 @@ Installables SourceExprCommand::parseInstallables(
if (file) evalSettings.pureEval.override(false); if (file) evalSettings.pureEval.override(false);
auto state = getEvalState(); auto state = getEvalState();
auto vFile = state->allocValue(); auto vFile = state->mem.allocValue();
if (file == "-") { if (file == "-") {
auto & e = state->parseStdin(); auto & e = state->parseStdin();

View file

@ -844,7 +844,7 @@ ProcessLineResult NixRepl::processLine(std::string line)
isVarName(name = removeWhitespace(line.substr(0, p)))) isVarName(name = removeWhitespace(line.substr(0, p))))
{ {
Expr & e = parseString(line.substr(p + 1)); Expr & e = parseString(line.substr(p + 1));
Value & v(*state.allocValue()); Value & v(*state.mem.allocValue());
v.mkThunk(env, e); v.mkThunk(env, e);
addVarToScope(state.symbols.create(name), v); addVarToScope(state.symbols.create(name), v);
} else { } else {
@ -893,7 +893,7 @@ void NixRepl::loadFlake(const std::string & flakeRefS)
void NixRepl::initEnv() void NixRepl::initEnv()
{ {
env = &state.allocEnv(envSize); env = &state.mem.allocEnv(envSize);
env->up = &state.baseEnv; env->up = &state.baseEnv;
displ = 0; displ = 0;
staticEnv->vars.clear(); staticEnv->vars.clear();
@ -939,7 +939,7 @@ void NixRepl::loadReplOverlays()
notice("Loading '%1%'...", Magenta("repl-overlays")); notice("Loading '%1%'...", Magenta("repl-overlays"));
auto replInitFilesFunction = getReplOverlaysEvalFunction(); auto replInitFilesFunction = getReplOverlaysEvalFunction();
Value &newAttrs(*state.allocValue()); Value &newAttrs(*state.mem.allocValue());
SmallValueVector<3> args = {replInitInfo(), bindingsToAttrs(), replOverlays()}; SmallValueVector<3> args = {replInitInfo(), bindingsToAttrs(), replOverlays()};
state.callFunction( state.callFunction(
*replInitFilesFunction, *replInitFilesFunction,
@ -964,7 +964,7 @@ Value * NixRepl::getReplOverlaysEvalFunction()
} }
auto evalReplInitFilesPath = CanonPath::root + "repl-overlays.nix"; auto evalReplInitFilesPath = CanonPath::root + "repl-overlays.nix";
*replOverlaysEvalFunction = state.allocValue(); *replOverlaysEvalFunction = state.mem.allocValue();
auto code = auto code =
#include "repl-overlays.nix.gen.hh" #include "repl-overlays.nix.gen.hh"
; ;
@ -981,8 +981,8 @@ Value * NixRepl::getReplOverlaysEvalFunction()
Value * NixRepl::replOverlays() Value * NixRepl::replOverlays()
{ {
Value * replInits(state.allocValue()); Value * replInits(state.mem.allocValue());
state.mkList(*replInits, evalSettings.replOverlays.get().size()); *replInits = state.mem.newList(evalSettings.replOverlays.get().size());
Value ** replInitElems = replInits->listElems(); Value ** replInitElems = replInits->listElems();
size_t i = 0; size_t i = 0;
@ -1024,11 +1024,11 @@ Value * NixRepl::replInitInfo()
{ {
auto builder = state.buildBindings(2); auto builder = state.buildBindings(2);
Value * currentSystem(state.allocValue()); Value * currentSystem(state.mem.allocValue());
currentSystem->mkString(evalSettings.getCurrentSystem()); currentSystem->mkString(evalSettings.getCurrentSystem());
builder.insert(state.symbols.create("currentSystem"), currentSystem); builder.insert(state.symbols.create("currentSystem"), currentSystem);
Value * info(state.allocValue()); Value * info(state.mem.allocValue());
info->mkAttrs(builder.finish()); info->mkAttrs(builder.finish());
return info; return info;
} }
@ -1070,7 +1070,7 @@ Value * NixRepl::bindingsToAttrs()
builder.insert(symbol, env->values[displacement]); builder.insert(symbol, env->values[displacement]);
} }
Value * attrs(state.allocValue()); Value * attrs(state.mem.allocValue());
attrs->mkAttrs(builder.finish()); attrs->mkAttrs(builder.finish());
return attrs; return attrs;
} }
@ -1092,7 +1092,7 @@ void NixRepl::evalString(std::string s, Value & v)
Value * NixRepl::evalFile(SourcePath & path) Value * NixRepl::evalFile(SourcePath & path)
{ {
auto & expr = state.parseExprFromFile(path, staticEnv); auto & expr = state.parseExprFromFile(path, staticEnv);
Value * result(state.allocValue()); Value * result(state.mem.allocValue());
expr.eval(state, *env, *result); expr.eval(state, *env, *result);
state.forceValue(*result, result->determinePos(noPos)); state.forceValue(*result, result->determinePos(noPos));
return result; return result;

View file

@ -54,7 +54,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
auto attrIndex = string2Int<unsigned int>(attr); auto attrIndex = string2Int<unsigned int>(attr);
/* Evaluate the expression. */ /* Evaluate the expression. */
Value * vNew = state.allocValue(); Value * vNew = state.mem.allocValue();
state.autoCallFunction(autoArgs, *v, *vNew); state.autoCallFunction(autoArgs, *v, *vNew);
v = vNew; v = vNew;
state.forceValue(*v, noPos); state.forceValue(*v, noPos);
@ -109,7 +109,7 @@ std::pair<SourcePath, uint32_t> findPackageFilename(EvalState & state, Value & v
{ {
Value * v2; Value * v2;
try { try {
auto dummyArgs = state.allocBindings(0); auto dummyArgs = state.mem.allocBindings(0);
v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v).first; v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v).first;
} catch (Error &) { } catch (Error &) {
throw NoPositionInfo("package '%s' has no source location information", what); throw NoPositionInfo("package '%s' has no source location information", what);

View file

@ -13,21 +13,21 @@ Bindings Bindings::EMPTY{0};
/* Allocate a new array of attributes for an attribute set with a specific /* Allocate a new array of attributes for an attribute set with a specific
capacity. The space is implicitly reserved after the Bindings capacity. The space is implicitly reserved after the Bindings
structure. */ structure. */
Bindings * EvalState::allocBindings(size_t capacity) Bindings * EvalMemory::allocBindings(size_t capacity)
{ {
if (capacity == 0) if (capacity == 0)
return &Bindings::EMPTY; return &Bindings::EMPTY;
if (capacity > std::numeric_limits<Bindings::size_t>::max()) if (capacity > std::numeric_limits<Bindings::size_t>::max())
throw Error("attribute set of size %d is too big", capacity); throw Error("attribute set of size %d is too big", capacity);
nrAttrsets++; stats.nrAttrsets++;
nrAttrsInAttrsets += capacity; stats.nrAttrsInAttrsets += capacity;
return new (gcAllocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity); return new (gcAllocBytes(sizeof(Bindings) + sizeof(Attr) * capacity)) Bindings((Bindings::size_t) capacity);
} }
Value & BindingsBuilder::alloc(Symbol name, PosIdx pos) Value & BindingsBuilder::alloc(Symbol name, PosIdx pos)
{ {
auto value = state.allocValue(); auto value = mem.allocValue();
bindings->push_back(Attr(name, value, pos)); bindings->push_back(Attr(name, value, pos));
return *value; return *value;
} }
@ -35,7 +35,7 @@ Value & BindingsBuilder::alloc(Symbol name, PosIdx pos)
Value & BindingsBuilder::alloc(std::string_view 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);
} }

View file

@ -10,7 +10,7 @@
namespace nix { namespace nix {
class EvalState; class EvalMemory;
struct Value; struct Value;
/** /**
@ -117,7 +117,7 @@ public:
return res; return res;
} }
friend class EvalState; friend class EvalMemory;
}; };
/** /**
@ -128,15 +128,17 @@ public:
class BindingsBuilder class BindingsBuilder
{ {
Bindings * bindings; Bindings * bindings;
EvalMemory & mem;
SymbolTable & symbols;
public: public:
// needed by std::back_inserter // needed by std::back_inserter
using value_type = Attr; using value_type = Attr;
EvalState & state; BindingsBuilder(EvalMemory & mem, SymbolTable & symbols, Bindings * bindings)
: bindings(bindings)
BindingsBuilder(EvalState & state, Bindings * bindings) , mem(mem)
: bindings(bindings), state(state) , symbols(symbols)
{ } { }
void insert(Symbol name, Value * value, PosIdx pos = noPos) void insert(Symbol name, Value * value, PosIdx pos = noPos)

View file

@ -9,7 +9,7 @@
namespace nix { namespace nix {
[[gnu::always_inline]] [[gnu::always_inline]]
Value * EvalState::allocValue() Value * EvalMemory::allocValue()
{ {
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
/* We use the boehm batch allocator to speed up allocations of Values (of which there are many). /* 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)); void * p = gcAllocBytes(sizeof(Value));
#endif #endif
nrValues++; stats.nrValues++;
return static_cast<Value *>(p); return static_cast<Value *>(p);
} }
[[gnu::always_inline]] [[gnu::always_inline]]
Env & EvalState::allocEnv(size_t size) Env & EvalMemory::allocEnv(size_t size)
{ {
nrEnvs++; stats.nrEnvs++;
nrValuesInEnvs += size; stats.nrValuesInEnvs += size;
Env * env; Env * env;

View file

@ -253,6 +253,15 @@ StaticSymbols::StaticSymbols(SymbolTable & symbols)
{ {
} }
EvalMemory::EvalMemory()
#if HAVE_BOEHMGC
: valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
, env1AllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
#endif
{
assert(libexprInitialised);
}
EvalState::EvalState( EvalState::EvalState(
const SearchPath & _searchPath, const SearchPath & _searchPath,
ref<Store> store, ref<Store> store,
@ -263,17 +272,11 @@ EvalState::EvalState(
, store(store) , store(store)
, buildStore(buildStore ? buildStore : store) , buildStore(buildStore ? buildStore : store)
, regexCache(makeRegexCache()) , regexCache(makeRegexCache())
#if HAVE_BOEHMGC , baseEnv(mem.allocEnv(128))
, valueAllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
, env1AllocCache(std::allocate_shared<void *>(traceable_allocator<void *>(), nullptr))
#endif
, baseEnv(allocEnv(128))
, staticBaseEnv{std::make_shared<StaticEnv>(nullptr, nullptr)} , staticBaseEnv{std::make_shared<StaticEnv>(nullptr, nullptr)}
{ {
countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0"; countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0";
assert(libexprInitialised);
static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes"); static_assert(sizeof(Env) <= 16, "environment must be <= 16 bytes");
/* Initialise the Nix expression search path. */ /* 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 * EvalState::addConstant(const std::string & name, const Value & v, Constant info)
{ {
Value * v2 = allocValue(); Value * v2 = mem.allocValue();
*v2 = v; *v2 = v;
addConstant(name, v2, info); addConstant(name, v2, info);
return v2; return v2;
@ -475,7 +478,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
the primop to a dummy value. */ the primop to a dummy value. */
if (primOp.arity == 0) { if (primOp.arity == 0) {
primOp.arity = 1; primOp.arity = 1;
auto vPrimOp = allocValue(); auto vPrimOp = mem.allocValue();
vPrimOp->mkPrimOp(new PrimOp(primOp)); vPrimOp->mkPrimOp(new PrimOp(primOp));
Value v; Value v;
v.mkApp(vPrimOp, vPrimOp); v.mkApp(vPrimOp, vPrimOp);
@ -489,7 +492,7 @@ Value * EvalState::addPrimOp(PrimOp && primOp)
if (primOp.name.starts_with("__")) if (primOp.name.starts_with("__"))
primOp.name = primOp.name.substr(2); primOp.name = primOp.name.substr(2);
Value * v = allocValue(); Value * v = mem.allocValue();
v->mkPrimOp(new PrimOp(primOp)); v->mkPrimOp(new PrimOp(primOp));
staticBaseEnv->vars.emplace_back(envName, baseEnvDispl); staticBaseEnv->vars.emplace_back(envName, baseEnvDispl);
baseEnv.values[baseEnvDispl++] = v; 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); v.mkList(size);
if (size > 2) if (size > 2)
v.bigList.elems = gcAllocType<Value *>(size); v.bigList.elems = gcAllocType<Value *>(size);
nrListElems += size; stats.nrListElems += size;
return v;
} }
@ -878,7 +883,7 @@ void EvalState::mkSingleDerivedPathString(
of thunks allocated. */ of thunks allocated. */
Value * Expr::maybeThunk(EvalState & state, Env & env) Value * Expr::maybeThunk(EvalState & state, Env & env)
{ {
Value * v = state.allocValue(); Value * v = state.mem.allocValue();
mkThunk(*v, env, *this); mkThunk(*v, env, *this);
return v; return v;
} }
@ -1064,7 +1069,7 @@ void ExprPath::eval(EvalState & state, Env & env, Value & v)
Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up) Env * ExprAttrs::buildInheritFromEnv(EvalState & state, Env & up)
{ {
Env & inheritEnv = state.allocEnv(inheritFromExprs->size()); Env & inheritEnv = state.mem.allocEnv(inheritFromExprs->size());
inheritEnv.up = &up; inheritEnv.up = &up;
Displacement displ = 0; Displacement displ = 0;
@ -1082,7 +1087,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
if (recursive) { if (recursive) {
/* Create a new environment that contains the attributes in /* Create a new environment that contains the attributes in
this `rec'. */ this `rec'. */
Env & env2(state.allocEnv(attrs.size())); Env & env2(state.mem.allocEnv(attrs.size()));
env2.up = &env; env2.up = &env;
dynamicEnv = &env2; dynamicEnv = &env2;
Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr; Env * inheritEnv = inheritFromExprs ? buildInheritFromEnv(state, env2) : nullptr;
@ -1097,7 +1102,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
for (auto & i : attrs) { for (auto & i : attrs) {
Value * vAttr; Value * vAttr;
if (hasOverrides && i.second.kind != AttrDef::Kind::Inherited) { 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); mkThunk(*vAttr, *i.second.chooseByKind(&env2, &env, inheritEnv), *i.second.e);
} else } else
vAttr = i.second.e->maybeThunk(state, *i.second.chooseByKind(&env2, &env, inheritEnv)); 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) { if (hasOverrides) {
Value * vOverrides = (*v.attrs)[overrides->second.displ].value; Value * vOverrides = (*v.attrs)[overrides->second.displ].value;
state.forceAttrs(*vOverrides, [&]() { return vOverrides->determinePos(noPos); }, "while evaluating the `__overrides` attribute"); 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) for (auto & i : *v.attrs)
newBnds->push_back(i); newBnds->push_back(i);
for (auto & i : *vOverrides->attrs) { 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 /* Create a new environment that contains the attributes in this
`let'. */ `let'. */
Env & env2(state.allocEnv(attrs->attrs.size())); Env & env2(state.mem.allocEnv(attrs->attrs.size()));
env2.up = &env; env2.up = &env;
Env * inheritEnv = attrs->inheritFromExprs ? attrs->buildInheritFromEnv(state, env2) : nullptr; 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) 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())) for (auto [n, v2] : enumerate(v.listItems()))
const_cast<Value * &>(v2) = elems[n]->maybeThunk(state, env); const_cast<Value * &>(v2) = elems[n]->maybeThunk(state, env);
} }
@ -1511,7 +1516,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
{ {
vRes = vCur; vRes = vCur;
for (size_t i = 0; i < nrArgs; ++i) { for (size_t i = 0; i < nrArgs; ++i) {
auto fun2 = allocValue(); auto fun2 = mem.allocValue();
*fun2 = vRes; *fun2 = vRes;
vRes.mkPrimOpApp(fun2, args[i]); vRes.mkPrimOpApp(fun2, args[i]);
} }
@ -1528,7 +1533,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
auto size = auto size =
(!lambda.arg ? 0 : 1) + (!lambda.arg ? 0 : 1) +
(lambda.hasFormals() ? lambda.formals->formals.size() : 0); (lambda.hasFormals() ? lambda.formals->formals.size() : 0);
Env & env2(allocEnv(size)); Env & env2(mem.allocEnv(size));
env2.up = vCur.lambda.env; env2.up = vCur.lambda.env;
Displacement displ = 0; 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 /* 'vCur' may be allocated on the stack of the calling
function, but for functors we may keep a reference, so function, but for functors we may keep a reference, so
heap-allocate a copy and use that instead. */ heap-allocate a copy and use that instead. */
Value * args2[] = {allocValue(), args[0]}; Value * args2[] = {mem.allocValue(), args[0]};
*args2[0] = vCur; *args2[0] = vCur;
try { try {
callFunction(*functor->value, 2, args2, vCur, functor->pos); 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) { if (fun.type() == nAttrs) {
auto found = fun.attrs->find(s.functor); auto found = fun.attrs->find(s.functor);
if (found != fun.attrs->end()) { if (found != fun.attrs->end()) {
Value * v = allocValue(); Value * v = mem.allocValue();
callFunction(*found->value, fun, *v, pos); callFunction(*found->value, fun, *v, pos);
forceValue(*v, pos); forceValue(*v, pos);
return autoCallFunction(args, *v, res); 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) void ExprWith::eval(EvalState & state, Env & env, Value & v)
{ {
Env & env2(state.allocEnv(1)); Env & env2(state.mem.allocEnv(1));
env2.up = &env; env2.up = &env;
env2.values[0] = attrs->maybeThunk(state, 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; return;
} }
mkList(v, len); v = mem.newList(len);
auto out = v.listElems(); auto out = v.listElems();
for (size_t n = 0, pos = 0; n < nrLists; ++n) { for (size_t n = 0, pos = 0; n < nrLists; ++n) {
auto l = lists[n]->listSize(); auto l = lists[n]->listSize();
@ -2577,11 +2582,12 @@ void EvalState::printStatistics()
struct rusage buf; struct rusage buf;
getrusage(RUSAGE_SELF, &buf); getrusage(RUSAGE_SELF, &buf);
float cpuTime = buf.ru_utime.tv_sec + ((float) buf.ru_utime.tv_usec / 1000000); 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 bEnvs = mem.nrEnvs * sizeof(Env) + mem.nrValuesInEnvs * sizeof(Value *);
uint64_t bLists = nrListElems * sizeof(Value *); uint64_t bLists = mem.nrListElems * sizeof(Value *);
uint64_t bValues = nrValues * sizeof(Value); uint64_t bValues = mem.nrValues * sizeof(Value);
uint64_t bAttrsets = nrAttrsets * sizeof(Bindings) + nrAttrsInAttrsets * sizeof(Attr); uint64_t bAttrsets = mem.nrAttrsets * sizeof(Bindings) + mem.nrAttrsInAttrsets * sizeof(Attr);
#if HAVE_BOEHMGC #if HAVE_BOEHMGC
GC_word heapSize, totalBytes; GC_word heapSize, totalBytes;
@ -2595,17 +2601,17 @@ void EvalState::printStatistics()
json topObj = json::object(); json topObj = json::object();
topObj["cpuTime"] = cpuTime; topObj["cpuTime"] = cpuTime;
topObj["envs"] = { topObj["envs"] = {
{"number", nrEnvs}, {"number", mem.nrEnvs},
{"elements", nrValuesInEnvs}, {"elements", mem.nrValuesInEnvs},
{"bytes", bEnvs}, {"bytes", bEnvs},
}; };
topObj["list"] = { topObj["list"] = {
{"elements", nrListElems}, {"elements", mem.nrListElems},
{"bytes", bLists}, {"bytes", bLists},
{"concats", nrListConcats}, {"concats", nrListConcats},
}; };
topObj["values"] = { topObj["values"] = {
{"number", nrValues}, {"number", mem.nrValues},
{"bytes", bValues}, {"bytes", bValues},
}; };
topObj["symbols"] = { topObj["symbols"] = {
@ -2613,9 +2619,9 @@ void EvalState::printStatistics()
{"bytes", symbols.totalSize()}, {"bytes", symbols.totalSize()},
}; };
topObj["sets"] = { topObj["sets"] = {
{"number", nrAttrsets}, {"number", mem.nrAttrsets},
{"bytes", bAttrsets}, {"bytes", bAttrsets},
{"elements", nrAttrsInAttrsets}, {"elements", mem.nrAttrsInAttrsets},
}; };
topObj["sizes"] = { topObj["sizes"] = {
{"Env", sizeof(Env)}, {"Env", sizeof(Env)},

View file

@ -227,6 +227,55 @@ struct StaticSymbols
explicit StaticSymbols(SymbolTable & symbols); explicit StaticSymbols(SymbolTable & symbols);
}; };
class EvalMemory
{
#if HAVE_BOEHMGC
/**
* Allocation cache for GC'd Value objects.
*/
std::shared_ptr<void *> valueAllocCache;
/**
* Allocation cache for size-1 Env objects.
*/
std::shared_ptr<void *> 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 class EvalState
{ {
@ -234,6 +283,7 @@ public:
SymbolTable symbols; SymbolTable symbols;
PosTable positions; PosTable positions;
const StaticSymbols s; const StaticSymbols s;
EvalMemory mem;
/** /**
* If set, force copying files to the Nix store even if they * If set, force copying files to the Nix store even if they
@ -308,18 +358,6 @@ private:
*/ */
std::shared_ptr<RegexCache> regexCache; std::shared_ptr<RegexCache> regexCache;
#if HAVE_BOEHMGC
/**
* Allocation cache for GC'd Value objects.
*/
std::shared_ptr<void *> valueAllocCache;
/**
* Allocation cache for size-1 Env objects.
*/
std::shared_ptr<void *> env1AllocCache;
#endif
public: public:
EvalState( EvalState(
@ -638,20 +676,11 @@ public:
*/ */
void autoCallFunction(Bindings & args, Value & fun, Value & res); 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) 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 mkThunk_(Value & v, Expr & expr);
void mkPos(Value & v, PosIdx pos); void mkPos(Value & v, PosIdx pos);
@ -745,13 +774,7 @@ private:
std::string mkSingleDerivedPathStringRaw( std::string mkSingleDerivedPathStringRaw(
const SingleDerivedPath & p); 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 nrLookups = 0;
unsigned long nrAttrsets = 0;
unsigned long nrAttrsInAttrsets = 0;
unsigned long nrAvoided = 0; unsigned long nrAvoided = 0;
unsigned long nrOpUpdates = 0; unsigned long nrOpUpdates = 0;
unsigned long nrOpUpdateValuesCopied = 0; unsigned long nrOpUpdateValuesCopied = 0;

View file

@ -765,11 +765,11 @@ void callFlake(EvalState & state,
const LockedFlake & lockedFlake, const LockedFlake & lockedFlake,
Value & vRes) Value & vRes)
{ {
auto vLocks = state.allocValue(); auto vLocks = state.mem.allocValue();
auto vRootSrc = state.allocValue(); auto vRootSrc = state.mem.allocValue();
auto vRootSubdir = state.allocValue(); auto vRootSubdir = state.mem.allocValue();
auto vTmp1 = state.allocValue(); auto vTmp1 = state.mem.allocValue();
auto vTmp2 = state.allocValue(); auto vTmp2 = state.mem.allocValue();
vLocks->mkString(lockedFlake.lockFile.to_string()); vLocks->mkString(lockedFlake.lockFile.to_string());
@ -784,7 +784,7 @@ void callFlake(EvalState & state,
vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir); vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir);
if (!state.vCallFlake) { if (!state.vCallFlake) {
state.vCallFlake = allocRootValue(state.allocValue()); state.vCallFlake = allocRootValue(state.mem.allocValue());
state.eval(state.parseExprFromString( state.eval(state.parseExprFromString(
#include "call-flake.nix.gen.hh" #include "call-flake.nix.gen.hh"
, CanonPath::root), **state.vCallFlake); , CanonPath::root), **state.vCallFlake);

View file

@ -28,7 +28,7 @@ class JSONSax : nlohmann::json_sax<json> {
Value & value(EvalState & state) Value & value(EvalState & state)
{ {
if (!v) if (!v)
v = allocRootValue(state.allocValue()); v = allocRootValue(state.mem.allocValue());
return **v; return **v;
} }
virtual ~JSONState() {} virtual ~JSONState() {}
@ -59,7 +59,7 @@ class JSONSax : nlohmann::json_sax<json> {
std::unique_ptr<JSONState> resolve(EvalState & state) override std::unique_ptr<JSONState> resolve(EvalState & state) override
{ {
Value & v = parent->value(state); 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) { for (size_t n = 0; n < values.size(); ++n) {
v.listElems()[n] = values[n]; v.listElems()[n] = values[n];
} }

View file

@ -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"]); attrs.alloc(state.s.name).mkString(drv.env["name"]);
auto & outputsVal = attrs.alloc(state.s.outputs); 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)) { for (const auto & [i, o] : enumerate(drv.outputs)) {
mkOutputString(state, attrs, *storePath, o); 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); w->mkAttrs(attrs);
if (!state.vImportedDrvToDerivation) { if (!state.vImportedDrvToDerivation) {
state.vImportedDrvToDerivation = allocRootValue(state.allocValue()); state.vImportedDrvToDerivation = allocRootValue(state.mem.allocValue());
state.eval(state.parseExprFromString( state.eval(state.parseExprFromString(
#include "imported-drv-to-derivation.nix.gen.hh" #include "imported-drv-to-derivation.nix.gen.hh"
, CanonPath::root), **state.vImportedDrvToDerivation); , CanonPath::root), **state.vImportedDrvToDerivation);
@ -230,7 +230,7 @@ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * v
else { else {
state.forceAttrs(*vScope, pos, "while evaluating the first argument passed to builtins.scopedImport"); 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; env->up = &state.baseEnv;
auto staticEnv = std::make_shared<StaticEnv>(nullptr, state.staticBaseEnv.get(), vScope->attrs->size()); auto staticEnv = std::make_shared<StaticEnv>(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. */ /* Create the result list. */
state.mkList(v, res.size()); v = state.mem.newList(res.size());
unsigned int n = 0; unsigned int n = 0;
for (auto & i : res) for (auto & i : res)
v.listElems()[n++] = i; 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 // Some filesystems or operating systems may not be able to return
// detailed node info quickly in this case we produce a thunk to // detailed node info quickly in this case we produce a thunk to
// query the file type lazily. // query the file type lazily.
auto epath = state.allocValue(); auto epath = state.mem.allocValue();
epath->mkPath(path + name); epath->mkPath(path + name);
if (!readFileType) if (!readFileType)
readFileType = &state.getBuiltin("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.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; size_t n = 0;
for (auto & i : *args[0]->attrs) 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, std::sort(v.listElems(), v.listElems() + n,
[](Value * v1, Value * v2) { return strcmp(v1->string.s, v2->string.s) < 0; }); [](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.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* // FIXME: this is incredibly evil, *why*
// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast) // NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast)
@ -1723,7 +1723,7 @@ static struct LazyPosAcessors {
void operator()(EvalState & state, const PosIdx pos, Value & line, Value & column) void operator()(EvalState & state, const PosIdx pos, Value & line, Value & column)
{ {
Value * posV = state.allocValue(); Value * posV = state.mem.allocValue();
posV->mkInt(pos.id); posV->mkInt(pos.id);
line.mkApp(&lineOfPos, posV); line.mkApp(&lineOfPos, posV);
column.mkApp(&columnOfPos, 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; res[found++] = i->value;
} }
state.mkList(v, found); v = state.mem.newList(found);
for (unsigned int n = 0; n < found; ++n) for (unsigned int n = 0; n < found; ++n)
v.listElems()[n] = res[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()); auto attrs = state.buildBindings(args[1]->attrs->size());
for (auto & i : *args[1]->attrs) { for (auto & i : *args[1]->attrs) {
Value * vName = state.allocValue(); Value * vName = state.mem.allocValue();
Value * vFun2 = state.allocValue(); Value * vFun2 = state.mem.allocValue();
vName->mkString(state.symbols[i.name]); vName->mkString(state.symbols[i.name]);
vFun2->mkApp(args[0], vName); vFun2->mkApp(args[0], vName);
attrs.alloc(i.name).mkApp(vFun2, i.value); 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()); auto attrs = state.buildBindings(attrsSeen.size());
for (auto & [sym, elem] : attrsSeen) { for (auto & [sym, elem] : attrsSeen) {
auto & list = attrs.alloc(sym); auto & list = attrs.alloc(sym);
state.mkList(list, elem.first); list = state.mem.newList(elem.first);
elem.second = list.listElems(); elem.second = list.listElems();
} }
v.mkAttrs(attrs.alreadySorted()); v.mkAttrs(attrs.alreadySorted());
@ -1972,11 +1972,11 @@ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * arg
} }
for (auto & attr : *v.attrs) { for (auto & attr : *v.attrs) {
auto name = state.allocValue(); auto name = state.mem.allocValue();
name->mkString(state.symbols[attr.name]); name->mkString(state.symbols[attr.name]);
auto call1 = state.allocValue(); auto call1 = state.mem.allocValue();
call1->mkApp(args[0], name); call1->mkApp(args[0], name);
auto call2 = state.allocValue(); auto call2 = state.mem.allocValue();
call2->mkApp(call1, attr.value); call2->mkApp(call1, attr.value);
attr.value = call2; attr.value = call2;
} }
@ -2029,7 +2029,7 @@ static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value
if (args[0]->listSize() == 0) if (args[0]->listSize() == 0)
state.error<EvalError>("'tail' called on an empty list").atPos(pos).debugThrow(); state.error<EvalError>("'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) for (unsigned int n = 0; n < v.listSize(); ++n)
v.listElems()[n] = args[0]->listElems()[n + 1]; 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.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) 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]); args[0], args[1]->listElems()[n]);
} }
@ -2082,7 +2082,7 @@ static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Val
if (same) if (same)
v = *args[1]; v = *args[1];
else { else {
state.mkList(v, k); v = state.mem.newList(k);
for (unsigned int n = 0; n < k; ++n) v.listElems()[n] = vs[n]; 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())) { for (auto [n, elem] : enumerate(args[2]->listItems())) {
Value * vs []{vCur, elem}; 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.callFunction(*args[0], 2, vs, *vCur, pos);
} }
state.forceValue(v, 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. // 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.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) { for (size_t n = 0; n < len; ++n) {
auto arg = state.allocValue(); auto arg = state.mem.allocValue();
arg->mkInt(n); 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.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) { for (unsigned int n = 0; n < len; ++n) {
state.forceValue(*args[1]->listElems()[n], pos); state.forceValue(*args[1]->listElems()[n], pos);
v.listElems()[n] = args[1]->listElems()[n]; 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 & vRight = attrs.alloc(state.s.right);
auto rsize = right.size(); auto rsize = right.size();
state.mkList(vRight, rsize); vRight = state.mem.newList(rsize);
if (rsize) if (rsize)
memcpy(vRight.listElems(), right.data(), sizeof(Value *) * rsize); memcpy(vRight.listElems(), right.data(), sizeof(Value *) * rsize);
auto & vWrong = attrs.alloc(state.s.wrong); auto & vWrong = attrs.alloc(state.s.wrong);
auto wsize = wrong.size(); auto wsize = wrong.size();
state.mkList(vWrong, wsize); vWrong = state.mem.newList(wsize);
if (wsize) if (wsize)
memcpy(vWrong.listElems(), wrong.data(), sizeof(Value *) * 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) { for (auto & i : attrs) {
auto & list = attrs2.alloc(i.first); auto & list = attrs2.alloc(i.first);
auto size = i.second.size(); auto size = i.second.size();
state.mkList(list, size); list = state.mem.newList(size);
memcpy(list.listElems(), i.second.data(), sizeof(Value *) * 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(); len += lists[n].listSize();
} }
state.mkList(v, len); v = state.mem.newList(len);
auto out = v.listElems(); auto out = v.listElems();
for (unsigned int n = 0, pos = 0; n < nrLists; ++n) { for (unsigned int n = 0, pos = 0; n < nrLists; ++n) {
auto l = lists[n].listSize(); 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 // the first match is the whole string
const size_t len = match.size() - 1; const size_t len = match.size() - 1;
state.mkList(v, len); v = state.mem.newList(len);
for (size_t i = 0; i < len; ++i) { for (size_t i = 0; i < len; ++i) {
if (!match[i+1].matched) if (!match[i+1].matched)
(v.listElems()[i] = state.allocValue())->mkNull(); (v.listElems()[i] = state.mem.allocValue())->mkNull();
else 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) { } 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. // Any matches results are surrounded by non-matching results.
const size_t len = std::distance(begin, end); 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; size_t idx = 0;
if (len == 0) { if (len == 0) {
@ -2617,24 +2617,24 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
auto match = *i; auto match = *i;
// Add a string for non-matched characters. // 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. // Add a list for matched substrings.
const size_t slen = match.size() - 1; 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. // 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) { for (size_t si = 0; si < slen; ++si) {
if (!match[si + 1].matched) if (!match[si + 1].matched)
(elem->listElems()[si] = state.allocValue())->mkNull(); (elem->listElems()[si] = state.mem.allocValue())->mkNull();
else 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. // Add a string for non-matched suffix characters.
if (idx == 2 * len) 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); assert(idx == 2 * len + 1);
@ -2764,9 +2764,9 @@ static void prim_splitVersion(EvalState & state, const PosIdx pos, Value * * arg
break; break;
components.emplace_back(component); components.emplace_back(component);
} }
state.mkList(v, components.size()); v = state.mem.newList(components.size());
for (const auto & [n, component] : enumerate(components)) 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) static Value getNixPath(EvalState & state, SearchPath & searchPath)
{ {
Value v; Value v;
state.mkList(v, searchPath.elements.size()); v = state.mem.newList(searchPath.elements.size());
int n = 0; int n = 0;
for (auto & i : searchPath.elements) { for (auto & i : searchPath.elements) {
auto attrs = state.buildBindings(2); auto attrs = state.buildBindings(2);
attrs.alloc("path").mkString(i.path.s); attrs.alloc("path").mkString(i.path.s);
attrs.alloc("prefix").mkString(i.prefix.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; return v;
} }
@ -2835,7 +2835,7 @@ void EvalState::createBaseEnv()
Null docs because it is documented separately. Null docs because it is documented separately.
*/ */
auto vDerivation = allocValue(); auto vDerivation = mem.allocValue();
addConstant("derivation", vDerivation, { addConstant("derivation", vDerivation, {
.type = nFunction, .type = nFunction,
}); });

View file

@ -149,9 +149,9 @@ void prim_getContext(EvalState & state, const PosIdx pos, Value * * args, Value
infoAttrs.alloc(sAllOutputs).mkBool(true); infoAttrs.alloc(sAllOutputs).mkBool(true);
if (!info.second.outputs.empty()) { if (!info.second.outputs.empty()) {
auto & outputsVal = infoAttrs.alloc(state.s.outputs); 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)) 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); attrs.alloc(state.store->printStorePath(info.first)).mkAttrs(infoAttrs);
} }

View file

@ -39,9 +39,9 @@ void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, Value &
auto array = toml::get<std::vector<toml::value>>(t); auto array = toml::get<std::vector<toml::value>>(t);
size_t size = array.size(); size_t size = array.size();
state.mkList(v, size); v = state.mem.newList(size);
for (size_t i = 0; i < size; ++i) 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;; break;;
case toml::value_t::boolean: case toml::value_t::boolean:

View file

@ -90,7 +90,7 @@ struct CmdBundle : InstallableCommand
lockFlags lockFlags
}; };
auto vRes = evalState->allocValue(); auto vRes = evalState->mem.allocValue();
evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos); evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos);
if (!evalState->isDerivation(*vRes)) if (!evalState->isDerivation(*vRes))

View file

@ -67,9 +67,9 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption
NixStringContext context; NixStringContext context;
if (apply) { if (apply) {
auto vApply = state->allocValue(); auto vApply = state->mem.allocValue();
state->eval(state->parseExprFromString(*apply, CanonPath::fromCwd()), *vApply); state->eval(state->parseExprFromString(*apply, CanonPath::fromCwd()), *vApply);
auto vRes = state->allocValue(); auto vRes = state->mem.allocValue();
state->callFunction(*vApply, *v, *vRes, noPos); state->callFunction(*vApply, *v, *vRes, noPos);
v = vRes; v = vRes;
} }

View file

@ -520,7 +520,7 @@ struct CmdFlakeCheck : FlakeCommand
try { try {
Activity act(*logger, lvlInfo, actUnknown, Activity act(*logger, lvlInfo, actUnknown,
fmt("checking NixOS configuration '%s'", attrPath)); 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; auto vToplevel = findAlongAttrPath(*state, "config.system.build.toplevel", bindings, v).first;
state->forceValue(*vToplevel, pos); state->forceValue(*vToplevel, pos);
if (!state->isDerivation(*vToplevel)) if (!state->isDerivation(*vToplevel))
@ -582,7 +582,7 @@ struct CmdFlakeCheck : FlakeCommand
{ {
Activity act(*logger, lvlInfo, actUnknown, "evaluating flake"); Activity act(*logger, lvlInfo, actUnknown, "evaluating flake");
auto vFlake = state->allocValue(); auto vFlake = state->mem.allocValue();
flake::callFlake(*state, flake, *vFlake); flake::callFlake(*state, flake, *vFlake);
enumerateOutputs(*state, enumerateOutputs(*state,

View file

@ -256,12 +256,12 @@ static void showHelp(std::vector<std::string> subcommand, NixArgs & toplevel)
evalSettings.pureEval.override(false); evalSettings.pureEval.override(false);
EvalState state({}, openStore("dummy://")); EvalState state({}, openStore("dummy://"));
auto vGenerateManpage = state.allocValue(); auto vGenerateManpage = state.mem.allocValue();
state.eval(state.parseExprFromString( state.eval(state.parseExprFromString(
#include "generate-manpage.nix.gen.hh" #include "generate-manpage.nix.gen.hh"
, CanonPath::root), *vGenerateManpage); , CanonPath::root), *vGenerateManpage);
auto vUtils = state.allocValue(); auto vUtils = state.mem.allocValue();
state.cacheFile( state.cacheFile(
CanonPath("/utils.nix"), CanonPath("/utils.nix"), CanonPath("/utils.nix"), CanonPath("/utils.nix"),
&state.parseExprFromString( &state.parseExprFromString(
@ -269,10 +269,10 @@ static void showHelp(std::vector<std::string> subcommand, NixArgs & toplevel)
, CanonPath::root), , CanonPath::root),
*vUtils); *vUtils);
auto vDump = state.allocValue(); auto vDump = state.mem.allocValue();
vDump->mkString(toplevel.dumpCli()); vDump->mkString(toplevel.dumpCli());
auto vRes = state.allocValue(); auto vRes = state.mem.allocValue();
state.callFunction(*vGenerateManpage, state.getBuiltin("false"), *vRes, noPos); state.callFunction(*vGenerateManpage, state.getBuiltin("false"), *vRes, noPos);
state.callFunction(*vRes, *vDump, *vRes, noPos); state.callFunction(*vRes, *vDump, *vRes, noPos);

View file

@ -75,7 +75,7 @@ struct CmdRepl : RawInstallablesCommand
auto what = installable.what(); auto what = installable.what();
state->forceValue(*val, pos); state->forceValue(*val, pos);
auto autoArgs = getAutoArgs(*state); auto autoArgs = getAutoArgs(*state);
auto valPost = state->allocValue(); auto valPost = state->mem.allocValue();
state->autoCallFunction(*autoArgs, *val, *valPost); state->autoCallFunction(*autoArgs, *val, *valPost);
state->forceValue(*valPost, pos); state->forceValue(*valPost, pos);
values.push_back( {valPost, what }); values.push_back( {valPost, what });

View file

@ -289,9 +289,9 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand
auto data = content->drain(); auto data = content->drain();
auto state = std::make_unique<EvalState>(SearchPath{}, store); auto state = std::make_unique<EvalState>(SearchPath{}, store);
auto v = state->allocValue(); auto v = state->mem.allocValue();
state->eval(state->parseExprFromString(data, CanonPath("/no-such-path")), *v); 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; auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first;
return store->parseStorePath(state->forceString(*v2, noPos, "while evaluating the path tho latest nix version")); return store->parseStorePath(state->forceString(*v2, noPos, "while evaluating the path tho latest nix version"));

View file

@ -25,7 +25,7 @@ RC_GTEST_FIXTURE_PROP(
prop_opaque_path_round_trip, prop_opaque_path_round_trip,
(const SingleDerivedPath::Opaque & o)) (const SingleDerivedPath::Opaque & o))
{ {
auto * v = state.allocValue(); auto * v = state.mem.allocValue();
state.mkStorePathString(o.path, *v); state.mkStorePathString(o.path, *v);
auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); auto d = state.coerceToSingleDerivedPath(noPos, *v, "");
RC_ASSERT(SingleDerivedPath { o } == d); RC_ASSERT(SingleDerivedPath { o } == d);
@ -46,7 +46,7 @@ RC_GTEST_FIXTURE_PROP(
ExperimentalFeatureSettings mockXpSettings; ExperimentalFeatureSettings mockXpSettings;
mockXpSettings.set("experimental-features", "ca-derivations"); mockXpSettings.set("experimental-features", "ca-derivations");
auto * v = state.allocValue(); auto * v = state.mem.allocValue();
state.mkOutputString(*v, b, std::nullopt, mockXpSettings); state.mkOutputString(*v, b, std::nullopt, mockXpSettings);
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "");
RC_ASSERT(SingleDerivedPath { b } == d); RC_ASSERT(SingleDerivedPath { b } == d);
@ -57,7 +57,7 @@ RC_GTEST_FIXTURE_PROP(
prop_derived_path_built_out_path_round_trip, prop_derived_path_built_out_path_round_trip,
(const SingleDerivedPath::Built & b, const StorePath & outPath)) (const SingleDerivedPath::Built & b, const StorePath & outPath))
{ {
auto * v = state.allocValue(); auto * v = state.mem.allocValue();
state.mkOutputString(*v, b, outPath); state.mkOutputString(*v, b, outPath);
auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, "");
RC_ASSERT(SingleDerivedPath { b } == d); RC_ASSERT(SingleDerivedPath { b } == d);

View file

@ -61,7 +61,7 @@ TEST_F(ValuePrintingTests, tAttrs)
Value vTwo; Value vTwo;
vTwo.mkInt(2); 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("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo); builder.insert(state.symbols.create("two"), &vTwo);
@ -79,8 +79,7 @@ TEST_F(ValuePrintingTests, tList)
Value vTwo; Value vTwo;
vTwo.mkInt(2); vTwo.mkInt(2);
Value vList; Value vList = state.mem.newList(5);
state.mkList(vList, 5);
vList.bigList.elems[0] = &vOne; vList.bigList.elems[0] = &vOne;
vList.bigList.elems[1] = &vTwo; vList.bigList.elems[1] = &vTwo;
vList.bigList.size = 3; vList.bigList.size = 3;
@ -202,16 +201,16 @@ TEST_F(ValuePrintingTests, depthAttrs)
Value vTwo; Value vTwo;
vTwo.mkInt(2); vTwo.mkInt(2);
BindingsBuilder builderEmpty(state, state.allocBindings(0)); BindingsBuilder builderEmpty = state.buildBindings(0);
Value vAttrsEmpty; Value vAttrsEmpty;
vAttrsEmpty.mkAttrs(builderEmpty.finish()); vAttrsEmpty.mkAttrs(builderEmpty.finish());
BindingsBuilder builderNested(state, state.allocBindings(1)); BindingsBuilder builderNested = state.buildBindings(1);
builderNested.insert(state.symbols.create("zero"), &vZero); builderNested.insert(state.symbols.create("zero"), &vZero);
Value vAttrsNested; Value vAttrsNested;
vAttrsNested.mkAttrs(builderNested.finish()); 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("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo); builder.insert(state.symbols.create("two"), &vTwo);
builder.insert(state.symbols.create("empty"), &vAttrsEmpty); builder.insert(state.symbols.create("empty"), &vAttrsEmpty);
@ -220,7 +219,7 @@ TEST_F(ValuePrintingTests, depthAttrs)
Value vAttrs; Value vAttrs;
vAttrs.mkAttrs(builder.finish()); 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("one"), &vOne);
builder2.insert(state.symbols.create("two"), &vTwo); builder2.insert(state.symbols.create("two"), &vTwo);
builder2.insert(state.symbols.create("nested"), &vAttrs); builder2.insert(state.symbols.create("nested"), &vAttrs);
@ -242,14 +241,14 @@ TEST_F(ValuePrintingTests, depthList)
Value vTwo; Value vTwo;
vTwo.mkInt(2); 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("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo); builder.insert(state.symbols.create("two"), &vTwo);
Value vAttrs; Value vAttrs;
vAttrs.mkAttrs(builder.finish()); 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("one"), &vOne);
builder2.insert(state.symbols.create("two"), &vTwo); builder2.insert(state.symbols.create("two"), &vTwo);
builder2.insert(state.symbols.create("nested"), &vAttrs); builder2.insert(state.symbols.create("nested"), &vAttrs);
@ -257,8 +256,7 @@ TEST_F(ValuePrintingTests, depthList)
Value vNested; Value vNested;
vNested.mkAttrs(builder2.finish()); vNested.mkAttrs(builder2.finish());
Value vList; Value vList = state.mem.newList(5);
state.mkList(vList, 5);
vList.bigList.elems[0] = &vOne; vList.bigList.elems[0] = &vOne;
vList.bigList.elems[1] = &vTwo; vList.bigList.elems[1] = &vTwo;
vList.bigList.elems[2] = &vNested; vList.bigList.elems[2] = &vNested;
@ -306,7 +304,7 @@ TEST_F(ValuePrintingTests, attrsTypeFirst)
Value vApple; Value vApple;
vApple.mkString("apple"); 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("type"), &vType);
builder.insert(state.symbols.create("apple"), &vApple); builder.insert(state.symbols.create("apple"), &vApple);
@ -417,7 +415,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrs)
Value vTwo; Value vTwo;
vTwo.mkInt(2); 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("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo); builder.insert(state.symbols.create("two"), &vTwo);
@ -436,7 +434,7 @@ TEST_F(ValuePrintingTests, ansiColorsDerivation)
Value vDerivation; Value vDerivation;
vDerivation.mkString("derivation"); vDerivation.mkString("derivation");
BindingsBuilder builder(state, state.allocBindings(10)); BindingsBuilder builder = state.buildBindings(10);
builder.insert(state.s.type, &vDerivation); builder.insert(state.s.type, &vDerivation);
Value vAttrs; Value vAttrs;
@ -487,7 +485,7 @@ TEST_F(ValuePrintingTests, ansiColorsDerivationError)
Value vDerivation; Value vDerivation;
vDerivation.mkString("derivation"); vDerivation.mkString("derivation");
BindingsBuilder builder(state, state.allocBindings(10)); BindingsBuilder builder = state.buildBindings(10);
builder.insert(state.s.type, &vDerivation); builder.insert(state.s.type, &vDerivation);
builder.insert(state.s.drvPath, &vError); builder.insert(state.s.drvPath, &vError);
@ -546,8 +544,7 @@ TEST_F(ValuePrintingTests, ansiColorsList)
Value vTwo; Value vTwo;
vTwo.mkInt(2); vTwo.mkInt(2);
Value vList; Value vList = state.mem.newList(5);
state.mkList(vList, 5);
vList.bigList.elems[0] = &vOne; vList.bigList.elems[0] = &vOne;
vList.bigList.elems[1] = &vTwo; vList.bigList.elems[1] = &vTwo;
vList.bigList.size = 3; vList.bigList.size = 3;
@ -653,13 +650,13 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsRepeated)
Value vZero; Value vZero;
vZero.mkInt(0); vZero.mkInt(0);
BindingsBuilder innerBuilder(state, state.allocBindings(1)); BindingsBuilder innerBuilder = state.buildBindings(1);
innerBuilder.insert(state.symbols.create("x"), &vZero); innerBuilder.insert(state.symbols.create("x"), &vZero);
Value vInner; Value vInner;
vInner.mkAttrs(innerBuilder.finish()); 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("a"), &vInner);
builder.insert(state.symbols.create("b"), &vInner); builder.insert(state.symbols.create("b"), &vInner);
@ -678,14 +675,13 @@ TEST_F(ValuePrintingTests, ansiColorsListRepeated)
Value vZero; Value vZero;
vZero.mkInt(0); vZero.mkInt(0);
BindingsBuilder innerBuilder(state, state.allocBindings(1)); BindingsBuilder innerBuilder = state.buildBindings(1);
innerBuilder.insert(state.symbols.create("x"), &vZero); innerBuilder.insert(state.symbols.create("x"), &vZero);
Value vInner; Value vInner;
vInner.mkAttrs(innerBuilder.finish()); vInner.mkAttrs(innerBuilder.finish());
Value vList; Value vList = state.mem.newList(3);
state.mkList(vList, 3);
vList.bigList.elems[0] = &vInner; vList.bigList.elems[0] = &vInner;
vList.bigList.elems[1] = &vInner; vList.bigList.elems[1] = &vInner;
vList.bigList.size = 2; vList.bigList.size = 2;
@ -702,14 +698,13 @@ TEST_F(ValuePrintingTests, listRepeated)
Value vZero; Value vZero;
vZero.mkInt(0); vZero.mkInt(0);
BindingsBuilder innerBuilder(state, state.allocBindings(1)); BindingsBuilder innerBuilder = state.buildBindings(1);
innerBuilder.insert(state.symbols.create("x"), &vZero); innerBuilder.insert(state.symbols.create("x"), &vZero);
Value vInner; Value vInner;
vInner.mkAttrs(innerBuilder.finish()); vInner.mkAttrs(innerBuilder.finish());
Value vList; Value vList = state.mem.newList(3);
state.mkList(vList, 3);
vList.bigList.elems[0] = &vInner; vList.bigList.elems[0] = &vInner;
vList.bigList.elems[1] = &vInner; vList.bigList.elems[1] = &vInner;
vList.bigList.size = 2; vList.bigList.size = 2;
@ -730,7 +725,7 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided)
Value vTwo; Value vTwo;
vTwo.mkInt(2); 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("one"), &vOne);
builder.insert(state.symbols.create("two"), &vTwo); builder.insert(state.symbols.create("two"), &vTwo);
@ -760,16 +755,13 @@ TEST_F(ValuePrintingTests, ansiColorsAttrsElided)
TEST_F(ValuePrintingTests, ansiColorsListElided) TEST_F(ValuePrintingTests, ansiColorsListElided)
{ {
BindingsBuilder emptyBuilder(state, state.allocBindings(1));
Value vOne; Value vOne;
vOne.mkInt(1); vOne.mkInt(1);
Value vTwo; Value vTwo;
vTwo.mkInt(2); vTwo.mkInt(2);
Value vList; Value vList = state.mem.newList(4);
state.mkList(vList, 4);
vList.bigList.elems[0] = &vOne; vList.bigList.elems[0] = &vOne;
vList.bigList.elems[1] = &vTwo; vList.bigList.elems[1] = &vTwo;
vList.bigList.size = 2; vList.bigList.size = 2;