Skip to content

Commit 32cc538

Browse files
committed
Insert stub static globals onto any incomplete ancestor class
Previously they were always created on either the class that was referred to, or on some parent or grandparent; however, this was inappropriate if all those classes were concrete (non-stub) types but some interface *was* a stub. In that case an interface will be arbitrarily picked and given a stub field.
1 parent b2d3d61 commit 32cc538

File tree

1 file changed

+39
-13
lines changed

1 file changed

+39
-13
lines changed

src/java_bytecode/java_bytecode_language.cpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,39 @@ static void create_stub_global_symbol(
420420
!add_failed, "caller should have checked symbol not already in table");
421421
}
422422

423+
/// Find any incomplete ancestor of a given class
424+
/// \param start_class_id: class to start searching from
425+
/// \param symbol_table: global symbol table
426+
/// \param class_hierarchy: global class hierarchy
427+
/// \return first incomplete ancestor encountered,
428+
/// including start_class_id itself.
429+
static irep_idt get_any_incomplete_ancestor(
430+
const irep_idt &start_class_id,
431+
const symbol_tablet &symbol_table,
432+
const class_hierarchyt &class_hierarchy)
433+
{
434+
// Depth-first search: return the first ancestor with ID_incomplete_class, or
435+
// irep_idt() if none found.
436+
std::vector<irep_idt> classes_to_check;
437+
classes_to_check.push_back(start_class_id);
438+
439+
while(!classes_to_check.empty())
440+
{
441+
irep_idt to_check = classes_to_check.back();
442+
classes_to_check.pop_back();
443+
444+
if(symbol_table.lookup_ref(to_check).type.get_bool(ID_incomplete_class))
445+
return to_check;
446+
447+
const class_hierarchyt::idst &parents =
448+
class_hierarchy.class_map.at(to_check).parents;
449+
classes_to_check.insert(
450+
classes_to_check.end(), parents.begin(), parents.end());
451+
}
452+
453+
INVARIANT(false, "input class id should have some incomplete ancestor");
454+
}
455+
423456
/// Search for getstatic and putstatic instructions in a class' bytecode and
424457
/// create stub symbols for any static fields that aren't already in the symbol
425458
/// table. The new symbols are null-initialised for reference-typed globals /
@@ -463,19 +496,12 @@ static void create_stub_global_symbols(
463496
true);
464497
if(!referred_component.is_valid())
465498
{
466-
// Create a new stub global on the first incomplete (stub) parent of
467-
// the class that was referred to:
468-
irep_idt add_to_class_id = class_id;
469-
while(!symbol_table.lookup_ref(add_to_class_id).type.get_bool(
470-
ID_incomplete_class))
471-
{
472-
const class_hierarchyt::idst &parents =
473-
class_hierarchy.class_map.at(add_to_class_id).parents;
474-
INVARIANT(
475-
!parents.empty(),
476-
"unresolved global reference should come from incomplete class");
477-
add_to_class_id = parents[0];
478-
}
499+
// Create a new stub global on an arbitrary incomplete ancestor of the
500+
// class that was referred to. This is just a guess, but we have no
501+
// better information to go on.
502+
irep_idt add_to_class_id =
503+
get_any_incomplete_ancestor(
504+
class_id, symbol_table, class_hierarchy);
479505

480506
irep_idt identifier =
481507
id2string(add_to_class_id) + "." + id2string(component);

0 commit comments

Comments
 (0)