diff options
author | Masahiro Yamada <masahiroy@kernel.org> | 2024-09-08 21:43:20 +0900 |
---|---|---|
committer | Masahiro Yamada <masahiroy@kernel.org> | 2024-09-20 09:21:52 +0900 |
commit | f93d6bfbd2f74d79041c153a59df5336f6e9a14a (patch) | |
tree | 7661981cefb2b35765a7ade7d22b9b742cb050a2 /scripts/kconfig/expr.h | |
parent | 440f67ccdcd31ca33d8d0439b16e4b6d4d7aba17 (diff) |
kconfig: use hash table to reuse expressions
Currently, every expression in Kconfig files produces a new abstract
syntax tree (AST), even if it is identical to a previously encountered
one.
Consider the following code:
config FOO
bool "FOO"
depends on (A || B) && C
config BAR
bool "BAR"
depends on (A || B) && C
config BAZ
bool "BAZ"
depends on A || B
The "depends on" lines are similar, but currently a separate AST is
allocated for each one.
The current data structure looks like this:
FOO->dep ==> AND BAR->dep ==> AND BAZ->dep ==> OR
/ \ / \ / \
OR C OR C A B
/ \ / \
A B A B
This is redundant; FOO->dep and BAR->dep have identical ASTs but
different memory instances.
We can optimize this; FOO->dep and BAR->dep can share the same AST, and
BAZ->dep can reference its sub tree.
The optimized data structure looks like this:
FOO->dep, BAR->dep ==> AND
/ \
BAZ->dep ==> OR C
/ \
A B
This commit introduces a hash table to keep track of allocated
expressions. If an identical expression is found, it is reused.
This does not necessarily result in memory savings, as menu_finalize()
transforms expressions without freeing up stale ones. This will be
addressed later.
One optimization that can be easily implemented is caching the
expression's value. Once FOO's dependency, (A || B) && C, is calculated,
it can be cached, eliminating the need to recalculate it for BAR.
This commit also reverts commit e983b7b17ad1 ("kconfig/menu.c: fix
multiple references to expressions in menu_add_prop()").
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Diffstat (limited to 'scripts/kconfig/expr.h')
-rw-r--r-- | scripts/kconfig/expr.h | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h index 4ab7422ddbd8..a398b2b2dbe0 100644 --- a/scripts/kconfig/expr.h +++ b/scripts/kconfig/expr.h @@ -29,11 +29,21 @@ enum expr_type { }; union expr_data { - struct expr *expr; - struct symbol *sym; + struct expr * const expr; + struct symbol * const sym; + void *_initdata; }; +/** + * struct expr - expression + * + * @node: link node for the hash table + * @type: expressoin type + * @left: left node + * @right: right node + */ struct expr { + struct hlist_node node; enum expr_type type; union expr_data left, right; }; @@ -275,8 +285,6 @@ struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); -struct expr *expr_copy(const struct expr *org); -void expr_free(struct expr *e); void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); bool expr_eq(struct expr *e1, struct expr *e2); tristate expr_calc_value(struct expr *e); |