Skip to content

Commit d4b811b

Browse files
committed
Use sharing_mapt as container in value_sett
goto-symex copies a state, which contains a value set, at each branching point. The paths originating at that branch point typically share most of the points-to information. Thus the copy is unnecessarily expensive, and so is the merge at the next join point, which will also result in one of the value sets to be destroyed. With sharing_mapt, the copy has constant cost, merging can make use of the delta view, and the cost of destruction only depends on the size of the delta.
1 parent 47bdb15 commit d4b811b

File tree

4 files changed

+118
-143
lines changed

4 files changed

+118
-143
lines changed

src/goto-symex/symex_main.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -676,16 +676,16 @@ void goto_symext::try_filter_value_sets(
676676
}
677677
if(jump_taken_value_set && !erase_from_jump_taken_value_set.empty())
678678
{
679-
value_sett::entryt *entry = jump_taken_value_set->get_entry_for_symbol(
679+
auto entry_index = jump_taken_value_set->get_index_of_symbol(
680680
symbol_expr->get_identifier(), symbol_type, "", ns);
681681
jump_taken_value_set->erase_values_from_entry(
682-
*entry, erase_from_jump_taken_value_set);
682+
*entry_index, erase_from_jump_taken_value_set);
683683
}
684684
if(jump_not_taken_value_set && !erase_from_jump_not_taken_value_set.empty())
685685
{
686-
value_sett::entryt *entry = jump_not_taken_value_set->get_entry_for_symbol(
686+
auto entry_index = jump_not_taken_value_set->get_index_of_symbol(
687687
symbol_expr->get_identifier(), symbol_type, "", ns);
688688
jump_not_taken_value_set->erase_values_from_entry(
689-
*entry, erase_from_jump_not_taken_value_set);
689+
*entry_index, erase_from_jump_not_taken_value_set);
690690
}
691691
}

src/pointer-analysis/value_set.cpp

Lines changed: 84 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,17 @@ bool value_sett::field_sensitive(const irep_idt &id, const typet &type)
4848
return type.id() == ID_struct || type.id() == ID_struct_tag;
4949
}
5050

51-
value_sett::entryt *value_sett::find_entry(const irep_idt &id)
52-
{
53-
auto found = values.find(id);
54-
return found == values.end() ? nullptr : &found->second;
55-
}
56-
5751
const value_sett::entryt *value_sett::find_entry(const irep_idt &id) const
5852
{
5953
auto found = values.find(id);
60-
return found == values.end() ? nullptr : &found->second;
54+
return !found.has_value() ? nullptr : &(found->get());
6155
}
6256

63-
value_sett::entryt &value_sett::get_entry(const entryt &e, const typet &type)
57+
void value_sett::update_entry(
58+
const entryt &e,
59+
const typet &type,
60+
const object_mapt &new_values,
61+
bool add_to_sets)
6462
{
6563
irep_idt index;
6664

@@ -69,10 +67,27 @@ value_sett::entryt &value_sett::get_entry(const entryt &e, const typet &type)
6967
else
7068
index=e.identifier;
7169

72-
std::pair<valuest::iterator, bool> r =
73-
values.insert(std::pair<irep_idt, entryt>(index, e));
74-
75-
return r.first->second;
70+
auto existing_entry = values.find(index);
71+
if(existing_entry.has_value())
72+
{
73+
entryt replacement = *existing_entry;
74+
if(add_to_sets)
75+
{
76+
if(make_union(replacement.object_map, new_values))
77+
values.replace(index, std::move(replacement));
78+
}
79+
else
80+
{
81+
replacement.object_map = new_values;
82+
values.replace(index, std::move(replacement));
83+
}
84+
}
85+
else
86+
{
87+
entryt new_entry = e;
88+
new_entry.object_map = new_values;
89+
values.insert(index, std::move(new_entry));
90+
}
7691
}
7792

