Skip to content

Commit 425f819

Browse files
author
Daniel Kroening
authored
Merge pull request #407 from smowton/java_basic_lazy_conversion
Java basic lazy method conversion
2 parents 85e7920 + 73e0479 commit 425f819

37 files changed

+997
-86
lines changed
222 Bytes
Binary file not shown.
222 Bytes
Binary file not shown.
292 Bytes
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
test.class
3+
--lazy-methods --verbosity 10 --function test.main
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
elaborate java::A\.f:\(\)V
7+
--
8+
elaborate java::B\.g:\(\)V
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// The most basic lazy loading test: A::f is directly called, B::g should be unreachable
2+
3+
public class test
4+
{
5+
A a;
6+
B b;
7+
public static void main()
8+
{
9+
A.f();
10+
}
11+
}
12+
13+
class A
14+
{
15+
public static void f() {}
16+
}
17+
18+
class B
19+
{
20+
public static void g() {}
21+
}
222 Bytes
Binary file not shown.
222 Bytes
Binary file not shown.
310 Bytes
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
test.class
3+
--lazy-methods --verbosity 10 --function test.main
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
elaborate java::A\.f:\(\)V
7+
--
8+
elaborate java::B\.g:\(\)V
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// This test checks that because A is instantiated in main and B is not,
2+
// A::f is reachable and B::g is not
3+
4+
public class test
5+
{
6+
A a;
7+
B b;
8+
public static void main()
9+
{
10+
A a = new A();
11+
a.f();
12+
}
13+
}
14+
15+
class A
16+
{
17+
public void f() {}
18+
}
19+
20+
class B
21+
{
22+
public void g() {}
23+
}
222 Bytes
Binary file not shown.
222 Bytes
Binary file not shown.
197 Bytes
Binary file not shown.
197 Bytes
Binary file not shown.
296 Bytes
Binary file not shown.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
test.class
3+
--lazy-methods --verbosity 10 --function test.main
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
elaborate java::A\.f:\(\)V
7+
--
8+
elaborate java::B\.g:\(\)V
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// This test checks that because `main` has a parameter of type C, which has a field of type A,
2+
// A::f is considered reachable, but B::g is not.
3+
4+
public class test
5+
{
6+
public static void main(C c)
7+
{
8+
c.a.f();
9+
}
10+
}
11+
12+
class A
13+
{
14+
public void f() {}
15+
}
16+
17+
class B
18+
{
19+
public void g() {}
20+
}
21+
22+
class C
23+
{
24+
A a;
25+
}
26+
27+
class D
28+
{
29+
B b;
30+
}

regression/failed-tests-printer.pl

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,25 @@
44

55
open LOG,"<tests.log" or die "Failed to open tests.log\n";
66

7-
my $ignore = 1;
7+
my $printed_this_test = 1;
88
my $current_test = "";
99

1010
while (<LOG>) {
1111
chomp;
1212
if (/^Test '(.+)'/) {
1313
$current_test = $1;
14-
$ignore = 0;
15-
} elsif (1 == $ignore) {
16-
next;
14+
$printed_this_test = 0;
1715
} elsif (/\[FAILED\]\s*$/) {
18-
$ignore = 1;
19-
print "Failed test: $current_test\n";
20-
my $outf = `sed -n '2p' $current_test/test.desc`;
21-
$outf =~ s/\..*$/.out/;
22-
system("cat $current_test/$outf");
23-
print "\n\n";
16+
if(0 == $printed_this_test) {
17+
$printed_this_test = 1;
18+
print "\n\n";
19+
print "Failed test: $current_test\n";
20+
my $outf = `sed -n '2p' $current_test/test.desc`;
21+
$outf =~ s/\..*$/.out/;
22+
system("cat $current_test/$outf");
23+
print "\n\nFailed test.desc lines:\n";
24+
}
25+
print "$_\n";
2426
}
2527
}
2628

src/cbmc/cbmc_parse_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class optionst;
5656
"(graphml-witness):" \
5757
"(java-max-vla-length):(java-unwind-enum-static)" \
5858
"(localize-faults)(localize-faults-method):" \
59+
"(lazy-methods)" \
5960
"(fixedbv)(floatbv)(all-claims)(all-properties)" // legacy, and will eventually disappear // NOLINT(whitespace/line_length)
6061

6162
class cbmc_parse_optionst:

src/goto-cc/compile.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -544,8 +544,8 @@ bool compilet::parse(const std::string &file_name)
544544

545545
language_filet language_file;
546546

547-
std::pair<language_filest::filemapt::iterator, bool>
548-
res=language_files.filemap.insert(
547+
std::pair<language_filest::file_mapt::iterator, bool>
548+
res=language_files.file_map.insert(
549549
std::pair<std::string, language_filet>(file_name, language_file));
550550

551551
language_filet &lf=res.first->second;
@@ -736,7 +736,7 @@ bool compilet::parse_source(const std::string &file_name)
736736
return true;
737737

738738
// so we remove it from the list afterwards
739-
language_files.filemap.erase(file_name);
739+
language_files.file_map.erase(file_name);
740740
return false;
741741
}
742742

src/goto-programs/get_goto_model.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ bool get_goto_modelt::operator()(const std::vector<std::string> &files)
7575
return true;
7676
}
7777

