40 const std::vector<irep_idt> &main_jar_classes,
41 const std::vector<load_extra_methodst> &lazy_methods_extra_entry_points,
43 const std::vector<irep_idt> &extra_instantiated_classes,
48 main_class(main_class),
49 main_jar_classes(main_jar_classes),
50 lazy_methods_extra_entry_points(lazy_methods_extra_entry_points),
51 java_class_loader(java_class_loader),
52 extra_instantiated_classes(extra_instantiated_classes),
53 pointer_type_selector(pointer_type_selector),
54 synthetic_methods(synthetic_methods)
73 it->type() == class_type &&
105 std::unordered_set<irep_idt> methods_to_convert_later =
112 std::vector<irep_idt> extra_methods =
113 extra_function_generator(symbol_table);
114 methods_to_convert_later.insert(extra_methods.begin(), extra_methods.end());
117 std::unordered_set<irep_idt> instantiated_classes;
120 std::unordered_set<irep_idt> initial_callable_methods;
122 initial_callable_methods,
123 instantiated_classes,
127 methods_to_convert_later,
namespacet(symbol_table), initial_lazy_methods);
128 methods_to_convert_later.insert(
129 initial_callable_methods.begin(), initial_callable_methods.end());
132 std::unordered_set<irep_idt> methods_already_populated;
133 std::unordered_set<exprt, irep_hash> virtual_function_calls;
134 bool class_initializer_seen =
false;
136 bool any_new_classes =
true;
137 while(any_new_classes)
139 bool any_new_methods =
true;
140 while(any_new_methods)
142 any_new_methods =
false;
143 while(!methods_to_convert_later.empty())
145 std::unordered_set<irep_idt> methods_to_convert;
146 std::swap(methods_to_convert, methods_to_convert_later);
147 for(
const auto &mname : methods_to_convert)
151 methods_already_populated,
152 class_initializer_seen,
155 methods_to_convert_later,
156 instantiated_classes,
157 virtual_function_calls);
158 any_new_methods |= conversion_result.new_method_seen;
159 class_initializer_seen |= conversion_result.class_initializer_seen;
166 debug() <<
"CI lazy methods: add virtual method targets ("
167 << virtual_function_calls.size() <<
" callsites)" <<
eom;
169 for(
const exprt &
function : virtual_function_calls)
173 instantiated_classes,
174 methods_to_convert_later,
180 methods_to_convert_later,
181 instantiated_classes,
182 virtual_function_calls,
192 for(
const auto &sym : symbol_table.
symbols)
196 if(sym.second.is_static_lifetime)
198 if(sym.second.type.id()==ID_code)
205 !methods_already_populated.count(sym.first))
212 keep_symbols.
add(sym.second);
215 debug() <<
"CI lazy methods: removed "
217 <<
" unreachable methods and globals" <<
eom;
219 symbol_table.
swap(keep_symbols);
232 std::unordered_set<irep_idt> &methods_to_convert_later,
233 std::unordered_set<irep_idt> &instantiated_classes,
234 const std::unordered_set<exprt, irep_hash> &virtual_function_calls,
238 methods_to_convert_later,
239 instantiated_classes,
243 bool any_new_classes =
false;
244 for(
const exprt &virtual_function_call : virtual_function_calls)
246 std::unordered_set<irep_idt> candidate_target_methods;
248 virtual_function_call,
249 instantiated_classes,
250 candidate_target_methods,
253 if(!candidate_target_methods.empty())
258 const irep_idt &call_class = virtual_function_call.get(ID_C_class);
259 bool added_class = instantiated_classes.count(call_class) == 0;
265 any_new_classes =
true;
269 virtual_function_call.get(ID_component_name);
271 instantiated_classes, call_basename, call_class, symbol_table);
275 methods_to_convert_later.insert(method_name);
277 return any_new_classes;
292 std::unordered_set<irep_idt> &methods_already_populated,
293 const bool class_initializer_already_seen,
296 std::unordered_set<irep_idt> &methods_to_convert_later,
297 std::unordered_set<irep_idt> &instantiated_classes,
298 std::unordered_set<exprt, irep_hash> &virtual_function_calls)
301 if(!methods_already_populated.insert(method_name).second)
304 debug() <<
"CI lazy methods: elaborate " << method_name <<
eom;
309 methods_to_convert_later,
310 instantiated_classes,
314 if(method_converter(method_name, needed_methods))
322 result.class_initializer_seen =
true;
323 const irep_idt initializer_signature =
325 if(symbol_table.
has_symbol(initializer_signature))
326 methods_to_convert_later.insert(initializer_signature);
328 result.new_method_seen =
true;
337 std::unordered_set<irep_idt>
340 std::unordered_set<irep_idt> methods_to_convert_later;
348 std::vector<irep_idt> reachable_classes;
350 reachable_classes.push_back(this->
main_class);
353 for(
const irep_idt &class_name : reachable_classes)
355 const auto &methods =
358 for(
const auto &method : methods)
363 methods_to_convert_later.insert(methodid);
369 return methods_to_convert_later;
381 const std::unordered_set<irep_idt> &entry_points,
385 for(
const auto &mname : entry_points)
387 const auto &symbol=ns.
lookup(mname);
389 for(
const auto ¶m : mtype.parameters())
391 if(param.type().id()==ID_pointer)
417 std::unordered_set<exprt, irep_hash> &result)
445 const exprt &called_function,
446 const std::unordered_set<irep_idt> &instantiated_classes,
447 std::unordered_set<irep_idt> &callable_methods,
452 const auto &call_class=called_function.
get(ID_C_class);
454 !call_class.empty(),
"All virtual calls should be aimed at a class");
455 const auto &call_basename=called_function.
get(ID_component_name);
457 !call_basename.empty(),
458 "Virtual function must have a reasonable name after removing class");
462 self_and_child_classes.push_back(call_class);
464 for(
const irep_idt &class_name : self_and_child_classes)
467 instantiated_classes, call_basename, class_name, symbol_table);
468 if(!method_name.
empty())
469 callable_methods.insert(method_name);
483 if(e.
id()==ID_symbol)
491 if(findit!=symbol_table.
symbols.end() &&
492 findit->second.is_static_lifetime)
494 needed.
add(findit->second);
517 const std::unordered_set<irep_idt> &instantiated_classes,
523 if(!instantiated_classes.count(classname))
528 call_resolver(classname, call_basename,
false);