Skip to content

Commit cf5b97a

Browse files
thomasspriggsantlechner
authored andcommitted
Exclude symbols with empty module from the module map
For languages such as Java, where the `module` field of `symbolt` is kept empty, maintaining the `internal_symbol_module_map` of the symbol table can cause a performance bottleneck. This is because all symbols end up mapped to the same key in this map. So when `symbol_tablet::erase` attempts to remove a symbol from this map the lookup results in a range containing the entire collection of symbols on which it then performs a linear search to find the exact symbol to remove. Languages which don't set the `module` field never need to do any lookups in the module map. The downstream EBMC repository always uses a non-empty module to do its lookups. Therefore we can leave symbols with an empty module out of the module map. This results in a performance improvement for Java, whilst retaining EBMC compatibilty.
1 parent 00c7e3d commit cf5b97a

File tree

1 file changed

+32
-19
lines changed

1 file changed

+32
-19
lines changed

src/util/symbol_table.cpp

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,18 @@ std::pair<symbolt &, bool> symbol_tablet::insert(symbolt symbol)
2828
{
2929
symbol_base_mapt::iterator base_result=
3030
internal_symbol_base_map.emplace(new_symbol.base_name, new_symbol.name);
31-
try
31+
if(!new_symbol.module.empty())
3232
{
33-
internal_symbol_module_map.emplace(new_symbol.module, new_symbol.name);
34-
}
35-
catch(...)
36-
{
37-
internal_symbol_base_map.erase(base_result);
38-
throw;
33+
try
34+
{
35+
internal_symbol_module_map.emplace(
36+
new_symbol.module, new_symbol.name);
37+
}
38+
catch(...)
39+
{
40+
internal_symbol_base_map.erase(base_result);
41+
throw;
42+
}
3943
}
4044
}
4145
catch(...)
@@ -103,18 +107,27 @@ void symbol_tablet::erase(const symbolst::const_iterator &entry)
103107
"current base_name: "+id2string(symbol.base_name)+")");
104108
internal_symbol_base_map.erase(base_it);
105109

106-
symbol_module_mapt::const_iterator
107-
module_it=symbol_module_map.lower_bound(entry->second.module),
108-
module_it_end=symbol_module_map.upper_bound(entry->second.module);
109-
while(module_it!=module_it_end && module_it->second!=symbol.name)
110-
++module_it;
111-
INVARIANT(
112-
module_it!=module_it_end,
113-
"symbolt::module should not be changed "
114-
"after it is added to the symbol_table "
115-
"(name: "+id2string(symbol.name)+", "
116-
"current module: "+id2string(symbol.module)+")");
117-
internal_symbol_module_map.erase(module_it);
110+
if(!entry->second.module.empty())
111+
{
112+
symbol_module_mapt::const_iterator module_it =
113+
symbol_module_map.lower_bound(
114+
entry->second.module),
115+
module_it_end =
116+
symbol_module_map.upper_bound(
117+
entry->second.module);
118+
while(module_it != module_it_end && module_it->second != symbol.name)
119+
++module_it;
120+
INVARIANT(
121+
module_it != module_it_end,
122+
"symbolt::module should not be changed "
123+
"after it is added to the symbol_table "
124+
"(name: " +
125+
id2string(symbol.name) +
126+
", "
127+
"current module: " +
128+
id2string(symbol.module) + ")");
129+
internal_symbol_module_map.erase(module_it);
130+
}
118131

119132
internal_symbols.erase(entry);
120133
}

0 commit comments

Comments
 (0)