7893
bool value_sett::insert(
@@ -103,7 +118,10 @@ void value_sett::output(
103118
const namespacet &ns,
104119
std::ostream &out) const
105120
{
106-
for(const auto &values_entry : values)
121+
valuest::viewt view;
122+
values.get_view(view);
123+
124+
for(const auto &values_entry : view)
107125
{
108126
irep_idt identifier, display_name;
109127

@@ -210,36 +228,26 @@ bool value_sett::make_union(const value_sett::valuest &new_values)
210228
{
211229
bool result=false;
212230

213-
valuest::iterator v_it=values.begin();
231+
value_sett::valuest::delta_viewt delta_view;
232+
233+
new_values.get_delta_view(values, delta_view, false);
214234

215-
for(valuest::const_iterator
216-
it=new_values.begin();
217-
it!=new_values.end();
218-
) // no it++
235+
for(const auto &delta_entry : delta_view)
219236
{
220-
if(v_it==values.end() || it->first<v_it->first)
237+
if(delta_entry.in_both)
221238
{
222-
values.insert(v_it, *it);
223-
result=true;
224-
it++;
225-
continue;
239+
entryt merged_entry = *values.find(delta_entry.k);
240+
if(make_union(merged_entry.object_map, delta_entry.m.object_map))
241+
{
242+
values.replace(delta_entry.k, std::move(merged_entry));
243+
result = true;
244+
}
226245
}
227-
else if(v_it->first<it->first)
246+
else
228247
{
229-
v_it++;
230-
continue;
248+
values.insert(delta_entry.k, delta_entry.m);
249+
result = true;
231250
}
232-
233-
assert(v_it->first==it->first);
234-
235-
entryt &e=v_it->second;
236-
const entryt &new_e=it->second;
237-
238-
if(make_union(e.object_map, new_e.object_map))
239-
result=true;
240-
241-
v_it++;
242-
it++;
243251
}
244252

245253
return result;
@@ -371,77 +379,55 @@ static std::string strip_first_field_from_suffix(
371379
return suffix.substr(field.length() + 1);
372380
}
373381

374-
template <class maybe_const_value_sett>
375-
auto value_sett::get_entry_for_symbol(
376-
maybe_const_value_sett &value_set,
377-
const irep_idt identifier,
382+
optionalt<irep_idt> value_sett::get_index_of_symbol(
383+
irep_idt identifier,
378384
const typet &type,
379385
const std::string &suffix,
380-
const namespacet &ns) ->
381-
typename std::conditional<std::is_const<maybe_const_value_sett>::value,
382-
const value_sett::entryt *,
383-
value_sett::entryt *>::type
386+
const namespacet &ns) const
384387
{
385388
if(
386389
type.id() != ID_pointer && type.id() != ID_signedbv &&
387390
type.id() != ID_unsignedbv && type.id() != ID_array &&
388391
type.id() != ID_struct && type.id() != ID_struct_tag &&
389392
type.id() != ID_union && type.id() != ID_union_tag)
390393
{
391-
return nullptr;
394+
return {};
392395
}
393396

397+
// look it up
398+
irep_idt index = id2string(identifier) + suffix;
399+
auto *entry = find_entry(index);
400+
if(entry)
401+
return std::move(index);
402+
394403
const typet &followed_type = type.id() == ID_struct_tag
395404
? ns.follow_tag(to_struct_tag_type(type))
396405
: type.id() == ID_union_tag
397406
? ns.follow_tag(to_union_tag_type(type))
398407
: type;
399408

400-
// look it up
401-
auto *entry = value_set.find_entry(id2string(identifier) + suffix);
402-
403409
// try first component name as suffix if not yet found
404-
if(
405-
!entry &&
406-
(followed_type.id() == ID_struct || followed_type.id() == ID_union))
410+
if(followed_type.id() == ID_struct || followed_type.id() == ID_union)
407411
{
408412
const struct_union_typet &struct_union_type =
409413
to_struct_union_type(followed_type);
410414

411415
const irep_idt &first_component_name =
412416
struct_union_type.components().front().get_name();
413417

414-
entry = value_set.find_entry(
415-
id2string(identifier) + "." + id2string(first_component_name) + suffix);
416-
}
417-
418-
if(!entry)
419-
{
420-
// not found? try without suffix
421-
entry = value_set.find_entry(identifier);
418+
index =
419+
id2string(identifier) + "." + id2string(first_component_name) + suffix;
420+
entry = find_entry(index);
421+
if(entry)
422+
return std::move(index);
422423
}
423424

424-
return entry;
425-
}
426-
427-
// Explicitly instantiate the two possible versions of the method above:
428-
429-
value_sett::entryt *value_sett::get_entry_for_symbol(
430-
irep_idt identifier,
431-
const typet &type,
432-
const std::string &suffix,
433-
const namespacet &ns)
434-
{
435-
return get_entry_for_symbol(*this, identifier, type, suffix, ns);
436-
}
425+
// not found? try without suffix
426+
entry = find_entry(identifier);
427+
if(entry)
428+
return std::move(identifier);
437429

438-
const value_sett::entryt *value_sett::get_entry_for_symbol(
439-
irep_idt identifier,
440-
const typet &type,
441-
const std::string &suffix,
442-
const namespacet &ns) const
443-
{
444-
return get_entry_for_symbol(*this, identifier, type, suffix, ns);
430+
return {};
445431
}
446432

447433
void value_sett::get_value_set_rec(
@@ -491,11 +477,11 @@ void value_sett::get_value_set_rec(
491477
}
492478
else if(expr.id()==ID_symbol)
493479
{
494-
const entryt *entry = get_entry_for_symbol(
480+
auto entry_index = get_index_of_symbol(
495481
to_symbol_expr(expr).get_identifier(), expr_type, suffix, ns);
496482

497-
if(entry)
498-
make_union(dest, entry->object_map);
483+
if(entry_index.has_value())
484+
make_union(dest, find_entry(*entry_index)->object_map);
499485
else
500486
insert(dest, exprt(ID_unknown, original_type));
501487
}
@@ -1314,12 +1300,8 @@ void value_sett::assign_rec(
13141300
{
13151301
const irep_idt &identifier=to_symbol_expr(lhs).get_identifier();
13161302

1317-
entryt &e = get_entry(entryt(identifier, suffix), lhs.type());
1318-
1319-
if(add_to_sets)
1320-
make_union(e.object_map, values_rhs);
1321-
else
1322-
e.object_map=values_rhs;
1303+
update_entry(
1304+
entryt{identifier, suffix}, lhs.type(), values_rhs, add_to_sets);
13231305
}
13241306
else if(lhs.id()==ID_dynamic_object)
13251307
{
@@ -1330,9 +1312,7 @@ void value_sett::assign_rec(
13301312
"value_set::dynamic_object"+
13311313
std::to_string(dynamic_object.get_instance());
13321314

1333-
entryt &e = get_entry(entryt(name, suffix), lhs.type());
1334-
1335-
make_union(e.object_map, values_rhs);
1315+
update_entry(entryt{name, suffix}, lhs.type(), values_rhs, true);
13361316
}
13371317
else if(lhs.id()==ID_dereference)
13381318
{
@@ -1640,12 +1620,19 @@ void value_sett::guard(
16401620
}
16411621

16421622
void value_sett::erase_values_from_entry(
1643-
entryt &entry,
1623+
const irep_idt &index,
16441624
const std::unordered_set<exprt, irep_hash> &values_to_erase)
16451625
{
1626+
if(values_to_erase.empty())
1627+
return;
1628+
1629+
auto entry = find_entry(index);
1630+
if(!entry)
1631+
return;
1632+
16461633
std::vector<object_map_dt::key_type> keys_to_erase;
16471634

1648-
for(auto &key_value : entry.object_map.read())
1635+
for(auto &key_value : entry->object_map.read())
16491636
{
16501637
const auto &rhs_object = to_expr(key_value);
16511638
if(values_to_erase.count(rhs_object))
@@ -1659,8 +1646,10 @@ void value_sett::erase_values_from_entry(
16591646
"value_sett::erase_value_from_entry() should erase exactly one value for "
16601647
"each element in the set it is given");
16611648

1649+
entryt replacement = *entry;
16621650
for(const auto &key_to_erase : keys_to_erase)
16631651
{
1664-
entry.object_map.write().erase(key_to_erase);
1652+
replacement.object_map.write().erase(key_to_erase);
16651653
}
1654+
values.replace(index, std::move(replacement));
16661655
}

0 commit comments

Comments
 (0)