[foreign-memaccess] RFR 8237648: Add support for var handle adaptation
Paul Sandoz
paul.sandoz at oracle.com
Thu Jan 23 01:49:21 UTC 2020
It’s also possible to create a throwing method handle with:
public static MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType) {
But I think that is still amenable to the scanning approach you suggest (look for the named function throwException and the method type arg to see if a checked exception).
It would be nice if any method handle could be structurally introspected with a public API. Instead we can traverse the LFs.
Paul.
> On Jan 22, 2020, at 3:59 PM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>
> Thinking more about this... it wouldn't be prohibitive to check for the validity of the method handles passed to the adapter methods.
>
> After all... the only method handles which can throw checked exceptions are the direct ones. And for a direct MH, we can crack it and see if it throws.
>
> All the bound method handles cannot introduce _new_ checked exceptions - but can of course propagate some of the checked exceptions thrown by some of the underlying target MHs.
>
> But, given a bound MH, we can always look a its bound arguments and do a recursive scan, to find any MH that is both 'direct' and 'throwy'.
>
> So, it seems there is a path to apply a validation and make sure no (checked) exceptions are thrown?
>
> Maurizio
>
> On 22/01/2020 21:16, Maurizio Cimadamore wrote:
>> Thanks for the feedback Paul,
>> what do you think on the topic of exceptions which Remi (correctly) brought up? VarHandle don't throw, but if you combine them with throwy MHs, they can start to throw...
>>
>> Maurizio
>>
>> On 22/01/2020 20:02, Paul Sandoz wrote:
>>> Hi,
>>>
>>> That’s really nice how this slotted into the existing infrastructure. Quite a powerful feature. I wondered when VHs were being developed whether we could and should do something like this but a strong enough use-case did not present itself at that time.
>>>
>>> There is this commented out class in VarHandles called GuardMethodGenerator that generates the VarHandleGuards source code. I try to keep that in sync with the actual code. I can update it afterwards.
>>>
>>>
>>> MethodHandles
>>> —
>>>
>>> 4957 public static VarHandle filterValue(VarHandle target, MethodHandle unbox, MethodHandle box) {
>>>
>>> The terms boxing and unboxing may be misleading in terms of the corresponding MHs functionality. I think they are dual mapping functions from domains S -> T and T -> S, as stated clearly in the documentation. Perhaps s/unbox/filterToTarget and s/filterFromTarget ?
>>>
>>>
>>>
>>> 5104 /**
>>> 5105 * Provides a var handle which adapts the coordinate values of the target var handle, by re-arranging them
>>> 5106 * so that the new coordinates match the provided ones. *
>>>
>>> Rogue “*” at end of line.
>>>
>>>
>>>
>>> 5225 public static VarHandle collectCoordinates(VarHandle target, int pos, MethodHandle filter) {
>>>
>>> When the filter returns void it drop coordinates. Is that useful? Are there cases were some coordinates would be redundant?
>>>
>>>
>>>
>>> 5244 private static List<Class<?>> coordinates(VarHandle handle) {
>>> 5245 return handle.accessModeType(VarHandle.AccessMode.GET).parameterList();
>>> 5246 }
>>>
>>>
>>> Usages of this method can be replaced with handle.coordinateTypes()
>>>
>>>
>>>
>>> I suspect to complete the set of combinators a useful addition is an expanding or spreading combinator e.g. taking a single coordinate type of say Index(x, y) and substituting with x and y. However, it's a little tricky with the existing MH functionality and I believe it requires filtering the composite coordinate into an array of its component values and then spreading the array elements to the separate target arguments. I am not confident that optimizes well, esp. for coordinates of different types.
>>>
>>> Paul.
>>>
>>>
>>>> On Jan 22, 2020, at 6:35 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>>>>
>>>> Hi,
>>>> this patch add support for some VarHandle adapters:
>>>>
>>>> http://cr.openjdk.java.net/~mcimadamore/panama/8237648/
>>>>
>>>> More specifically, the following adaptations are supported:
>>>>
>>>> * filterValue
>>>> * insertCoordinates
>>>> * filterCoordinates
>>>> * collectCoordinates
>>>> * permuteCoordinates
>>>>
>>>> This fixes an expressiveness mismatch between VarHandle and MethodHandles, as one could adapt MethodHandles, but cannot adapt VarHandles (the only way to do that is to map a VarHandle to a MethodHandle - using an AccessMode - and then use the MethodHandle).
>>>>
>>>> To achieve this, only minimal surgery to j.l.invoke classes was required: the basic idea is to introduce a new class of VarHandle, namely IndirectVarHandle, which is merely an aggregate of a bunch of method handles, one per supported access modes. This means that we have now the ability to take apart an existing var handle into its MH components, adapt such components and repackage them into a brand new VarHandle.
>>>>
>>>> To save unnecessary bytecode spinning, the component MethodHandles of an indirect VarHandle are only created on-demand - that is, if you only ever use the GET access mode - the machinery will not create the method handles for all the access modes which could be in principle be supported by the new var handle.
>>>>
>>>> Since adapting a VarHandle might introduce changes in some of the coordinate types, I've disabled the VarHandleGuards fastpath for indirect handles, as the fast path does an invokeBasic and it skips any kind of type adaptation. While invokeBasic will detect e.g. a long vs. int mismatch, it does not detect (by design) a String vs. Runnable mismatch, so it is preferrable for indirect handles to always have an asType() adaptation. If the client is doing things "by the books" and using exact types in the VarHandle call, the asType() will do nothing and performances will not be negatively affected.
>>>>
>>>> I also needed to tweak lambda form generation for var handles a bit, to obtain the direct var handle associated with an indirect handle before calling the linker method (otherwise we might end up the underlying VarHandle routine with the wrong VarHandle type).
>>>>
>>>> I think overall, this implementation strategy proved to be flexible and relatively efficient - we can easily add as many adapters as we want, since we can build on the already rich MethodHandle combinator API.
>>>>
>>>> Cheers
>>>> Maurizio
>>>>
>>>>
More information about the panama-dev
mailing list