Skip to content

Commit 9f3b058

Browse files
authored
Merge pull request #4539 from smowton/smowton/feature/sharing-map-improvements
Minor sharing-map improvements, used to avoid copying in value_sett
2 parents d5df938 + ff16508 commit 9f3b058

File tree

7 files changed

+310
-81
lines changed

7 files changed

+310
-81
lines changed

src/pointer-analysis/value_set.cpp

Lines changed: 85 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,19 @@ void value_sett::update_entry(
7070
auto existing_entry = values.find(index);
7171
if(existing_entry.has_value())
7272
{
73-
entryt replacement = *existing_entry;
7473
if(add_to_sets)
7574
{
76-
if(make_union(replacement.object_map, new_values))
77-
values.replace(index, std::move(replacement));
75+
if(make_union_would_change(existing_entry->get().object_map, new_values))
76+
{
77+
values.update(index, [&new_values, this](entryt &entry) {
78+
make_union(entry.object_map, new_values);
79+
});
80+
}
7881
}
7982
else
8083
{
81-
replacement.object_map = new_values;
82-
values.replace(index, std::move(replacement));
84+
values.update(
85+
index, [&new_values](entryt &entry) { entry.object_map = new_values; });
8386
}
8487
}
8588
else
@@ -90,8 +93,8 @@ void value_sett::update_entry(
9093
}
9194
}
9295

