Skip to content

Commit 2520c51

Browse files
author
thk123
committed
Tighten up lazy loading for virtual functions implemented in base class
Previously we would load all base classes and all their methods. However, we don't need this, we only need methods that aren't overridden in the specific derived class we are trying to find virtual calls on.
1 parent a068313 commit 2520c51

File tree

2 files changed

+47
-37
lines changed

2 files changed

+47
-37
lines changed

src/java_bytecode/gather_methods_lazily.cpp

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -297,13 +297,8 @@ void gather_methods_lazilyt::initialize_needed_classes_from_pointer(
297297
{
298298
const symbol_typet &class_type=to_symbol_type(pointer_type.subtype());
299299
const auto &param_classid=class_type.get_identifier();
300-
std::vector<irep_idt> class_and_parents=
301-
class_hierarchy.get_parents_trans(param_classid);
302300

303-
class_and_parents.push_back(param_classid);
304-
305-
for(const auto &classid : class_and_parents)
306-
lazy_methods.add_needed_class(classid);
301+
lazy_methods.add_needed_class(param_classid);
307302

308303
gather_field_types(pointer_type.subtype(), ns, lazy_methods);
309304
}
@@ -360,6 +355,15 @@ void gather_methods_lazilyt::get_virtual_method_targets(
360355

361356
auto old_size=needed_methods.size();
362357

358+
const irep_idt &self_method=
359+
get_virtual_method_target(
360+
needed_classes, call_basename, call_class, symbol_table);
361+
362+
if(!self_method.empty())
363+
{
364+
needed_methods.push_back(self_method);
365+
}
366+
363367
auto child_classes=class_hierarchy.get_children_trans(call_class);
364368
for(const auto &child_class : child_classes)
365369
{
@@ -373,36 +377,6 @@ void gather_methods_lazilyt::get_virtual_method_targets(
373377
needed_methods.push_back(child_method);
374378
}
375379

376-
irep_idt parent_class_id=call_class;
377-
while(1)
378-
{
379-
auto parent_method=
380-
get_virtual_method_target(
381-
needed_classes,
382-
call_basename,
383-
parent_class_id,
384-
symbol_table);
385-
if(!parent_method.empty())
386-
{
387-
needed_methods.push_back(parent_method);
388-
break;
389-
}
390-
else
391-
{
392-
auto findit=class_hierarchy.class_map.find(parent_class_id);
393-
if(findit==class_hierarchy.class_map.end())
394-
break;
395-
else
396-
{
397-
const auto &entry=findit->second;
398-
if(entry.parents.empty())
399-
break;
400-
else
401-
parent_class_id=entry.parents[0];
402-
}
403-
}
404-
}
405-
406380
if(needed_methods.size()==old_size)
407381
{
408382
// Didn't find any candidate callee. Generate a stub.
@@ -494,9 +468,41 @@ irep_idt gather_methods_lazilyt::get_virtual_method_target(
494468
// Program-wide, is this class ever instantiated?
495469
if(!needed_classes.count(classname))
496470
return irep_idt();
497-
auto methodid=id2string(classname)+"."+id2string(call_basename);
471+
auto methodid=build_virtual_method_name(classname, call_basename);
498472
if(symbol_table.has_symbol(methodid))
499473
return methodid;
500474
else
475+
{
476+
// no method found for this specific classs, but a call to this class
477+
// will be resolved in one of its base classes so we should work up the
478+
// heirarchy to see if one resovles
479+
class_hierarchyt::idst parent_classes=
480+
class_hierarchy.get_parents_trans(classname);
481+
for(const irep_idt &parent_class_id : parent_classes)
482+
{
483+
auto parent_method_id=
484+
build_virtual_method_name(parent_class_id, call_basename);
485+
if(symbol_table.has_symbol(parent_method_id))
486+
{
487+
return parent_method_id;
488+
}
489+
}
501490
return irep_idt();
491+
}
492+
}
493+
494+
495+
/// Build a method name as found in a GOTO symbol table equivalent to the name
496+
/// of a concrete call of method component_method_name on class class_name
497+
/// \param component_method_name: The name of the function
498+
/// \param class_name: The class the implementation would be found on.
499+
/// \return A name for looking up in the symbol table for classes `class_name`'s
500+
/// implementation of `component_name`
501+
irep_idt gather_methods_lazilyt::build_virtual_method_name(
502+
const irep_idt &class_name, const irep_idt &component_method_name)
503+
{
504+
// Verify the parameters are called in the correct order.
505+
PRECONDITION(id2string(class_name).find("::")!=std::string::npos);
506+
PRECONDITION(id2string(component_method_name).find("(")!=std::string::npos);
507+
return id2string(class_name)+'.'+id2string(component_method_name);
502508
}

src/java_bytecode/gather_methods_lazily.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ class gather_methods_lazilyt:public messaget
9393
const irep_idt &classname,
9494
const symbol_tablet &symbol_table);
9595

96+
static irep_idt build_virtual_method_name(
97+
const irep_idt &class_name,
98+
const irep_idt &component_method_name);
99+
96100
class_hierarchyt class_hierarchy;
97101
const irep_idt main_class;
98102
const std::vector<irep_idt> main_jar_classes;

0 commit comments

Comments
 (0)