11
11
#include < java_bytecode/java_entry_point.h>
12
12
#include < java_bytecode/java_class_loader.h>
13
13
#include < java_bytecode/java_utils.h>
14
- #include < util/safe_pointer.h>
15
14
#include < util/suffix.h>
16
15
#include < java_bytecode/java_string_library_preprocess.h>
17
16
@@ -61,14 +60,14 @@ ci_lazy_methodst::ci_lazy_methodst(
61
60
// / from the main entry point (usually provided with the --function command-
62
61
// / line option
63
62
// / \param symbol_table: global symbol table
64
- // / \param [out] lazy_methods : map from method names to relevant symbol and
63
+ // / \param [out] method_bytecode : map from method names to relevant symbol and
65
64
// / parsed-method objects.
66
65
// / \param method_converter: Function for converting methods on demand.
67
66
// / \return Returns false on success
68
67
bool ci_lazy_methodst::operator ()(
69
68
symbol_tablet &symbol_table,
70
- lazy_methodst &lazy_methods ,
71
- method_convertert method_converter)
69
+ method_bytecodet &method_bytecode ,
70
+ const method_convertert & method_converter)
72
71
{
73
72
std::vector<irep_idt> method_worklist1;
74
73
std::vector<irep_idt> method_worklist2;
@@ -141,21 +140,17 @@ bool ci_lazy_methodst::operator()(
141
140
{
142
141
if (!methods_already_populated.insert (mname).second )
143
142
continue ;
144
- auto findit=lazy_methods.find (mname);
145
- if (findit==lazy_methods.end ())
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)))
146
150
{
147
- debug () << " Skip " << mname << eom;
151
+ // Couldn't convert this function
148
152
continue ;
149
153
}
150
- debug () << " CI lazy methods: elaborate " << mname << eom;
151
- const auto &parsed_method=findit->second ;
152
- // Note this wraps *references* to method_worklist2, needed_classes:
153
- ci_lazy_methods_neededt new_lazy_methods (
154
- method_worklist2,
155
- needed_classes,
156
- symbol_table);
157
- method_converter (
158
- *parsed_method.first , *parsed_method.second , new_lazy_methods);
159
154
gather_virtual_callsites (
160
155
symbol_table.lookup_ref (mname).value ,
161
156
virtual_callsites);
@@ -189,15 +184,23 @@ bool ci_lazy_methodst::operator()(
189
184
190
185
for (const auto &sym : symbol_table.symbols )
191
186
{
187
+ // Don't keep global variables (unless they're gathered below from a
188
+ // function that references them)
192
189
if (sym.second .is_static_lifetime )
193
190
continue ;
194
- if (lazy_methods.count (sym.first ) &&
195
- !methods_already_populated.count (sym.first ))
196
- {
197
- continue ;
198
- }
199
191
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
200
202
gather_needed_globals (sym.second .value , symbol_table, keep_symbols);
203
+ }
201
204
keep_symbols.add (sym.second );
202
205
}
203
206
@@ -263,13 +266,13 @@ void ci_lazy_methodst::resolve_method_names(
263
266
// / \param entry_points: list of fully-qualified function names that
264
267
// / we should assume are reachable
265
268
// / \param ns: global namespace
266
- // / \param [out] lazy_methods : Populated with all Java reference types whose
267
- // / references may be passed, directly or indirectly, to any of the functions
268
- // / in `entry_points`.
269
+ // / \param [out] needed_lazy_methods : Populated with all Java reference types
270
+ // / whose references may be passed, directly or indirectly, to any of the
271
+ // / functions in `entry_points`.
269
272
void ci_lazy_methodst::initialize_needed_classes (
270
273
const std::vector<irep_idt> &entry_points,
271
274
const namespacet &ns,
272
- ci_lazy_methods_neededt &lazy_methods )
275
+ ci_lazy_methods_neededt &needed_lazy_methods )
273
276
{
274
277
for (const auto &mname : entry_points)
275
278
{
@@ -281,67 +284,66 @@ void ci_lazy_methodst::initialize_needed_classes(
281
284
{
282
285
const pointer_typet &original_pointer=to_pointer_type (param.type ());
283
286
initialize_all_needed_classes_from_pointer (
284
- original_pointer, ns, lazy_methods );
287
+ original_pointer, ns, needed_lazy_methods );
285
288
}
286
289
}
287
290
}
288
291
289
292
// Also add classes whose instances are magically
290
293
// created by the JVM and so won't be spotted by
291
294
// looking for constructors and calls as usual:
292
- lazy_methods .add_needed_class (" java::java.lang.String" );
293
- lazy_methods .add_needed_class (" java::java.lang.Class" );
294
- lazy_methods .add_needed_class (" java::java.lang.Object" );
295
+ needed_lazy_methods .add_needed_class (" java::java.lang.String" );
296
+ needed_lazy_methods .add_needed_class (" java::java.lang.Class" );
297
+ needed_lazy_methods .add_needed_class (" java::java.lang.Object" );
295
298
296
299
// As in class_loader, ensure these classes stay available
297
300
for (const auto &id : extra_needed_classes)
298
- lazy_methods .add_needed_class (" java::" + id2string (id));
301
+ needed_lazy_methods .add_needed_class (" java::" + id2string (id));
299
302
}
300
303
301
304
// / Build up list of methods for types for a pointer and any types it
302
305
// / might be subsituted for. See
303
306
// / `initialize_needed_classes` for more details.
304
307
// / \param pointer_type: The type to gather methods for.
305
308
// / \param ns: global namespace
306
- // / \param [out] lazy_methods : Populated with all Java reference types whose
307
- // / references may be passed, directly or indirectly, to any of the functions
308
- // / in `entry_points
309
+ // / \param [out] needed_lazy_methods : Populated with all Java reference types
310
+ // / whose references may be passed, directly or indirectly, to any of the
311
+ // / functions in `entry_points`
309
312
void ci_lazy_methodst::initialize_all_needed_classes_from_pointer (
310
313
const pointer_typet &pointer_type,
311
314
const namespacet &ns,
312
- ci_lazy_methods_neededt &lazy_methods )
315
+ ci_lazy_methods_neededt &needed_lazy_methods )
313
316
{
314
- initialize_needed_classes_from_pointer (
315
- pointer_type, ns, lazy_methods);
317
+ initialize_needed_classes_from_pointer (pointer_type, ns, needed_lazy_methods);
316
318
317
319
const pointer_typet &subbed_pointer_type=
318
320
pointer_type_selector.convert_pointer_type (pointer_type, ns);
319
321
320
322
if (subbed_pointer_type!=pointer_type)
321
323
{
322
324
initialize_needed_classes_from_pointer (
323
- subbed_pointer_type, ns, lazy_methods );
325
+ subbed_pointer_type, ns, needed_lazy_methods );
324
326
}
325
327
}
326
328
327
329
// / Build up list of methods for types for a specific pointer type. See
328
330
// / `initialize_needed_classes` for more details.
329
331
// / \param pointer_type: The type to gather methods for.
330
332
// / \param ns: global namespace
331
- // / \param [out] lazy_methods : Populated with all Java reference types whose
332
- // / references may be passed, directly or indirectly, to any of the functions
333
- // / in `entry_points
333
+ // / \param [out] needed_lazy_methods : Populated with all Java reference types
334
+ // / whose references may be passed, directly or indirectly, to any of the
335
+ // / functions in `entry_points`
334
336
void ci_lazy_methodst::initialize_needed_classes_from_pointer (
335
337
const pointer_typet &pointer_type,
336
338
const namespacet &ns,
337
- ci_lazy_methods_neededt &lazy_methods )
339
+ ci_lazy_methods_neededt &needed_lazy_methods )
338
340
{
339
341
const symbol_typet &class_type=to_symbol_type (pointer_type.subtype ());
340
342
const auto ¶m_classid=class_type.get_identifier ();
341
343
342
- if (lazy_methods .add_needed_class (param_classid))
344
+ if (needed_lazy_methods .add_needed_class (param_classid))
343
345
{
344
- gather_field_types (pointer_type.subtype (), ns, lazy_methods );
346
+ gather_field_types (pointer_type.subtype (), ns, needed_lazy_methods );
345
347
}
346
348
}
347
349
@@ -462,30 +464,30 @@ void ci_lazy_methodst::gather_needed_globals(
462
464
gather_needed_globals (*opit, symbol_table, needed);
463
465
}
464
466
465
- // / See param lazy_methods
467
+ // / See param needed_lazy_methods
466
468
// / \param class_type: root of class tree to search
467
469
// / \param ns: global namespace
468
- // / \param [out] lazy_methods : Popualted with all Java reference types reachable
469
- // / starting at `class_type`. For example if `class_type` is
470
+ // / \param [out] needed_lazy_methods : Popualted with all Java reference types
471
+ // / reachable starting at `class_type`. For example if `class_type` is
470
472
// / `symbol_typet("java::A")` and A has a B field, then `B` (but not `A`) will
471
473
// / noted as a needed class.
472
474
void ci_lazy_methodst::gather_field_types (
473
475
const typet &class_type,
474
476
const namespacet &ns,
475
- ci_lazy_methods_neededt &lazy_methods )
477
+ ci_lazy_methods_neededt &needed_lazy_methods )
476
478
{
477
479
const auto &underlying_type=to_struct_type (ns.follow (class_type));
478
480
for (const auto &field : underlying_type.components ())
479
481
{
480
482
if (field.type ().id ()==ID_struct || field.type ().id ()==ID_symbol)
481
- gather_field_types (field.type (), ns, lazy_methods );
483
+ gather_field_types (field.type (), ns, needed_lazy_methods );
482
484
else if (field.type ().id ()==ID_pointer)
483
485
{
484
486
// Skip array primitive pointers, for example:
485
487
if (field.type ().subtype ().id ()!=ID_symbol)
486
488
continue ;
487
489
initialize_all_needed_classes_from_pointer (
488
- to_pointer_type (field.type ()), ns, lazy_methods );
490
+ to_pointer_type (field.type ()), ns, needed_lazy_methods );
489
491
}
490
492
}
491
493
}
0 commit comments