Skip to content

Commit 49089b1

Browse files
committed
Fix lazy loading of enum static initializers
Rather than calling clinit_wrapper on every parameter to the entry method that is an enum, we should first load all the classes that may be needed before we enter the entry method, and then call clinit_wrapper on all of those which are enums. For example, the case of an enum field of an argument to the entry method would have previously hit an invariant violation.
1 parent 85a81ea commit 49089b1

File tree

3 files changed

+23
-21
lines changed

3 files changed

+23
-21
lines changed

jbmc/src/java_bytecode/ci_lazy_methods.cpp

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -382,16 +382,6 @@ void ci_lazy_methodst::initialize_instantiated_classes(
382382
if(param.type().id()==ID_pointer)
383383
{
384384
const pointer_typet &original_pointer = to_pointer_type(param.type());
385-
const auto &original_type = ns.follow(original_pointer.subtype());
386-
// Special case for enums. We may want to generalise this, see TG-4689
387-
// and the comment in java_object_factoryt::gen_nondet_pointer_init.
388-
if(
389-
can_cast_type<java_class_typet>(original_type) &&
390-
to_java_class_type(original_type).get_base("java::java.lang.Enum"))
391-
{
392-
add_clinit_call_for_pointer_type(
393-
original_pointer, ns.get_symbol_table(), needed_lazy_methods);
394-
}
395385
needed_lazy_methods.add_all_needed_classes(original_pointer);
396386
}
397387
}
@@ -407,28 +397,35 @@ void ci_lazy_methodst::initialize_instantiated_classes(
407397
// As in class_loader, ensure these classes stay available
408398
for(const auto &id : extra_instantiated_classes)
409399
needed_lazy_methods.add_needed_class("java::" + id2string(id));
400+
401+
// Special case for enums. We may want to generalise this, see TG-4689
402+
// and the comment in java_object_factoryt::gen_nondet_pointer_init.
403+
for(const auto &found_class : needed_lazy_methods.get_instantiated_classes())
404+
{
405+
const auto &class_type = to_java_class_type(ns.lookup(found_class).type);
406+
if(class_type.get_base("java::java.lang.Enum"))
407+
add_clinit_call(found_class, ns.get_symbol_table(), needed_lazy_methods);
408+
}
410409
}
411410

412411
/// Helper function for `initialize_instantiated_classes`.
413-
/// For a given pointer_typet that is being noted as needed in
414-
/// `needed_lazy_methods`, notes that its static initializer is also needed.
415-
/// This applies the same logic to the class of `pointer_type` that
412+
/// For a given class id that is being noted as needed in `needed_lazy_methods`,
413+
/// notes that its static initializer is also needed.
414+
/// This applies the same logic to the given class that
416415
/// `java_bytecode_convert_methodt::get_clinit_call` applies e.g. to classes
417416
/// whose constructor we call in a method body. This duplication is unavoidable
418417
/// due to the fact that ci_lazy_methods essentially has to go through the same
419418
/// logic as __CPROVER_start in its initial setup.
420-
/// \param pointer_type: The given pointer_typet
419+
/// \param class_id: The given class id
421420
/// \param symbol_table: Used to look up occurrences of static initializers
422421
/// \param [out] needed_lazy_methods: Gets notified of any static initializers
423422
/// that need to be loaded
424-
void ci_lazy_methodst::add_clinit_call_for_pointer_type(
425-
const pointer_typet &pointer_type,
423+
void ci_lazy_methodst::add_clinit_call(
424+
const irep_idt &class_id,
426425
const symbol_tablet &symbol_table,
427426
ci_lazy_methods_neededt &needed_lazy_methods)
428427
{
429-
const irep_idt &pointer_id =
430-
to_symbol_type(pointer_type.subtype()).get_identifier();
431-
const irep_idt &clinit_wrapper = clinit_wrapper_name(pointer_id);
428+
const irep_idt &clinit_wrapper = clinit_wrapper_name(class_id);
432429
if(symbol_table.symbols.count(clinit_wrapper))
433430
needed_lazy_methods.add_needed_method(clinit_wrapper);
434431
}

jbmc/src/java_bytecode/ci_lazy_methods.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ class ci_lazy_methodst:public messaget
120120
const namespacet &ns,
121121
ci_lazy_methods_neededt &needed_lazy_methods);
122122

123-
void add_clinit_call_for_pointer_type(
124-
const pointer_typet &pointer_type,
123+
void add_clinit_call(
124+
const irep_idt &class_id,
125125
const symbol_tablet &symbol_table,
126126
ci_lazy_methods_neededt &needed_lazy_methods);
127127

jbmc/src/java_bytecode/ci_lazy_methods_needed.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ class ci_lazy_methods_neededt
3434
pointer_type_selector(pointer_type_selector)
3535
{}
3636

37+
std::unordered_set<irep_idt> get_instantiated_classes()
38+
{
39+
return instantiated_classes;
40+
}
41+
3742
void add_needed_method(const irep_idt &);
3843
// Returns true if new
3944
bool add_needed_class(const irep_idt &);

0 commit comments

Comments
 (0)