diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 7943f73ad..872c98404 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -55,6 +55,11 @@ #endif +#define TRACY_TRACE(evalstate, expr) \ + std::ostringstream tracyss; \ + tracyss << evalstate.positions[(expr)->getPos()] << " " << (expr)->showExprType(); \ + ZoneTransientN(nix, tracyss.str().c_str(), true); + using json = nlohmann::json; namespace nix { @@ -1204,29 +1209,34 @@ void Expr::eval(EvalState & state, Env & env, Value & v) void ExprInt::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v = this->v; } void ExprFloat::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v = this->v; } void ExprString::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v = this->v; } void ExprPath::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v = this->v; } void ExprAttrs::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v.mkAttrs(state.buildBindings(attrs.size() + dynamicAttrs.size()).finish()); auto dynamicEnv = &env; @@ -1311,6 +1321,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v) void ExprLet::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); /* Create a new environment that contains the attributes in this `let'. */ Env & env2(state.allocEnv(attrs->attrs.size())); @@ -1329,6 +1340,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v) void ExprList::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); state.mkList(v, elems.size()); for (auto [n, v2] : enumerate(v.listItems())) const_cast(v2) = elems[n]->maybeThunk(state, env); @@ -1337,6 +1349,7 @@ void ExprList::eval(EvalState & state, Env & env, Value & v) Value * ExprList::maybeThunk(EvalState & state, Env & env) { + TRACY_TRACE(state, this); if (elems.empty()) { return &state.vEmptyList; } @@ -1346,6 +1359,7 @@ Value * ExprList::maybeThunk(EvalState & state, Env & env) void ExprVar::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Value * v2 = state.lookupVar(&env, *this, false); state.forceValue(*v2, pos); v = *v2; @@ -1373,7 +1387,7 @@ static std::string showAttrPath(EvalState & state, Env & env, const AttrPath & a void ExprSelect::eval(EvalState & state, Env & env, Value & v) { - ZoneScopedN("select"); + TRACY_TRACE(state, this) Value vTmp; PosIdx pos2; Value * vAttrs = &vTmp; @@ -1438,6 +1452,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v) void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this) Value vTmp; Value * vAttrs = &vTmp; @@ -1463,6 +1478,7 @@ void ExprOpHasAttr::eval(EvalState & state, Env & env, Value & v) void ExprLambda::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this) v.mkLambda(&env, this); } @@ -1720,6 +1736,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & void ExprCall::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Value vFun; fun->eval(state, env, vFun); @@ -1797,6 +1814,7 @@ https://nixos.org/manual/nix/stable/language/constructs.html#functions.)", symbo void ExprWith::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Env & env2(state.allocEnv(1)); env2.up = &env; env2.values[0] = attrs->maybeThunk(state, env); @@ -1807,6 +1825,7 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v) void ExprIf::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); // We cheat in the parser, and pass the position of the condition as the position of the if itself. (state.evalBool(env, cond, pos, "while evaluating a branch condition") ? then : else_)->eval(state, env, v); } @@ -1814,6 +1833,7 @@ void ExprIf::eval(EvalState & state, Env & env, Value & v) void ExprAssert::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); if (!state.evalBool(env, cond, pos, "in the condition of the assert statement")) { std::ostringstream out; cond->show(state.symbols, out); @@ -1825,12 +1845,14 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v) void ExprOpNot::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v.mkBool(!state.evalBool(env, e, getPos(), "in the argument of the not operator")); // XXX: FIXME: ! } void ExprOpEq::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Value v1; e1->eval(state, env, v1); Value v2; e2->eval(state, env, v2); v.mkBool(state.eqValues(v1, v2, pos, "while testing two values for equality")); @@ -1839,6 +1861,7 @@ void ExprOpEq::eval(EvalState & state, Env & env, Value & v) void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Value v1; e1->eval(state, env, v1); Value v2; e2->eval(state, env, v2); v.mkBool(!state.eqValues(v1, v2, pos, "while testing two values for inequality")); @@ -1847,6 +1870,7 @@ void ExprOpNEq::eval(EvalState & state, Env & env, Value & v) void ExprOpAnd::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v.mkBool(state.evalBool(env, e1, pos, "in the left operand of the AND (&&) operator") && state.evalBool(env, e2, pos, "in the right operand of the AND (&&) operator")); } @@ -1859,12 +1883,14 @@ void ExprOpOr::eval(EvalState & state, Env & env, Value & v) void ExprOpImpl::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); v.mkBool(!state.evalBool(env, e1, pos, "in the left operand of the IMPL (->) operator") || state.evalBool(env, e2, pos, "in the right operand of the IMPL (->) operator")); } void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Value v1, v2; state.evalAttrs(env, e1, v1, pos, "in the left operand of the update (//) operator"); state.evalAttrs(env, e2, v2, pos, "in the right operand of the update (//) operator"); @@ -1903,6 +1929,7 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v) void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); Value v1; e1->eval(state, env, v1); Value v2; e2->eval(state, env, v2); Value * lists[2] = { &v1, &v2 }; @@ -1941,6 +1968,7 @@ void EvalState::concatLists(Value & v, size_t nrLists, Value * * lists, const Po void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); NixStringContext context; std::vector s; size_t sSize = 0; @@ -2033,12 +2061,14 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v) void ExprPos::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); state.mkPos(v, pos); } void ExprBlackHole::eval(EvalState & state, Env & env, Value & v) { + TRACY_TRACE(state, this); state.error("infinite recursion encountered") .debugThrow(); } diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk index 2290d6f9a..9529b8a1e 100644 --- a/src/libexpr/local.mk +++ b/src/libexpr/local.mk @@ -13,7 +13,7 @@ libexpr_SOURCES := \ $(d)/parser-tab.cc \ $(d)/tracy/public/TracyClient.cpp -libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libmain -I src/libexpr -I src/libexpr/tracy/public +libexpr_CXXFLAGS += -I src/libutil -I src/libstore -I src/libfetchers -I src/libmain -I src/libexpr -I src/libexpr/tracy/public -DTRACY_ENABLE=1 libexpr_LIBS = libutil libstore libfetchers @@ -49,3 +49,4 @@ $(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh $(d)/eval.cc: $(d)/primops/derivation.nix.gen.hh $(d)/fetchurl.nix.gen.hh $(d)/flake/call-flake.nix.gen.hh $(buildprefix)src/libexpr/primops/fromTOML.o: ERROR_SWITCH_ENUM = +$(buildprefix)src/libexpr/tracy/public/TracyClient.o: ERROR_SWITCH_ENUM = diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index b6189c2a9..3bf5268fb 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -156,6 +156,7 @@ struct Expr virtual Value * maybeThunk(EvalState & state, Env & env); virtual void setName(Symbol name); virtual PosIdx getPos() const { return noPos; } + virtual const char* showExprType() const { return "undefined"; } }; #define COMMON_METHODS \ @@ -168,6 +169,7 @@ struct ExprInt : Expr Value v; ExprInt(NixInt n) { v.mkInt(n); }; Value * maybeThunk(EvalState & state, Env & env) override; + const char* showExprType() const { return "int"; } COMMON_METHODS }; @@ -176,6 +178,7 @@ struct ExprFloat : Expr Value v; ExprFloat(NixFloat nf) { v.mkFloat(nf); }; Value * maybeThunk(EvalState & state, Env & env) override; + const char* showExprType() const { return "float"; } COMMON_METHODS }; @@ -185,6 +188,7 @@ struct ExprString : Expr Value v; ExprString(std::string &&s) : s(std::move(s)) { v.mkString(this->s.data()); }; Value * maybeThunk(EvalState & state, Env & env) override; + const char* showExprType() const { return "string"; } COMMON_METHODS }; @@ -198,6 +202,7 @@ struct ExprPath : Expr v.mkPath(&*accessor, this->s.c_str()); } Value * maybeThunk(EvalState & state, Env & env) override; + const char* showExprType() const { return "path"; } COMMON_METHODS }; @@ -229,6 +234,7 @@ struct ExprVar : Expr ExprVar(const PosIdx & pos, Symbol name) : pos(pos), name(name) { }; Value * maybeThunk(EvalState & state, Env & env) override; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "var"; } COMMON_METHODS }; @@ -240,6 +246,7 @@ struct ExprSelect : Expr ExprSelect(const PosIdx & pos, Expr * e, AttrPath attrPath, Expr * def) : pos(pos), e(e), def(def), attrPath(std::move(attrPath)) { }; ExprSelect(const PosIdx & pos, Expr * e, Symbol name) : pos(pos), e(e), def(0) { attrPath.push_back(AttrName(name)); }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "select"; } COMMON_METHODS }; @@ -249,6 +256,7 @@ struct ExprOpHasAttr : Expr AttrPath attrPath; ExprOpHasAttr(Expr * e, AttrPath attrPath) : e(e), attrPath(std::move(attrPath)) { }; PosIdx getPos() const override { return e->getPos(); } + const char* showExprType() const { return "op_has_attr"; } COMMON_METHODS }; @@ -278,6 +286,7 @@ struct ExprAttrs : Expr ExprAttrs(const PosIdx &pos) : recursive(false), pos(pos) { }; ExprAttrs() : recursive(false) { }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "attrs"; } COMMON_METHODS }; @@ -285,6 +294,7 @@ struct ExprList : Expr { std::vector elems; ExprList() { }; + const char* showExprType() const { return "list"; } COMMON_METHODS Value * maybeThunk(EvalState & state, Env & env) override; @@ -345,6 +355,7 @@ struct ExprLambda : Expr std::string showNamePos(const EvalState & state) const; inline bool hasFormals() const { return formals != nullptr; } PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "lambda"; } COMMON_METHODS }; @@ -357,6 +368,7 @@ struct ExprCall : Expr : fun(fun), args(args), pos(pos) { } PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "call"; } COMMON_METHODS }; @@ -365,6 +377,7 @@ struct ExprLet : Expr ExprAttrs * attrs; Expr * body; ExprLet(ExprAttrs * attrs, Expr * body) : attrs(attrs), body(body) { }; + const char* showExprType() const { return "let"; } COMMON_METHODS }; @@ -376,6 +389,7 @@ struct ExprWith : Expr ExprWith * parentWith; ExprWith(const PosIdx & pos, Expr * attrs, Expr * body) : pos(pos), attrs(attrs), body(body) { }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "with"; } COMMON_METHODS }; @@ -385,6 +399,7 @@ struct ExprIf : Expr Expr * cond, * then, * else_; ExprIf(const PosIdx & pos, Expr * cond, Expr * then, Expr * else_) : pos(pos), cond(cond), then(then), else_(else_) { }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "if"; } COMMON_METHODS }; @@ -394,6 +409,7 @@ struct ExprAssert : Expr Expr * cond, * body; ExprAssert(const PosIdx & pos, Expr * cond, Expr * body) : pos(pos), cond(cond), body(body) { }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "assert"; } COMMON_METHODS }; @@ -422,6 +438,7 @@ struct ExprOpNot : Expr } \ void eval(EvalState & state, Env & env, Value & v) override; \ PosIdx getPos() const override { return pos; } \ + const char* showExprType() const { return #name; } \ }; MakeBinOp(ExprOpEq, "==") @@ -440,6 +457,7 @@ struct ExprConcatStrings : Expr ExprConcatStrings(const PosIdx & pos, bool forceString, std::vector> * es) : pos(pos), forceString(forceString), es(es) { }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "concat_strings"; } COMMON_METHODS }; @@ -448,6 +466,7 @@ struct ExprPos : Expr PosIdx pos; ExprPos(const PosIdx & pos) : pos(pos) { }; PosIdx getPos() const override { return pos; } + const char* showExprType() const { return "pos"; } COMMON_METHODS }; @@ -457,6 +476,7 @@ struct ExprBlackHole : Expr void show(const SymbolTable & symbols, std::ostream & str) const override {} void eval(EvalState & state, Env & env, Value & v) override; void bindVars(EvalState & es, const std::shared_ptr & env) override {} + const char* showExprType() const { return "blackhole"; } }; extern ExprBlackHole eBlackHole;