[foreign-memaccess] [Rev 01] RFR: 8245459: Add support for complex filter value var handle adaptation

Paul Sandoz psandoz at openjdk.java.net
Thu May 21 20:21:18 UTC 2020


On Wed, 20 May 2020 13:14:14 GMT, Maurizio Cimadamore <mcimadamore at openjdk.org> wrote:

>> It is sometimes necessary to apply a carrier transform on a VarHandle that is expressed in more than just a pair of
>> unary function (e.g. from `A->B` and `B->A`). Sometimes the transform needs to act on some bit of external state.
>> It would be nice if `MemoryHandles::filterValue` would be enhanced to accept all functions of the kind:
>> 
>> `(C... A) ->B`
>> `(C... B) -> A`
>> 
>> So that the resulting VarHandle will apply carrier transform from A to B and will also add extra coordinate types
>> (C...) which can be used by the transform filters.
>> To enhance `MemoryHandles::filterValue` this way regular MH adapters are not enough; while we can implement setters, by
>> combining the filters with `MethodHandles::collectArguments` there is no way to implement the getters - since that
>> would require a method handle transform which adapts a return value *and* adds some extra parameters to the adapter
>> handle (which are then forwarded to the filter).  This patch adds the missing method handle primitive to do that; for
>> now it's a package private method, namely `MethodHandles::collectReturnValue`. If people think that this could be
>> useful, we can evaluate whether to open this up for method handle combinator API as well.  This required to add a new
>> kind of lambda form using the `LambdaFormEditor`, which was a bit tricky to get right (we currently have no transforms
>> which operates on both arguments *and* return values, which makes it tricky).  The implementation of
>> `MemoryHandles::filterValue` is also a bit more complex, since if there are additional coordinates added by collecting
>> arguments/return values, such additional coordinates might be added multiple times, so we need some steps to 'join' the
>> extra coordinates (with a call to `MethodHandle::permuteArguments`) so that extra coordinate show up only once in the
>> final adapter.  If the filter functions used for adapting are just unary functions, then the implementation falls back
>> to the simpler behavior we had before, and the permutation step is skipped (in such cases, `collectArguments` ==
>> `filterArguments` and `collectReturnValue` == `filterReturnValue`).
>
> Maurizio Cimadamore has updated the pull request incrementally with one additional commit since the last revision:
> 
>   Add more comments on LambdaFormEditor

Well done, that's tricky work with lambda forms.

src/java.base/share/classes/java/lang/invoke/MethodHandles.java line 5496:

> 5495:      */
> 5496:     /* package */ static MethodHandle collectReturnValue(MethodHandle target, MethodHandle filter) {
> 5497:         MethodType targetType = target.type();

Do you need to check that the type of last parameter of the filter function is equal to the return type of the target?
Filter parameters size constraints > 0
Can the filter return void?

src/java.base/share/classes/java/lang/invoke/MethodHandles.java line 5478:

> 5477:     /**
> 5478:      * Filter the return value of a target method handle with a filter function. The filter function is
> 5479:      * applied to the return value of the original handle; if the filter specifies more than one parameters,

Suggested improvement to JavaDoc:
Adapts a target method handle by post-processing
its return value and additional arguments (if any) with a filter
(another method handle).
The result of the filter is returned from the adapter.

If the target returns a value, the filter must accept that value as
as the trailing argument, with the additional arguments proceeding that.
If the target returns void, the filter must accept only the additional arguments.

The return type of the filter
replaces the return type of the target
in the resulting adapted method handle.

The trailing argument type of the filter (if any) must be identical to the
return type of the target.

The additional argument types of the filter (if any) are appended (in order)
to the argument types of the target method handle and become the argument
types of the resulting adapted method handle.

Here is pseudocode for the resulting adapter. In the code,
{@code T}/{@code t} represent the result type and value of the
{@code target}; {@code V}, the result type of the {@code filter};
{@code A}/{@code a}, the types and values of the parameters and arguments
of the {@code target} as well as the resulting adapter.
{@code B}/{@code b}, the types and values of the additional parameters and arguments
of the {@code filter} as well as appended to the resulting adapter.
...

-------------

PR: https://git.openjdk.java.net/panama-foreign/pull/179


More information about the panama-dev mailing list