AST profiling enhnacements in support of script optimization for lambdas/whens

This commit is contained in:
Vern Paxson 2023-06-16 15:50:00 -07:00 committed by Arne Welzel
parent 46983cfb2f
commit 110ba7a0a1
3 changed files with 63 additions and 32 deletions

View file

@ -28,7 +28,23 @@ ProfileFunc::ProfileFunc(const Func* func, const StmtPtr& body, bool _abs_rec_fi
profiled_func = func;
profiled_body = body.get();
abs_rec_fields = _abs_rec_fields;
Profile(func->GetType().get(), body);
auto ft = func->GetType()->AsFuncType();
auto& fcaps = ft->GetCaptures();
if ( fcaps )
{
int offset = 0;
for ( auto& c : *fcaps )
{
auto cid = c.Id().get();
captures.insert(cid);
captures_offsets[cid] = offset++;
}
}
Profile(ft, body);
}
ProfileFunc::ProfileFunc(const Stmt* s, bool _abs_rec_fields)
@ -48,10 +64,15 @@ ProfileFunc::ProfileFunc(const Expr* e, bool _abs_rec_fields)
{
auto func = e->AsLambdaExpr();
for ( auto oid : func->OuterIDs() )
captures.insert(oid);
int offset = 0;
Profile(func->GetType()->AsFuncType(), func->Ingredients().Body());
for ( auto oid : func->OuterIDs() )
{
captures.insert(oid);
captures_offsets[oid] = offset++;
}
Profile(func->GetType()->AsFuncType(), func->Ingredients()->Body());
}
else
@ -91,9 +112,9 @@ TraversalCode ProfileFunc::PreStmt(const Stmt* s)
auto w = s->AsWhenStmt();
auto wi = w->Info();
auto wl = wi ? wi->Lambda() : nullptr;
if ( wl )
lambdas.push_back(wl.get());
for ( auto wl : wi->WhenNewLocals() )
when_locals.insert(wl);
}
break;
@ -171,6 +192,11 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e)
auto n = e->AsNameExpr();
auto id = n->Id();
// Turns out that NameExpr's can be constructed using a
// different Type* than that of the identifier itself,
// so be sure we track the latter too.
TrackType(id->GetType());
if ( id->IsGlobal() )
{
globals.insert(id);
@ -179,30 +205,24 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e)
const auto& t = id->GetType();
if ( t->Tag() == TYPE_FUNC && t->AsFuncType()->Flavor() == FUNC_FLAVOR_EVENT )
events.insert(id->Name());
break;
}
else
{
// This is a tad ugly. Unfortunately due to the
// weird way that Zeek function *declarations* work,
// there's no reliable way to get the list of
// parameters for a function *definition*, since
// they can have different names than what's present
// in the declaration. So we identify them directly,
// by knowing that they come at the beginning of the
// frame ... and being careful to avoid misconfusing
// a lambda capture with a low frame offset as a
// parameter.
if ( captures.count(id) == 0 && id->Offset() < num_params )
params.insert(id);
// This is a tad ugly. Unfortunately due to the
// weird way that Zeek function *declarations* work,
// there's no reliable way to get the list of
// parameters for a function *definition*, since
// they can have different names than what's present
// in the declaration. So we identify them directly,
// by knowing that they come at the beginning of the
// frame ... and being careful to avoid misconfusing
// a lambda capture with a low frame offset as a
// parameter.
if ( captures.count(id) == 0 && id->Offset() < num_params )
params.insert(id);
locals.insert(id);
}
// Turns out that NameExpr's can be constructed using a
// different Type* than that of the identifier itself,
// so be sure we track the latter too.
TrackType(id->GetType());
locals.insert(id);
break;
}
@ -350,7 +370,12 @@ TraversalCode ProfileFunc::PreExpr(const Expr* e)
params.insert(i);
}
// Avoid recursing into the body.
// In general, we don't want to recurse into the body.
// However, we still want to *profile* it so we can
// identify calls within it.
ProfileFunc body_pf(l->Ingredients()->Body().get(), false);
script_calls.insert(body_pf.ScriptCalls().begin(), body_pf.ScriptCalls().end());
return TC_ABORTSTMT;
}