Skip to content

Commit 9d42bc8

Browse files
author
thk123
committed
Move method for gathering all instantiated types into ci_lazy_methods_needed
1 parent b67ae26 commit 9d42bc8

File tree

4 files changed

+134
-148
lines changed

4 files changed

+134
-148
lines changed

jbmc/src/java_bytecode/ci_lazy_methods.cpp

Lines changed: 9 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,10 @@ bool ci_lazy_methodst::operator()(
113113
{
114114
std::unordered_set<irep_idt> initial_callable_methods;
115115
ci_lazy_methods_neededt initial_lazy_methods(
116-
initial_callable_methods, instantiated_classes, symbol_table);
116+
initial_callable_methods,
117+
instantiated_classes,
118+
symbol_table,
119+
pointer_type_selector);
117120
initialize_instantiated_classes(
118121
methods_to_convert_later, namespacet(symbol_table), initial_lazy_methods);
119122
methods_to_convert_later.insert(
@@ -298,7 +301,10 @@ ci_lazy_methodst::convert_and_analyze_method(
298301
// Note this wraps *references* to methods_to_convert_later &
299302
// instantiated_classes
300303
ci_lazy_methods_neededt needed_methods(
301-
methods_to_convert_later, instantiated_classes, symbol_table);
304+
methods_to_convert_later,
305+
instantiated_classes,
306+
symbol_table,
307+
pointer_type_selector);
302308

303309
const bool could_not_convert_function =
304310
method_converter(method_name, needed_methods);
@@ -430,8 +436,7 @@ void ci_lazy_methodst::initialize_instantiated_classes(
430436
if(param.type().id()==ID_pointer)
431437
{
432438
const pointer_typet &original_pointer=to_pointer_type(param.type());
433-
initialize_all_instantiated_classes_from_pointer(
434-
original_pointer, ns, needed_lazy_methods);
439+
needed_lazy_methods.add_all_needed_classes(original_pointer);
435440
}
436441
}
437442
}
@@ -448,75 +453,6 @@ void ci_lazy_methodst::initialize_instantiated_classes(
448453
needed_lazy_methods.add_needed_class("java::" + id2string(id));
449454
}
450455

451-
/// Build up list of methods for types for a pointer and any types it
452-
/// might be subsituted for. See
453-
/// `initialize_instantiated_classes` for more details.
454-
/// \param pointer_type: The type to gather methods for.
455-
/// \param ns: global namespace
456-
/// \param [out] needed_lazy_methods: Populated with all Java reference types
457-
/// whose references may be passed, directly or indirectly, to any of the
458-
/// functions in `entry_points`
459-
void ci_lazy_methodst::initialize_all_instantiated_classes_from_pointer(
460-
const pointer_typet &pointer_type,
461-
const namespacet &ns,
462-
ci_lazy_methods_neededt &needed_lazy_methods)
463-
{
464-
initialize_instantiated_classes_from_pointer(
465-
pointer_type,
466-
ns,
467-
needed_lazy_methods);
468-
469-
// TODO we should be passing here a map that maps generic parameters
470-
// to concrete types in the current context TG-2664
471-
const pointer_typet &subbed_pointer_type =
472-
pointer_type_selector.convert_pointer_type(pointer_type, {}, ns);
473-
474-
if(subbed_pointer_type!=pointer_type)
475-
{
476-
initialize_instantiated_classes_from_pointer(
477-
subbed_pointer_type, ns, needed_lazy_methods);
478-
}
479-
}
480-
481-
/// Build up list of methods for types for a specific pointer type. See
482-
/// `initialize_instantiated_classes` for more details.
483-
/// \param pointer_type: The type to gather methods for.
484-
/// \param ns: global namespace
485-
/// \param [out] needed_lazy_methods: Populated with all Java reference types
486-
/// whose references may be passed, directly or indirectly, to any of the
487-
/// functions in `entry_points`
488-
void ci_lazy_methodst::initialize_instantiated_classes_from_pointer(
489-
const pointer_typet &pointer_type,
490-
const namespacet &ns,
491-
ci_lazy_methods_neededt &needed_lazy_methods)
492-
{
493-
const symbol_typet &class_type=to_symbol_type(pointer_type.subtype());
494-
const auto &param_classid=class_type.get_identifier();
495-
496-
// Note here: different arrays may have different element types, so we should
497-
// explore again even if we've seen this classid before in the array case.
498-
if(needed_lazy_methods.add_needed_class(param_classid) ||
499-
is_java_array_tag(param_classid))
500-
{
501-
gather_field_types(pointer_type.subtype(), ns, needed_lazy_methods);
502-
}
503-
504-
if(is_java_generic_type(pointer_type))
505-
{
506-
// Assume if this is a generic like X<A, B, C>, then any concrete parameters
507-
// will at some point be instantiated.
508-
const auto &generic_args =
509-
to_java_generic_type(pointer_type).generic_type_arguments();
510-
for(const auto &generic_arg : generic_args)
511-
{
512-
if(!is_java_generic_parameter(generic_arg))
513-
{
514-
initialize_instantiated_classes_from_pointer(
515-
generic_arg, ns, needed_lazy_methods);
516-
}
517-
}
518-
}
519-
}
520456

521457
/// Get places where virtual functions are called.
522458
/// \param e: expression tree to search
@@ -611,64 +547,6 @@ void ci_lazy_methodst::gather_needed_globals(
611547
gather_needed_globals(*opit, symbol_table, needed);
612548
}
613549

614-
/// See param needed_lazy_methods
615-
/// \param class_type: root of class tree to search
616-
/// \param ns: global namespace
617-
/// \param [out] needed_lazy_methods: Popualted with all Java reference types
618-
/// reachable starting at `class_type`. For example if `class_type` is
619-
/// `symbol_typet("java::A")` and A has a B field, then `B` (but not `A`) will
620-
/// noted as a needed class.
621-
void ci_lazy_methodst::gather_field_types(
622-
const typet &class_type,
623-
const namespacet &ns,
624-
ci_lazy_methods_neededt &needed_lazy_methods)
625-
{
626-
const auto &underlying_type=to_struct_type(ns.follow(class_type));
627-
if(is_java_array_tag(underlying_type.get_tag()))
628-
{
629-
// If class_type is not a symbol this may be a reference array,
630-
// but we can't tell what type.
631-
if(class_type.id() == ID_symbol)
632-
{
633-
const typet &element_type =
634-
java_array_element_type(to_symbol_type(class_type));
635-
if(element_type.id() == ID_pointer)
636-
{
637-
// This is a reference array -- mark its element type available.
638-
initialize_all_instantiated_classes_from_pointer(
639-
to_pointer_type(element_type), ns, needed_lazy_methods);
640-
}
641-
}
642-
}
643-
else
644-
{
645-
for(const auto &field : underlying_type.components())
646-
{
647-
if(field.type().id() == ID_struct || field.type().id() == ID_symbol)
648-
gather_field_types(field.type(), ns, needed_lazy_methods);
649-
else if(field.type().id() == ID_pointer)
650-
{
651-
if(field.type().subtype().id() == ID_symbol)
652-
{
653-
initialize_all_instantiated_classes_from_pointer(
654-
to_pointer_type(field.type()), ns, needed_lazy_methods);
655-
}
656-
else
657-
{
658-
// If raw structs were possible this would lead to missed
659-
// dependencies, as both array element and specialised generic type
660-
// information cannot be obtained in this case.
661-
// We should therefore only be skipping pointers such as the uint16t*
662-
// in our internal String representation.
663-
INVARIANT(
664-
field.type().subtype().id() != ID_struct,
665-
"struct types should be referred to by symbol at this stage");
666-
}
667-
}
668-
}
669-
}
670-
}
671-
672550
/// Find a virtual callee, if one is defined and the callee type is known to
673551
/// exist.
674552
/// \param instantiated_classes: set of classes that can be instantiated.

jbmc/src/java_bytecode/ci_lazy_methods.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,6 @@ class ci_lazy_methodst:public messaget
121121
const namespacet &ns,
122122
ci_lazy_methods_neededt &needed_lazy_methods);
123123

