RFC: Refactoring SystemABI

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Fri Nov 23 16:53:36 UTC 2018


For the records, I took the liberty to put together a patch which 
illustrates how we can get rid of dependencies on receiver object. The 
patch is based on current tip, and does not include other SystemABI 
changes (from Henry) - so that the actual differences will be more visible.

With this, UpcallHandler doesn't have much of an API. The only two 
methods used from outside are getNativeEntryPoint() [called immediately 
after creation] and free(). If, as discussed we move free() in 
SystemABI, then we can model upcalls with just a Pointer<?>. Cool!

http://cr.openjdk.java.net/~mcimadamore/panama/upcall-recv-removal/

(I had to comment a bunch of lines in a test that was checking for == 
equality on functional interface objects)

Maurizio

On 23/11/2018 12:19, Maurizio Cimadamore wrote:
> (as also observed by Jorn), Pulling even more on this string, I think 
> we can drop receiver object from the getUpcallHandle method alltogether.
>
> The current API looks like this:
>
> UpcallHandle upcallStub(Object receiver, MethodHandle target, 
> NativeMethodType nmt);
>
> I think we can simplify to this:
>
> UpcallHandle upcallStub(MethodHandle target, NativeMethodType nmt);
>
>
> In fact, the method already takes a MethodHandle - so we could require 
> clients to pass in a 'bound' method handle, where the receiver object 
> has already been 'attached' to the target MH. This will also make the 
> SystemABI more flexible too, because, while in the case of the binder 
> there is _always_ a receiver object (the receiver is an instance of a 
> functional interface obtained from some lambda expression passed to 
> the Scope::allocateCallback), in general this need not be the case - 
> and one could envision cases where clients would want a callback to 
> point to some static method with the right signature.
>
> So, I think handling the receiver on the binder side (by binding it to 
> the MH) is the right thing to do.
>
> So, with all the simplifications discussed in this thread, the API 
> would become:
>
> Pointer<?> upcallStub(MethodHandle target, NativeMethodType nmt);
>
> That is, gone is the UpcallHandle abstraction.
>
> Additionally, we will have to add a new method to SystemABI:
>
> void freeUpcallStub(Pointer<?>)
>
> Which is used by Scope::close.
>
>
> As mentioned in an earlier message, the downcall logic in SystemABI 
> will have to special case the case where a stub entry point is passed. 
> In such cases, the ABI will recover the method handle associated with 
> the stub (we currently do so by saving a Java object in the stub 
> itself - but other ways are possible too, e.g. global hashmap), and 
> return the (already bound) method handle, which will already feature 
> the right signature.
>
>
> This will eliminate code paths duplication in CallbackImplGenerator 
> and also CallbackImpl - where currently we do different things 
> depending on whether the underlying pointer is a stub.
>
> I think this looks good?
>
> Maurizio
>
>
> On 23/11/2018 02:06, Maurizio Cimadamore wrote:
>>
>> On 23/11/2018 01:47, Maurizio Cimadamore wrote:
>>> What is it that bothers you about this approach? 
>>
>> Let me clarify - I like that you are thinking of ways to reduce the 
>> surface of the API - but it seems that moving a method (getReceiver) 
>> from UpcallHandle to SystemABI doesn't buy all that much.
>>
>> I personally prefer having a simple UpcallHandle lookup method in the 
>> ABI, and then a way to get form the Handle to the receiver as it 
>> seems more composable this way. Right now, true, we always need to do 
>> both things at the same time (to speed up things in the upcall 
>> machinery), but maybe having a 'are you a stub' predicate will turn 
>> out handy even on its own (in case the user wants to write some 
>> pointer-walking code).
>>
>> But, if we really wanted to save some API estate, I think a better 
>> approach (if viable) would be to completely hide the stub detection 
>> logic. As you said very clearly yourself, we have this issue:
>>
>> "There is a shortcut being taken when native code gives us a Pointer 
>> back to one of our upcall stubs, and we want to call it from Java. In 
>> that case we don't really need to call into native, to call our own 
>> upcall stub to then call back into Java to call our target method."
>>
>> This is the reason behind the 'isStub/getReceiver' logic. But let's 
>> analyze this use case more in detail: we have a pointer to function, 
>> and we want to do a downcall using that pointer as the entry point. 
>> But this means that, in order to do the downcall, we will call 
>> SystemABI.downcallHandle (again). So, I think it is theoretically 
>> possible that the ABI would say: "hey, I know this guy!" and instead 
>> of giving you a MethodHandle that 'goes down' it gives you a 
>> MethodHandle that stays in Java-land. And the binder would not even 
>> know.
>>
>> If my conjecture is correct, then we just need your minimal 
>> UpcallHandle interface (pointer + free) and no 
>> getReceiver/getFunctorObject at all. And, if you pull on this some 
>> more, you realize that UpcallHandle is not even needed: just use a 
>> Pointer, and add a 'freeUpcallHandle(Pointer<?>)' to the SystemABI. 
>> That'd be sweet.
>>
>> Thoughts?
>>
>> Maurizio
>>


More information about the panama-dev mailing list