libexpr: turn debug frames into exprs
this way we don't have to even check whether we need a debug frame when the debugger isn't enabled. not doing this gives us an eval performance improvement of roughly 7% on nixos system eval and 2% for `nix search`. Change-Id: I1cdad3de61f865ea54d6e09d63a281688e828768
This commit is contained in:
+7
-42
@@ -1205,19 +1205,6 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
|
||||
*i.second.chooseByKind(&env2, &env, inheritEnv));
|
||||
}
|
||||
|
||||
auto dts = state.ctx.debug
|
||||
? makeDebugTraceStacker(
|
||||
state,
|
||||
*this,
|
||||
env2,
|
||||
getPos()
|
||||
? std::make_shared<Pos>(state.ctx.positions[getPos()])
|
||||
: nullptr,
|
||||
"while evaluating a '%1%' expression",
|
||||
"let"
|
||||
)
|
||||
: nullptr;
|
||||
|
||||
body->eval(state, env2, v);
|
||||
}
|
||||
|
||||
@@ -1308,16 +1295,6 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
||||
}
|
||||
|
||||
try {
|
||||
auto dts = state.ctx.debug
|
||||
? makeDebugTraceStacker(
|
||||
state,
|
||||
*this,
|
||||
env,
|
||||
state.ctx.positions[getPos()],
|
||||
"while evaluating the attribute '%1%'",
|
||||
showAttrPath(state, env, attrPath))
|
||||
: nullptr;
|
||||
|
||||
for (auto const & [partIdx, currentAttrName] : enumerate(attrPath)) {
|
||||
state.ctx.stats.nrLookups++;
|
||||
|
||||
@@ -1619,13 +1596,6 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
|
||||
/* Evaluate the body. */
|
||||
try {
|
||||
auto dts = ctx.debug
|
||||
? makeDebugTraceStacker(
|
||||
*this, *lambda.body, env2, ctx.positions[lambda.pos],
|
||||
"while calling %s",
|
||||
lambda.getQuotedName(ctx.symbols))
|
||||
: nullptr;
|
||||
|
||||
lambda.body->eval(*this, env2, vCur);
|
||||
} catch (Error & e) {
|
||||
if (loggerSettings.showTrace.get()) {
|
||||
@@ -1758,18 +1728,6 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||
|
||||
void ExprCall::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
auto dts = state.ctx.debug
|
||||
? makeDebugTraceStacker(
|
||||
state,
|
||||
*this,
|
||||
env,
|
||||
getPos()
|
||||
? std::make_shared<Pos>(state.ctx.positions[getPos()])
|
||||
: nullptr,
|
||||
"while calling a function"
|
||||
)
|
||||
: nullptr;
|
||||
|
||||
Value vFun;
|
||||
fun->eval(state, env, vFun);
|
||||
|
||||
@@ -2116,6 +2074,13 @@ void ExprBlackHole::eval(EvalState & state, Env & env, Value & v)
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
void ExprDebugFrame::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
auto dts =
|
||||
makeDebugTraceStacker(state, *inner, env, state.ctx.positions[pos], message);
|
||||
inner->eval(state, env, v);
|
||||
}
|
||||
|
||||
// always force this to be separate, otherwise forceValue may inline it and take
|
||||
// a massive perf hit
|
||||
[[gnu::noinline]]
|
||||
|
||||
+36
-4
@@ -330,6 +330,10 @@ struct VarBinder : ExprVisitor
|
||||
|
||||
using ExprVisitor::visit;
|
||||
|
||||
void visit(ExprDebugFrame & e, std::unique_ptr<Expr> & ptr) override
|
||||
{
|
||||
visit(e.inner);
|
||||
}
|
||||
void visit(ExprLiteral & e, std::unique_ptr<Expr> & ptr) override;
|
||||
void visit(ExprVar & e, std::unique_ptr<Expr> & ptr) override;
|
||||
void visit(ExprInheritFrom & e, std::unique_ptr<Expr> & ptr) override;
|
||||
@@ -380,13 +384,41 @@ struct DebugVarBinder : VarBinder
|
||||
OVERRIDE(ExprLiteral)
|
||||
OVERRIDE(ExprVar)
|
||||
OVERRIDE(ExprInheritFrom)
|
||||
OVERRIDE(ExprSelect)
|
||||
void visit(ExprSelect & e, std::unique_ptr<Expr> & ptr) override
|
||||
{
|
||||
es.debug->exprEnvs.insert(std::make_pair(&e, env));
|
||||
VarBinder::visit(e, ptr);
|
||||
|
||||
ptr = std::make_unique<ExprDebugFrame>(e.pos, std::move(ptr), "while evaluating an attribute");
|
||||
}
|
||||
OVERRIDE(ExprOpHasAttr)
|
||||
OVERRIDE(ExprSet)
|
||||
OVERRIDE(ExprList)
|
||||
OVERRIDE(ExprLambda)
|
||||
OVERRIDE(ExprCall)
|
||||
OVERRIDE(ExprLet)
|
||||
void visit(ExprLambda & e, std::unique_ptr<Expr> & ptr) override
|
||||
{
|
||||
es.debug->exprEnvs.insert(std::make_pair(&e, env));
|
||||
VarBinder::visit(e, ptr);
|
||||
|
||||
e.body = std::make_unique<ExprDebugFrame>(
|
||||
e.pos, std::move(e.body), HintFmt("while calling %s", e.getQuotedName(es.symbols)).str()
|
||||
);
|
||||
}
|
||||
void visit(ExprCall & e, std::unique_ptr<Expr> & ptr) override
|
||||
{
|
||||
es.debug->exprEnvs.insert(std::make_pair(&e, env));
|
||||
VarBinder::visit(e, ptr);
|
||||
|
||||
ptr = std::make_unique<ExprDebugFrame>(e.pos, std::move(ptr), "while calling a function");
|
||||
}
|
||||
void visit(ExprLet & e, std::unique_ptr<Expr> & ptr) override
|
||||
{
|
||||
es.debug->exprEnvs.insert(std::make_pair(&e, env));
|
||||
VarBinder::visit(e, ptr);
|
||||
|
||||
e.body = std::make_unique<ExprDebugFrame>(
|
||||
e.pos, std::move(e.body), HintFmt("while evaluating a '%1%' expression", "let").str()
|
||||
);
|
||||
}
|
||||
OVERRIDE(ExprWith)
|
||||
OVERRIDE(ExprIf)
|
||||
OVERRIDE(ExprAssert)
|
||||
|
||||
@@ -41,6 +41,7 @@ JSON printAttrPathToJson(const SymbolTable & symbols, const AttrPath & attrPath)
|
||||
|
||||
/* Abstract syntax of Nix expressions. */
|
||||
|
||||
struct ExprDebugFrame;
|
||||
struct ExprLiteral;
|
||||
struct ExprString;
|
||||
struct ExprPath;
|
||||
@@ -70,6 +71,7 @@ struct ExprBlackHole;
|
||||
|
||||
struct ExprVisitor
|
||||
{
|
||||
virtual void visit(ExprDebugFrame & e, std::unique_ptr<Expr> & ptr) = 0;
|
||||
virtual void visit(ExprLiteral & e, std::unique_ptr<Expr> & ptr) = 0;
|
||||
virtual void visit(ExprVar & e, std::unique_ptr<Expr> & ptr) = 0;
|
||||
virtual void visit(ExprInheritFrom & e, std::unique_ptr<Expr> & ptr) = 0;
|
||||
@@ -146,6 +148,26 @@ inline void ExprVisitor::visit(std::unique_ptr<Expr> & ptr)
|
||||
ptr->accept(*this, ptr);
|
||||
}
|
||||
|
||||
struct ExprDebugFrame : Expr
|
||||
{
|
||||
std::unique_ptr<Expr> inner;
|
||||
std::string message;
|
||||
|
||||
ExprDebugFrame(PosIdx pos, std::unique_ptr<Expr> inner, std::string message)
|
||||
: Expr(pos)
|
||||
, inner(std::move(inner))
|
||||
, message(std::move(message))
|
||||
{
|
||||
}
|
||||
|
||||
JSON toJSON(const SymbolTable & symbols) const override
|
||||
{
|
||||
return inner->toJSON(symbols);
|
||||
}
|
||||
void eval(EvalState & state, Env & env, Value & v) override;
|
||||
void accept(ExprVisitor & ev, std::unique_ptr<Expr> & ptr) override { ev.visit(*this, ptr); }
|
||||
};
|
||||
|
||||
struct ExprLiteral : Expr
|
||||
{
|
||||
protected:
|
||||
|
||||
Reference in New Issue
Block a user