Skip to content

Commit 289a439

Browse files
author
Owen Jones
committed
Deal with virtual function calls with no candidate targets
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.
1 parent 9347615 commit 289a439

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

src/java_bytecode/ci_lazy_methods.cpp

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ bool ci_lazy_methodst::operator()(
123123
std::unordered_set<irep_idt> methods_already_populated;
124124
std::unordered_set<exprt, irep_hash> virtual_function_calls;
125125

126-
bool any_new_methods = true;
126+
bool any_new_classes = true;
127+
while(any_new_classes)
128+
{bool any_new_methods = true;
127129
while(any_new_methods)
128130
{
129131
any_new_methods=false;
@@ -153,16 +155,58 @@ bool ci_lazy_methodst::operator()(
153155
}
154156
}
155157

156-
// Given the object types we now know may be created, populate more
157-
// possible virtual function call targets:
158+
// Given the object types we now know may be created, populate more
159+
// possible virtual function call targets:
158160

159-
debug() << "CI lazy methods: add virtual method targets ("
160-
<< virtual_function_calls.size() << " callsites)" << eom;
161+
debug() << "CI lazy methods: add virtual method targets ("
162+
<< virtual_function_calls.size() << " callsites)" << eom;
161163

162-
for(const exprt &function : virtual_function_calls)
164+
for(const exprt &function : virtual_function_calls)
165+
{
166+
get_virtual_method_targets(
167+
function,
168+
instantiated_classes,
169+
methods_to_convert_later,
170+
symbol_table);
171+
}
172+
}
173+
174+
any_new_classes = false;
175+
176+
// Look for virtual callsites with no candidate targets. If we have
177+
// invokevirtual A.f and we don't believe either A or any of its children
178+
// may exist, we assume specifically A is somehow instantiated. Note this
179+
// may result in an abstract class being classified as instantiated, which
180+
// stands in for some unknown concrete subclass: in this case the called
181+
// method will be a stub.
182+
for(const exprt &virtual_function_call : virtual_function_calls)
163183
{
184+
std::unordered_set<irep_idt> candidate_target_methods;
164185
get_virtual_method_targets(
165-
function, instantiated_classes, methods_to_convert_later, symbol_table);
186+
virtual_function_call,
187+
instantiated_classes,
188+
candidate_target_methods,
189+
symbol_table);
190+
191+
if(!candidate_target_methods.empty())
192+
continue;
193+
194+
// Add the call class to instantiated_classes and assert that it
195+
// didn't already exist
196+
const irep_idt &call_class = virtual_function_call.get(ID_C_class);
197+
auto ret_class = instantiated_classes.insert(call_class);
198+
CHECK_RETURN(ret_class.second);
199+
any_new_classes = true;
200+
201+
// Check that `get_virtual_method_target` returns a method now
202+
const irep_idt &call_basename =
203+
virtual_function_call.get(ID_component_name);
204+
const irep_idt method_name = get_virtual_method_target(
205+
instantiated_classes, call_basename, call_class, symbol_table);
206+
CHECK_RETURN(!method_name.empty());
207+
208+
// Add what it returns to methods_to_convert_later
209+
methods_to_convert_later.insert(method_name);
166210
}
167211
}
168212

0 commit comments

Comments
 (0)