Skip to content

Commit a890c8e

Browse files
committed
Zero-initialize object factory structs
Previously these were incrementally populated (assigning each field in turn); the zero init was skipped because it is technically redundant. However, this prevents symex (and perhaps other analyses) from propagating useful information, as the first write appears to be a partial update on top of uninitialised data, and each subsequent write is based on its predecessor. Hence objects produced by the factory end up represented as a stack of WITH operations, ultimately based on an undefined symbol (e.g. dynamic_object1#0). With this change symex becomes able to constant propagate the initial object, reducing equation complexity, and objects that don't have any fields to nondet initialise can potentially be constant- propagated throughout their lifetime.
1 parent 10d0042 commit a890c8e

File tree

1 file changed

+22
-16
lines changed

1 file changed

+22
-16
lines changed

src/java_bytecode/java_object_factory.cpp

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/c_types.h>
1717
#include <util/std_code.h>
1818
#include <util/std_expr.h>
19+
#include <util/message.h>
1920
#include <util/namespace.h>
2021
#include <util/nondet_bool.h>
2122
#include <util/nondet_ifthenelse.h>
@@ -25,6 +26,7 @@ Author: Daniel Kroening, [email protected]
2526

2627
#include <linking/zero_initializer.h>
2728

29+
#include <goto-programs/class_identifier.h>
2830
#include <goto-programs/goto_functions.h>
2931

3032
#include <java_bytecode/select_pointer_type.h>
@@ -1046,8 +1048,26 @@ void java_object_factoryt::gen_nondet_struct_init(
10461048
const componentst &components=struct_type.components();
10471049

10481050
if(!is_sub)
1051+
{
10491052
class_identifier=struct_tag;
10501053

1054+
// Add an initial all-zero write. Most of the fields of this will be
1055+
// overwritten, but it helps to have a whole-structure write that analysis
1056+
// passes can easily recognise leaves no uninitialised state behind.
1057+
1058+
// This code mirrors `goto_convertt::do_java_new`:
1059+
null_message_handlert nullout;
1060+
exprt zero_object=
1061+
zero_initializer(
1062+
struct_type, source_locationt(), ns, nullout);
1063+
irep_idt qualified_clsid = "java::" + id2string(class_identifier);
1064+
set_class_identifier(
1065+
to_struct_expr(zero_object), ns, symbol_typet(qualified_clsid));
1066+
1067+
assignments.copy_to_operands(
1068+
code_assignt(expr, zero_object));
1069+
}
1070+
10511071
for(const auto &component : components)
10521072
{
10531073
const typet &component_type=component.type();
@@ -1057,25 +1077,11 @@ void java_object_factoryt::gen_nondet_struct_init(
10571077

10581078
if(name=="@class_identifier")
10591079
{
1060-
if(update_in_place==update_in_placet::MUST_UPDATE_IN_PLACE)
1061-
continue;
1062-
1063-
if(skip_classid)
1064-
continue;
1065-
1066-
irep_idt qualified_clsid = "java::" + id2string(class_identifier);
1067-
constant_exprt ci(qualified_clsid, string_typet());
1068-
code_assignt code(me, ci);
1069-
code.add_source_location()=loc;
1070-
assignments.copy_to_operands(code);
1080+
continue;
10711081
}
10721082
else if(name=="@lock")
10731083
{
1074-
if(update_in_place==update_in_placet::MUST_UPDATE_IN_PLACE)
1075-
continue;
1076-
code_assignt code(me, from_integer(0, me.type()));
1077-
code.add_source_location()=loc;
1078-
assignments.copy_to_operands(code);
1084+
continue;
10791085
}
10801086
else
10811087
{

0 commit comments

Comments
 (0)