Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

+170 -277
+13
scripts/include/hash.h
··· 12 12 return hash; 13 13 } 14 14 15 + /* simplified version of functions from include/linux/hash.h */ 16 + #define GOLDEN_RATIO_32 0x61C88647 17 + 18 + static inline unsigned int hash_32(unsigned int val) 19 + { 20 + return 0x61C88647 * val; 21 + } 22 + 23 + static inline unsigned int hash_ptr(const void *ptr) 24 + { 25 + return hash_32((unsigned int)(unsigned long)ptr); 26 + } 27 + 15 28 #endif /* HASH_H */
+131 -250
scripts/kconfig/expr.c
··· 9 9 #include <stdlib.h> 10 10 #include <string.h> 11 11 12 + #include <hash.h> 12 13 #include <xalloc.h> 14 + #include "internal.h" 13 15 #include "lkc.h" 14 16 15 17 #define DEBUG_EXPR 0 16 18 19 + HASHTABLE_DEFINE(expr_hashtable, EXPR_HASHSIZE); 20 + 17 21 static struct expr *expr_eliminate_yn(struct expr *e); 22 + 23 + /** 24 + * expr_lookup - return the expression with the given type and sub-nodes 25 + * This looks up an expression with the specified type and sub-nodes. If such 26 + * an expression is found in the hash table, it is returned. Otherwise, a new 27 + * expression node is allocated and added to the hash table. 28 + * @type: expression type 29 + * @l: left node 30 + * @r: right node 31 + * return: expression 32 + */ 33 + static struct expr *expr_lookup(enum expr_type type, void *l, void *r) 34 + { 35 + struct expr *e; 36 + int hash; 37 + 38 + hash = hash_32((unsigned int)type ^ hash_ptr(l) ^ hash_ptr(r)); 39 + 40 + hash_for_each_possible(expr_hashtable, e, node, hash) { 41 + if (e->type == type && e->left._initdata == l && 42 + e->right._initdata == r) 43 + return e; 44 + } 45 + 46 + e = xmalloc(sizeof(*e)); 47 + e->type = type; 48 + e->left._initdata = l; 49 + e->right._initdata = r; 50 + 51 + hash_add(expr_hashtable, &e->node, hash); 52 + 53 + return e; 54 + } 18 55 19 56 struct expr *expr_alloc_symbol(struct symbol *sym) 20 57 { 21 - struct expr *e = xcalloc(1, sizeof(*e)); 22 - e->type = E_SYMBOL; 23 - e->left.sym = sym; 24 - return e; 58 + return expr_lookup(E_SYMBOL, sym, NULL); 25 59 } 26 60 27 61 struct expr *expr_alloc_one(enum expr_type type, struct expr *ce) 28 62 { 29 - struct expr *e = xcalloc(1, sizeof(*e)); 30 - e->type = type; 31 - e->left.expr = ce; 32 - return e; 63 + return expr_lookup(type, ce, NULL); 33 64 } 34 65 35 66 struct expr *expr_alloc_two(enum expr_type type, struct expr *e1, struct expr *e2) 36 67 { 37 - struct expr *e = xcalloc(1, sizeof(*e)); 38 - e->type = type; 39 - e->left.expr = e1; 40 - e->right.expr = e2; 41 - return e; 68 + return expr_lookup(type, e1, e2); 42 69 } 43 70 44 71 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2) 45 72 { 46 - struct expr *e = xcalloc(1, sizeof(*e)); 47 - e->type = type; 48 - e->left.sym = s1; 49 - e->right.sym = s2; 50 - return e; 73 + return expr_lookup(type, s1, s2); 51 74 } 52 75 53 76 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2) ··· 87 64 return e2 ? expr_alloc_two(E_OR, e1, e2) : e1; 88 65 } 89 66 90 - struct expr *expr_copy(const struct expr *org) 91 - { 92 - struct expr *e; 93 - 94 - if (!org) 95 - return NULL; 96 - 97 - e = xmalloc(sizeof(*org)); 98 - memcpy(e, org, sizeof(*org)); 99 - switch (org->type) { 100 - case E_SYMBOL: 101 - e->left = org->left; 102 - break; 103 - case E_NOT: 104 - e->left.expr = expr_copy(org->left.expr); 105 - break; 106 - case E_EQUAL: 107 - case E_GEQ: 108 - case E_GTH: 109 - case E_LEQ: 110 - case E_LTH: 111 - case E_UNEQUAL: 112 - e->left.sym = org->left.sym; 113 - e->right.sym = org->right.sym; 114 - break; 115 - case E_AND: 116 - case E_OR: 117 - e->left.expr = expr_copy(org->left.expr); 118 - e->right.expr = expr_copy(org->right.expr); 119 - break; 120 - default: 121 - fprintf(stderr, "can't copy type %d\n", e->type); 122 - free(e); 123 - e = NULL; 124 - break; 125 - } 126 - 127 - return e; 128 - } 129 - 130 - void expr_free(struct expr *e) 131 - { 132 - if (!e) 133 - return; 134 - 135 - switch (e->type) { 136 - case E_SYMBOL: 137 - break; 138 - case E_NOT: 139 - expr_free(e->left.expr); 140 - break; 141 - case E_EQUAL: 142 - case E_GEQ: 143 - case E_GTH: 144 - case E_LEQ: 145 - case E_LTH: 146 - case E_UNEQUAL: 147 - break; 148 - case E_OR: 149 - case E_AND: 150 - expr_free(e->left.expr); 151 - expr_free(e->right.expr); 152 - break; 153 - default: 154 - fprintf(stderr, "how to free type %d?\n", e->type); 155 - break; 156 - } 157 - free(e); 158 - } 159 - 160 67 static int trans_count; 161 68 162 69 /* ··· 99 146 */ 100 147 static void __expr_eliminate_eq(enum expr_type type, struct expr **ep1, struct expr **ep2) 101 148 { 149 + struct expr *l, *r; 150 + 102 151 /* Recurse down to leaves */ 103 152 104 153 if ((*ep1)->type == type) { 105 - __expr_eliminate_eq(type, &(*ep1)->left.expr, ep2); 106 - __expr_eliminate_eq(type, &(*ep1)->right.expr, ep2); 154 + l = (*ep1)->left.expr; 155 + r = (*ep1)->right.expr; 156 + __expr_eliminate_eq(type, &l, ep2); 157 + __expr_eliminate_eq(type, &r, ep2); 158 + *ep1 = expr_alloc_two(type, l, r); 107 159 return; 108 160 } 109 161 if ((*ep2)->type == type) { 110 - __expr_eliminate_eq(type, ep1, &(*ep2)->left.expr); 111 - __expr_eliminate_eq(type, ep1, &(*ep2)->right.expr); 162 + l = (*ep2)->left.expr; 163 + r = (*ep2)->right.expr; 164 + __expr_eliminate_eq(type, ep1, &l); 165 + __expr_eliminate_eq(type, ep1, &r); 166 + *ep2 = expr_alloc_two(type, l, r); 112 167 return; 113 168 } 114 169 ··· 132 171 /* *ep1 and *ep2 are equal leaves. Prepare them for elimination. */ 133 172 134 173 trans_count++; 135 - expr_free(*ep1); expr_free(*ep2); 136 174 switch (type) { 137 175 case E_OR: 138 176 *ep1 = expr_alloc_symbol(&symbol_no); ··· 231 271 return expr_eq(e1->left.expr, e2->left.expr); 232 272 case E_AND: 233 273 case E_OR: 234 - e1 = expr_copy(e1); 235 - e2 = expr_copy(e2); 236 274 old_count = trans_count; 237 275 expr_eliminate_eq(&e1, &e2); 238 276 res = (e1->type == E_SYMBOL && e2->type == E_SYMBOL && 239 277 e1->left.sym == e2->left.sym); 240 - expr_free(e1); 241 - expr_free(e2); 242 278 trans_count = old_count; 243 279 return res; 244 280 case E_RANGE: ··· 253 297 } 254 298 255 299 /* 256 - * Recursively performs the following simplifications in-place (as well as the 300 + * Recursively performs the following simplifications (as well as the 257 301 * corresponding simplifications with swapped operands): 258 302 * 259 303 * expr && n -> n ··· 265 309 */ 266 310 static struct expr *expr_eliminate_yn(struct expr *e) 267 311 { 268 - struct expr *tmp; 312 + struct expr *l, *r; 269 313 270 314 if (e) switch (e->type) { 271 315 case E_AND: 272 - e->left.expr = expr_eliminate_yn(e->left.expr); 273 - e->right.expr = expr_eliminate_yn(e->right.expr); 274 - if (e->left.expr->type == E_SYMBOL) { 275 - if (e->left.expr->left.sym == &symbol_no) { 276 - expr_free(e->left.expr); 277 - expr_free(e->right.expr); 278 - e->type = E_SYMBOL; 279 - e->left.sym = &symbol_no; 280 - e->right.expr = NULL; 281 - return e; 282 - } else if (e->left.expr->left.sym == &symbol_yes) { 283 - free(e->left.expr); 284 - tmp = e->right.expr; 285 - *e = *(e->right.expr); 286 - free(tmp); 287 - return e; 288 - } 316 + l = expr_eliminate_yn(e->left.expr); 317 + r = expr_eliminate_yn(e->right.expr); 318 + if (l->type == E_SYMBOL) { 319 + if (l->left.sym == &symbol_no) 320 + return l; 321 + else if (l->left.sym == &symbol_yes) 322 + return r; 289 323 } 290 - if (e->right.expr->type == E_SYMBOL) { 291 - if (e->right.expr->left.sym == &symbol_no) { 292 - expr_free(e->left.expr); 293 - expr_free(e->right.expr); 294 - e->type = E_SYMBOL; 295 - e->left.sym = &symbol_no; 296 - e->right.expr = NULL; 297 - return e; 298 - } else if (e->right.expr->left.sym == &symbol_yes) { 299 - free(e->right.expr); 300 - tmp = e->left.expr; 301 - *e = *(e->left.expr); 302 - free(tmp); 303 - return e; 304 - } 324 + if (r->type == E_SYMBOL) { 325 + if (r->left.sym == &symbol_no) 326 + return r; 327 + else if (r->left.sym == &symbol_yes) 328 + return l; 305 329 } 306 330 break; 307 331 case E_OR: 308 - e->left.expr = expr_eliminate_yn(e->left.expr); 309 - e->right.expr = expr_eliminate_yn(e->right.expr); 310 - if (e->left.expr->type == E_SYMBOL) { 311 - if (e->left.expr->left.sym == &symbol_no) { 312 - free(e->left.expr); 313 - tmp = e->right.expr; 314 - *e = *(e->right.expr); 315 - free(tmp); 316 - return e; 317 - } else if (e->left.expr->left.sym == &symbol_yes) { 318 - expr_free(e->left.expr); 319 - expr_free(e->right.expr); 320 - e->type = E_SYMBOL; 321 - e->left.sym = &symbol_yes; 322 - e->right.expr = NULL; 323 - return e; 324 - } 332 + l = expr_eliminate_yn(e->left.expr); 333 + r = expr_eliminate_yn(e->right.expr); 334 + if (l->type == E_SYMBOL) { 335 + if (l->left.sym == &symbol_no) 336 + return r; 337 + else if (l->left.sym == &symbol_yes) 338 + return l; 325 339 } 326 - if (e->right.expr->type == E_SYMBOL) { 327 - if (e->right.expr->left.sym == &symbol_no) { 328 - free(e->right.expr); 329 - tmp = e->left.expr; 330 - *e = *(e->left.expr); 331 - free(tmp); 332 - return e; 333 - } else if (e->right.expr->left.sym == &symbol_yes) { 334 - expr_free(e->left.expr); 335 - expr_free(e->right.expr); 336 - e->type = E_SYMBOL; 337 - e->left.sym = &symbol_yes; 338 - e->right.expr = NULL; 339 - return e; 340 - } 340 + if (r->type == E_SYMBOL) { 341 + if (r->left.sym == &symbol_no) 342 + return l; 343 + else if (r->left.sym == &symbol_yes) 344 + return r; 341 345 } 342 346 break; 343 347 default: ··· 315 399 struct symbol *sym1, *sym2; 316 400 317 401 if (expr_eq(e1, e2)) 318 - return expr_copy(e1); 402 + return e1; 319 403 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) 320 404 return NULL; 321 405 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) ··· 380 464 struct symbol *sym1, *sym2; 381 465 382 466 if (expr_eq(e1, e2)) 383 - return expr_copy(e1); 467 + return e1; 384 468 if (e1->type != E_EQUAL && e1->type != E_UNEQUAL && e1->type != E_SYMBOL && e1->type != E_NOT) 385 469 return NULL; 386 470 if (e2->type != E_EQUAL && e2->type != E_UNEQUAL && e2->type != E_SYMBOL && e2->type != E_NOT) ··· 477 561 */ 478 562 static void expr_eliminate_dups1(enum expr_type type, struct expr **ep1, struct expr **ep2) 479 563 { 480 - struct expr *tmp; 564 + struct expr *tmp, *l, *r; 481 565 482 566 /* Recurse down to leaves */ 483 567 484 568 if ((*ep1)->type == type) { 485 - expr_eliminate_dups1(type, &(*ep1)->left.expr, ep2); 486 - expr_eliminate_dups1(type, &(*ep1)->right.expr, ep2); 569 + l = (*ep1)->left.expr; 570 + r = (*ep1)->right.expr; 571 + expr_eliminate_dups1(type, &l, ep2); 572 + expr_eliminate_dups1(type, &r, ep2); 573 + *ep1 = expr_alloc_two(type, l, r); 487 574 return; 488 575 } 489 576 if ((*ep2)->type == type) { 490 - expr_eliminate_dups1(type, ep1, &(*ep2)->left.expr); 491 - expr_eliminate_dups1(type, ep1, &(*ep2)->right.expr); 577 + l = (*ep2)->left.expr; 578 + r = (*ep2)->right.expr; 579 + expr_eliminate_dups1(type, ep1, &l); 580 + expr_eliminate_dups1(type, ep1, &r); 581 + *ep2 = expr_alloc_two(type, l, r); 492 582 return; 493 583 } 494 584 ··· 504 582 case E_OR: 505 583 tmp = expr_join_or(*ep1, *ep2); 506 584 if (tmp) { 507 - expr_free(*ep1); expr_free(*ep2); 508 585 *ep1 = expr_alloc_symbol(&symbol_no); 509 586 *ep2 = tmp; 510 587 trans_count++; ··· 512 591 case E_AND: 513 592 tmp = expr_join_and(*ep1, *ep2); 514 593 if (tmp) { 515 - expr_free(*ep1); expr_free(*ep2); 516 594 *ep1 = expr_alloc_symbol(&symbol_yes); 517 595 *ep2 = tmp; 518 596 trans_count++; ··· 541 621 542 622 oldcount = trans_count; 543 623 do { 624 + struct expr *l, *r; 625 + 544 626 trans_count = 0; 545 627 switch (e->type) { 546 628 case E_OR: case E_AND: 547 - e->left.expr = expr_eliminate_dups(e->left.expr); 548 - e->right.expr = expr_eliminate_dups(e->right.expr); 549 - expr_eliminate_dups1(e->type, &e->left.expr, &e->right.expr); 629 + l = expr_eliminate_dups(e->left.expr); 630 + r = expr_eliminate_dups(e->right.expr); 631 + expr_eliminate_dups1(e->type, &l, &r); 632 + e = expr_alloc_two(e->type, l, r); 550 633 default: 551 634 ; 552 635 } ··· 591 668 */ 592 669 struct expr *expr_transform(struct expr *e) 593 670 { 594 - struct expr *tmp; 595 - 596 671 if (!e) 597 672 return NULL; 598 673 switch (e->type) { ··· 603 682 case E_SYMBOL: 604 683 break; 605 684 default: 606 - e->left.expr = expr_transform(e->left.expr); 607 - e->right.expr = expr_transform(e->right.expr); 685 + e = expr_alloc_two(e->type, 686 + expr_transform(e->left.expr), 687 + expr_transform(e->right.expr)); 608 688 } 609 689 610 690 switch (e->type) { ··· 614 692 break; 615 693 if (e->right.sym == &symbol_no) { 616 694 // A=n -> !A 617 - e->type = E_NOT; 618 - e->left.expr = expr_alloc_symbol(e->left.sym); 619 - e->right.sym = NULL; 695 + e = expr_alloc_one(E_NOT, expr_alloc_symbol(e->left.sym)); 620 696 break; 621 697 } 622 698 if (e->right.sym == &symbol_mod) { 623 699 // A=m -> n 624 700 printf("boolean symbol %s tested for 'm'? test forced to 'n'\n", e->left.sym->name); 625 - e->type = E_SYMBOL; 626 - e->left.sym = &symbol_no; 627 - e->right.sym = NULL; 701 + e = expr_alloc_symbol(&symbol_no); 628 702 break; 629 703 } 630 704 if (e->right.sym == &symbol_yes) { 631 705 // A=y -> A 632 - e->type = E_SYMBOL; 633 - e->right.sym = NULL; 706 + e = expr_alloc_symbol(e->left.sym); 634 707 break; 635 708 } 636 709 break; ··· 634 717 break; 635 718 if (e->right.sym == &symbol_no) { 636 719 // A!=n -> A 637 - e->type = E_SYMBOL; 638 - e->right.sym = NULL; 720 + e = expr_alloc_symbol(e->left.sym); 639 721 break; 640 722 } 641 723 if (e->right.sym == &symbol_mod) { 642 724 // A!=m -> y 643 725 printf("boolean symbol %s tested for 'm'? test forced to 'y'\n", e->left.sym->name); 644 - e->type = E_SYMBOL; 645 - e->left.sym = &symbol_yes; 646 - e->right.sym = NULL; 726 + e = expr_alloc_symbol(&symbol_yes); 647 727 break; 648 728 } 649 729 if (e->right.sym == &symbol_yes) { 650 730 // A!=y -> !A 651 - e->type = E_NOT; 652 - e->left.expr = expr_alloc_symbol(e->left.sym); 653 - e->right.sym = NULL; 731 + e = expr_alloc_one(E_NOT, e->left.expr); 654 732 break; 655 733 } 656 734 break; ··· 653 741 switch (e->left.expr->type) { 654 742 case E_NOT: 655 743 // !!A -> A 656 - tmp = e->left.expr->left.expr; 657 - free(e->left.expr); 658 - free(e); 659 - e = tmp; 660 - e = expr_transform(e); 744 + e = e->left.expr->left.expr; 661 745 break; 662 746 case E_EQUAL: 663 747 case E_UNEQUAL: 664 748 // !(A=B) -> A!=B 665 - tmp = e->left.expr; 666 - free(e); 667 - e = tmp; 668 - e->type = e->type == E_EQUAL ? E_UNEQUAL : E_EQUAL; 749 + e = expr_alloc_comp(e->left.expr->type == E_EQUAL ? E_UNEQUAL : E_EQUAL, 750 + e->left.expr->left.sym, 751 + e->left.expr->right.sym); 669 752 break; 670 753 case E_LEQ: 671 754 case E_GEQ: 672 755 // !(A<=B) -> A>B 673 - tmp = e->left.expr; 674 - free(e); 675 - e = tmp; 676 - e->type = e->type == E_LEQ ? E_GTH : E_LTH; 756 + e = expr_alloc_comp(e->left.expr->type == E_LEQ ? E_GTH : E_LTH, 757 + e->left.expr->left.sym, 758 + e->left.expr->right.sym); 677 759 break; 678 760 case E_LTH: 679 761 case E_GTH: 680 762 // !(A<B) -> A>=B 681 - tmp = e->left.expr; 682 - free(e); 683 - e = tmp; 684 - e->type = e->type == E_LTH ? E_GEQ : E_LEQ; 763 + e = expr_alloc_comp(e->left.expr->type == E_LTH ? E_GEQ : E_LEQ, 764 + e->left.expr->left.sym, 765 + e->left.expr->right.sym); 685 766 break; 686 767 case E_OR: 687 768 // !(A || B) -> !A && !B 688 - tmp = e->left.expr; 689 - e->type = E_AND; 690 - e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); 691 - tmp->type = E_NOT; 692 - tmp->right.expr = NULL; 769 + e = expr_alloc_and(expr_alloc_one(E_NOT, e->left.expr->left.expr), 770 + expr_alloc_one(E_NOT, e->left.expr->right.expr)); 693 771 e = expr_transform(e); 694 772 break; 695 773 case E_AND: 696 774 // !(A && B) -> !A || !B 697 - tmp = e->left.expr; 698 - e->type = E_OR; 699 - e->right.expr = expr_alloc_one(E_NOT, tmp->right.expr); 700 - tmp->type = E_NOT; 701 - tmp->right.expr = NULL; 775 + e = expr_alloc_or(expr_alloc_one(E_NOT, e->left.expr->left.expr), 776 + expr_alloc_one(E_NOT, e->left.expr->right.expr)); 702 777 e = expr_transform(e); 703 778 break; 704 779 case E_SYMBOL: 705 - if (e->left.expr->left.sym == &symbol_yes) { 780 + if (e->left.expr->left.sym == &symbol_yes) 706 781 // !'y' -> 'n' 707 - tmp = e->left.expr; 708 - free(e); 709 - e = tmp; 710 - e->type = E_SYMBOL; 711 - e->left.sym = &symbol_no; 712 - break; 713 - } 714 - if (e->left.expr->left.sym == &symbol_mod) { 782 + e = expr_alloc_symbol(&symbol_no); 783 + else if (e->left.expr->left.sym == &symbol_mod) 715 784 // !'m' -> 'm' 716 - tmp = e->left.expr; 717 - free(e); 718 - e = tmp; 719 - e->type = E_SYMBOL; 720 - e->left.sym = &symbol_mod; 721 - break; 722 - } 723 - if (e->left.expr->left.sym == &symbol_no) { 785 + e = expr_alloc_symbol(&symbol_mod); 786 + else if (e->left.expr->left.sym == &symbol_no) 724 787 // !'n' -> 'y' 725 - tmp = e->left.expr; 726 - free(e); 727 - e = tmp; 728 - e->type = E_SYMBOL; 729 - e->left.sym = &symbol_yes; 730 - break; 731 - } 788 + e = expr_alloc_symbol(&symbol_yes); 732 789 break; 733 790 default: 734 791 ; ··· 821 940 case E_EQUAL: 822 941 if (type == E_EQUAL) { 823 942 if (sym == &symbol_yes) 824 - return expr_copy(e); 943 + return e; 825 944 if (sym == &symbol_mod) 826 945 return expr_alloc_symbol(&symbol_no); 827 946 if (sym == &symbol_no) 828 - return expr_alloc_one(E_NOT, expr_copy(e)); 947 + return expr_alloc_one(E_NOT, e); 829 948 } else { 830 949 if (sym == &symbol_yes) 831 - return expr_alloc_one(E_NOT, expr_copy(e)); 950 + return expr_alloc_one(E_NOT, e); 832 951 if (sym == &symbol_mod) 833 952 return expr_alloc_symbol(&symbol_yes); 834 953 if (sym == &symbol_no) 835 - return expr_copy(e); 954 + return e; 836 955 } 837 956 break; 838 957 case E_SYMBOL:
+12 -4
scripts/kconfig/expr.h
··· 29 29 }; 30 30 31 31 union expr_data { 32 - struct expr *expr; 33 - struct symbol *sym; 32 + struct expr * const expr; 33 + struct symbol * const sym; 34 + void *_initdata; 34 35 }; 35 36 37 + /** 38 + * struct expr - expression 39 + * 40 + * @node: link node for the hash table 41 + * @type: expressoin type 42 + * @left: left node 43 + * @right: right node 44 + */ 36 45 struct expr { 46 + struct hlist_node node; 37 47 enum expr_type type; 38 48 union expr_data left, right; 39 49 }; ··· 285 275 struct expr *expr_alloc_comp(enum expr_type type, struct symbol *s1, struct symbol *s2); 286 276 struct expr *expr_alloc_and(struct expr *e1, struct expr *e2); 287 277 struct expr *expr_alloc_or(struct expr *e1, struct expr *e2); 288 - struct expr *expr_copy(const struct expr *org); 289 - void expr_free(struct expr *e); 290 278 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2); 291 279 bool expr_eq(struct expr *e1, struct expr *e2); 292 280 tristate expr_calc_value(struct expr *e);
+4
scripts/kconfig/internal.h
··· 11 11 #define for_all_symbols(sym) \ 12 12 hash_for_each(sym_hashtable, sym, node) 13 13 14 + #define EXPR_HASHSIZE (1U << 14) 15 + 16 + extern HASHTABLE_DECLARE(expr_hashtable, EXPR_HASHSIZE); 17 + 14 18 struct menu; 15 19 16 20 extern struct menu *current_menu, *current_entry;
+10 -23
scripts/kconfig/menu.c
··· 107 107 108 108 switch (e->type) { 109 109 case E_NOT: 110 - e->left.expr = rewrite_m(e->left.expr); 110 + e = expr_alloc_one(E_NOT, rewrite_m(e->left.expr)); 111 111 break; 112 112 case E_OR: 113 113 case E_AND: 114 - e->left.expr = rewrite_m(e->left.expr); 115 - e->right.expr = rewrite_m(e->right.expr); 114 + e = expr_alloc_two(e->type, 115 + rewrite_m(e->left.expr), 116 + rewrite_m(e->right.expr)); 116 117 break; 117 118 case E_SYMBOL: 118 119 /* change 'm' into 'm' && MODULES */ ··· 193 192 struct menu *menu = current_entry; 194 193 195 194 while ((menu = menu->parent) != NULL) { 196 - struct expr *dup_expr; 197 195 198 196 if (!menu->visibility) 199 197 continue; 200 - /* 201 - * Do not add a reference to the menu's visibility 202 - * expression but use a copy of it. Otherwise the 203 - * expression reduction functions will modify 204 - * expressions that have multiple references which 205 - * can cause unwanted side effects. 206 - */ 207 - dup_expr = expr_copy(menu->visibility); 208 - 209 198 prop->visible.expr = expr_alloc_and(prop->visible.expr, 210 - dup_expr); 199 + menu->visibility); 211 200 } 212 201 } 213 202 ··· 313 322 */ 314 323 basedep = rewrite_m(menu->dep); 315 324 basedep = expr_transform(basedep); 316 - basedep = expr_alloc_and(expr_copy(parent->dep), basedep); 325 + basedep = expr_alloc_and(parent->dep, basedep); 317 326 basedep = expr_eliminate_dups(basedep); 318 327 menu->dep = basedep; 319 328 ··· 357 366 */ 358 367 dep = rewrite_m(prop->visible.expr); 359 368 dep = expr_transform(dep); 360 - dep = expr_alloc_and(expr_copy(basedep), dep); 369 + dep = expr_alloc_and(basedep, dep); 361 370 dep = expr_eliminate_dups(dep); 362 371 prop->visible.expr = dep; 363 372 ··· 368 377 if (prop->type == P_SELECT) { 369 378 struct symbol *es = prop_get_symbol(prop); 370 379 es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, 371 - expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); 380 + expr_alloc_and(expr_alloc_symbol(menu->sym), dep)); 372 381 } else if (prop->type == P_IMPLY) { 373 382 struct symbol *es = prop_get_symbol(prop); 374 383 es->implied.expr = expr_alloc_or(es->implied.expr, 375 - expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep))); 384 + expr_alloc_and(expr_alloc_symbol(menu->sym), dep)); 376 385 } 377 386 } 378 387 } ··· 432 441 */ 433 442 dep = expr_trans_compare(dep, E_UNEQUAL, &symbol_no); 434 443 dep = expr_eliminate_dups(expr_transform(dep)); 435 - dep2 = expr_copy(basedep); 444 + dep2 = basedep; 436 445 expr_eliminate_eq(&dep, &dep2); 437 - expr_free(dep); 438 446 if (!expr_is_yes(dep2)) { 439 447 /* Not superset, quit */ 440 - expr_free(dep2); 441 448 break; 442 449 } 443 450 /* Superset, put in submenu */ 444 - expr_free(dep2); 445 451 next: 446 452 _menu_finalize(menu, false); 447 453 menu->parent = parent; 448 454 last_menu = menu; 449 455 } 450 - expr_free(basedep); 451 456 if (last_menu) { 452 457 parent->list = parent->next; 453 458 parent->next = last_menu->next;