78-
std::pair<language_filest::filemapt::iterator, bool>
79-
result=language_files.filemap.insert(
78+
std::pair<language_filest::file_mapt::iterator, bool>
79+
result=language_files.file_map.insert(
8080
std::pair<std::string, language_filet>(filename, language_filet()));
8181

8282
language_filet &lf=result.first->second;

src/goto-programs/remove_virtual_functions.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,8 @@ void remove_virtual_functionst::get_functions(
339339
component_name,
340340
functions);
341341

342-
functions.push_back(root_function);
342+
if(root_function.symbol_expr!=symbol_exprt())
343+
functions.push_back(root_function);
343344
}
344345

345346
/*******************************************************************\

src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include "java_root_class.h"
1515
#include "java_types.h"
1616
#include "java_bytecode_convert_method.h"
17+
#include "java_bytecode_language.h"
1718

1819
#include <util/namespace.h>
1920
#include <util/std_expr.h>
@@ -27,11 +28,15 @@ class java_bytecode_convert_classt:public messaget
2728
symbol_tablet &_symbol_table,
2829
message_handlert &_message_handler,
2930
bool _disable_runtime_checks,
30-
size_t _max_array_length):
31+
size_t _max_array_length,
32+
lazy_methodst& _lazy_methods,
33+
lazy_methods_modet _lazy_methods_mode):
3134
messaget(_message_handler),
3235
symbol_table(_symbol_table),
3336
disable_runtime_checks(_disable_runtime_checks),
34-
max_array_length(_max_array_length)
37+
max_array_length(_max_array_length),
38+
lazy_methods(_lazy_methods),
39+
lazy_methods_mode(_lazy_methods_mode)
3540
{
3641
}
3742

@@ -52,6 +57,8 @@ class java_bytecode_convert_classt:public messaget
5257
symbol_tablet &symbol_table;
5358
const bool disable_runtime_checks;
5459
const size_t max_array_length;
60+
lazy_methodst &lazy_methods;
61+
lazy_methods_modet lazy_methods_mode;
5562

5663
// conversion
5764
void convert(const classt &c);
@@ -75,6 +82,13 @@ Function: java_bytecode_convert_classt::convert
7582

7683
void java_bytecode_convert_classt::convert(const classt &c)
7784
{
85+
std::string qualified_classname="java::"+id2string(c.name);
86+
if(symbol_table.has_symbol(qualified_classname))
87+
{
88+
debug() << "Skip class " << c.name << " (already loaded)" << eom;
89+
return;
90+
}
91+
7892
class_typet class_type;
7993

8094
class_type.set_tag(c.name);
@@ -107,7 +121,7 @@ void java_bytecode_convert_classt::convert(const classt &c)
107121
symbolt new_symbol;
108122
new_symbol.base_name=c.name;
109123
new_symbol.pretty_name=c.name;
110-
new_symbol.name="java::"+id2string(c.name);
124+
new_symbol.name=qualified_classname;
111125
class_type.set(ID_name, new_symbol.name);
112126
new_symbol.type=class_type;
113127
new_symbol.mode=ID_java;
@@ -128,13 +142,35 @@ void java_bytecode_convert_classt::convert(const classt &c)
128142

129143
// now do methods
130144
for(const auto &method : c.methods)
131-
java_bytecode_convert_method(
145+
{
146+
const irep_idt method_identifier=
147+
id2string(qualified_classname)+
148+
"."+id2string(method.name)+
149+
":"+method.signature;
150+
// Always run the lazy pre-stage, as it symbol-table
151+
// registers the function.
152+
java_bytecode_convert_method_lazy(
132153
*class_symbol,
154+
method_identifier,
133155
method,
134-
symbol_table,
135-
get_message_handler(),
136-
disable_runtime_checks,
137-
max_array_length);
156+
symbol_table);
157+
if(lazy_methods_mode==LAZY_METHODS_MODE_EAGER)
158+
{
159+
// Upgrade to a fully-realized symbol now:
160+
java_bytecode_convert_method(
161+
*class_symbol,
162+
method,
163+
symbol_table,
164+
get_message_handler(),
165+
disable_runtime_checks,
166+
max_array_length);
167+
}
168+
else
169+
{
170+
// Wait for our caller to decide what needs elaborating.
171+
lazy_methods[method_identifier]=std::make_pair(class_symbol, &method);
172+
}
173+
}
138174

139175
// is this a root class?
140176
if(c.extends.empty())
@@ -322,13 +358,17 @@ bool java_bytecode_convert_class(
322358
symbol_tablet &symbol_table,
323359
message_handlert &message_handler,
324360
bool disable_runtime_checks,
325-
size_t max_array_length)
361+
size_t max_array_length,
362+
lazy_methodst &lazy_methods,
363+
lazy_methods_modet lazy_methods_mode)
326364
{
327365
java_bytecode_convert_classt java_bytecode_convert_class(
328366
symbol_table,
329367
message_handler,
330368
disable_runtime_checks,
331-
max_array_length);
369+
max_array_length,
370+
lazy_methods,
371+
lazy_methods_mode);
332372

333373
try
334374
{

src/java_bytecode/java_bytecode_convert_class.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@ Author: Daniel Kroening, [email protected]
1313
#include <util/message.h>
1414

1515
#include "java_bytecode_parse_tree.h"
16+
#include "java_bytecode_language.h"
1617

1718
bool java_bytecode_convert_class(
1819
const java_bytecode_parse_treet &parse_tree,
1920
symbol_tablet &symbol_table,
2021
message_handlert &message_handler,
2122
bool disable_runtime_checks,
22-
size_t max_array_length);
23+
size_t max_array_length,
24+
lazy_methodst &,
25+
lazy_methods_modet);
2326

2427
#endif // CPROVER_JAVA_BYTECODE_JAVA_BYTECODE_CONVERT_CLASS_H

0 commit comments

Comments
 (0)