Skip to content

Commit bf16106

Browse files
committed
Store lambda methods kinds in java_class_typet
This paves the way for supporting multiple lambda method kinds, e.g. newinvokespecial lambdas which instantiate and construct a type.
1 parent a1f60ea commit bf16106

File tree

6 files changed

+84
-46
lines changed

6 files changed

+84
-46
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_class.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,8 @@ void java_bytecode_convert_classt::convert(
426426
lambda_entry.second.is_unknown_handle()
427427
? class_type.add_unknown_lambda_method_handle()
428428
: class_type.add_lambda_method_handle(
429-
"java::" + id2string(lambda_entry.second.lambda_method_ref));
429+
"java::" + id2string(lambda_entry.second.lambda_method_ref),
430+
lambda_entry.second.handle_type);
430431
}
431432

432433
// Load annotations

jbmc/src/java_bytecode/java_bytecode_parse_tree.h

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ Author: Daniel Kroening, kroening@kroening.com
1818
#include <util/std_types.h>
1919

2020
#include "bytecode_info.h"
21+
#include "java_types.h"
2122

2223
struct java_bytecode_parse_treet
2324
{
@@ -224,16 +225,11 @@ struct java_bytecode_parse_treet
224225
irep_idt outer_class; // when no outer class is set, there is no outer class
225226
size_t enum_elements=0;
226227

227-
enum class method_handle_typet
228-
{
229-
LAMBDA_METHOD_HANDLE,
230-
UNKNOWN_HANDLE
231-
};
232-
233228
typedef std::vector<u2> u2_valuest;
234229
struct lambda_method_handlet
235230
{
236-
method_handle_typet handle_type = method_handle_typet::UNKNOWN_HANDLE;
231+
java_class_typet::method_handle_typet handle_type =
232+
java_class_typet::method_handle_typet::UNKNOWN_HANDLE;
237233
irep_idt lambda_method_name;
238234
irep_idt lambda_method_ref;
239235
irep_idt interface_type;
@@ -255,7 +251,8 @@ struct java_bytecode_parse_treet
255251

256252
bool is_unknown_handle() const
257253
{
258-
return handle_type == method_handle_typet::UNKNOWN_HANDLE;
254+
return handle_type ==
255+
java_class_typet::method_handle_typet::UNKNOWN_HANDLE;
259256
}
260257
};
261258

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ class java_bytecode_parsert final : public parsert
5454
using fieldt = java_bytecode_parse_treet::fieldt;
5555
using instructiont = java_bytecode_parse_treet::instructiont;
5656
using annotationt = java_bytecode_parse_treet::annotationt;
57-
using method_handle_typet =
58-
java_bytecode_parse_treet::classt::method_handle_typet;
57+
using method_handle_typet = java_class_typet::method_handle_typet;
5958
using lambda_method_handlet =
6059
java_bytecode_parse_treet::classt::lambda_method_handlet;
6160

@@ -330,6 +329,11 @@ class method_handle_infot : public structured_pool_entryt
330329
reference_index = entry.ref2;
331330
}
332331

332+
method_handle_kindt get_reference_kind() const
333+
{
334+
return reference_kind;
335+
}
336+
333337
base_ref_infot get_reference(const pool_entry_lookupt &pool_entry) const
334338
{
335339
const base_ref_infot ref_entry{pool_entry(reference_index)};

jbmc/src/java_bytecode/java_types.h

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -450,34 +450,62 @@ class java_class_typet:public class_typet
450450
set(ID_interface, interface);
451451
}
452452

