Skip to content

Commit 6d44836

Browse files
author
Matthias Güdemann
committed
Use optionalt<lambda_method_handlet> as return value
1 parent f765a0d commit 6d44836

File tree

2 files changed

+69
-59
lines changed

2 files changed

+69
-59
lines changed

src/java_bytecode/java_bytecode_parse_tree.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,7 @@ class java_bytecode_parse_treet
197197
}
198198
};
199199

200-
typedef std::vector<lambda_method_handlet> lambda_method_handlest;
201-
typedef std::map<irep_idt, lambda_method_handlest>
200+
typedef std::map<std::pair<irep_idt, size_t>, lambda_method_handlet>
202201
lambda_method_handle_mapt;
203202
lambda_method_handle_mapt lambda_method_handle_map;
204203

src/java_bytecode/java_bytecode_parser.cpp

+68-57
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Author: Daniel Kroening, [email protected]
1919
#include <util/prefix.h>
2020
#include <util/std_expr.h>
2121
#include <util/string_constant.h>
22+
#include <util/optional.h>
2223

2324
#include "java_bytecode_parse_tree.h"
2425
#include "java_types.h"
@@ -47,12 +48,10 @@ class java_bytecode_parsert:public parsert
4748
typedef java_bytecode_parse_treet::instructiont instructiont;
4849
typedef java_bytecode_parse_treet::annotationt annotationt;
4950
typedef java_bytecode_parse_treet::annotationst annotationst;
50-
typedef java_bytecode_parse_treet::classt::lambda_method_handlet
51-
lambda_method_handlet;
5251
typedef java_bytecode_parse_treet::classt::method_handle_typet
5352
method_handle_typet;
54-
typedef java_bytecode_parse_treet::classt::lambda_method_handlest
55-
lambda_method_handlest;
53+
typedef java_bytecode_parse_treet::classt::lambda_method_handlet
54+
lambda_method_handlet;
5655
typedef java_bytecode_parse_treet::classt::lambda_method_handle_mapt
5756
lambda_method_handle_mapt;
5857

@@ -134,7 +133,7 @@ class java_bytecode_parsert:public parsert
134133
void get_class_refs();
135134
void get_class_refs_rec(const typet &);
136135
void parse_local_variable_type_table(methodt &method);
137-
void parse_method_handle(const pool_entryt &, lambda_method_handlet &);
136+
optionalt<lambda_method_handlet> parse_method_handle(const pool_entryt &);
138137

139138
void skip_bytes(std::size_t bytes)
140139
{
@@ -1417,6 +1416,8 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14171416
}
14181417
else if(attribute_name == "BootstrapMethods")
14191418
{
1419+
// for this attribute
1420+
// cf. https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.23
14201421
INVARIANT(
14211422
!parsed_class.attribute_bootstrapmethods_read,
14221423
"only one BootstrapMethods argument is allowed in a class file");
@@ -1430,15 +1431,15 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14301431
const pool_entryt &entry = pool_entry(bootstrap_methodhandle_ref);
14311432
u2 num_bootstrap_arguments = read_u2();
14321433

1433-
lambda_method_handlet handle;
1434+
optionalt<lambda_method_handlet> handle = parse_method_handle(entry);
14341435
debug() << "INFO: parse BootstrapMethod handle "
1435-
<< num_bootstrap_arguments << " #args"
1436-
<< eom;
1437-
parse_method_handle(entry, handle);
1436+
<< num_bootstrap_arguments << " #args" << eom;
1437+
14381438
if(
1439-
handle.handle_type ==
1440-
method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT ||
1441-
handle.handle_type == method_handle_typet::BOOTSTRAP_METHOD_HANDLE)
1439+
handle.has_value() &&
1440+
(handle->handle_type ==
1441+
method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT ||
1442+
handle->handle_type == method_handle_typet::BOOTSTRAP_METHOD_HANDLE))
14421443
{
14431444
// try parsing bootstrap method handle
14441445
if(num_bootstrap_arguments >= 3)
@@ -1485,8 +1486,7 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14851486
}
14861487
if(!recognized)
14871488
{
1488-
debug() << "format of BootstrapMethods entry not recognized"
1489-
<< eom;
1489+
debug() << "format of BootstrapMethods entry not recognized" << eom;
14901490
return;
14911491
}
14921492

