Making FMA more flexible

Jorn Vernee jorn.vernee at oracle.com
Wed Apr 29 19:39:28 UTC 2020


     public void callback(NativeObject... args);

...

     this.type = MethodType.methodType(void.class, MemoryAddress[].class);

It looks like you have a mismatch between the type you are looking up, 
and the declared type of the method. Would expect the latter to be 
this.type = MethodType.methodType(void.class, NativeObject[].class);

After getting that MethodHandle, you will have to adapt it so that it 
takes only the supported carrier types (primitives + MemoryAddress + 
MemorySegment). How to do this will depend on what you want, but you 
will probably need a combination of MethodHandles::collectArguments [1], 
MethodHandles::filterArguments [2], and MethodHandle::asCollector [3].

Note that upcalls don't currently support varargs, so the MethodHandle 
you pass to SystemABI.upcallStub will have to have an exact type/arity, 
for instance (MemoryAddress, MemoryAddress)void.

For instance, let's say you have a convert method that can convert from 
a MemoryAddress[] to a NativeObject[]:

     public static NativeObject[] convert(MemoryAddress[] ma) {
         return null;
     }

you could do something like:

     MethodHandles.Lookup lookup = lookup();
     MethodHandle MH_callback = lookup.findVirtual(NativeCallback.class, 
"callback", MethodType.methodType(void.class, NativeObject[].class));
     MethodHandle MH_convert = lookup.findStatic(Converters.class, 
"convert", MethodType.methodType(NativeObject[].class, 
MemoryAddress[].class));

     NativeCallback nc = na -> {// the target callback instance
         // ...
     };
     MethodHandle mh = MH_callback.bindTo(nc); // bind the MH to the 
particular instance

     mh = MethodHandles.filterArguments(mh, 0, MH_convert); // 'filter' 
the first argument using the 'convert' method
     mh = mh.asCollector(MemoryAddress[].class, 2); // takes 2 
MemoryAddresses
     System.out.println(mh); // prints 
'MethodHandle(MemoryAddress,MemoryAddress)void'

HTH

Jorn

[1] : 
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/invoke/MethodHandles.html#collectArguments(java.lang.invoke.MethodHandle,int,java.lang.invoke.MethodHandle)
[2] : 
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/invoke/MethodHandles.html#filterArguments(java.lang.invoke.MethodHandle,int,java.lang.invoke.MethodHandle...)
[3] : 
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/invoke/MethodHandle.html#asCollector(java.lang.Class,int)

On 29/04/2020 19:58, Ty Young wrote:
>
> On 4/29/20 12:36 PM, Maurizio Cimadamore wrote:
>>
>> On 29/04/2020 18:22, Ty Young wrote:
>>>
>>> On 4/29/20 11:37 AM, Maurizio Cimadamore wrote:
>>>
>>>
>>> *snip*
>>>
>>>
>>>> The function descriptor has to be passed to SystemABI to create the 
>>>> handle in the first place. At this (low) level, just primitive 
>>>> types, segments and addresses.
>>>>
>>>> *after* you get the method handle, you can adapt and obtain a new 
>>>> (higher-level) handle.
>>>
>>>
>>> Thanks.
>>>
>>>
>>> Question: does MethodHandle have the ability to reference a 
>>> yet-to-be-implemented method as a MethodHandle? I'm trying to use an 
>>> abstract class to handle the business logic and just have individual 
>>> classes implement(via extends) the "callback" method, but it fails, 
>>> saying it can't be found. Is there a specific code path that needs 
>>> to be taken?
>>
>> You should be able to create a method handle out of an 
>> abstract/interface method, which will do the right thing on dispatch.
>>
>> Perhaps paste some code or pointers and maybe I'll be able to point 
>> you in the right direction.
>
>
> Right, just wanted to make sure there wasn't a specific method I 
> needed for it.
>
>
> Interface:
>
>
> public interface NativeCallback extends NativeObject
> {
>     public void callback(NativeObject... args);
> }
>
>
> public abstract class AbstractNativeCallback implements NativeCallback
> {
>     private final MethodType type;
>     private final MethodHandle handle;
>     private final FunctionDescriptor descriptor;
>     private final MemoryAddress address;
>
>     public AbstractNativeCallback() throws NoSuchMethodException, 
> IllegalAccessException
>     {
>         this.type = MethodType.methodType(void.class, 
> MemoryAddress[].class);
>         this.handle = 
> MethodHandles.lookup().findVirtual(NativeCallback.class, "callback", 
> type);
>
>         MemoryLayout[] classes = new 
> MemoryLayout[this.handle.type().parameterCount()-1];
>
>         for(int i = 1; i < this.handle.type().parameterCount()-1; i++)
>             classes[i] = 
> PlatformTypeLayouts.convert(this.handle.type().parameterType(i));
>
>         this.descriptor = FunctionDescriptor.ofVoid(classes);
>
>         this.address = 
> SystemABI.getSystemABI().upcallStub(this.handle, this.descriptor);
>     }
>
>     @Override
>     public MemoryAddress getAddress()
>     {
>         return this.address;
>     }
>
> }
>
>
> My issue here I guess is that the actual method's MethodType is 
> different than what FMA will allow(MemoryAddress). Am I using the 
> wrong Lookup method?
>
>
>>
>> Maurizio
>>
>>>
>>>
>>>>
>>>> Maurizio
>>>>


More information about the panama-dev mailing list