tracking of when statements/expressions occur in a "when" context

This commit is contained in:
Vern Paxson 2022-05-12 13:45:45 -07:00
parent 5a32e58e04
commit 9ada7ac4e7
6 changed files with 45 additions and 17 deletions

View file

@ -2830,8 +2830,10 @@ ValPtr IndexSliceAssignExpr::Eval(Frame* f) const
return nullptr;
}
IndexExpr::IndexExpr(ExprPtr arg_op1, ListExprPtr arg_op2, bool arg_is_slice)
: BinaryExpr(EXPR_INDEX, std::move(arg_op1), std::move(arg_op2)), is_slice(arg_is_slice)
IndexExpr::IndexExpr(ExprPtr arg_op1, ListExprPtr arg_op2, bool arg_is_slice,
bool arg_is_inside_when)
: BinaryExpr(EXPR_INDEX, std::move(arg_op1), std::move(arg_op2)), is_slice(arg_is_slice),
is_inside_when(arg_is_inside_when)
{
if ( IsError() )
return;
@ -4467,8 +4469,8 @@ ValPtr InExpr::Fold(Val* v1, Val* v2) const
return val_mgr->Bool(res);
}
CallExpr::CallExpr(ExprPtr arg_func, ListExprPtr arg_args, bool in_hook)
: Expr(EXPR_CALL), func(std::move(arg_func)), args(std::move(arg_args))
CallExpr::CallExpr(ExprPtr arg_func, ListExprPtr arg_args, bool in_hook, bool _in_when)
: Expr(EXPR_CALL), func(std::move(arg_func)), args(std::move(arg_args)), in_when(_in_when)
{
if ( func->IsError() || args->IsError() )
{

View file

@ -1005,7 +1005,7 @@ public:
class IndexExpr : public BinaryExpr
{
public:
IndexExpr(ExprPtr op1, ListExprPtr op2, bool is_slice = false);
IndexExpr(ExprPtr op1, ListExprPtr op2, bool is_slice = false, bool is_inside_when = false);
bool CanAdd() const override;
bool CanDel() const override;
@ -1021,6 +1021,7 @@ public:
ValPtr Eval(Frame* f) const override;
bool IsSlice() const { return is_slice; }
bool IsInsideWhen() const { return is_inside_when; }
// Optimization-related:
ExprPtr Duplicate() override;
@ -1034,6 +1035,7 @@ protected:
void ExprDescribe(ODesc* d) const override;
bool is_slice;
bool is_inside_when;
};
// The following execute the heart of IndexExpr functionality for
@ -1059,6 +1061,13 @@ extern VectorValPtr vector_bool_select(VectorTypePtr vt, const VectorVal* v1, co
// indices to select).
extern VectorValPtr vector_int_select(VectorTypePtr vt, const VectorVal* v1, const VectorVal* v2);
// The following is used for index expressions that occur inside "when"
// clauses. It tracks all the results produced by evaluating indexing
// aggregates, so that if any of them are Modifiable(), the associated
// Trigger can register interest in changes to them.
//
// One Fine Day we should do the equivalent for accessing fields in records,
// too.
class IndexExprWhen final : public IndexExpr
{
public:
@ -1077,7 +1086,7 @@ public:
}
IndexExprWhen(ExprPtr op1, ListExprPtr op2, bool is_slice = false)
: IndexExpr(std::move(op1), std::move(op2), is_slice)
: IndexExpr(std::move(op1), std::move(op2), is_slice, true)
{
}
@ -1398,13 +1407,14 @@ protected:
class CallExpr final : public Expr
{
public:
CallExpr(ExprPtr func, ListExprPtr args, bool in_hook = false);
CallExpr(ExprPtr func, ListExprPtr args, bool in_hook = false, bool in_when = false);
Expr* Func() const { return func.get(); }
ListExpr* Args() const { return args.get(); }
ListExprPtr ArgsPtr() const { return args; }
bool IsPure() const override;
bool IsInWhen() const { return in_when; }
ValPtr Eval(Frame* f) const override;
@ -1424,6 +1434,7 @@ protected:
ExprPtr func;
ListExprPtr args;
bool in_when;
};
/**

View file

@ -5,7 +5,7 @@
// Switching parser table type fixes ambiguity problems.
%define lr.type ielr
%expect 196
%expect 195
%token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY
%token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF
@ -13,7 +13,8 @@
%token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_DEFAULT TOK_DELETE
%token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FALLTHROUGH
%token TOK_FILE TOK_FOR TOK_FUNCTION TOK_GLOBAL TOK_HOOK TOK_ID TOK_IF TOK_INT
%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE
%token TOK_INTERVAL TOK_LIST TOK_MODULE
%token TOK_LOCAL TOK_WHEN_LOCAL
%token TOK_NEXT TOK_OF TOK_OPAQUE TOK_PATTERN TOK_PATTERN_END TOK_PATTERN_TEXT
%token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF
%token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET
@ -111,7 +112,7 @@ extern int conditional_epoch; // let's us track embedded conditionals
// Whether the file we're currently parsing includes @if conditionals.
extern bool current_file_has_conditionals;
YYLTYPE GetCurrentLocation();
extern YYLTYPE GetCurrentLocation();
extern int yyerror(const char[]);
extern int brolex();
@ -133,7 +134,8 @@ extern Expr* g_curr_debug_expr;
extern bool in_debug;
extern const char* g_curr_debug_error;
static int in_when_cond = 0;
extern int in_when_cond;
static int in_hook = 0;
int in_init = 0;
int in_record = 0;
@ -618,7 +620,7 @@ expr:
$$ = get_assign_expr({AdoptRef{}, $1}, {AdoptRef{}, $3}, in_init).release();
}
| TOK_LOCAL local_id '=' rhs
| TOK_WHEN_LOCAL local_id '=' rhs
{
set_location(@2, @4);
if ( ! locals_at_this_scope.empty() )
@ -780,7 +782,7 @@ expr:
}
else
$$ = new CallExpr({AdoptRef{}, $1}, {AdoptRef{}, $4}, in_hook > 0);
$$ = new CallExpr({AdoptRef{}, $1}, {AdoptRef{}, $4}, in_hook > 0, in_when_cond);
}
| TOK_HOOK { ++in_hook; } expr

View file

@ -68,6 +68,10 @@ std::unordered_set<std::string> files_with_conditionals;
zeek::detail::int_list if_stack;
// Whether we're parsing a "when" conditional, for which we treat
// the "local" keyword differently.
int in_when_cond = 0;
int line_number = 1;
const char* filename = 0; // Absolute path of file currently being parsed.
const char* last_filename = 0; // Absolute path of last file parsed.
@ -278,7 +282,7 @@ int return TOK_INT;
interval return TOK_INTERVAL;
is return TOK_IS;
list return TOK_LIST;
local return TOK_LOCAL;
local return in_when_cond ? TOK_WHEN_LOCAL : TOK_LOCAL;
module return TOK_MODULE;
next return TOK_NEXT;
of return TOK_OF;
@ -586,7 +590,8 @@ YYLTYPE zeek::detail::GetCurrentLocation()
return currloc;
}
void zeek::detail::SetCurrentLocation(YYLTYPE currloc) {
void zeek::detail::SetCurrentLocation(YYLTYPE currloc)
{
::filename = currloc.filename;
line_number = currloc.first_line;
}

View file

@ -1863,7 +1863,7 @@ ExprPtr IndexExpr::Duplicate()
{
auto op1_d = op1->Duplicate();
auto op2_l = op2->Duplicate()->AsListExprPtr();
return SetSucc(new IndexExpr(op1_d, op2_l, is_slice));
return SetSucc(new IndexExpr(op1_d, op2_l, is_slice, is_inside_when));
}
bool IndexExpr::HasReducedOps(Reducer* c) const

View file

@ -129,7 +129,15 @@ TraversalCode ProfileFunc::PreStmt(const Stmt* s)
return TC_ABORTSTMT;
case STMT_WHEN:
{
++num_when_stmts;
auto w = s->AsWhenStmt();
auto wi = w->Info();
auto wl = wi ? wi->Lambda() : nullptr;
if ( wl )
lambdas.push_back(wl.get());
}
break;
case STMT_FOR: