diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index b0e9c190d..bef32d3df 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -57,12 +57,12 @@ #define TRACY_TRACE(evalstate, expr) \ std::ostringstream tracyss; \ - tracyss << evalstate.positions[(expr)->getPos()] << " " << (expr)->showExprType(); \ + tracyss << (evalstate).positions[(expr)->getPos()] << " " << (expr)->showExprType(); \ ZoneTransientN(nix, tracyss.str().c_str(), true); #define TRACY_TRACE_TYPE_STR(evalstate, expr, typestr) \ std::ostringstream tracyss; \ - tracyss << (evalstate).positions[(expr)->getPos()] << " " << typestr; \ + tracyss << (evalstate).positions[(expr)->getPos()] << " " << typestr; \ ZoneTransientN(nix, tracyss.str().c_str(), true); using json = nlohmann::json; @@ -81,7 +81,6 @@ static char * allocString(size_t size) return t; } - static char * dupString(const char * s) { char * t; diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 9529b8a1e..4436a8eb8 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -21,6 +21,12 @@ libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS) ifdef HOST_LINUX libexpr_LDFLAGS += -ldl endif +ifneq ($(TRACY_PROFILER), no) +libexpr_LDFLAGS += -ltracy +# We have to set TRACY_ENABLE to have tracy actually send the trace +# events, it's no-op without them. +libexpr_CXXFLAGS += -DTRACY_ENABLE=1 +endif # The dependency on libgc must be propagated (i.e. meaning that # programs/libraries that use libexpr must explicitly pass -lgc), diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index f8ded0cf8..5be38c661 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -32,6 +32,13 @@ #include +#include + +#define TRACY_TRACE_PRIMOP(es, posidx, typestr) \ + std::ostringstream tracyss; \ + tracyss << es.positions[posidx] << " " << typestr; \ + ZoneTransientN(nix, tracyss.str().c_str(), true); + namespace nix { @@ -120,6 +127,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context) static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, bool resolveSymlinks = true) { + TRACY_TRACE_PRIMOP(state, pos, "realizePath"); NixStringContext context; auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path"); @@ -170,6 +178,7 @@ static void mkOutputString( argument. */ static void import(EvalState & state, const PosIdx pos, Value & vPath, Value * vScope, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.import"); auto path = realisePath(state, pos, vPath, false); auto path2 = path.path.abs(); @@ -334,6 +343,7 @@ extern "C" typedef void (*ValueInitializer)(EvalState & state, Value & v); /* Load a ValueInitializer from a DSO and return whatever it initializes */ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.importNative"); auto path = realisePath(state, pos, *args[0]); std::string sym(state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.importNative")); @@ -361,6 +371,7 @@ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Valu /* Execute a program and parse its output */ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.exec"); state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.exec"); auto elems = args[0]->listElems(); auto count = args[0]->listSize(); @@ -402,6 +413,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v) /* Return a string representing the type of the expression. */ static void prim_typeOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.typeOf"); state.forceValue(*args[0], pos); std::string t; switch (args[0]->type()) { @@ -436,6 +448,7 @@ static RegisterPrimOp primop_typeOf({ /* Determine whether the argument is the null value. */ static void prim_isNull(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isNull"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nNull); } @@ -454,6 +467,7 @@ static RegisterPrimOp primop_isNull({ /* Determine whether the argument is a function. */ static void prim_isFunction(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isFunction"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nFunction); } @@ -470,6 +484,7 @@ static RegisterPrimOp primop_isFunction({ /* Determine whether the argument is an integer. */ static void prim_isInt(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isInt"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nInt); } @@ -486,6 +501,7 @@ static RegisterPrimOp primop_isInt({ /* Determine whether the argument is a float. */ static void prim_isFloat(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isFloat"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nFloat); } @@ -502,6 +518,7 @@ static RegisterPrimOp primop_isFloat({ /* Determine whether the argument is a string. */ static void prim_isString(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isString"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nString); } @@ -518,6 +535,7 @@ static RegisterPrimOp primop_isString({ /* Determine whether the argument is a Boolean. */ static void prim_isBool(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isBool"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nBool); } @@ -534,6 +552,7 @@ static RegisterPrimOp primop_isBool({ /* Determine whether the argument is a path. */ static void prim_isPath(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isPath"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nPath); } @@ -644,6 +663,7 @@ static Bindings::iterator getAttr( static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.genericClosure"); state.forceAttrs(*args[0], noPos, "while evaluating the first argument passed to builtins.genericClosure"); /* Get the start set. */ @@ -754,6 +774,7 @@ static RegisterPrimOp primop_break({ )", .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.break"); if (state.debugRepl && !state.debugTraces.empty()) { auto error = Error(ErrorInfo { .level = lvlInfo, @@ -787,6 +808,7 @@ static RegisterPrimOp primop_abort({ )", .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.abort"); NixStringContext context; auto s = state.coerceToString(pos, *args[0], context, "while evaluating the error message passed to builtins.abort").toOwned(); @@ -806,6 +828,7 @@ static RegisterPrimOp primop_throw({ )", .fun = [](EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.throw"); NixStringContext context; auto s = state.coerceToString(pos, *args[0], context, "while evaluating the error message passed to builtin.throw").toOwned(); @@ -815,6 +838,7 @@ static RegisterPrimOp primop_throw({ static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.addErrorContext"); try { state.forceValue(*args[1], pos); v = *args[1]; @@ -836,6 +860,7 @@ static RegisterPrimOp primop_addErrorContext(PrimOp { static void prim_ceil(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.ceil"); auto value = state.forceFloat(*args[0], args[0]->determinePos(pos), "while evaluating the first argument passed to builtins.ceil"); v.mkInt(ceil(value)); @@ -856,6 +881,7 @@ static RegisterPrimOp primop_ceil({ static void prim_floor(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.floor"); auto value = state.forceFloat(*args[0], args[0]->determinePos(pos), "while evaluating the first argument passed to builtins.floor"); v.mkInt(floor(value)); } @@ -877,6 +903,7 @@ static RegisterPrimOp primop_floor({ * else => {success=false; value=false;} */ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.tryEval"); auto attrs = state.buildBindings(2); /* increment state.trylevel, and decrement it when this function returns. */ @@ -930,6 +957,7 @@ static RegisterPrimOp primop_tryEval({ /* Return an environment variable. Use with care. */ static void prim_getEnv(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.getEnv"); std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getEnv")); v.mkString(evalSettings.restrictEval || evalSettings.pureEval ? "" : getEnv(name).value_or("")); } @@ -954,6 +982,7 @@ static RegisterPrimOp primop_getEnv({ /* Evaluate the first argument, then return the second argument. */ static void prim_seq(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.seq"); state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); v = *args[1]; @@ -973,6 +1002,7 @@ static RegisterPrimOp primop_seq({ attrsets), then return the second argument. */ static void prim_deepSeq(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.deepSeq"); state.forceValueDeep(*args[0]); state.forceValue(*args[1], pos); v = *args[1]; @@ -993,6 +1023,7 @@ static RegisterPrimOp primop_deepSeq({ return the second expression. Useful for debugging. */ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.trace"); state.forceValue(*args[0], pos); if (args[0]->type() == nString) printError("trace: %1%", args[0]->string_view()); @@ -1019,6 +1050,7 @@ static RegisterPrimOp primop_trace({ */ static void prim_second(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.second"); state.forceValue(*args[1], pos); v = *args[1]; } @@ -1038,6 +1070,7 @@ static void derivationStrictInternal(EvalState & state, const std::string & name derivation. */ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.derivationStrict"); state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.derivationStrict"); Bindings * attrs = args[0]->attrs; @@ -1436,6 +1469,7 @@ static RegisterPrimOp primop_derivationStrict(PrimOp { ‘out’. */ static void prim_placeholder(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.placeholder"); v.mkString(hashPlaceholder(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.placeholder"))); } @@ -1459,6 +1493,7 @@ static RegisterPrimOp primop_placeholder({ /* Convert the argument to a path. !!! obsolete? */ static void prim_toPath(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.toPath"); NixStringContext context; auto path = state.coerceToPath(pos, *args[0], context, "while evaluating the first argument passed to builtins.toPath"); v.mkString(path.path.abs(), context); @@ -1484,6 +1519,7 @@ static RegisterPrimOp primop_toPath({ corner cases. */ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.storePath"); if (evalSettings.pureEval) state.debugThrowLastTrace(EvalError({ .msg = hintfmt("'%s' is not allowed in pure evaluation mode", "builtins.storePath"), @@ -1531,6 +1567,7 @@ static RegisterPrimOp primop_storePath({ static void prim_pathExists(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.pathExists"); try { auto & arg = *args[0]; @@ -1563,6 +1600,7 @@ static RegisterPrimOp primop_pathExists({ following the last slash. */ static void prim_baseNameOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.baseNameOf"); NixStringContext context; v.mkString(baseNameOf(*state.coerceToString(pos, *args[0], context, "while evaluating the first argument passed to builtins.baseNameOf", @@ -1585,6 +1623,7 @@ static RegisterPrimOp primop_baseNameOf({ of the argument. */ static void prim_dirOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.dirOf"); state.forceValue(*args[0], pos); if (args[0]->type() == nPath) { auto path = args[0]->path(); @@ -1613,6 +1652,7 @@ static RegisterPrimOp primop_dirOf({ /* Return the contents of a file as a string. */ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.readFile"); auto path = realisePath(state, pos, *args[0]); auto s = path.readFile(); if (s.find((char) 0) != std::string::npos) @@ -1650,6 +1690,7 @@ static RegisterPrimOp primop_readFile({ which are desugared to 'findFile __nixPath "x"'. */ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.findFile"); state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.findFile"); SearchPath searchPath; @@ -1742,6 +1783,7 @@ static RegisterPrimOp primop_findFile(PrimOp { /* Return the cryptographic hash of a file in base-16. */ static void prim_hashFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.hashFile"); auto algo = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashFile"); std::optional ha = parseHashAlgo(algo); if (!ha) @@ -1777,6 +1819,7 @@ static std::string_view fileTypeToString(InputAccessor::Type type) static void prim_readFileType(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.readFileType"); auto path = realisePath(state, pos, *args[0], false); /* Retrieve the directory entry type and stringize it. */ v.mkString(fileTypeToString(path.lstat().type)); @@ -1795,6 +1838,7 @@ static RegisterPrimOp primop_readFileType({ /* Read a directory (without . or ..) */ static void prim_readDir(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.readDir"); auto path = realisePath(state, pos, *args[0]); // Retrieve directory entries for all nodes in a directory. @@ -1852,6 +1896,7 @@ static RegisterPrimOp primop_readDir({ /* Extend single element string context with another output. */ static void prim_outputOf(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.outputOf"); SingleDerivedPath drvPath = state.coerceToSingleDerivedPath(pos, *args[0], "while evaluating the first argument to builtins.outputOf"); OutputNameView outputName = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument to builtins.outputOf"); @@ -1899,6 +1944,7 @@ static RegisterPrimOp primop_outputOf({ be sensibly or completely represented (e.g., functions). */ static void prim_toXML(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.toXML"); std::ostringstream out; NixStringContext context; printValueAsXML(state, true, false, *args[0], out, context, pos); @@ -2007,6 +2053,7 @@ static RegisterPrimOp primop_toXML({ represented (e.g., functions). */ static void prim_toJSON(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.toJSON"); std::ostringstream out; NixStringContext context; printValueAsJSON(state, true, *args[0], pos, out, context); @@ -2030,6 +2077,7 @@ static RegisterPrimOp primop_toJSON({ /* Parse a JSON string to a value. */ static void prim_fromJSON(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.fromJSON"); auto s = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.fromJSON"); try { parseJSON(state, s, v); @@ -2058,6 +2106,7 @@ static RegisterPrimOp primop_fromJSON({ as an input by derivations. */ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.toFile"); NixStringContext context; std::string name(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.toFile")); std::string contents(state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.toFile")); @@ -2207,6 +2256,7 @@ static void addPath( Value & v, const NixStringContext & context) { + TRACY_TRACE_PRIMOP(state, pos, "primop.addPath"); try { StorePathSet refs; @@ -2256,6 +2306,7 @@ static void addPath( static void prim_filterSource(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.filterSource"); NixStringContext context; auto path = state.coerceToPath(pos, *args[1], context, "while evaluating the second argument (the path to filter) passed to 'builtins.filterSource'"); @@ -2321,6 +2372,7 @@ static RegisterPrimOp primop_filterSource({ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.path"); std::optional path; std::string name; Value * filterFun = nullptr; @@ -2404,6 +2456,7 @@ static RegisterPrimOp primop_path({ strings. */ static void prim_attrNames(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.attrNames"); state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.attrNames"); state.mkList(v, args[0]->attrs->size()); @@ -2431,6 +2484,7 @@ static RegisterPrimOp primop_attrNames({ order as attrNames. */ static void prim_attrValues(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.attrValues"); state.forceAttrs(*args[0], pos, "while evaluating the argument passed to builtins.attrValues"); state.mkList(v, args[0]->attrs->size()); @@ -2463,6 +2517,7 @@ static RegisterPrimOp primop_attrValues({ /* Dynamic version of the `.' operator. */ void prim_getAttr(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.getAttr"); auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.getAttr"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.getAttr"); Bindings::iterator i = getAttr( @@ -2492,6 +2547,7 @@ static RegisterPrimOp primop_getAttr({ /* Return position information of the specified attribute. */ static void prim_unsafeGetAttrPos(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.unsafeGetAttrPos"); auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.unsafeGetAttrPos"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.unsafeGetAttrPos"); Bindings::iterator i = args[1]->attrs->find(state.symbols.create(attr)); @@ -2510,6 +2566,7 @@ static RegisterPrimOp primop_unsafeGetAttrPos(PrimOp { /* Dynamic version of the `?' operator. */ static void prim_hasAttr(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.hasAttr"); auto attr = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hasAttr"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.hasAttr"); v.mkBool(args[1]->attrs->find(state.symbols.create(attr)) != args[1]->attrs->end()); @@ -2544,6 +2601,7 @@ static RegisterPrimOp primop_isAttrs({ static void prim_removeAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.removeAttrs"); state.forceAttrs(*args[0], pos, "while evaluating the first argument passed to builtins.removeAttrs"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.removeAttrs"); @@ -2593,6 +2651,7 @@ static RegisterPrimOp primop_removeAttrs({ name, the first takes precedence. */ static void prim_listToAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.listToAttrs"); state.forceList(*args[0], pos, "while evaluating the argument passed to builtins.listToAttrs"); auto attrs = state.buildBindings(args[0]->listSize()); @@ -2649,6 +2708,7 @@ static RegisterPrimOp primop_listToAttrs({ static void prim_intersectAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.intersectAttrs"); state.forceAttrs(*args[0], pos, "while evaluating the first argument passed to builtins.intersectAttrs"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.intersectAttrs"); @@ -2727,6 +2787,7 @@ static RegisterPrimOp primop_intersectAttrs({ static void prim_catAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.catAttrs"); auto attrName = state.symbols.create(state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.catAttrs")); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.catAttrs"); @@ -2764,6 +2825,7 @@ static RegisterPrimOp primop_catAttrs({ static void prim_functionArgs(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.functionArgs"); state.forceValue(*args[0], pos); if (args[0]->isPrimOpApp() || args[0]->isPrimOp()) { v.mkAttrs(&state.emptyBindings); @@ -2807,6 +2869,7 @@ static RegisterPrimOp primop_functionArgs({ /* */ static void prim_mapAttrs(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.mapAttrs"); state.forceAttrs(*args[1], pos, "while evaluating the second argument passed to builtins.mapAttrs"); auto attrs = state.buildBindings(args[1]->attrs->size()); @@ -2839,6 +2902,7 @@ static RegisterPrimOp primop_mapAttrs({ static void prim_zipAttrsWith(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.zipAttrsWith"); // we will first count how many values are present for each given key. // we then allocate a single attrset and pre-populate it with lists of // appropriate sizes, stash the pointers to the list elements of each, @@ -2926,6 +2990,7 @@ static RegisterPrimOp primop_zipAttrsWith({ /* Determine whether the argument is a list. */ static void prim_isList(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.isList"); state.forceValue(*args[0], pos); v.mkBool(args[0]->type() == nList); } @@ -2954,6 +3019,7 @@ static void elemAt(EvalState & state, const PosIdx pos, Value & list, int n, Val /* Return the n-1'th element of a list. */ static void prim_elemAt(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.elemAt"); elemAt(state, pos, *args[0], state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.elemAt"), v); } @@ -2970,6 +3036,7 @@ static RegisterPrimOp primop_elemAt({ /* Return the first element of a list. */ static void prim_head(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.head"); elemAt(state, pos, *args[0], 0, v); } @@ -2989,6 +3056,7 @@ static RegisterPrimOp primop_head({ don't want to use it! */ static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.tail"); state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.tail"); if (args[0]->listSize() == 0) state.debugThrowLastTrace(Error({ @@ -3020,6 +3088,7 @@ static RegisterPrimOp primop_tail({ /* Apply a function to every element of a list. */ static void prim_map(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.map"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.map"); if (args[1]->listSize() == 0) { @@ -3056,6 +3125,7 @@ static RegisterPrimOp primop_map({ returns true. */ static void prim_filter(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.filter"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.filter"); if (args[1]->listSize() == 0) { @@ -3099,6 +3169,7 @@ static RegisterPrimOp primop_filter({ /* Return true if a list contains a given element. */ static void prim_elem(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.elem"); bool res = false; state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.elem"); for (auto elem : args[1]->listItems()) @@ -3122,6 +3193,7 @@ static RegisterPrimOp primop_elem({ /* Concatenate a list of lists. */ static void prim_concatLists(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.concatLists"); state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.concatLists"); state.concatLists(v, args[0]->listSize(), args[0]->listElems(), pos, "while evaluating a value of the list passed to builtins.concatLists"); } @@ -3138,6 +3210,7 @@ static RegisterPrimOp primop_concatLists({ /* Return the length of a list. This is an O(1) time operation. */ static void prim_length(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.length"); state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.length"); v.mkInt(args[0]->listSize()); } @@ -3155,6 +3228,7 @@ static RegisterPrimOp primop_length({ right. The operator is applied strictly. */ static void prim_foldlStrict(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.foldStrict"); state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.foldlStrict"); state.forceList(*args[2], pos, "while evaluating the third argument passed to builtins.foldlStrict"); @@ -3218,6 +3292,7 @@ static void anyOrAll(bool any, EvalState & state, const PosIdx pos, Value * * ar static void prim_any(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.any"); anyOrAll(true, state, pos, args, v); } @@ -3233,6 +3308,7 @@ static RegisterPrimOp primop_any({ static void prim_all(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.all"); anyOrAll(false, state, pos, args, v); } @@ -3248,6 +3324,7 @@ static RegisterPrimOp primop_all({ static void prim_genList(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.genList"); auto len = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.genList"); if (len < 0) @@ -3286,6 +3363,7 @@ static void prim_lessThan(EvalState & state, const PosIdx pos, Value * * args, V static void prim_sort(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.sort"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.sort"); auto len = args[1]->listSize(); @@ -3345,6 +3423,7 @@ static RegisterPrimOp primop_sort({ static void prim_partition(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.partition"); state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.partition"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.partition"); @@ -3405,6 +3484,7 @@ static RegisterPrimOp primop_partition({ static void prim_groupBy(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.groupBy"); state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.groupBy"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.groupBy"); @@ -3457,6 +3537,7 @@ static RegisterPrimOp primop_groupBy({ static void prim_concatMap(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.concatMap"); state.forceFunction(*args[0], pos, "while evaluating the first argument passed to builtins.concatMap"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.concatMap"); auto nrLists = args[1]->listSize(); @@ -3500,6 +3581,7 @@ static RegisterPrimOp primop_concatMap({ static void prim_add(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.add"); state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); if (args[0]->type() == nFloat || args[1]->type() == nFloat) @@ -3521,6 +3603,7 @@ static RegisterPrimOp primop_add({ static void prim_sub(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.sub"); state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); if (args[0]->type() == nFloat || args[1]->type() == nFloat) @@ -3542,6 +3625,7 @@ static RegisterPrimOp primop_sub({ static void prim_mul(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.mul"); state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); if (args[0]->type() == nFloat || args[1]->type() == nFloat) @@ -3563,6 +3647,7 @@ static RegisterPrimOp primop_mul({ static void prim_div(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.div"); state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); @@ -3600,6 +3685,7 @@ static RegisterPrimOp primop_div({ static void prim_bitAnd(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.bitAnd"); v.mkInt(state.forceInt(*args[0], pos, "while evaluating the first argument passed to builtins.bitAnd") & state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.bitAnd")); } @@ -3645,6 +3731,7 @@ static RegisterPrimOp primop_bitXor({ static void prim_lessThan(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.lessThan"); state.forceValue(*args[0], pos); state.forceValue(*args[1], pos); // pos is exact here, no need for a message. @@ -3674,6 +3761,7 @@ static RegisterPrimOp primop_lessThan({ `"/nix/store/whatever..."'. */ static void prim_toString(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.toString"); NixStringContext context; auto s = state.coerceToString(pos, *args[0], context, "while evaluating the first argument passed to builtins.toString", @@ -3711,6 +3799,7 @@ static RegisterPrimOp primop_toString({ non-negative. */ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.substring"); int start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring"); if (start < 0) @@ -3761,6 +3850,7 @@ static RegisterPrimOp primop_substring({ static void prim_stringLength(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.stringLength"); NixStringContext context; auto s = state.coerceToString(pos, *args[0], context, "while evaluating the argument passed to builtins.stringLength"); v.mkInt(s->size()); @@ -3779,6 +3869,7 @@ static RegisterPrimOp primop_stringLength({ /* Return the cryptographic hash of a string in base-16. */ static void prim_hashString(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.hashString"); auto algo = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashString"); std::optional ha = parseHashAlgo(algo); if (!ha) @@ -3806,6 +3897,7 @@ static RegisterPrimOp primop_hashString({ static void prim_convertHash(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.convertHash"); state.forceAttrs(*args[0], pos, "while evaluating the first argument passed to builtins.convertHash"); auto &inputAttrs = args[0]->attrs; @@ -3923,6 +4015,7 @@ std::shared_ptr makeRegexCache() void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.match"); auto re = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.match"); try { @@ -4003,6 +4096,7 @@ static RegisterPrimOp primop_match({ non-matching parts interleaved by the lists of the matching groups. */ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.split"); auto re = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.split"); try { @@ -4106,6 +4200,7 @@ static RegisterPrimOp primop_split({ static void prim_concatStringsSep(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.concatStringsSep"); NixStringContext context; auto sep = state.forceString(*args[0], context, pos, "while evaluating the first argument (the separator string) passed to builtins.concatStringsSep"); @@ -4136,6 +4231,7 @@ static RegisterPrimOp primop_concatStringsSep({ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.replaceStrings"); state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.replaceStrings"); state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.replaceStrings"); if (args[0]->listSize() != args[1]->listSize()) @@ -4218,6 +4314,7 @@ static RegisterPrimOp primop_replaceStrings({ static void prim_parseDrvName(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.parseDrvName"); auto name = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.parseDrvName"); DrvName parsed(name); auto attrs = state.buildBindings(2); @@ -4242,6 +4339,7 @@ static RegisterPrimOp primop_parseDrvName({ static void prim_compareVersions(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.compareVersions"); auto version1 = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.compareVersions"); auto version2 = state.forceStringNoCtx(*args[1], pos, "while evaluating the second argument passed to builtins.compareVersions"); v.mkInt(compareVersions(version1, version2)); @@ -4262,6 +4360,7 @@ static RegisterPrimOp primop_compareVersions({ static void prim_splitVersion(EvalState & state, const PosIdx pos, Value * * args, Value & v) { + TRACY_TRACE_PRIMOP(state, pos, "primop.splitVersion"); auto version = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.splitVersion"); auto iter = version.cbegin(); Strings components;