From 1f60a0c2f48e6ccb8a8f26cb262580552c52e150 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 22 Dec 2024 22:32:02 +0100 Subject: [PATCH 1/6] filterx/expr: remove unused lexer argument from filterx_expr_set_location_with_text() Signed-off-by: Balazs Scheidler --- lib/filterx/filterx-expr.c | 4 ++-- lib/filterx/filterx-expr.h | 2 +- lib/filterx/filterx-grammar.ym | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/filterx/filterx-expr.c b/lib/filterx/filterx-expr.c index 88e181a7d..0790860f7 100644 --- a/lib/filterx/filterx-expr.c +++ b/lib/filterx/filterx-expr.c @@ -30,13 +30,13 @@ #include "stats/stats-cluster-single.h" void -filterx_expr_set_location_with_text(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc, const gchar *text) +filterx_expr_set_location_with_text(FilterXExpr *self, CFG_LTYPE *lloc, const gchar *text) { if (!self->lloc) self->lloc = g_new0(CFG_LTYPE, 1); *self->lloc = *lloc; - if (debug_flag) + if (debug_flag && text) self->expr_text = g_strdup(text); } diff --git a/lib/filterx/filterx-expr.h b/lib/filterx/filterx-expr.h index 1864c4b37..11afbfa7b 100644 --- a/lib/filterx/filterx-expr.h +++ b/lib/filterx/filterx-expr.h @@ -147,7 +147,7 @@ filterx_expr_unset_available(FilterXExpr *self) } void filterx_expr_set_location(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc); -void filterx_expr_set_location_with_text(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc, const gchar *text); +void filterx_expr_set_location_with_text(FilterXExpr *self, CFG_LTYPE *lloc, const gchar *text); EVTTAG *filterx_expr_format_location_tag(FilterXExpr *self); void filterx_expr_init_instance(FilterXExpr *self); FilterXExpr *filterx_expr_new(void); diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index b39b5f9b8..707dd722e 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -171,7 +171,7 @@ block : '{' stmts '}' { FilterXExpr *block = filterx_compound_expr_new(FALSE); filterx_compound_expr_add_list(block, $2); - filterx_expr_set_location_with_text(block, lexer, &@$, "{ ... }"); + filterx_expr_set_location_with_text(block, &@$, "{ ... }"); $$ = block; } ; From eb6cc07daf391a6457b2a7fb3d3e9b0cb134e3f5 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 22 Dec 2024 22:16:16 +0100 Subject: [PATCH 2/6] filterx: add optimize() method for expressions This new method can be used to rewrite the expression tree after parsing in order to execute faster. This is where we can check literal values and potentially evaluate literal expressions. Signed-off-by: Balazs Scheidler --- lib/filterx/expr-compound.c | 14 +++++++ lib/filterx/expr-condition.c | 12 +++++- lib/filterx/expr-function.c | 20 ++++++++++ lib/filterx/expr-function.h | 1 + lib/filterx/expr-generator.c | 20 ++++++++++ lib/filterx/expr-generator.h | 1 + lib/filterx/expr-get-subscript.c | 11 ++++++ lib/filterx/expr-getattr.c | 10 +++++ lib/filterx/expr-literal-generator.c | 23 ++++++++++++ lib/filterx/expr-plus-generator.c | 11 ++++++ lib/filterx/expr-regexp-search.c | 10 +++++ lib/filterx/expr-regexp-subst.c | 10 +++++ lib/filterx/expr-regexp.c | 10 +++++ lib/filterx/expr-set-subscript.c | 13 +++++++ lib/filterx/expr-setattr.c | 12 ++++++ lib/filterx/expr-unset.c | 14 +++++++ lib/filterx/filterx-expr.c | 55 ++++++++++++++++++++++++++++ lib/filterx/filterx-expr.h | 6 ++- lib/filterx/filterx-pipe.c | 2 + 19 files changed, 253 insertions(+), 2 deletions(-) diff --git a/lib/filterx/expr-compound.c b/lib/filterx/expr-compound.c index 041a7b242..edf922e91 100644 --- a/lib/filterx/expr-compound.c +++ b/lib/filterx/expr-compound.c @@ -136,6 +136,19 @@ _eval(FilterXExpr *s) return result; } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXCompoundExpr *self = (FilterXCompoundExpr *) s; + + for (gint i = 0; i < self->exprs->len; i++) + { + FilterXExpr **expr = (FilterXExpr **) &g_ptr_array_index(self->exprs, i); + *expr = filterx_expr_optimize(*expr); + } + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -220,6 +233,7 @@ filterx_compound_expr_new(gboolean return_value_of_last_expr) filterx_expr_init_instance(&self->super); self->super.eval = _eval; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; diff --git a/lib/filterx/expr-condition.c b/lib/filterx/expr-condition.c index 95494fe34..ba0c3b1bc 100644 --- a/lib/filterx/expr-condition.c +++ b/lib/filterx/expr-condition.c @@ -38,6 +38,16 @@ struct _FilterXConditional FilterXExpr *false_branch; }; +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXConditional *self = (FilterXConditional *) s; + + self->true_branch = filterx_expr_optimize(self->true_branch); + self->false_branch = filterx_expr_optimize(self->false_branch); + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -68,7 +78,6 @@ _init(FilterXExpr *s, GlobalConfig *cfg) return filterx_expr_init_method(s, cfg); } - static void _deinit(FilterXExpr *s, GlobalConfig *cfg) { @@ -170,6 +179,7 @@ filterx_conditional_new(FilterXExpr *condition) FilterXConditional *self = g_new0(FilterXConditional, 1); filterx_expr_init_instance(&self->super); self->super.eval = _eval; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; diff --git a/lib/filterx/expr-function.c b/lib/filterx/expr-function.c index 013bcf7e0..bedc06399 100644 --- a/lib/filterx/expr-function.c +++ b/lib/filterx/expr-function.c @@ -134,6 +134,19 @@ _simple_eval(FilterXExpr *s) return res; } +static FilterXExpr * +_simple_optimize(FilterXExpr *s) +{ + FilterXSimpleFunction *self = (FilterXSimpleFunction *) s; + + for (guint64 i = 0; i < self->args->len; i++) + { + FilterXExpr **arg = (FilterXExpr **) &g_ptr_array_index(self->args, i); + *arg = filterx_expr_optimize(*arg); + } + return filterx_function_optimize_method(&self->super); +} + static gboolean _simple_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -206,6 +219,7 @@ filterx_simple_function_new(const gchar *function_name, FilterXFunctionArgs *arg filterx_function_init_instance(&self->super, function_name); self->super.super.eval = _simple_eval; + self->super.super.optimize = _simple_optimize; self->super.super.init = _simple_init; self->super.super.deinit = _simple_deinit; self->super.super.free_fn = _simple_free; @@ -225,6 +239,12 @@ filterx_simple_function_new(const gchar *function_name, FilterXFunctionArgs *arg return NULL; } +FilterXExpr * +filterx_function_optimize_method(FilterXFunction *s) +{ + return NULL; +} + gboolean filterx_function_init_method(FilterXFunction *s, GlobalConfig *cfg) { diff --git a/lib/filterx/expr-function.h b/lib/filterx/expr-function.h index 0c1085f2a..f657c0333 100644 --- a/lib/filterx/expr-function.h +++ b/lib/filterx/expr-function.h @@ -70,6 +70,7 @@ enum FilterXFunctionError }; void filterx_function_init_instance(FilterXFunction *s, const gchar *function_name); +FilterXExpr *filterx_function_optimize_method(FilterXFunction *s); gboolean filterx_function_init_method(FilterXFunction *s, GlobalConfig *cfg); void filterx_function_deinit_method(FilterXFunction *s, GlobalConfig *cfg); void filterx_function_free_method(FilterXFunction *s); diff --git a/lib/filterx/expr-generator.c b/lib/filterx/expr-generator.c index 378c989a5..246400f34 100644 --- a/lib/filterx/expr-generator.c +++ b/lib/filterx/expr-generator.c @@ -55,10 +55,20 @@ filterx_expr_is_generator(FilterXExpr *s) return s && s->eval == _eval; } +FilterXExpr * +filterx_generator_optimize_method(FilterXExpr *s) +{ + FilterXExprGenerator *self = (FilterXExprGenerator *) s; + + self->fillable = filterx_expr_optimize(self->fillable); + return NULL; +} + void filterx_generator_init_instance(FilterXExpr *s) { filterx_expr_init_instance(s); + s->optimize = filterx_generator_optimize_method; s->init = filterx_generator_init_method; s->deinit = filterx_generator_deinit_method; s->eval = _eval; @@ -109,6 +119,15 @@ _create_container_eval(FilterXExpr *s) return self->generator->create_container(self->generator, self->fillable_parent); } +static FilterXExpr * +_create_container_optimize(FilterXExpr *s) +{ + FilterXExprGeneratorCreateContainer *self = (FilterXExprGeneratorCreateContainer *) s; + + self->fillable_parent = filterx_expr_optimize(self->fillable_parent); + return NULL; +} + static gboolean _create_container_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -172,6 +191,7 @@ filterx_generator_create_container_new(FilterXExpr *g, FilterXExpr *fillable_par filterx_expr_init_instance(&self->super); self->generator = (FilterXExprGenerator *) g; self->fillable_parent = fillable_parent; + self->super.optimize = _create_container_optimize; self->super.init = _create_container_init; self->super.deinit = _create_container_deinit; self->super.eval = _create_container_eval; diff --git a/lib/filterx/expr-generator.h b/lib/filterx/expr-generator.h index f3026c448..6308d73f9 100644 --- a/lib/filterx/expr-generator.h +++ b/lib/filterx/expr-generator.h @@ -37,6 +37,7 @@ struct FilterXExprGenerator_ void filterx_generator_set_fillable(FilterXExpr *s, FilterXExpr *fillable); void filterx_generator_init_instance(FilterXExpr *s); +FilterXExpr *filterx_generator_optimize_method(FilterXExpr *s); gboolean filterx_generator_init_method(FilterXExpr *s, GlobalConfig *cfg); void filterx_generator_deinit_method(FilterXExpr *s, GlobalConfig *cfg); void filterx_generator_free_method(FilterXExpr *s); diff --git a/lib/filterx/expr-get-subscript.c b/lib/filterx/expr-get-subscript.c index 32a1d51ce..13bfe4dd2 100644 --- a/lib/filterx/expr-get-subscript.c +++ b/lib/filterx/expr-get-subscript.c @@ -105,6 +105,16 @@ _unset(FilterXExpr *s) return result; } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXGetSubscript *self = (FilterXGetSubscript *) s; + + self->operand = filterx_expr_optimize(self->operand); + self->key = filterx_expr_optimize(self->key); + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -163,6 +173,7 @@ filterx_get_subscript_new(FilterXExpr *operand, FilterXExpr *key) self->super.eval = _eval; self->super.is_set = _isset; self->super.unset = _unset; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; diff --git a/lib/filterx/expr-getattr.c b/lib/filterx/expr-getattr.c index f85bf1585..825029472 100644 --- a/lib/filterx/expr-getattr.c +++ b/lib/filterx/expr-getattr.c @@ -92,6 +92,15 @@ _isset(FilterXExpr *s) return result; } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXGetAttr *self = (FilterXGetAttr *) s; + + self->operand = filterx_expr_optimize(self->operand); + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -143,6 +152,7 @@ filterx_getattr_new(FilterXExpr *operand, FilterXString *attr_name) self->super.eval = _eval; self->super.unset = _unset; self->super.is_set = _isset; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; diff --git a/lib/filterx/expr-literal-generator.c b/lib/filterx/expr-literal-generator.c index 465496bec..5776b6760 100644 --- a/lib/filterx/expr-literal-generator.c +++ b/lib/filterx/expr-literal-generator.c @@ -59,6 +59,13 @@ _literal_generator_elem_init(FilterXLiteralGeneratorElem *self, GlobalConfig *cf return TRUE; } +static void +_literal_generator_elem_optimize(FilterXLiteralGeneratorElem *self) +{ + self->key = filterx_expr_optimize(self->key); + self->value = filterx_expr_optimize(self->value); +} + static void _literal_generator_elem_deinit(FilterXLiteralGeneratorElem *self, GlobalConfig *cfg) { @@ -140,6 +147,21 @@ _literal_generator_generate(FilterXExprGenerator *s, FilterXObject *fillable) return _eval_elements(fillable, self->elements); } +static FilterXExpr * +_literal_generator_optimize(FilterXExpr *s) +{ + FilterXExprLiteralGenerator *self = (FilterXExprLiteralGenerator *) s; + + for (GList *link = self->elements; link; link = link->next) + { + FilterXLiteralGeneratorElem *elem = (FilterXLiteralGeneratorElem *) link->data; + + _literal_generator_elem_optimize(elem); + } + + return filterx_generator_optimize_method(s); +} + static gboolean _literal_generator_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -191,6 +213,7 @@ _literal_generator_init_instance(FilterXExprLiteralGenerator *self) { filterx_generator_init_instance(&self->super.super); self->super.generate = _literal_generator_generate; + self->super.super.optimize = _literal_generator_optimize; self->super.super.init = _literal_generator_init; self->super.super.deinit = _literal_generator_deinit; self->super.super.free_fn = _literal_generator_free; diff --git a/lib/filterx/expr-plus-generator.c b/lib/filterx/expr-plus-generator.c index a0677ab65..662a6ae48 100644 --- a/lib/filterx/expr-plus-generator.c +++ b/lib/filterx/expr-plus-generator.c @@ -100,6 +100,16 @@ _expr_plus_generator_create_container(FilterXExprGenerator *s, FilterXExpr *fill return generator->create_container(generator, fillable_parent); } +static FilterXExpr * +_expr_plus_generator_optimize(FilterXExpr *s) +{ + FilterXOperatorPlusGenerator *self = (FilterXOperatorPlusGenerator *) s; + + self->lhs = filterx_expr_optimize(self->lhs); + self->rhs = filterx_expr_optimize(self->rhs); + return filterx_generator_optimize_method(s); +} + static gboolean _expr_plus_generator_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -142,6 +152,7 @@ filterx_operator_plus_generator_new(FilterXExpr *lhs, FilterXExpr *rhs) self->lhs = lhs; self->rhs = rhs; self->super.generate = _expr_plus_generator_generate; + self->super.super.optimize = _expr_plus_generator_optimize; self->super.super.init = _expr_plus_generator_init; self->super.super.deinit = _expr_plus_generator_deinit; self->super.super.free_fn = _expr_plus_generator_free; diff --git a/lib/filterx/expr-regexp-search.c b/lib/filterx/expr-regexp-search.c index 2efd9cf69..4769def16 100644 --- a/lib/filterx/expr-regexp-search.c +++ b/lib/filterx/expr-regexp-search.c @@ -214,6 +214,15 @@ _regexp_search_generator_create_container(FilterXExprGenerator *s, FilterXExpr * return filterx_generator_create_dict_container(s, fillable_parent); } +static FilterXExpr * +_regexp_search_generator_optimize(FilterXExpr *s) +{ + FilterXExprRegexpSearchGenerator *self = (FilterXExprRegexpSearchGenerator *) s; + + self->lhs = filterx_expr_optimize(self->lhs); + return filterx_generator_optimize_method(s); +} + static gboolean _regexp_search_generator_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -293,6 +302,7 @@ filterx_generator_function_regexp_search_new(FilterXFunctionArgs *args, GError * filterx_generator_function_init_instance(&self->super, "regexp_search"); self->super.super.generate = _regexp_search_generator_generate; + self->super.super.super.optimize = _regexp_search_generator_optimize; self->super.super.super.init = _regexp_search_generator_init; self->super.super.super.deinit = _regexp_search_generator_deinit; self->super.super.super.free_fn = _regexp_search_generator_free; diff --git a/lib/filterx/expr-regexp-subst.c b/lib/filterx/expr-regexp-subst.c index ba6d2bb95..ed0c6264d 100644 --- a/lib/filterx/expr-regexp-subst.c +++ b/lib/filterx/expr-regexp-subst.c @@ -333,6 +333,15 @@ _extract_subst_args(FilterXFuncRegexpSubst *self, FilterXFunctionArgs *args, GEr return TRUE; } +static FilterXExpr * +_subst_optimize(FilterXExpr *s) +{ + FilterXFuncRegexpSubst *self = (FilterXFuncRegexpSubst *) s; + + self->string_expr = filterx_expr_optimize(self->string_expr); + return filterx_function_optimize_method(&self->super); +} + static gboolean _subst_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -369,6 +378,7 @@ filterx_function_regexp_subst_new(FilterXFunctionArgs *args, GError **error) FilterXFuncRegexpSubst *self = g_new0(FilterXFuncRegexpSubst, 1); filterx_function_init_instance(&self->super, "regexp_subst"); self->super.super.eval = _subst_eval; + self->super.super.optimize = _subst_optimize; self->super.super.init = _subst_init; self->super.super.deinit = _subst_deinit; self->super.super.free_fn = _subst_free; diff --git a/lib/filterx/expr-regexp.c b/lib/filterx/expr-regexp.c index cc02da193..f6ed993d6 100644 --- a/lib/filterx/expr-regexp.c +++ b/lib/filterx/expr-regexp.c @@ -65,6 +65,15 @@ _regexp_match_eval(FilterXExpr *s) return result; } +static FilterXExpr * +_regexp_match_optimize(FilterXExpr *s) +{ + FilterXExprRegexpMatch *self = (FilterXExprRegexpMatch *) s; + + self->lhs = filterx_expr_optimize(self->lhs); + return NULL; +} + static gboolean _regexp_match_init(FilterXExpr *s, GlobalConfig *cfg) { @@ -104,6 +113,7 @@ filterx_expr_regexp_match_new(FilterXExpr *lhs, const gchar *pattern) filterx_expr_init_instance(&self->super); self->super.eval = _regexp_match_eval; + self->super.optimize = _regexp_match_optimize; self->super.init = _regexp_match_init; self->super.deinit = _regexp_match_deinit; self->super.free_fn = _regexp_match_free; diff --git a/lib/filterx/expr-set-subscript.c b/lib/filterx/expr-set-subscript.c index cfb5c100a..040c0650c 100644 --- a/lib/filterx/expr-set-subscript.c +++ b/lib/filterx/expr-set-subscript.c @@ -148,6 +148,17 @@ _set_subscript_eval(FilterXExpr *s) return result; } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXSetSubscript *self = (FilterXSetSubscript *) s; + + self->object = filterx_expr_optimize(self->object); + self->new_value = filterx_expr_optimize(self->new_value); + self->key = filterx_expr_optimize(self->key); + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -213,6 +224,7 @@ filterx_nullv_set_subscript_new(FilterXExpr *object, FilterXExpr *key, FilterXEx filterx_expr_init_instance(&self->super); self->super.eval = _nullv_set_subscript_eval; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; @@ -230,6 +242,7 @@ filterx_set_subscript_new(FilterXExpr *object, FilterXExpr *key, FilterXExpr *ne filterx_expr_init_instance(&self->super); self->super.eval = _set_subscript_eval; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; diff --git a/lib/filterx/expr-setattr.c b/lib/filterx/expr-setattr.c index 3151a7ed4..c15a2dd5a 100644 --- a/lib/filterx/expr-setattr.c +++ b/lib/filterx/expr-setattr.c @@ -131,6 +131,16 @@ _setattr_eval(FilterXExpr *s) return result; } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXSetAttr *self = (FilterXSetAttr *) s; + + self->object = filterx_expr_optimize(self->object); + self->new_value = filterx_expr_optimize(self->new_value); + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -188,6 +198,7 @@ filterx_nullv_setattr_new(FilterXExpr *object, FilterXString *attr_name, FilterX filterx_expr_init_instance(&self->super); self->super.eval = _nullv_setattr_eval; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; @@ -208,6 +219,7 @@ filterx_setattr_new(FilterXExpr *object, FilterXString *attr_name, FilterXExpr * filterx_expr_init_instance(&self->super); self->super.eval = _setattr_eval; + self->super.optimize = _optimize; self->super.init = _init; self->super.deinit = _deinit; self->super.free_fn = _free; diff --git a/lib/filterx/expr-unset.c b/lib/filterx/expr-unset.c index b3dfa97a5..b536fcb02 100644 --- a/lib/filterx/expr-unset.c +++ b/lib/filterx/expr-unset.c @@ -46,6 +46,19 @@ _eval(FilterXExpr *s) return filterx_boolean_new(TRUE); } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXExprUnset *self = (FilterXExprUnset *) s; + + for (guint i = 0; i < self->exprs->len; i++) + { + FilterXExpr **expr = (FilterXExpr **) &g_ptr_array_index(self->exprs, i); + *expr = filterx_expr_optimize(*expr); + } + return NULL; +} + static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) { @@ -98,6 +111,7 @@ filterx_function_unset_new(FilterXFunctionArgs *args, GError **error) filterx_function_init_instance(&self->super, "unset"); self->super.super.eval = _eval; + self->super.super.optimize = _optimize; self->super.super.init = _init; self->super.super.deinit = _deinit; self->super.super.free_fn = _free; diff --git a/lib/filterx/filterx-expr.c b/lib/filterx/filterx-expr.c index 0790860f7..ab21621d0 100644 --- a/lib/filterx/filterx-expr.c +++ b/lib/filterx/filterx-expr.c @@ -65,6 +65,40 @@ filterx_expr_format_location_tag(FilterXExpr *self) return evt_tag_str("expr", "n/a"); } +FilterXExpr * +filterx_expr_optimize(FilterXExpr *self) +{ + if (!self) + return NULL; + + if (self->optimized) + return self; + + self->optimized = TRUE; + g_assert(!self->inited); + + if (!self->optimize) + return self; + + FilterXExpr *optimized = self->optimize(self); + if (!optimized) + return self; + + /* the new expression may be also be optimized */ + optimized = filterx_expr_optimize(optimized); + + msg_trace("FilterX: expression optimized", + filterx_expr_format_location_tag(self)); + if (self->lloc) + { + /* copy location information to the optimized representation */ + filterx_expr_set_location_with_text(optimized, self->lloc, self->expr_text); + } + /* consume original expression */ + filterx_expr_unref(self); + return optimized; +} + gboolean filterx_expr_init_method(FilterXExpr *self, GlobalConfig *cfg) { @@ -127,6 +161,15 @@ filterx_expr_unref(FilterXExpr *self) } } +FilterXExpr * +filterx_unary_op_optimize_method(FilterXExpr *s) +{ + FilterXUnaryOp *self = (FilterXUnaryOp *) s; + + self->operand = filterx_expr_optimize(self->operand); + return NULL; +} + gboolean filterx_unary_op_init_method(FilterXExpr *s, GlobalConfig *cfg) { @@ -174,6 +217,7 @@ void filterx_unary_op_init_instance(FilterXUnaryOp *self, const gchar *name, FilterXExpr *operand) { filterx_expr_init_instance(&self->super); + self->super.optimize = filterx_unary_op_optimize_method; self->super.init = filterx_unary_op_init_method; self->super.deinit = filterx_unary_op_deinit_method; self->super.free_fn = filterx_unary_op_free_method; @@ -192,6 +236,16 @@ filterx_binary_op_free_method(FilterXExpr *s) filterx_expr_free_method(s); } +FilterXExpr * +filterx_binary_op_optimize_method(FilterXExpr *s) +{ + FilterXBinaryOp *self = (FilterXBinaryOp *) s; + + self->lhs = filterx_expr_optimize(self->lhs); + self->rhs = filterx_expr_optimize(self->rhs); + return NULL; +} + gboolean filterx_binary_op_init_method(FilterXExpr *s, GlobalConfig *cfg) { @@ -234,6 +288,7 @@ void filterx_binary_op_init_instance(FilterXBinaryOp *self, const gchar *name, FilterXExpr *lhs, FilterXExpr *rhs) { filterx_expr_init_instance(&self->super); + self->super.optimize = filterx_binary_op_optimize_method; self->super.init = filterx_binary_op_init_method; self->super.deinit = filterx_binary_op_deinit_method; self->super.free_fn = filterx_binary_op_free_method; diff --git a/lib/filterx/filterx-expr.h b/lib/filterx/filterx-expr.h index 11afbfa7b..0a5388ccf 100644 --- a/lib/filterx/filterx-expr.h +++ b/lib/filterx/filterx-expr.h @@ -37,7 +37,7 @@ struct _FilterXExpr /* not thread-safe */ guint32 ref_cnt; - guint32 ignore_falsy_result:1, suppress_from_trace:1, inited:1; + guint32 ignore_falsy_result:1, suppress_from_trace:1, inited:1, optimized:1; /* not to be used except for FilterXMessageRef, replace any cached values * with the unmarshaled version */ @@ -53,6 +53,7 @@ struct _FilterXExpr gboolean (*init)(FilterXExpr *self, GlobalConfig *cfg); void (*deinit)(FilterXExpr *self, GlobalConfig *cfg); + FilterXExpr *(*optimize)(FilterXExpr *self); void (*free_fn)(FilterXExpr *self); const gchar *type; @@ -149,6 +150,7 @@ filterx_expr_unset_available(FilterXExpr *self) void filterx_expr_set_location(FilterXExpr *self, CfgLexer *lexer, CFG_LTYPE *lloc); void filterx_expr_set_location_with_text(FilterXExpr *self, CFG_LTYPE *lloc, const gchar *text); EVTTAG *filterx_expr_format_location_tag(FilterXExpr *self); +FilterXExpr *filterx_expr_optimize(FilterXExpr *self); void filterx_expr_init_instance(FilterXExpr *self); FilterXExpr *filterx_expr_new(void); FilterXExpr *filterx_expr_ref(FilterXExpr *self); @@ -191,6 +193,7 @@ typedef struct _FilterXUnaryOp const gchar *name; } FilterXUnaryOp; +FilterXExpr *filterx_unary_op_optimize_method(FilterXExpr *s); gboolean filterx_unary_op_init_method(FilterXExpr *s, GlobalConfig *cfg); void filterx_unary_op_deinit_method(FilterXExpr *s, GlobalConfig *cfg); void filterx_unary_op_free_method(FilterXExpr *s); @@ -203,6 +206,7 @@ typedef struct _FilterXBinaryOp const gchar *name; } FilterXBinaryOp; +FilterXExpr *filterx_binary_op_optimize_method(FilterXExpr *s); gboolean filterx_binary_op_init_method(FilterXExpr *s, GlobalConfig *cfg); void filterx_binary_op_deinit_method(FilterXExpr *s, GlobalConfig *cfg); void filterx_binary_op_free_method(FilterXExpr *s); diff --git a/lib/filterx/filterx-pipe.c b/lib/filterx/filterx-pipe.c index 1f2142edb..20c7dad90 100644 --- a/lib/filterx/filterx-pipe.c +++ b/lib/filterx/filterx-pipe.c @@ -41,6 +41,8 @@ log_filterx_pipe_init(LogPipe *s) if (!self->name) self->name = cfg_tree_get_rule_name(&cfg->tree, ENC_FILTER, s->expr_node); + self->block = filterx_expr_optimize(self->block); + if (!filterx_expr_init(self->block, cfg)) return FALSE; From 1cb798ef36263ee63fbfd67c4f85e149c34cfd88 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Sun, 22 Dec 2024 22:47:43 +0100 Subject: [PATCH 3/6] filterx/expr-boolalg: move optimizations from the constructor to optimize() Signed-off-by: Balazs Scheidler --- lib/filterx/expr-boolalg.c | 128 ++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 57 deletions(-) diff --git a/lib/filterx/expr-boolalg.c b/lib/filterx/expr-boolalg.c index b10dd5aad..d3f8eb855 100644 --- a/lib/filterx/expr-boolalg.c +++ b/lib/filterx/expr-boolalg.c @@ -36,6 +36,20 @@ _literal_expr_truthy(FilterXExpr *expr) return truthy; } +static FilterXExpr * +_optimize_not(FilterXExpr *s) +{ + FilterXUnaryOp *self = (FilterXUnaryOp *) s; + + if (filterx_unary_op_optimize_method(s)) + g_assert_not_reached(); + + if (!filterx_expr_is_literal(self->operand)) + return NULL; + + return filterx_literal_new(filterx_boolean_new(!_literal_expr_truthy(self->operand))); +} + static FilterXObject * _eval_not(FilterXExpr *s) { @@ -57,20 +71,41 @@ _eval_not(FilterXExpr *s) FilterXExpr * filterx_unary_not_new(FilterXExpr *operand) { - if (filterx_expr_is_literal(operand)) - { - FilterXExpr *optimized = filterx_literal_new(filterx_boolean_new(!_literal_expr_truthy(operand))); - filterx_expr_unref(operand); - return optimized; - } - FilterXUnaryOp *self = g_new0(FilterXUnaryOp, 1); filterx_unary_op_init_instance(self, "not", operand); + self->super.optimize = _optimize_not; self->super.eval = _eval_not; return &self->super; } +static FilterXExpr * +_optimize_and(FilterXExpr *s) +{ + FilterXBinaryOp *self = (FilterXBinaryOp *) s; + + if (filterx_binary_op_optimize_method(s)) + g_assert_not_reached(); + + if (!filterx_expr_is_literal(self->lhs)) + return NULL; + + if (!_literal_expr_truthy(self->lhs)) + return filterx_literal_new(filterx_boolean_new(FALSE)); + + if (!filterx_expr_is_literal(self->rhs)) + { + /* we can't optimize the AND away, but the LHS is a literal & truthy + * value. In this case we won't need to evaluate this every time in + * eval(), so unset it */ + filterx_expr_unref(self->lhs); + self->lhs = NULL; + return NULL; + } + + return filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(self->rhs))); +} + static FilterXObject * _eval_and(FilterXExpr *s) { @@ -108,38 +143,42 @@ _eval_and(FilterXExpr *s) FilterXExpr * filterx_binary_and_new(FilterXExpr *lhs, FilterXExpr *rhs) { - FilterXExpr *optimized = NULL; - if (filterx_expr_is_literal(lhs)) - { - if (!_literal_expr_truthy(lhs)) - { - optimized = filterx_literal_new(filterx_boolean_new(FALSE)); - goto optimize; - } - - if (filterx_expr_is_literal(rhs)) - { - optimized = filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(rhs))); - goto optimize; - } - } - FilterXBinaryOp *self = g_new0(FilterXBinaryOp, 1); filterx_binary_op_init_instance(self, "and", lhs, rhs); - if (filterx_expr_is_literal(lhs)) + + self->super.optimize = _optimize_and; + self->super.eval = _eval_and; + return &self->super; + +} + +static FilterXExpr * +_optimize_or(FilterXExpr *s) +{ + FilterXBinaryOp *self = (FilterXBinaryOp *) s; + + if (filterx_binary_op_optimize_method(s)) + g_assert_not_reached(); + + if (!filterx_expr_is_literal(self->lhs)) + return NULL; + + if (_literal_expr_truthy(self->lhs)) + return filterx_literal_new(filterx_boolean_new(TRUE)); + + if (!filterx_expr_is_literal(self->rhs)) { + /* we can't optimize the OR away (as rhs is not literal), but we do + * know that the lhs is literal and is a falsy value. In this case we + * won't need to evaluate this every time in eval(), so unset it */ + filterx_expr_unref(self->lhs); self->lhs = NULL; + return NULL; } - self->super.eval = _eval_and; - return &self->super; - -optimize: - filterx_expr_unref(lhs); - filterx_expr_unref(rhs); - return optimized; + return filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(self->rhs))); } static FilterXObject * @@ -179,36 +218,11 @@ _eval_or(FilterXExpr *s) FilterXExpr * filterx_binary_or_new(FilterXExpr *lhs, FilterXExpr *rhs) { - FilterXExpr *optimized = NULL; - if (filterx_expr_is_literal(lhs)) - { - if (_literal_expr_truthy(lhs)) - { - optimized = filterx_literal_new(filterx_boolean_new(TRUE)); - goto optimize; - } - - if (filterx_expr_is_literal(rhs)) - { - optimized = filterx_literal_new(filterx_boolean_new(_literal_expr_truthy(rhs))); - goto optimize; - } - } - FilterXBinaryOp *self = g_new0(FilterXBinaryOp, 1); filterx_binary_op_init_instance(self, "or", lhs, rhs); - if (filterx_expr_is_literal(lhs)) - { - filterx_expr_unref(self->lhs); - self->lhs = NULL; - } + self->super.optimize = _optimize_or; self->super.eval = _eval_or; return &self->super; - -optimize: - filterx_expr_unref(lhs); - filterx_expr_unref(rhs); - return optimized; } From ec48b4ccc3b69defd704f76566d03a56246760b5 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 23 Dec 2024 08:42:31 +0100 Subject: [PATCH 4/6] filterx/expr-plus: use optimize() method Signed-off-by: Balazs Scheidler --- lib/filterx/expr-plus.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/lib/filterx/expr-plus.c b/lib/filterx/expr-plus.c index f5e562f4a..f31d7f181 100644 --- a/lib/filterx/expr-plus.c +++ b/lib/filterx/expr-plus.c @@ -57,6 +57,25 @@ _eval(FilterXExpr *s) return res; } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXOperatorPlus *self = (FilterXOperatorPlus *) s; + + if (filterx_binary_op_optimize_method(s)) + g_assert_not_reached(); + + if (filterx_expr_is_literal(self->super.lhs)) + self->literal_lhs = filterx_expr_eval_typed(self->super.lhs); + + if (filterx_expr_is_literal(self->super.rhs)) + self->literal_rhs = filterx_expr_eval(self->super.rhs); + + if (self->literal_lhs && self->literal_rhs) + return filterx_literal_new(_eval(&self->super.super)); + return NULL; +} + static void _filterx_operator_plus_free(FilterXExpr *s) { @@ -72,21 +91,9 @@ filterx_operator_plus_new(FilterXExpr *lhs, FilterXExpr *rhs) { FilterXOperatorPlus *self = g_new0(FilterXOperatorPlus, 1); filterx_binary_op_init_instance(&self->super, "plus", lhs, rhs); + self->super.super.optimize = _optimize; self->super.super.eval = _eval; self->super.super.free_fn = _filterx_operator_plus_free; - if (filterx_expr_is_literal(lhs)) - self->literal_lhs = filterx_expr_eval_typed(lhs); - - if (filterx_expr_is_literal(rhs)) - self->literal_rhs = filterx_expr_eval(rhs); - - if (filterx_expr_is_literal(lhs) && filterx_expr_is_literal(rhs)) - { - FilterXExpr *optimized = filterx_literal_new(_eval(&self->super.super)); - filterx_expr_unref(&self->super.super); - return optimized; - } - return &self->super.super; } From 5daa6421f95ca4142d4c4ee286225b1a92f61043 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 23 Dec 2024 09:38:22 +0100 Subject: [PATCH 5/6] filterx/expr-comparison: use optimize() method Signed-off-by: Balazs Scheidler --- lib/filterx/expr-comparison.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/lib/filterx/expr-comparison.c b/lib/filterx/expr-comparison.c index 8220b6770..e94c7d93c 100644 --- a/lib/filterx/expr-comparison.c +++ b/lib/filterx/expr-comparison.c @@ -237,6 +237,24 @@ _eval(FilterXExpr *s) return filterx_boolean_new(result); } +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXComparison *self = (FilterXComparison *) s; + + gint compare_mode = self->operator & FCMPX_MODE_MASK; + if (filterx_expr_is_literal(self->super.lhs)) + self->literal_lhs = _eval_based_on_compare_mode(self->super.lhs, compare_mode); + + if (filterx_expr_is_literal(self->super.rhs)) + self->literal_rhs = _eval_based_on_compare_mode(self->super.rhs, compare_mode); + + if (self->literal_lhs && self->literal_rhs) + return filterx_literal_new(_eval(&self->super.super)); + + return NULL; +} + static void _filterx_comparison_free(FilterXExpr *s) { @@ -254,23 +272,10 @@ filterx_comparison_new(FilterXExpr *lhs, FilterXExpr *rhs, gint operator) FilterXComparison *self = g_new0(FilterXComparison, 1); filterx_binary_op_init_instance(&self->super, "comparison", lhs, rhs); + self->super.super.optimize = _optimize; self->super.super.eval = _eval; self->super.super.free_fn = _filterx_comparison_free; self->operator = operator; - gint compare_mode = self->operator & FCMPX_MODE_MASK; - if (filterx_expr_is_literal(lhs)) - self->literal_lhs = _eval_based_on_compare_mode(lhs, compare_mode); - - if (filterx_expr_is_literal(rhs)) - self->literal_rhs = _eval_based_on_compare_mode(rhs, compare_mode); - - if (filterx_expr_is_literal(lhs) && filterx_expr_is_literal(rhs)) - { - FilterXExpr *optimized = filterx_literal_new(_eval(&self->super.super)); - filterx_expr_unref(&self->super.super); - return optimized; - } - return &self->super.super; } From 626a2cfe800e17faf14f5f2f6cdf4218f20798f0 Mon Sep 17 00:00:00 2001 From: Balazs Scheidler Date: Mon, 23 Dec 2024 12:21:49 +0100 Subject: [PATCH 6/6] filterx/expr-conditional: use optimize() Signed-off-by: Balazs Scheidler --- lib/filterx/expr-condition.c | 87 +++++++++++++++++----------------- lib/filterx/expr-condition.h | 2 - lib/filterx/filterx-grammar.ym | 24 ++-------- 3 files changed, 49 insertions(+), 64 deletions(-) diff --git a/lib/filterx/expr-condition.c b/lib/filterx/expr-condition.c index ba0c3b1bc..ee49c2b59 100644 --- a/lib/filterx/expr-condition.c +++ b/lib/filterx/expr-condition.c @@ -38,15 +38,6 @@ struct _FilterXConditional FilterXExpr *false_branch; }; -static FilterXExpr * -_optimize(FilterXExpr *s) -{ - FilterXConditional *self = (FilterXConditional *) s; - - self->true_branch = filterx_expr_optimize(self->true_branch); - self->false_branch = filterx_expr_optimize(self->false_branch); - return NULL; -} static gboolean _init(FilterXExpr *s, GlobalConfig *cfg) @@ -155,6 +146,50 @@ _eval(FilterXExpr *s) return result; } +static void +_optimize_branches(FilterXExpr *s) +{ + FilterXConditional *self = (FilterXConditional *) s; + + self->condition = filterx_expr_optimize(self->condition); + self->true_branch = filterx_expr_optimize(self->true_branch); + self->false_branch = filterx_expr_optimize(self->false_branch); +} + +static FilterXExpr * +_optimize(FilterXExpr *s) +{ + FilterXConditional *self = (FilterXConditional *) s; + + _optimize_branches(s); + + if (!filterx_expr_is_literal(self->condition)) + return FALSE; + + FilterXObject *condition_value = filterx_expr_eval(self->condition); + + g_assert(condition_value); + gboolean condition_truthy = filterx_object_truthy(condition_value); + filterx_object_unref(condition_value); + + if (condition_truthy) + { + if (self->true_branch) + return filterx_expr_ref(self->true_branch); + else + return filterx_expr_ref(self->condition); + } + else + { + if (self->false_branch) + return filterx_expr_ref(self->false_branch); + else + return filterx_literal_new(filterx_boolean_new(TRUE)); + } + + return NULL; +} + void filterx_conditional_set_true_branch(FilterXExpr *s, FilterXExpr *true_branch) { @@ -207,37 +242,3 @@ filterx_conditional_find_tail(FilterXExpr *s) } return s; } - -FilterXExpr * -filterx_literal_conditional(FilterXExpr *condition, FilterXExpr *true_branch, FilterXExpr *false_branch) -{ - g_assert(filterx_expr_is_literal(condition)); - - FilterXObject *condition_value = filterx_expr_eval(condition); - g_assert(condition_value); - - FilterXExpr *optimized = NULL; - - if (filterx_object_truthy(condition_value)) - { - if (true_branch) - optimized = true_branch; - else - optimized = filterx_expr_ref(condition); - - filterx_expr_unref(false_branch); - } - else - { - if (false_branch) - optimized = false_branch; - else - optimized = filterx_literal_new(filterx_boolean_new(TRUE)); - - filterx_expr_unref(true_branch); - } - - filterx_object_unref(condition_value); - filterx_expr_unref(condition); - return optimized; -} diff --git a/lib/filterx/expr-condition.h b/lib/filterx/expr-condition.h index 8b602de07..cd463f8ea 100644 --- a/lib/filterx/expr-condition.h +++ b/lib/filterx/expr-condition.h @@ -31,6 +31,4 @@ void filterx_conditional_set_false_branch(FilterXExpr *s, FilterXExpr *false_bra FilterXExpr *filterx_conditional_find_tail(FilterXExpr *s); FilterXExpr *filterx_conditional_new(FilterXExpr *condition); -FilterXExpr *filterx_literal_conditional(FilterXExpr *condition, FilterXExpr *true_branch, FilterXExpr *false_branch); - #endif diff --git a/lib/filterx/filterx-grammar.ym b/lib/filterx/filterx-grammar.ym index 707dd722e..e0cc8090f 100644 --- a/lib/filterx/filterx-grammar.ym +++ b/lib/filterx/filterx-grammar.ym @@ -641,29 +641,15 @@ ternary : expr '?' expr ':' expr { filterx_expr_set_location($1, lexer, &@1); - if (filterx_expr_is_literal($1)) - { - $$ = filterx_literal_conditional($1, $3, $5); - } - else - { - $$ = filterx_conditional_new($1); - filterx_conditional_set_true_branch($$, $3); - filterx_conditional_set_false_branch($$, $5); - } + $$ = filterx_conditional_new($1); + filterx_conditional_set_true_branch($$, $3); + filterx_conditional_set_false_branch($$, $5); } | expr '?' ':' expr { filterx_expr_set_location($1, lexer, &@1); - if (filterx_expr_is_literal($1)) - { - $$ = filterx_literal_conditional($1, NULL, $4); - } - else - { - $$ = filterx_conditional_new($1); - filterx_conditional_set_false_branch($$, $4); - } + $$ = filterx_conditional_new($1); + filterx_conditional_set_false_branch($$, $4); } ;