Skip to content

Commit

Permalink
Deal with virtual function calls with no candidate targets
Browse files Browse the repository at this point in the history
During virtual method resolution, if a virtual function call has no
candidate targets then we add the class it was called on as an
instantiated class.
  • Loading branch information
Owen Jones committed Apr 19, 2018
1 parent 9347615 commit 289a439
Showing 1 changed file with 51 additions and 7 deletions.
58 changes: 51 additions & 7 deletions src/java_bytecode/ci_lazy_methods.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ bool ci_lazy_methodst::operator()(
std::unordered_set<irep_idt> methods_already_populated;
std::unordered_set<exprt, irep_hash> virtual_function_calls;

bool any_new_methods = true;
bool any_new_classes = true;
while(any_new_classes)
{bool any_new_methods = true;
while(any_new_methods)
{
any_new_methods=false;
Expand Down Expand Up @@ -153,16 +155,58 @@ bool ci_lazy_methodst::operator()(
}
}

// Given the object types we now know may be created, populate more
// possible virtual function call targets:
// Given the object types we now know may be created, populate more
// possible virtual function call targets:

debug() << "CI lazy methods: add virtual method targets ("
<< virtual_function_calls.size() << " callsites)" << eom;
debug() << "CI lazy methods: add virtual method targets ("
<< virtual_function_calls.size() << " callsites)" << eom;

for(const exprt &function : virtual_function_calls)
for(const exprt &function : virtual_function_calls)
{
get_virtual_method_targets(
function,
instantiated_classes,
methods_to_convert_later,
symbol_table);
}
}

any_new_classes = false;

// Look for virtual callsites with no candidate targets. If we have
// invokevirtual A.f and we don't believe either A or any of its children
// may exist, we assume specifically A is somehow instantiated. Note this
// may result in an abstract class being classified as instantiated, which
// stands in for some unknown concrete subclass: in this case the called
// method will be a stub.
for(const exprt &virtual_function_call : virtual_function_calls)
{
std::unordered_set<irep_idt> candidate_target_methods;
get_virtual_method_targets(
function, instantiated_classes, methods_to_convert_later, symbol_table);
virtual_function_call,
instantiated_classes,
candidate_target_methods,
symbol_table);

if(!candidate_target_methods.empty())
continue;

// Add the call class to instantiated_classes and assert that it
// didn't already exist
const irep_idt &call_class = virtual_function_call.get(ID_C_class);
auto ret_class = instantiated_classes.insert(call_class);
CHECK_RETURN(ret_class.second);
any_new_classes = true;

// Check that `get_virtual_method_target` returns a method now
const irep_idt &call_basename =
virtual_function_call.get(ID_component_name);
const irep_idt method_name = get_virtual_method_target(
instantiated_classes, call_basename, call_class, symbol_table);
CHECK_RETURN(!method_name.empty());

// Add what it returns to methods_to_convert_later
methods_to_convert_later.insert(method_name);
}
}

Expand Down

0 comments on commit 289a439

Please sign in to comment.