@@ -1496,39 +1496,40 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
14961496
pool_entry(argument_index2);
14971497
const pool_entryt &method_type_argument = pool_entry(argument_index3);
14981498

1499-
if(!(interface_type_argument.tag == CONSTANT_MethodType &&
1500-
method_handle_argument.tag == CONSTANT_MethodHandle &&
1501-
method_type_argument.tag == CONSTANT_MethodType))
1499+
if(
1500+
!(interface_type_argument.tag == CONSTANT_MethodType &&
1501+
method_handle_argument.tag == CONSTANT_MethodHandle &&
1502+
method_type_argument.tag == CONSTANT_MethodType))
15021503
return;
15031504

1504-
lambda_method_handlet lambda_method_handle;
15051505
debug() << "INFO: parse lambda handle" << eom;
1506-
parse_method_handle(method_handle_argument, lambda_method_handle);
1506+
optionalt<lambda_method_handlet> lambda_method_handle =
1507+
parse_method_handle(method_handle_argument);
1508+
15071509
if(
1508-
lambda_method_handle.handle_type !=
1509-
method_handle_typet::LAMBDA_METHOD_HANDLE)
1510+
lambda_method_handle.has_value() &&
1511+
lambda_method_handle->handle_type !=
1512+
method_handle_typet::LAMBDA_METHOD_HANDLE)
15101513
{
1511-
lambda_method_handlet empty_handle;
1512-
parsed_class.lambda_method_handle_map[parsed_class.name].push_back(
1513-
empty_handle);
15141514
error() << "ERROR: could not parse lambda function method handle"
15151515
<< eom;
15161516
}
15171517
else
15181518
{
1519-
lambda_method_handle.interface_type = pool_entry(interface_type_argument.ref1).s;
1520-
lambda_method_handle.method_type = pool_entry(method_type_argument.ref1).s;
1521-
parsed_class.lambda_method_handle_map[parsed_class.name].push_back(
1522-
lambda_method_handle);
1523-
debug()
1524-
<< "lambda function reference "
1525-
<< id2string(lambda_method_handle.lambda_method_name) << " in class \""
1526-
<< parsed_class.name << "\""
1527-
<< "\n interface type is "
1528-
<< id2string(pool_entry(interface_type_argument.ref1).s)
1529-
<< "\n method type is "
1530-
<< id2string(pool_entry(method_type_argument.ref1).s)
1531-
<< eom;
1519+
lambda_method_handle->interface_type =
1520+
pool_entry(interface_type_argument.ref1).s;
1521+
lambda_method_handle->method_type =
1522+
pool_entry(method_type_argument.ref1).s;
1523+
debug() << "lambda function reference "
1524+
<< id2string(lambda_method_handle->lambda_method_name)
1525+
<< " in class \"" << parsed_class.name << "\""
1526+
<< "\n interface type is "
1527+
<< id2string(pool_entry(interface_type_argument.ref1).s)
1528+
<< "\n method type is "
1529+
<< id2string(pool_entry(method_type_argument.ref1).s)
1530+
<< eom;
1531+
parsed_class.lambda_method_handle_map[{parsed_class.name, i}] =
1532+
*lambda_method_handle;
15321533
}
15331534
}
15341535
else
@@ -1541,9 +1542,6 @@ void java_bytecode_parsert::rclass_attribute(classt &parsed_class)
15411542
}
15421543
else
15431544
{
1544-
lambda_method_handlet empty_handle;
1545-
parsed_class.lambda_method_handle_map[parsed_class.name].push_back(
1546-
empty_handle);
15471545
// skip bytes to align for next entry
15481546
for(size_t i = 0; i < num_bootstrap_arguments; i++)
15491547
read_u2();
@@ -1683,15 +1681,15 @@ void java_bytecode_parsert::parse_local_variable_type_table(methodt &method)
16831681
/// Read method handle pointed to from constant pool entry at index, return type
16841682
/// of method handle and name if lambda function is found.
16851683
/// \param entry: the constant pool entry of the methodhandle_info structure
1686-
/// \param[out] handle: the method_handle type of the methodhandle_structure,
1687-
/// either for a recognized bootstrap method, for a lambda function or unknown
1688-
void java_bytecode_parsert::parse_method_handle(
1689-
const pool_entryt &entry,
1690-
lambda_method_handlet &handle)
1684+
/// \returns: the method_handle type of the methodhandle_structure,
1685+
/// either for a recognized bootstrap method or for a lambda function
1686+
optionalt<java_bytecode_parsert::lambda_method_handlet>
1687+
java_bytecode_parsert::parse_method_handle(const pool_entryt &entry)
16911688
{
16921689
INVARIANT(
16931690
entry.tag == CONSTANT_MethodHandle,
16941691
"constant pool entry must be a MethodHandle");
1692+
lambda_method_handlet lambda_method_handle;
16951693
const auto &ref_entry = pool_entry(entry.ref2);
16961694
INVARIANT(
16971695
(entry.ref1 > 0 && entry.ref1 < 10),
@@ -1701,30 +1699,43 @@ void java_bytecode_parsert::parse_method_handle(
17011699
const auto &nameandtype_entry = pool_entry(ref_entry.ref2);
17021700

17031701
const std::string method_name =
1704-
id2string(pool_entry(class_entry.ref1).s) + "."
1705-
+ id2string(pool_entry(nameandtype_entry.ref1).s)
1706-
+ id2string(pool_entry(nameandtype_entry.ref2).s);
1702+
id2string(pool_entry(class_entry.ref1).s) + "." +
1703+
id2string(pool_entry(nameandtype_entry.ref1).s) +
1704+
id2string(pool_entry(nameandtype_entry.ref2).s);
17071705

17081706
if(
17091707
method_name ==
17101708
"java/lang/invoke/LambdaMetafactory.metafactory(Ljava/lang/invoke/"
17111709
"MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/"
17121710
"lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/"
17131711
"MethodType;)Ljava/lang/invoke/CallSite;")
1714-
handle.handle_type = method_handle_typet::BOOTSTRAP_METHOD_HANDLE;
1715-
// names seem to be lambda$$POSTFIX$NUM
1716-
// where $POSTFIX is $FUN for a function name in which the lambda is define
1717-
// "static" when it is a static member of the class
1718-
// "new" when it is a class variable, instantiated in <init>
1719-
else if(has_prefix(id2string(pool_entry(nameandtype_entry.ref1).s), "lambda$"))
17201712
{
1721-
handle.lambda_method_name = pool_entry(nameandtype_entry.ref1).s;
1722-
handle.handle_type = method_handle_typet::LAMBDA_METHOD_HANDLE;
1713+
lambda_method_handle.handle_type =
1714+
method_handle_typet::BOOTSTRAP_METHOD_HANDLE;
1715+
}
1716+
else if(
1717+
has_prefix(id2string(pool_entry(nameandtype_entry.ref1).s), "lambda$"))
1718+
{
1719+
// names seem to be lambda$POSTFIX$NUM
1720+
// where POSTFIX is FUN for a function name in which the lambda is define
1721+
// "static" when it is a static member of the class
1722+
// "new" when it is a class variable, instantiated in <init>
1723+
lambda_method_handle.lambda_method_name =
1724+
pool_entry(nameandtype_entry.ref1).s;
1725+
lambda_method_handle.handle_type =
1726+
method_handle_typet::LAMBDA_METHOD_HANDLE;
17231727
}
17241728
else if(
17251729
method_name ==
17261730
"java/lang/invoke/LambdaMetafactory.altMetafactory(Ljava/lang/invoke/"
17271731
"MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/"
17281732
"MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;")
1729-
handle.handle_type = method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT;
1733+
{
1734+
lambda_method_handle.handle_type =
1735+
method_handle_typet::BOOTSTRAP_METHOD_HANDLE_ALT;
1736+
}
1737+
else
1738+
return {};
1739+
1740+
return lambda_method_handle;
17301741
}

0 commit comments

Comments
 (0)