Skip to content

Commit 986c6e5

Browse files
committed
java_static_lifetime_init: Deterministic order of initialisation
Much like the C front-end, ensure that the collection of objects of static lifetime is initialised in a fixed order, based on their names. Previously, the (unspecified) order in an unordered set and unordered map determined the sequence of instructions being generated, which resulted in jdiff regression tests sometimes failing. Those failures were caused by __CPROVER_initialize sometimes showing up among the list of goto functions that differed.
1 parent 0f7f62b commit 986c6e5

File tree

1 file changed

+29
-23
lines changed

1 file changed

+29
-23
lines changed

jbmc/src/java_bytecode/java_entry_point.cpp

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -259,34 +259,40 @@ void java_static_lifetime_init(
259259
// external. Iterate over a copy of the symtab, as its iterators are
260260
// invalidated by object_factory:
261261

262-
std::list<irep_idt> symbol_names;
262+
// sort alphabetically for reproducible results
263+
std::set<std::string> symbol_names;
263264
for(const auto &entry : symbol_table.symbols)
264-
symbol_names.push_back(entry.first);
265-
266-
// Don't use a for-each loop here because the loop extends the list, and the
267-
// for-each loop may only read `.end()` once.
268-
for(
269-
auto symbol_it = symbol_names.begin();
270-
symbol_it != symbol_names.end();
271-
++symbol_it)
265+
symbol_names.insert(id2string(entry.first));
266+
267+
std::set<std::string> additional_symbols;
268+
while(!symbol_names.empty() || !additional_symbols.empty())
272269
{
273-
const symbolt &sym = symbol_table.lookup_ref(*symbol_it);
274-
if(should_init_symbol(sym))
270+
if(!additional_symbols.empty())
271+
symbol_names.swap(additional_symbols);
272+
273+
for(const auto &symbol_name : symbol_names)
275274
{
276-
auto new_symbols = init_symbol(
277-
sym,
278-
code_block,
279-
symbol_table,
280-
source_location,
281-
assume_init_pointers_not_null,
282-
object_factory_parameters,
283-
pointer_type_selector,
284-
string_refinement_enabled,
285-
message_handler);
286-
symbol_names.insert(
287-
symbol_names.end(), new_symbols.begin(), new_symbols.end());
275+
const symbolt &sym = symbol_table.lookup_ref(symbol_name);
276+
if(should_init_symbol(sym))
277+
{
278+
auto new_symbols = init_symbol(
279+
sym,
280+
code_block,
281+
symbol_table,
282+
source_location,
283+
assume_init_pointers_not_null,
284+
object_factory_parameters,
285+
pointer_type_selector,
286+
string_refinement_enabled,
287+
message_handler);
288+
for(const auto &new_symbol_name : new_symbols)
289+
additional_symbols.insert(id2string(new_symbol_name));
290+
}
288291
}
292+
293+
symbol_names.clear();
289294
}
295+
290296
initialize_symbol.value = std::move(code_block);
291297
}
292298

0 commit comments

Comments
 (0)