Skip to content

Commit df455b8

Browse files
committed
Avoid recomputing class hierarchy
The class hierarchy never changes once the symbol table is computed. By sharing one instance owned by the driver program, particularly across function passes, we can avoid many potentially expensive recomputations.
1 parent eb5df0a commit df455b8

File tree

9 files changed

+93
-24
lines changed

9 files changed

+93
-24
lines changed

jbmc/src/janalyzer/janalyzer_parse_options.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -673,9 +673,11 @@ bool janalyzer_parse_optionst::process_goto_program(const optionst &options)
673673

674674
// remove Java throw and catch
675675
// This introduces instanceof, so order is important:
676-
remove_exceptions(goto_model, get_message_handler());
677-
// remove rtti
678-
remove_instanceof(goto_model, get_message_handler());
676+
remove_exceptions(goto_model, nullptr, get_message_handler());
677+
678+
// Java instanceof -> clsid comparison:
679+
class_hierarchyt class_hierarchy(goto_model.symbol_table);
680+
remove_instanceof(goto_model, class_hierarchy, get_message_handler());
679681

680682
// do partial inlining
681683
status() << "Partial Inlining" << eom;

jbmc/src/java_bytecode/remove_exceptions.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,21 +87,31 @@ class remove_exceptionst
8787

8888
explicit remove_exceptionst(
8989
symbol_table_baset &_symbol_table,
90+
const class_hierarchyt *class_hierarchy,
9091
function_may_throwt _function_may_throw,
9192
bool remove_added_instanceof,
9293
message_handlert &message_handler)
9394
: symbol_table(_symbol_table),
95+
class_hierarchy(class_hierarchy),
9496
function_may_throw(_function_may_throw),
9597
remove_added_instanceof(remove_added_instanceof),
9698
message_handler(message_handler)
9799
{
100+
if(remove_added_instanceof)
101+
{
102+
INVARIANT(
103+
class_hierarchy != nullptr,
104+
"remove_exceptions needs a class hierarchy to remove instanceof "
105+
"statements (either supply one, or don't use REMOVE_ADDED_INSTANCEOF)");
106+
}
98107
}
99108

100109
void operator()(goto_functionst &goto_functions);
101110
void operator()(goto_programt &goto_program);
102111

