Implement parameter adaptation in LambdaMetaFactory #1078
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is based on work started in #701, and has been rebased on #1056 to incorporate additional fixes.
Summary:
Implemented modeling of parameter adaptation. This is required to handle conversion of primitives to their wrapper types (boxing and unboxing).
Enabled writing generated classes to another format, such as .class.
Generated class names follow naming pattern based on the class enclosing the original invoke dynamic instruction.
Removed BridgeMethodSource; ThunkMethodSource handles all cases. The implementation follows Better lambda support via modeling of LambdaMetaFactory #701: samMethodType and the bridges are signatures to be implemented by the functional object, and each one delegates to the implMethod. Bridge methods should only be necessary for the altMetaFactory, and in practice we have found no cases in the wild from the OpenJDK compiler (and only one from the Eclipse compiler).
Although WIP: Synthetic LambdaMetaFactory implementation to handle invokeDynamic #1056 contains fixes for invocation style handling, this may add even more fixes (this was implemented prior to WIP: Synthetic LambdaMetaFactory implementation to handle invokeDynamic #1056, and I have not performed a detailed comparison).
Why these changes are needed:
The following class contains a method reference which requires a parameter adaptation from int to Integer. This conversion has to be implemented within the thunk class; it cannot be performed at the call site in parameterBoxing(). See the LambdaMetaFactory javadoc and JLS 5.1.7 for details.
Testing:
For dynamic testing, we converted the JavaPoet library (which uses lambdas), and all JUnits continued to pass.
In addition, we wrote some tests which we converted to Jimple text format and visually inspected. These include enumerated cases for parameter adaptation (Adapt.java), and a method reference to an array constructor (ArrayConstructorReference.java). These may be worth turning into test cases, I have included them in the zip file.
Additional observations:
Synchronization issues persist in WIP: Synthetic LambdaMetaFactory implementation to handle invokeDynamic #1056. Added synchronization to LambdaMetaFactory.makeLambdaHelper() as a workaround, but this is likely the wrong way to fix the race conditions. Two distinct stack traces are included in the zip file which result if the method is unsynchronized. Perhaps the data structures in Scene are not properly synchronized with respect to whatever operations the LambdaMetaFactory performs?
Before integration, consider making this feature optional. When writing transformed class files, the invokedynamic instructions will have been replaced (by design). This might be undesirable for some use cases.
The names of generated classes are potentially non-deterministic because a single counter is used to name the classes, and method conversion may occur in parallel. This issue need not block integration, but it might complicate creating test cases.
LMF-attachments.zip