453-
// it may be better to introduce a class like
454-
// class java_lambda_method_handlet : private irept
455-
// {
456-
// java_lambda_method_handlet(const irep_idt &id) : irept(id)
457-
// {
458-
// }
459-
//
460-
// const irep_idt &get_lambda_method_handle() const
461-
// {
462-
// return id();
463-
// }
464-
// };
465-
using java_lambda_method_handlest = irept::subt;
453+
enum class method_handle_typet
454+
{
455+
LAMBDA_METHOD_HANDLE,
456+
LAMBDA_CONSTRUCTOR_HANDLE,
457+
UNKNOWN_HANDLE
458+
};
459+
460+
class java_lambda_method_handlet : public irept
461+
{
462+
public:
463+
java_lambda_method_handlet(
464+
const irep_idt &id,
465+
method_handle_typet handle_type)
466+
: irept(id)
467+
{
468+
set(ID_handle_type, static_cast<int>(handle_type));
469+
}
470+
471+
java_lambda_method_handlet()
472+
{
473+
set(
474+
ID_handle_type, static_cast<int>(method_handle_typet::UNKNOWN_HANDLE));
475+
}
476+
477+
const irep_idt &get_lambda_method_identifier() const
478+
{
479+
return id();
480+
}
481+
482+
method_handle_typet get_handle_type() const
483+
{
484+
return (method_handle_typet)get_int(ID_handle_type);
485+
}
486+
};
487+
488+
using java_lambda_method_handlest = std::vector<java_lambda_method_handlet>;
466489

467490
const java_lambda_method_handlest &lambda_method_handles() const
468491
{
469-
return find(ID_java_lambda_method_handles).get_sub();
492+
return (const java_lambda_method_handlest &)find(
493+
ID_java_lambda_method_handles)
494+
.get_sub();
470495
}
471496

472497
java_lambda_method_handlest &lambda_method_handles()
473498
{
474-
return add(ID_java_lambda_method_handles).get_sub();
499+
return (java_lambda_method_handlest &)add(ID_java_lambda_method_handles)
500+
.get_sub();
475501
}
476502