124-
void initialize_all_instantiated_classes_from_pointer(
125-
const pointer_typet &pointer_type,
126-
const namespacet &ns,
127-
ci_lazy_methods_neededt &needed_lazy_methods);
128-
129-
void initialize_instantiated_classes_from_pointer(
130-
const pointer_typet &pointer_type,
131-
const namespacet &ns,
132-
ci_lazy_methods_neededt &needed_lazy_methods);
133-
134124
void gather_virtual_callsites(
135125
const exprt &e,
136126
std::unordered_set<exprt, irep_hash> &result);
@@ -146,11 +136,6 @@ class ci_lazy_methodst:public messaget
146136
const symbol_tablet &symbol_table,
147137
symbol_tablet &needed);
148138

149-
void gather_field_types(
150-
const typet &class_type,
151-
const namespacet &ns,
152-
ci_lazy_methods_neededt &needed_lazy_methods);
153-
154139
irep_idt get_virtual_method_target(
155140
const std::unordered_set<irep_idt> &instantiated_classes,
156141
const irep_idt &call_basename,

jbmc/src/java_bytecode/ci_lazy_methods_needed.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ Author: Chris Smowton, [email protected]
1111

1212
#include "ci_lazy_methods.h"
1313

14+
#include <java_bytecode/select_pointer_type.h>
1415
#include <string>
16+
#include <util/namespace.h>
17+
#include <util/std_types.h>
1518

1619
/// Notes `method_symbol_name` is referenced from some reachable function, and
1720
/// should therefore be elaborated.
@@ -41,3 +44,108 @@ bool ci_lazy_methods_neededt::add_needed_class(
4144

4245
return true;
4346
}
47+
48+
/// Add to the needed classes all classes specified, the replacement type if it
49+
/// will be replaced, and all fields it contains.
50+
/// \param pointer_type: The type to add
51+
void ci_lazy_methods_neededt::add_all_needed_classes(
52+
const pointer_typet &pointer_type)
53+
{
54+
namespacet ns{symbol_table};
55+
initialize_instantiated_classes_from_pointer(pointer_type, ns);
56+
57+
// TODO we should be passing here a map that maps generic parameters
58+
// to concrete types in the current context TG-2664
59+
const pointer_typet &subbed_pointer_type =
60+
pointer_type_selector.convert_pointer_type(pointer_type, {}, ns);
61+
62+
if(subbed_pointer_type != pointer_type)
63+
{
64+
initialize_instantiated_classes_from_pointer(subbed_pointer_type, ns);
65+
}
66+
}
67+
68+
/// Build up list of methods for types for a specific pointer type. See
69+
/// `add_all_needed_classes` for more details.
70+
/// \param pointer_type: The type to gather methods for.
71+
/// \param ns: global namespace
72+
void ci_lazy_methods_neededt::initialize_instantiated_classes_from_pointer(
73+
const pointer_typet &pointer_type,
74+
const namespacet &ns)
75+
{
76+
const symbol_typet &class_type = to_symbol_type(pointer_type.subtype());
77+
const auto &param_classid = class_type.get_identifier();
78+
79+
// Note here: different arrays may have different element types, so we should
80+
// explore again even if we've seen this classid before in the array case.
81+
if(add_needed_class(param_classid) || is_java_array_tag(param_classid))
82+
{
83+
gather_field_types(pointer_type.subtype(), ns);
84+
}
85+
86+
if(is_java_generic_type(pointer_type))
87+
{
88+
// Assume if this is a generic like X<A, B, C>, then any concrete parameters
89+
// will at some point be instantiated.
90+
const auto &generic_args =
91+
to_java_generic_type(pointer_type).generic_type_arguments();
92+
for(const auto &generic_arg : generic_args)
93+
{
94+
if(!is_java_generic_parameter(generic_arg))
95+
{
96+
initialize_instantiated_classes_from_pointer(generic_arg, ns);
97+
}
98+
}
99+
}
100+
}
101+
102+
/// For a given type, gather all fields referenced by that type
103+
/// \param class_type: root of class tree to search
104+
/// \param ns: global namespaces.
105+
void ci_lazy_methods_neededt::gather_field_types(
106+
const typet &class_type,
107+
const namespacet &ns)
108+
{
109+
const auto &underlying_type = to_struct_type(ns.follow(class_type));
110+
if(is_java_array_tag(underlying_type.get_tag()))
111+
{
112+
// If class_type is not a symbol this may be a reference array,
113+
// but we can't tell what type.
114+
if(class_type.id() == ID_symbol)
115+
{
116+
const typet &element_type =
117+
java_array_element_type(to_symbol_type(class_type));
118+
if(element_type.id() == ID_pointer)
119+
{
120+
// This is a reference array -- mark its element type available.
121+
add_all_needed_classes(to_pointer_type(element_type));
122+
}
123+
}
124+
}
125+
else
126+
{
127+
for(const auto &field : underlying_type.components())
128+
{
129+
if(field.type().id() == ID_struct || field.type().id() == ID_symbol)
130+
gather_field_types(field.type(), ns);
131+
else if(field.type().id() == ID_pointer)
132+
{
133+
if(field.type().subtype().id() == ID_symbol)
134+
{
135+
add_all_needed_classes(to_pointer_type(field.type()));
136+
}
137+
else
138+
{
139+
// If raw structs were possible this would lead to missed
140+
// dependencies, as both array element and specialised generic type
141+
// information cannot be obtained in this case.
142+
// We should therefore only be skipping pointers such as the uint16t*
143+
// in our internal String representation.
144+
INVARIANT(
145+
field.type().subtype().id() != ID_struct,
146+
"struct types should be referred to by symbol at this stage");
147+
}
148+
}
149+
}
150+
}
151+
}

jbmc/src/java_bytecode/ci_lazy_methods_needed.h

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,29 @@ Author: Chris Smowton, [email protected]
1717
#include <unordered_set>
1818
#include <util/symbol_table.h>
1919

20+
class select_pointer_typet;
21+
class pointer_typet;
22+
2023
class ci_lazy_methods_neededt
2124
{
2225
public:
2326
ci_lazy_methods_neededt(
2427
std::unordered_set<irep_idt> &_callable_methods,
2528
std::unordered_set<irep_idt> &_instantiated_classes,
26-
symbol_tablet &_symbol_table)
29+
symbol_tablet &_symbol_table,
30+
const select_pointer_typet &pointer_type_selector)
2731
: callable_methods(_callable_methods),
2832
instantiated_classes(_instantiated_classes),
29-
symbol_table(_symbol_table)
33+
symbol_table(_symbol_table),
34+
pointer_type_selector(pointer_type_selector)
3035
{}
3136

3237
void add_needed_method(const irep_idt &);
3338
// Returns true if new
3439
bool add_needed_class(const irep_idt &);
3540

41+
void add_all_needed_classes(const pointer_typet &pointer_type);
42+
3643
private:
3744
// callable_methods is a vector because it's used as a work-list
3845
// which is periodically cleared. It can't be relied upon to
@@ -45,6 +52,14 @@ class ci_lazy_methods_neededt
4552
// repeatedly exploring a class hierarchy.
4653
std::unordered_set<irep_idt> &instantiated_classes;
4754
symbol_tablet &symbol_table;
55+
56+
const select_pointer_typet &pointer_type_selector;
57+
58+
void initialize_instantiated_classes_from_pointer(
59+
const pointer_typet &pointer_type,
60+
const namespacet &ns);
61+
62+
void gather_field_types(const typet &class_type, const namespacet &ns);
4863
};
4964

5065
#endif

0 commit comments

Comments
 (0)