Skip to content

Commit 6cc4d04

Browse files
committed
Add method documentation for lambda body synthesis
1 parent 0fb0063 commit 6cc4d04

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

jbmc/src/java_bytecode/java_bytecode_parser.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,12 @@ void java_bytecode_parsert::parse_local_variable_type_table(methodt &method)
18811881
}
18821882
}
18831883

1884+
/// Translate the lambda method reference kind in a class file into the kind
1885+
/// of handling the method requires. invokestatic/special translate into direct
1886+
/// method calls; invokevirtual/interface translate into virtual dispatch,
1887+
/// newinvokespecial translates into a special instantiate-and-construct
1888+
/// sequence. The field-manipulation reference kinds appear never to happen in
1889+
/// reality and don't have syntax in the Java language.
18841890
static java_class_typet::method_handle_typet get_method_handle_type(
18851891
method_handle_infot::method_handle_kindt java_handle_kind)
18861892
{

jbmc/src/java_bytecode/java_types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,14 +450,24 @@ class java_class_typet:public class_typet
450450
set(ID_interface, interface);
451451
}
452452

453+
/// Indicates what sort of code should be synthesised for a lambda call:
453454
enum class method_handle_typet
454455
{
456+
/// Direct call to the given method
455457
LAMBDA_STATIC_METHOD_HANDLE,
458+
/// Virtual call to the given interface or method
456459
LAMBDA_VIRTUAL_METHOD_HANDLE,
460+
/// Instantiate the needed type then call a constructor
457461
LAMBDA_CONSTRUCTOR_HANDLE,
462+
/// Can't be called
458463
UNKNOWN_HANDLE
459464
};
460465

466+
/// Represents a lambda call to a method. We store the method being called in
467+
/// the same class_method_descriptor_exprt as java_bytecode_convert_method
468+
/// uses to translate virtual method calls to denote the method targeted, and
469+
/// use method_handle_typet above to indicate what kind of dispatch should be
470+
/// used.
461471
class java_lambda_method_handlet : public irept
462472
{
463473
public:

jbmc/src/java_bytecode/lambda_synthesis.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ class no_unique_unimplemented_method_exceptiont : public std::exception
102102
const std::string message;
103103
};
104104

105+
/// Find the unique abstract method that isn't equals(...) or hashCode() in a
106+
/// list of methods. Returns the method's symbol-table identifier if one is
107+
/// found, or empty if there are no matching methods, or throws
108+
/// no_unique_unimplemented_method_exceptiont if there are at least two.
105109
static optionalt<irep_idt> get_unique_abstract_method(
106110
const java_class_typet::methodst &methods,
107111
const namespacet &ns)
@@ -131,6 +135,10 @@ static optionalt<irep_idt> get_unique_abstract_method(
131135
return result;
132136
}
133137

138+
/// Find the unique unimplemented method on a given interface type, including
139+
/// considering its parents. Returns the method's symbol-table identifier if one
140+
/// is found, or empty if there are no unimplemented methods, or throws
141+
/// no_unique_unimplemented_method_exceptiont if there are at least two.
134142
static optionalt<irep_idt> get_unique_unimplemented_method(
135143
const irep_idt &interface_id,
136144
const namespacet &ns)
@@ -529,6 +537,16 @@ static symbol_exprt create_and_declare_local(
529537
return new_instance_var;
530538
}
531539

540+
/// Instantiates an object suitable for calling a given constructor (but does
541+
/// not actually call it). Adds a local to symbol_table, and code implementing
542+
/// the required operation to result; returns a symbol carrying a reference to
543+
/// the newly instantiated object.
544+
/// \param function_id: ID of the function that `result` falls within
545+
/// \param lambda_method_symbol: the constructor that will be called, and so
546+
/// whose `this` parameter we should instantiate.
547+
/// \param symbol_table: symbol table, will gain a local variable
548+
/// \param result: will gain instructions instantiating the required type
549+
/// \return the newly instantiated symbol
532550
static symbol_exprt instantiate_new_object(
533551
const irep_idt &function_id,
534552
const symbolt &lambda_method_symbol,
@@ -566,6 +584,22 @@ static symbol_exprt instantiate_new_object(
566584
return new_instance_var;
567585
}
568586

587+
/// Create the body for the synthetic method implementing an invokedynamic
588+
/// method. For most lambdas this means creating a simple function body like
589+
/// TR new_synthetic_method(T1 param1, T2 param2, ...) {
590+
/// return target_method(capture1, capture2, ..., param1, param2, ...);
591+
/// }, where the first parameter might be a `this` parameter.
592+
/// For a constructor method, the generated code will be of the form
593+
/// TNew new_synthetic_method(T1 param1, T2 param2, ...) {
594+
/// return new TNew(capture1, capture2, ..., param1, param2, ...);
595+
/// }
596+
/// i.e. the TNew object will be both instantiated and constructed.
597+
/// \param function_id: synthetic method whose body should be generated;
598+
/// information about the lambda method to generate has already been stored
599+
/// in the symbol table by create_invokedynamic_synthetic_classes.
600+
/// \param symbol_table: will gain local variable symbols
601+
/// \param message_handler: log
602+
/// \return the method body for `function_id`
569603
codet invokedynamic_synthetic_method(
570604
const irep_idt &function_id,
571605
symbol_table_baset &symbol_table,

0 commit comments

Comments
 (0)