477-
void add_lambda_method_handle(const irep_idt &identifier)
503+
void add_lambda_method_handle(
504+
const irep_idt &identifier,
505+
method_handle_typet handle_type)
478506
{
479507
// creates a symbol_exprt for the identifier and pushes it in the vector
480-
lambda_method_handles().emplace_back(identifier);
508+
lambda_method_handles().emplace_back(identifier, handle_type);
481509
}
482510
void add_unknown_lambda_method_handle()
483511
{

jbmc/src/java_bytecode/lambda_synthesis.cpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ irep_idt lambda_synthetic_class_name(
5151
/// methods) of the class where the lambda is called
5252
/// \param index: Index of the lambda method handle in the vector
5353
/// \return Symbol of the lambda method if the method handle has a known type
54-
static optionalt<symbolt> get_lambda_method_symbol(
54+
static optionalt<java_class_typet::java_lambda_method_handlet>
55+
get_lambda_method_handle(
5556
const symbol_table_baset &symbol_table,
5657
const java_class_typet::java_lambda_method_handlest &lambda_method_handles,
5758
const size_t index)
@@ -62,15 +63,18 @@ static optionalt<symbolt> get_lambda_method_symbol(
6263
// internally by the string solver.
6364
if(index >= lambda_method_handles.size())
6465
return {};
65-
const irept &lambda_method_handle = lambda_method_handles.at(index);
66+
const auto &lambda_method_handle = lambda_method_handles.at(index);
6667
// If the lambda method handle has an unknown type, it does not refer to
6768
// any symbol (it has an empty identifier)
68-
if(!lambda_method_handle.id().empty())
69-
return symbol_table.lookup_ref(lambda_method_handle.id());
69+
if(
70+
lambda_method_handle.get_handle_type() !=
71+
java_class_typet::method_handle_typet::UNKNOWN_HANDLE)
72+
return lambda_method_handle;
7073
return {};
7174
}
7275

73-
static optionalt<irep_idt> lambda_method_name(
76+
static optionalt<java_class_typet::java_lambda_method_handlet>
77+
lambda_method_handle(
7478
const symbol_tablet &symbol_table,
7579
const irep_idt &method_identifier,
7680
const java_method_typet &dynamic_method_type)
@@ -84,11 +88,8 @@ static optionalt<irep_idt> lambda_method_name(
8488
const auto &lambda_method_handles = class_type.lambda_method_handles();
8589
auto lambda_handle_index =
8690
dynamic_method_type.get_int(ID_java_lambda_method_handle_index);
87-
const auto lambda_method_symbol = get_lambda_method_symbol(
91+
return get_lambda_method_handle(
8892
symbol_table, lambda_method_handles, lambda_handle_index);
89-
if(lambda_method_symbol)
90-
return lambda_method_symbol->name;
91-
return {};
9293
}
9394

9495
static optionalt<irep_idt> interface_method_id(
@@ -131,7 +132,7 @@ static optionalt<irep_idt> interface_method_id(
131132

132133
symbolt synthetic_class_symbol(
133134
const irep_idt &synthetic_class_name,
134-
const irep_idt &lambda_method_name,
135+
const java_class_typet::java_lambda_method_handlet &lambda_method_handle,
135136
const struct_tag_typet &functional_interface_tag,
136137
const java_method_typet &dynamic_method_type)
137138
{
@@ -142,8 +143,7 @@ symbolt synthetic_class_symbol(
142143
strip_java_namespace_prefix(synthetic_class_name));
143144
synthetic_class_type.set_name(synthetic_class_name);
144145
synthetic_class_type.set_synthetic(true);
145-
synthetic_class_type.set(
146-
ID_java_lambda_method_identifier, lambda_method_name);
146+
synthetic_class_type.set(ID_java_lambda_method_handle, lambda_method_handle);
147147
struct_tag_typet base_tag("java::java.lang.Object");
148148
synthetic_class_type.add_base(base_tag);
149149
synthetic_class_type.add_base(functional_interface_tag);
@@ -309,9 +309,9 @@ void create_invokedynamic_synthetic_classes(
309309
continue;
310310
const auto &dynamic_method_type =
311311
to_java_method_type(instruction.args.at(0).type());
312-
const auto lambda_method_name = ::lambda_method_name(
312+
const auto lambda_handle = lambda_method_handle(
313313
symbol_table, method_identifier, dynamic_method_type);
314-
if(!lambda_method_name)
314+
if(!lambda_handle)
315315
{
316316
log.debug() << "ignoring invokedynamic at " << method_identifier
317317
<< " address " << instruction.address
@@ -329,8 +329,9 @@ void create_invokedynamic_synthetic_classes(
329329
if(!interface_method_id)
330330
continue;
331331
log.debug() << "identified invokedynamic at " << method_identifier
332-
<< " address " << instruction.address
333-
<< " for lambda: " << *lambda_method_name << messaget::eom;
332+
<< " address " << instruction.address << " for lambda: "
333+
<< lambda_handle->get_lambda_method_identifier()
334+
<< messaget::eom;
334335
const irep_idt synthetic_class_name =
335336
lambda_synthetic_class_name(method_identifier, instruction.address);
336337
symbol_table.add(constructor_symbol(
@@ -342,7 +343,7 @@ void create_invokedynamic_synthetic_classes(
342343
synthetic_class_name));
343344
symbol_table.add(synthetic_class_symbol(
344345
synthetic_class_name,
345-
*lambda_method_name,
346+
*lambda_handle,
346347
functional_interface_tag,
347348
dynamic_method_type));
348349
}
@@ -488,8 +489,13 @@ codet invokedynamic_synthetic_method(
488489
lambda_method_args.push_back(param_symbol.symbol_expr());
489490
}
490491

492+
const auto &lambda_method_handle =
493+
static_cast<const java_class_typet::java_lambda_method_handlet &>(
494+
class_type.find(ID_java_lambda_method_handle));
495+
491496
const auto &lambda_method_symbol =
492-
ns.lookup(class_type.get(ID_java_lambda_method_identifier));
497+
ns.lookup(lambda_method_handle.get_lambda_method_identifier());
498+
const auto handle_type = lambda_method_handle.get_handle_type();
493499

494500
if(return_type != empty_typet())
495501
{

src/util/irep_ids.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,8 @@ IREP_ID_TWO(C_java_generic_symbol, #java_generic_symbol)
647647
IREP_ID_ONE(generic_types)
648648
IREP_ID_TWO(implicit_generic_types, #implicit_generic_types)
649649
IREP_ID_ONE(type_variables)
650+
IREP_ID_ONE(handle_type)
651+
IREP_ID_ONE(java_lambda_method_handle)
650652
IREP_ID_TWO(java_lambda_method_handle_index, lambda_method_handle_index)
651653
IREP_ID_TWO(java_lambda_method_handles, lambda_method_handles)
652654
IREP_ID_TWO(java_lambda_method_identifier, lambda_method_identifier)

0 commit comments

Comments
 (0)