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