From ec6aeb95cab15c66e6d73c526ade84a31e73f6f3 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sun, 27 May 2012 09:15:59 +0300 Subject: [PATCH] extra: don't create a new merged estate if ->right and ->left are equivalent This saves memory. We couldn't do this before because the ->related list was getting modified after we called set_state(). Signed-off-by: Dan Carpenter --- smatch_estate.c | 36 ++++++++++++++++++++++++++++++++++++ smatch_extra.c | 3 +++ smatch_extra.h | 1 + 3 files changed, 40 insertions(+) diff --git a/smatch_estate.c b/smatch_estate.c index 7e157520..6df31b81 100644 --- a/smatch_estate.c +++ b/smatch_estate.c @@ -58,6 +58,42 @@ long long estate_max(struct smatch_state *state) return rl_max(estate_ranges(state)); } +static int rlists_equiv(struct related_list *one, struct related_list *two) +{ + struct relation *one_rel; + struct relation *two_rel; + + PREPARE_PTR_LIST(one, one_rel); + PREPARE_PTR_LIST(two, two_rel); + for (;;) { + if (!one_rel && !two_rel) + return 1; + if (!one_rel || !two_rel) + return 0; + if (one_rel->sym != two_rel->sym) + return 0; + if (strcmp(one_rel->name, two_rel->name)) + return 0; + NEXT_PTR_LIST(one_rel); + NEXT_PTR_LIST(two_rel); + } + FINISH_PTR_LIST(two_rel); + FINISH_PTR_LIST(one_rel); + + return 1; +} + +int estates_equiv(struct smatch_state *one, struct smatch_state *two) +{ + if (one == two) + return 1; + if (!rlists_equiv(estate_related(one), estate_related(two))) + return 0; + if (strcmp(one->name, two->name) == 0) + return 1; + return 0; +} + static struct data_info *alloc_dinfo(void) { struct data_info *ret; diff --git a/smatch_extra.c b/smatch_extra.c index 94fd75e0..ee0da52a 100644 --- a/smatch_extra.c +++ b/smatch_extra.c @@ -152,6 +152,9 @@ static struct smatch_state *merge_func(const char *name, struct symbol *sym, struct range_list *value_ranges; struct related_list *rlist; + if (estates_equiv(s1, s2)) + return s1; + value_ranges = range_list_union(estate_ranges(s1), estate_ranges(s2)); tmp = alloc_estate_range_list(value_ranges); rlist = get_shared_relations(estate_related(s1), estate_related(s2)); diff --git a/smatch_extra.h b/smatch_extra.h index c9776fd0..80f1b3c4 100644 --- a/smatch_extra.h +++ b/smatch_extra.h @@ -72,6 +72,7 @@ void __extra_pre_loop_hook_after(struct sm_state *sm, struct expression *condition); /* also implemented in smatch_extra */ +int estates_equiv(struct smatch_state *one, struct smatch_state *two); struct smatch_state *clone_estate(struct smatch_state *state); struct sm_state *set_extra_mod(const char *name, struct symbol *sym, struct smatch_state *state); struct sm_state *set_extra_expr_mod(struct expression *expr, struct smatch_state *state); -- 2.11.4.GIT