93-
bool value_sett::insert(
94-
object_mapt &dest,
96+
value_sett::insert_actiont value_sett::get_insert_action(
97+
const object_mapt &dest,
9598
object_numberingt::number_type n,
9699
const offsett &offset) const
97100
{
@@ -100,108 +103,113 @@ bool value_sett::insert(
100103
if(entry==dest.read().end())
101104
{
102105
// new
103-
dest.write()[n] = offset;
104-
return true;
106+
return insert_actiont::INSERT;
105107
}
106108
else if(!entry->second)
107-
return false; // no change
109+
return insert_actiont::NONE;
108110
else if(offset && *entry->second == *offset)
109-
return false; // no change
111+
return insert_actiont::NONE;
110112
else
111-
{
112-
dest.write()[n].reset();
113-
return true;
114-
}
113+
return insert_actiont::RESET_OFFSET;
115114
}
116115

117-
void value_sett::output(
118-
const namespacet &ns,
119-
std::ostream &out) const
116+
bool value_sett::insert(
117+
object_mapt &dest,
118+
object_numberingt::number_type n,
119+
const offsett &offset) const
120120
{
121-
valuest::viewt view;
122-
values.get_view(view);
121+
auto insert_action = get_insert_action(dest, n, offset);
122+
if(insert_action == insert_actiont::NONE)
123+
return false;
123124

124-
for(const auto &values_entry : view)
125-
{
126-
irep_idt identifier, display_name;
125+
auto &new_offset = dest.write()[n];
126+
if(insert_action == insert_actiont::INSERT)
127+
new_offset = offset;
128+
else
129+
new_offset.reset();
127130

128-
const entryt &e = values_entry.second;
131+
return true;
132+
}
133+
134+
void value_sett::output(const namespacet &ns, std::ostream &out) const
135+
{
136+
values.iterate([&](const irep_idt &, const entryt &e) {
137+
irep_idt identifier, display_name;
129138

130139
if(has_prefix(id2string(e.identifier), "value_set::dynamic_object"))
131140
{
132-
display_name=id2string(e.identifier)+e.suffix;
133-
identifier="";
141+
display_name = id2string(e.identifier) + e.suffix;
142+
identifier = "";
134143
}
135-
else if(e.identifier=="value_set::return_value")
144+
else if(e.identifier == "value_set::return_value")
136145
{
137-
display_name="RETURN_VALUE"+e.suffix;
138-
identifier="";
146+
display_name = "RETURN_VALUE" + e.suffix;
147+
identifier = "";
139148
}
140149
else
141150
{
142-
#if 0
143-
const symbolt &symbol=ns.lookup(e.identifier);
144-
display_name=id2string(symbol.display_name())+e.suffix;
145-
identifier=symbol.name;
146-
#else
147-
identifier=id2string(e.identifier);
148-
display_name=id2string(identifier)+e.suffix;
149-
#endif
151+
#if 0
152+
const symbolt &symbol=ns.lookup(e.identifier);
153+
display_name=id2string(symbol.display_name())+e.suffix;
154+
identifier=symbol.name;
155+
#else
156+
identifier = id2string(e.identifier);
157+
display_name = id2string(identifier) + e.suffix;
158+
#endif
150159
}
151160

152161
out << display_name;
153162

154163
out << " = { ";
155164

156-
const object_map_dt &object_map=e.object_map.read();
165+
const object_map_dt &object_map = e.object_map.read();
157166

158-
std::size_t width=0;
167+
std::size_t width = 0;
159168

160-
for(object_map_dt::const_iterator
161-
o_it=object_map.begin();
162-
o_it!=object_map.end();
169+
for(object_map_dt::const_iterator o_it = object_map.begin();
170+
o_it != object_map.end();
163171
o_it++)
164172
{
165-
const exprt &o=object_numbering[o_it->first];
173+
const exprt &o = object_numbering[o_it->first];
166174

167175
std::string result;
168176

169-
if(o.id()==ID_invalid || o.id()==ID_unknown)
170-
result=from_expr(ns, identifier, o);
177+
if(o.id() == ID_invalid || o.id() == ID_unknown)
178+
result = from_expr(ns, identifier, o);
171179
else
172180
{
173-
result="<"+from_expr(ns, identifier, o)+", ";
181+
result = "<" + from_expr(ns, identifier, o) + ", ";
174182

175183
if(o_it->second)
176184
result += integer2string(*o_it->second) + "";
177185
else
178-
result+='*';
186+
result += '*';
179187

180188
if(o.type().is_nil())
181-
result+=", ?";
189+
result += ", ?";
182190
else
183-
result+=", "+from_type(ns, identifier, o.type());
191+
result += ", " + from_type(ns, identifier, o.type());
184192

185-
result+='>';
193+
result += '>';
186194
}
187195

188196
out << result;
189197

190-
width+=result.size();
198+
width += result.size();
191199

192200
object_map_dt::const_iterator next(o_it);
193201
next++;
194202

195-
if(next!=object_map.end())
203+
if(next != object_map.end())
196204
{
197205
out << ", ";
198-
if(width>=40)
206+
if(width >= 40)
199207
out << "\n ";
200208
}
201209
}
202210

203211
out << " } \n";
204-
}
212+
});
205213
}
206214

207215
exprt value_sett::to_expr(const object_map_dt::value_type &it) const
@@ -236,10 +244,12 @@ bool value_sett::make_union(const value_sett::valuest &new_values)
236244
{
237245
if(delta_entry.in_both)
238246
{
239-
entryt merged_entry = *values.find(delta_entry.k);
240-
if(make_union(merged_entry.object_map, delta_entry.m.object_map))
247+
if(make_union_would_change(
248+
delta_entry.other_m.object_map, delta_entry.m.object_map))
241249
{
242-
values.replace(delta_entry.k, std::move(merged_entry));
250+
values.update(delta_entry.k, [&](entryt &existing_entry) {
251+
make_union(existing_entry.object_map, delta_entry.m.object_map);
252+
});
243253
result = true;
244254
}
245255
}
@@ -253,6 +263,24 @@ bool value_sett::make_union(const value_sett::valuest &new_values)
253263
return result;
254264
}
255265

266+
bool value_sett::make_union_would_change(
267+
const object_mapt &dest,
268+
const object_mapt &src) const
269+
{
270+
for(const auto &number_and_offset : src.read())
271+
{
272+
if(
273+
get_insert_action(
274+
dest, number_and_offset.first, number_and_offset.second) !=
275+
insert_actiont::NONE)
276+
{
277+
return true;
278+
}
279+
}
280+
281+
return false;
282+
}
283+
256284
bool value_sett::make_union(object_mapt &dest, const object_mapt &src) const
257285
{
258286
bool result=false;

src/pointer-analysis/value_set.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,24 @@ class value_sett
232232
object_numberingt::number_type n,
233233
const offsett &offset) const;
234234

235+
enum class insert_actiont
236+
{
237+
INSERT,
238+
RESET_OFFSET,
239+
NONE
240+
};
241+
242+
/// Determines what would happen if object number \p n was inserted into map
243+
/// \p dest with offset \p offset -- the possibilities being, nothing (the
244+
/// entry is already present), a new entry would be inserted (no existing
245+
/// entry with number \p n was found), or an existing entry's offset would be
246+
/// reset (indicating there is already an entry with number \p n, but with
247+
/// differing offset).
248+
insert_actiont get_insert_action(
249+
const object_mapt &dest,
250+
object_numberingt::number_type n,
251+
const offsett &offset) const;
252+
235253
/// Adds an expression and offset to an object map. If the
236254
/// destination map has an existing element for the same expression
237255
/// with a differing offset its offset is marked unknown.
@@ -360,6 +378,13 @@ class value_sett
360378
/// \return true if anything changed.
361379
bool make_union(object_mapt &dest, const object_mapt &src) const;
362380

381+
/// Determines whether merging two RHS expression sets would cause any change
382+
/// \param dest: set that would be merged into
383+
/// \param src: set that would be merged in
384+
/// \return true if anything changed.
385+
bool make_union_would_change(const object_mapt &dest, const object_mapt &src)
386+
const;
387+
363388
/// Merges an entire existing value_sett's data into this one
364389
/// \param new_values: new values to merge in
365390
/// \return true if anything changed.

src/util/invariant.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Author: Martin Brain, [email protected]
1616

1717
#include <iostream>
1818

19+
bool cbmc_invariants_should_throw = false;
20+
1921
// Backtraces compiler and C library specific
2022
// So we should include something explicitly from the C library
2123
// to check if the C library is glibc.
@@ -26,7 +28,6 @@ Author: Martin Brain, [email protected]
2628
#include <execinfo.h>
2729
#include <cxxabi.h>
2830

29-
3031
/// Attempts to demangle the function name assuming the glibc
3132
/// format of stack entry:
3233
///

src/util/invariant.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,28 @@ Author: Martin Brain, [email protected]
6464
** CPROVER_INVARIANT_* macros.
6565
*/
6666

67+
/// Set this to true to cause invariants to throw a C++ exception rather than
68+
/// abort the program. This is currently untested behaviour, and may fail to
69+
/// clean up partly-completed CBMC operations or release resources. You should
70+
/// probably only use this to gather or report more information about the
71+
/// failure and then abort. Default off.
72+
extern bool cbmc_invariants_should_throw;
73+
74+
/// Helper to enable invariant throwing as above bounded to an object lifetime:
75+
struct cbmc_invariants_should_throwt
76+
{
77+
bool old_state;
78+
cbmc_invariants_should_throwt() : old_state(cbmc_invariants_should_throw)
79+
{
80+
cbmc_invariants_should_throw = true;
81+
}
82+
83+
~cbmc_invariants_should_throwt()
84+
{
85+
cbmc_invariants_should_throw = old_state;
86+
}
87+
};
88+
6789
/// A logic error, augmented with a distinguished field to hold a backtrace.
6890
/// Classes that extend this one should share the same initial constructor
6991
/// parameters: their constructor signature should be of the form:
@@ -230,10 +252,14 @@ CBMC_NORETURN
230252
backtrace,
231253
condition,
232254
std::forward<Params>(params)...);
233-
// We now have a structured exception ready to use;
234-
// in future this is the place to put a 'throw'.
235-
report_exception_to_stderr(to_throw);
236-
abort();
255+
256+
if(cbmc_invariants_should_throw)
257+
throw to_throw;
258+
else
259+
{
260+
report_exception_to_stderr(to_throw);
261+
abort();
262+
}
237263
}
238264

239265
/// This is a wrapper function used by the macro 'INVARIANT(CONDITION, REASON)'.

0 commit comments

Comments
 (0)