103112
protected:
104113
symbol_table_baset &symbol_table;
114+
const class_hierarchyt *class_hierarchy;
105115
function_may_throwt function_may_throw;
106116
bool remove_added_instanceof;
107117
message_handlert &message_handler;
@@ -345,7 +355,14 @@ void remove_exceptionst::add_exception_dispatch_sequence(
345355
t_exc->guard=check;
346356

347357
if(remove_added_instanceof)
348-
remove_instanceof(t_exc, goto_program, symbol_table, message_handler);
358+
{
359+
remove_instanceof(
360+
t_exc,
361+
goto_program,
362+
symbol_table,
363+
*class_hierarchy,
364+
message_handler);
365+
}
349366
}
350367
}
351368
}
@@ -576,6 +593,7 @@ void remove_exceptionst::operator()(goto_programt &goto_program)
576593
/// removes throws/CATCH-POP/CATCH-PUSH
577594
void remove_exceptions(
578595
symbol_table_baset &symbol_table,
596+
const class_hierarchyt *class_hierarchy,
579597
goto_functionst &goto_functions,
580598
message_handlert &message_handler,
581599
remove_exceptions_typest type)
@@ -589,6 +607,7 @@ void remove_exceptions(
589607
};
590608
remove_exceptionst remove_exceptions(
591609
symbol_table,
610+
class_hierarchy,
592611
function_may_throw,
593612
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF,
594613
message_handler);
@@ -605,13 +624,16 @@ void remove_exceptions(
605624
/// \param symbol_table: global symbol table. The `@inflight_exception` global
606625
/// may be added if not already present. It will not be initialised; that is
607626
/// the caller's responsibility.
627+
/// \param class_hierarchy: class hierarchy analysis of symbol_table.
628+
/// Only needed if type == REMOVE_ADDED_INSTANCEOF; otherwise may be null.
608629
/// \param message_handler: logging output
609630
/// \param type: specifies whether instanceof operations generated by this pass
610631
/// should be lowered to class-identifier comparisons (using
611632
/// remove_instanceof).
612633
void remove_exceptions(
613634
goto_programt &goto_program,
614635
symbol_table_baset &symbol_table,
636+
const class_hierarchyt *class_hierarchy,
615637
message_handlert &message_handler,
616638
remove_exceptions_typest type)
617639
{
@@ -620,6 +642,7 @@ void remove_exceptions(
620642

621643
remove_exceptionst remove_exceptions(
622644
symbol_table,
645+
class_hierarchy,
623646
any_function_may_throw,
624647
type == remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF,
625648
message_handler);
@@ -640,9 +663,14 @@ void remove_exceptions(
640663
/// remove_instanceof).
641664
void remove_exceptions(
642665
goto_modelt &goto_model,
666+
const class_hierarchyt *class_hierarchy,
643667
message_handlert &message_handler,
644668
remove_exceptions_typest type)
645669
{
646670
remove_exceptions(
647-
goto_model.symbol_table, goto_model.goto_functions, message_handler, type);
671+
goto_model.symbol_table,
672+
class_hierarchy,
673+
goto_model.goto_functions,
674+
message_handler,
675+
type);
648676
}

jbmc/src/java_bytecode/remove_exceptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Date: December 2016
1414
#ifndef CPROVER_JAVA_BYTECODE_REMOVE_EXCEPTIONS_H
1515
#define CPROVER_JAVA_BYTECODE_REMOVE_EXCEPTIONS_H
1616

17+
#include <goto-programs/class_hierarchy.h>
1718
#include <goto-programs/goto_model.h>
1819

1920
#include <util/message.h>
@@ -34,12 +35,14 @@ enum class remove_exceptions_typest
3435
void remove_exceptions(
3536
goto_programt &goto_program,
3637
symbol_table_baset &symbol_table,
38+
const class_hierarchyt *class_hierarchy,
3739
message_handlert &message_handler,
3840
remove_exceptions_typest type =
3941
remove_exceptions_typest::DONT_REMOVE_INSTANCEOF);
4042

4143
void remove_exceptions(
4244
goto_modelt &goto_model,
45+
const class_hierarchyt *class_hierarchy,
4346
message_handlert &message_handler,
4447
remove_exceptions_typest type =
4548
remove_exceptions_typest::DONT_REMOVE_INSTANCEOF);

jbmc/src/java_bytecode/remove_instanceof.cpp

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@ class remove_instanceoft
2424
{
2525
public:
2626
remove_instanceoft(
27-
symbol_table_baset &symbol_table, message_handlert &message_handler)
28-
: symbol_table(symbol_table)
29-
, ns(symbol_table)
30-
, message_handler(message_handler)
27+
symbol_table_baset &symbol_table,
28+
const class_hierarchyt &class_hierarchy,
29+
message_handlert &message_handler)
30+
: symbol_table(symbol_table),
31+
class_hierarchy(class_hierarchy),
32+
ns(symbol_table),
33+
message_handler(message_handler)
3134
{
32-
class_hierarchy(symbol_table);
3335
}
3436

3537
// Lower instanceof for a single function
@@ -40,8 +42,8 @@ class remove_instanceoft
4042

4143
protected:
4244
symbol_table_baset &symbol_table;
45+
const class_hierarchyt &class_hierarchy;
4346
namespacet ns;
44-
class_hierarchyt class_hierarchy;
4547
message_handlert &message_handler;
4648

4749
bool lower_instanceof(
@@ -240,14 +242,16 @@ bool remove_instanceoft::lower_instanceof(goto_programt &goto_program)
240242
/// \param target: The instruction to work on.
241243
/// \param goto_program: The function body containing the instruction.
242244
/// \param symbol_table: The symbol table to add symbols to.
245+
/// \param class_hierarchy: class hierarchy analysis of symbol_table
243246
/// \param message_handler: logging output
244247
void remove_instanceof(
245248
goto_programt::targett target,
246249
goto_programt &goto_program,
247250
symbol_table_baset &symbol_table,
251+
const class_hierarchyt &class_hierarchy,
248252
message_handlert &message_handler)
249253
{
250-
remove_instanceoft rem(symbol_table, message_handler);
254+
remove_instanceoft rem(symbol_table, class_hierarchy, message_handler);
251255
rem.lower_instanceof(goto_program, target);
252256
}
253257

@@ -256,13 +260,15 @@ void remove_instanceof(
256260
/// \remarks Extra auxiliary variables may be introduced into symbol_table.
257261
/// \param function: The function to work on.
258262
/// \param symbol_table: The symbol table to add symbols to.
263+
/// \param class_hierarchy: class hierarchy analysis of symbol_table
259264
/// \param message_handler: logging output
260265
void remove_instanceof(
261266
goto_functionst::goto_functiont &function,
262267
symbol_table_baset &symbol_table,
268+
const class_hierarchyt &class_hierarchy,
263269
message_handlert &message_handler)
264270
{
265-
remove_instanceoft rem(symbol_table, message_handler);
271+
remove_instanceoft rem(symbol_table, class_hierarchy, message_handler);
266272
rem.lower_instanceof(function.body);
267273
}
268274

@@ -271,13 +277,15 @@ void remove_instanceof(
271277
/// \remarks Extra auxiliary variables may be introduced into symbol_table.
272278
/// \param goto_functions: The functions to work on.
273279
/// \param symbol_table: The symbol table to add symbols to.
280+
/// \param class_hierarchy: class hierarchy analysis of symbol_table
274281
/// \param message_handler: logging output
275282
void remove_instanceof(
276283
goto_functionst &goto_functions,
277284
symbol_table_baset &symbol_table,
285+
const class_hierarchyt &class_hierarchy,
278286
message_handlert &message_handler)
279287
{
280-
remove_instanceoft rem(symbol_table, message_handler);
288+
remove_instanceoft rem(symbol_table, class_hierarchy, message_handler);
281289
bool changed=false;
282290
for(auto &f : goto_functions.function_map)
283291
changed=rem.lower_instanceof(f.second.body) || changed;
@@ -289,12 +297,18 @@ void remove_instanceof(
289297
/// class-identifier test.
290298
/// \remarks Extra auxiliary variables may be introduced into symbol_table.
291299
/// \param goto_model: The functions to work on and the symbol table to add
300+
/// \param class_hierarchy: class hierarchy analysis of goto_model's symbol
301+
/// table
292302
/// \param message_handler: logging output
293303
/// symbols to.
294304
void remove_instanceof(
295305
goto_modelt &goto_model,
306+
const class_hierarchyt &class_hierarchy,
296307
message_handlert &message_handler)
297308
{
298309
remove_instanceof(
299-
goto_model.goto_functions, goto_model.symbol_table, message_handler);
310+
goto_model.goto_functions,
311+
goto_model.symbol_table,
312+
class_hierarchy,
313+
message_handler);
300314
}

jbmc/src/java_bytecode/remove_instanceof.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ Author: Chris Smowton, [email protected]
7979
#ifndef CPROVER_JAVA_BYTECODE_REMOVE_INSTANCEOF_H
8080
#define CPROVER_JAVA_BYTECODE_REMOVE_INSTANCEOF_H
8181

82+
#include <goto-programs/class_hierarchy.h>
8283
#include <goto-programs/goto_functions.h>
8384
#include <goto-programs/goto_model.h>
8485

@@ -89,18 +90,24 @@ void remove_instanceof(
8990
goto_programt::targett target,
9091
goto_programt &goto_program,
9192
symbol_table_baset &symbol_table,
93+
const class_hierarchyt &class_hierarchy,
9294
message_handlert &);
9395

9496
void remove_instanceof(
9597
goto_functionst::goto_functiont &function,
9698
symbol_table_baset &symbol_table,
99+
const class_hierarchyt &class_hierarchy,
97100
message_handlert &);
98101

99102
void remove_instanceof(
100103
goto_functionst &goto_functions,
101104
symbol_table_baset &symbol_table,
105+
const class_hierarchyt &class_hierarchy,
102106
message_handlert &);
103107

104-
void remove_instanceof(goto_modelt &model, message_handlert &);
108+
void remove_instanceof(
109+
goto_modelt &model,
110+
const class_hierarchyt &class_hierarchy,
111+
message_handlert &);
105112

106113
#endif

jbmc/src/jbmc/jbmc_parse_options.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,9 @@ int jbmc_parse_optionst::doit()
552552
*this, options, get_message_handler());
553553
lazy_goto_model.initialize(cmdline, options);
554554

555+
class_hierarchy =
556+
util_make_unique<class_hierarchyt>(lazy_goto_model.symbol_table);
557+
555558
// The precise wording of this error matches goto-symex's complaint when no
556559
// __CPROVER_start exists (if we just go ahead and run it anyway it will
557560
// trip an invariant when it tries to load it)
@@ -629,12 +632,13 @@ int jbmc_parse_optionst::get_goto_program(
629632
*this, options, get_message_handler());
630633
lazy_goto_model.initialize(cmdline, options);
631634

635+
class_hierarchy =
636+
util_make_unique<class_hierarchyt>(lazy_goto_model.symbol_table);
637+
632638
// Show the class hierarchy
633639
if(cmdline.isset("show-class-hierarchy"))
634640
{
635-
class_hierarchyt hierarchy;
636-
hierarchy(lazy_goto_model.symbol_table);
637-
show_class_hierarchy(hierarchy, ui_message_handler);
641+
show_class_hierarchy(*class_hierarchy, ui_message_handler);
638642
return CPROVER_EXIT_SUCCESS;
639643
}
640644

@@ -729,7 +733,8 @@ void jbmc_parse_optionst::process_goto_function(
729733
try
730734
{
731735
// Removal of RTTI inspection:
732-
remove_instanceof(goto_function, symbol_table, get_message_handler());
736+
remove_instanceof(
737+
goto_function, symbol_table, *class_hierarchy, get_message_handler());
733738
// Java virtual functions -> explicit dispatch tables:
734739
remove_virtual_functions(function);
735740

@@ -743,6 +748,7 @@ void jbmc_parse_optionst::process_goto_function(
743748
remove_exceptions(
744749
goto_function.body,
745750
symbol_table,
751+
class_hierarchy.get(),
746752
get_message_handler(),
747753
remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
748754
}
@@ -888,6 +894,7 @@ bool jbmc_parse_optionst::process_goto_functions(
888894
// (introduces instanceof but request it is removed)
889895
remove_exceptions(
890896
goto_model,
897+
class_hierarchy.get(),
891898
get_message_handler(),
892899
remove_exceptions_typest::REMOVE_ADDED_INSTANCEOF);
893900

jbmc/src/jbmc/jbmc_parse_options.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class jbmc_parse_optionst:
123123
object_factory_parameterst object_factory_params;
124124
bool stub_objects_are_not_null;
125125

126+
std::unique_ptr<class_hierarchyt> class_hierarchy;
127+
126128
void get_command_line_options(optionst &);
127129
int get_goto_program(
128130
std::unique_ptr<goto_modelt> &goto_model, const optionst &);

jbmc/src/jdiff/jdiff_parse_options.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,14 @@ bool jdiff_parse_optionst::process_goto_program(
351351

352352
// Java virtual functions -> explicit dispatch tables:
353353
remove_virtual_functions(goto_model);
354-
// remove catch and throw
355-
remove_exceptions(goto_model, get_message_handler());
354+
355+
// remove Java throw and catch
356+
// This introduces instanceof, so order is important:
357+
remove_exceptions(goto_model, nullptr, get_message_handler());
358+
356359
// Java instanceof -> clsid comparison:
357-
remove_instanceof(goto_model, get_message_handler());
360+
class_hierarchyt class_hierarchy(goto_model.symbol_table);
361+
remove_instanceof(goto_model, class_hierarchy, get_message_handler());
358362

359363
mm_io(goto_model);
360364

jbmc/unit/java_bytecode/java_replace_nondet/replace_nondet.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,9 @@ void load_and_test_method(
141141

142142
// Emulate some of the passes that we'd normally do before replace_java_nondet
143143
// is called.
144-
remove_instanceof(goto_function, symbol_table, null_message_handler);
144+
class_hierarchyt class_hierarchy(symbol_table);
145+
remove_instanceof(
146+
goto_function, symbol_table, class_hierarchy, null_message_handler);
145147

146148
remove_virtual_functions(model_function);
147149

0 commit comments

Comments
 (0)