Skip to content

Commit d556380

Browse files
Make string solver functions get converted correctly first time
Previously they were replaced after everything else was done
1 parent ada4475 commit d556380

11 files changed

+154
-121
lines changed

src/java_bytecode/ci_lazy_methods.cpp

+21-16
Original file line numberDiff line numberDiff line change
@@ -140,19 +140,17 @@ bool ci_lazy_methodst::operator()(
140140
{
141141
if(!methods_already_populated.insert(mname).second)
142142
continue;
143-
method_bytecodet::opt_reft cmb = method_bytecode.get(mname);
144-
if(!cmb)
143+
debug() << "CI lazy methods: elaborate " << mname << eom;
144+
if(
145+
method_converter(
146+
mname,
147+
// Note this wraps *references* to method_worklist2 & needed_classes
148+
ci_lazy_methods_neededt(
149+
method_worklist2, needed_classes, symbol_table)))
145150
{
146-
debug() << "Skip " << mname << eom;
151+
// Couldn't convert this function
147152
continue;
148153
}
149-
debug() << "CI lazy methods: elaborate " << mname << eom;
150-
method_converter(
151-
symbol_table.lookup_ref(cmb->get().class_id),
152-
cmb->get().method,
153-
// Note this wraps *references* to method_worklist2 & needed_classes
154-
ci_lazy_methods_neededt(
155-
method_worklist2, needed_classes, symbol_table));
156154
gather_virtual_callsites(
157155
symbol_table.lookup_ref(mname).value,
158156
virtual_callsites);
@@ -186,16 +184,23 @@ bool ci_lazy_methodst::operator()(
186184

187185
for(const auto &sym : symbol_table.symbols)
188186
{
187+
// Don't keep global variables (unless they're gathered below from a
188+
// function that references them)
189189
if(sym.second.is_static_lifetime)
190190
continue;
191-
if(
192-
method_bytecode.contains_method(sym.first) &&
193-
!methods_already_populated.count(sym.first))
194-
{
195-
continue;
196-
}
197191
if(sym.second.type.id()==ID_code)
192+
{
193+
// Don't keep functions that belong to this language that we haven't
194+
// converted above
195+
if(
196+
method_bytecode.contains_method(sym.first) &&
197+
!methods_already_populated.count(sym.first))
198+
{
199+
continue;
200+
}
201+
// If this is a function then add all the things used in it
198202
gather_needed_globals(sym.second.value, symbol_table, keep_symbols);
203+
}
199204
keep_symbols.add(sym.second);
200205
}
201206

src/java_bytecode/ci_lazy_methods.h

+3-4
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,9 @@ class method_bytecodet
8484
}
8585
};
8686

87-
typedef std::function<void(
88-
const symbolt &,
89-
const java_bytecode_parse_treet::methodt &,
90-
ci_lazy_methods_neededt)> method_convertert;
87+
typedef std::function<
88+
bool(const irep_idt &function_id, ci_lazy_methods_neededt)>
89+
method_convertert;
9190

9291
class ci_lazy_methodst:public messaget
9392
{

src/java_bytecode/java_bytecode_convert_method.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ class patternt
7979
/// \return Assigns parameter names (side-effects on `ftype`) to function stub
8080
/// parameters, which are initially nameless as method conversion hasn't
8181
/// happened. Also creates symbols in `symbol_table`.
82-
void assign_parameter_names(
82+
static void assign_parameter_names(
8383
code_typet &ftype,
8484
const irep_idt &name_prefix,
85-
symbol_tablet &symbol_table)
85+
symbol_table_baset &symbol_table)
8686
{
8787
code_typet::parameterst &parameters=ftype.parameters();
8888

@@ -2847,7 +2847,7 @@ codet java_bytecode_convert_methodt::convert_instructions(
28472847
void java_bytecode_convert_method(
28482848
const symbolt &class_symbol,
28492849
const java_bytecode_parse_treet::methodt &method,
2850-
symbol_tablet &symbol_table,
2850+
symbol_table_baset &symbol_table,
28512851
message_handlert &message_handler,
28522852
size_t max_array_length,
28532853
optionalt<ci_lazy_methods_neededt> needed_lazy_methods,

src/java_bytecode/java_bytecode_convert_method.h

+1-19
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,12 @@ class class_hierarchyt;
2424
void java_bytecode_convert_method(
2525
const symbolt &class_symbol,
2626
const java_bytecode_parse_treet::methodt &,
27-
symbol_tablet &symbol_table,
27+
symbol_table_baset &symbol_table,
2828
message_handlert &message_handler,
2929
size_t max_array_length,
3030
optionalt<ci_lazy_methods_neededt> needed_lazy_methods,
3131
java_string_library_preprocesst &string_preprocess);
3232

33-
inline void java_bytecode_convert_method(
34-
const symbolt &class_symbol,
35-
const java_bytecode_parse_treet::methodt &method,
36-
symbol_tablet &symbol_table,
37-
message_handlert &message_handler,
38-
size_t max_array_length,
39-
java_string_library_preprocesst &string_preprocess)
40-
{
41-
java_bytecode_convert_method(
42-
class_symbol,
43-
method,
44-
symbol_table,
45-
message_handler,
46-
max_array_length,
47-
optionalt<ci_lazy_methods_neededt>(),
48-
string_preprocess);
49-
}
50-
5133
void java_bytecode_convert_method_lazy(
5234
const symbolt &class_symbol,
5335
const irep_idt &method_identifier,

src/java_bytecode/java_bytecode_convert_method_class.h

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ class java_bytecode_convert_methodt:public messaget
3131
{
3232
public:
3333
java_bytecode_convert_methodt(
34-
symbol_tablet &_symbol_table,
34+
symbol_table_baset &symbol_table,
3535
message_handlert &_message_handler,
3636
size_t _max_array_length,
3737
optionalt<ci_lazy_methods_neededt> needed_lazy_methods,
3838
java_string_library_preprocesst &_string_preprocess)
3939
: messaget(_message_handler),
40-
symbol_table(_symbol_table),
40+
symbol_table(symbol_table),
4141
max_array_length(_max_array_length),
4242
needed_lazy_methods(std::move(needed_lazy_methods)),
4343
string_preprocess(_string_preprocess),
@@ -58,7 +58,7 @@ class java_bytecode_convert_methodt:public messaget
5858
}
5959

6060
protected:
61-
symbol_tablet &symbol_table;
61+
symbol_table_baset &symbol_table;
6262
const size_t max_array_length;
6363
optionalt<ci_lazy_methods_neededt> needed_lazy_methods;
6464

src/java_bytecode/java_bytecode_language.cpp

+64-62
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Author: Daniel Kroening, [email protected]
1414
#include <util/suffix.h>
1515
#include <util/config.h>
1616
#include <util/cmdline.h>
17+
#include <util/journalling_symbol_table.h>
1718
#include <util/string2int.h>
1819
#include <util/invariant.h>
1920
#include <json/json_parser.h>
@@ -247,16 +248,20 @@ bool java_bytecode_languaget::typecheck(
247248
}
248249
else if(lazy_methods_mode==LAZY_METHODS_MODE_EAGER)
249250
{
250-
// Simply elaborate all methods symbols now.
251+
journalling_symbol_tablet journalling_symbol_table =
252+
journalling_symbol_tablet::wrap(symbol_table);
253+
// Convert all methods for which we have bytecode now
251254
for(const auto &method_sig : method_bytecode)
252255
{
253-
java_bytecode_convert_method(
254-
symbol_table.lookup_ref(method_sig.second.class_id),
255-
method_sig.second.method,
256-
symbol_table,
257-
get_message_handler(),
258-
max_user_array_length,
259-
string_preprocess);
256+
convert_single_method(method_sig.first, journalling_symbol_table);
257+
}
258+
// Now convert all newly added string methods
259+
id_sett string_methods;
260+
string_preprocess.get_all_function_names(string_methods);
261+
for(const auto &fn_name : journalling_symbol_table.get_inserted())
262+
{
263+
if(string_methods.count(fn_name) != 0)
264+
convert_single_method(fn_name, symbol_table);
260265
}
261266
}
262267
// Otherwise our caller is in charge of elaborating methods on demand.
@@ -310,19 +315,13 @@ bool java_bytecode_languaget::do_ci_lazy_method_conversion(
310315
symbol_tablet &symbol_table,
311316
method_bytecodet &method_bytecode)
312317
{
313-
const auto method_converter = [&](
314-
const symbolt &symbol,
315-
const java_bytecode_parse_treet::methodt &method,
316-
ci_lazy_methods_neededt new_lazy_methods) {
317-
java_bytecode_convert_method(
318-
symbol,
319-
method,
320-
symbol_table,
321-
get_message_handler(),
322-
max_user_array_length,
323-
std::move(new_lazy_methods),
324-
string_preprocess);
325-
};
318+
const method_convertert method_converter =
319+
[this, &symbol_table]
320+
(const irep_idt &function_id, ci_lazy_methods_neededt lazy_methods_needed)
321+
{
322+
return convert_single_method(
323+
function_id, symbol_table, std::move(lazy_methods_needed));
324+
};
326325

327326
ci_lazy_methodst method_gather(
328327
symbol_table,
@@ -349,9 +348,11 @@ const select_pointer_typet &
349348
/// \return Populates `methods` with the complete list of lazy methods that are
350349
/// available to convert (those which are valid parameters for
351350
/// `convert_lazy_method`)
352-
void java_bytecode_languaget::methods_provided(
353-
std::set<irep_idt> &methods) const
351+
void java_bytecode_languaget::methods_provided(id_sett &methods) const
354352
{
353+
// Add all string solver methods to map
354+
string_preprocess.get_all_function_names(methods);
355+
// Add all concrete methods to map
355356
for(const auto &kv : method_bytecode)
356357
methods.insert(kv.first);
357358
}
@@ -368,59 +369,60 @@ void java_bytecode_languaget::convert_lazy_method(
368369
const irep_idt &function_id,
369370
symbol_tablet &symbol_table)
370371
{
371-
const method_bytecodet::class_method_and_bytecodet &cmb =
372-
*method_bytecode.get(function_id);
373-
java_bytecode_convert_method(
374-
symbol_table.lookup_ref(cmb.class_id),
375-
cmb.method,
376-
symbol_table,
377-
get_message_handler(),
378-
max_user_array_length,
379-
string_preprocess);
372+
convert_single_method(function_id, symbol_table);
380373
}
381374

382-
/// Replace methods of the String library that are in the symbol table by code
383-
/// generated by string_preprocess.
384-
/// \param context: a symbol table
385-
void java_bytecode_languaget::replace_string_methods(
386-
symbol_table_baset &context)
375+
/// \brief Convert a method (one whose type is known but whose body hasn't
376+
/// been converted) but don't run typecheck, etc
377+
/// \remarks Amends the symbol table entry for function `function_id`, which
378+
/// should be a method provided by this instance of `java_bytecode_languaget`
379+
/// to have a value representing the method body.
380+
/// \param function_id: method ID to convert
381+
/// \param symbol_table: global symbol table
382+
/// \param needed_lazy_methods: optionally a collection of needed methods to
383+
/// update with any methods touched during the conversion
384+
bool java_bytecode_languaget::convert_single_method(
385+
const irep_idt &function_id,
386+
symbol_table_baset &symbol_table,
387+
optionalt<ci_lazy_methods_neededt> needed_lazy_methods)
387388
{
388-
// Symbols that have code type are potentialy to be replaced
389-
std::list<symbolt> code_symbols;
390-
forall_symbols(symbol, context.symbols)
389+
const symbolt &symbol = symbol_table.lookup_ref(function_id);
390+
391+
// Nothing to do if body is already loaded
392+
if(symbol.value.is_not_nil())
393+
return false;
394+
395+
exprt generated_code =
396+
string_preprocess.code_for_function(symbol, symbol_table);
397+
if(generated_code.is_not_nil())
391398
{
392-
if(symbol->second.type.id()==ID_code)
393-
code_symbols.push_back(symbol->second);
399+
// Populate body of the function with code generated by string preprocess
400+
symbol_table.get_writeable_ref(function_id).value = generated_code;
401+
return false;
394402
}
395403

396-
for(const auto &symbol : code_symbols)
404+
// No string solver implementation, check if have bytecode for it
405+
method_bytecodet::opt_reft cmb = method_bytecode.get(function_id);
406+
if(cmb)
397407
{
398-
const irep_idt &id=symbol.name;
399-
exprt generated_code=string_preprocess.code_for_function(
400-
id, to_code_type(symbol.type), symbol.location, context);
401-
if(generated_code.is_not_nil())
402-
{
403-
// Replace body of the function by code generated by string preprocess
404-
symbolt &symbol=*context.get_writeable(id);
405-
symbol.value=generated_code;
406-
// Specifically instrument the new code, since this comes after the
407-
// blanket instrumentation pass called before typechecking.
408-
java_bytecode_instrument_symbol(
409-
context,
410-
symbol,
411-
throw_runtime_exceptions,
412-
get_message_handler());
413-
}
408+
java_bytecode_convert_method(
409+
symbol_table.lookup_ref(cmb->get().class_id),
410+
cmb->get().method,
411+
symbol_table,
412+
get_message_handler(),
413+
max_user_array_length,
414+
std::move(needed_lazy_methods),
415+
string_preprocess);
416+
return false;
414417
}
418+
419+
return true;
415420
}
416421

417422
bool java_bytecode_languaget::final(symbol_table_baset &symbol_table)
418423
{
419424
PRECONDITION(language_options_initialized);
420425

421-
// replace code of String methods calls by code we generate
422-
replace_string_methods(symbol_table);
423-
424426
return false;
425427
}
426428

src/java_bytecode/java_bytecode_language.h

+14-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Author: Daniel Kroening, [email protected]
1717
#include <util/make_unique.h>
1818

1919
#include "ci_lazy_methods.h"
20+
#include "ci_lazy_methods_needed.h"
2021
#include "java_class_loader.h"
2122
#include "java_string_library_preprocess.h"
2223

@@ -103,8 +104,6 @@ class java_bytecode_languaget:public languaget
103104
symbol_tablet &context,
104105
const std::string &module) override;
105106

106-
void replace_string_methods(symbol_table_baset &context);
107-
108107
virtual bool final(symbol_table_baset &context) override;
109108

110109
void show_parse(std::ostream &out) override;
@@ -150,12 +149,24 @@ class java_bytecode_languaget:public languaget
150149
std::set<std::string> extensions() const override;
151150

152151
void modules_provided(std::set<std::string> &modules) override;
153-
virtual void methods_provided(std::set<irep_idt> &methods) const override;
152+
virtual void methods_provided(id_sett &methods) const override;
154153
virtual void convert_lazy_method(
155154
const irep_idt &function_id,
156155
symbol_tablet &symbol_table) override;
157156

158157
protected:
158+
void convert_single_method(
159+
const irep_idt &function_id,
160+
symbol_table_baset &symbol_table)
161+
{
162+
convert_single_method(
163+
function_id, symbol_table, optionalt<ci_lazy_methods_neededt>());
164+
}
165+
bool convert_single_method(
166+
const irep_idt &function_id,
167+
symbol_table_baset &symbol_table,
168+
optionalt<ci_lazy_methods_neededt> needed_lazy_methods);
169+
159170
bool do_ci_lazy_method_conversion(symbol_tablet &, method_bytecodet &);
160171
const select_pointer_typet &get_pointer_type_selector() const;
161172

0 commit comments

Comments
 (0)