[foreign] RFR 8210757: Add binder support for direct native invocation strategy

Jorn Vernee jbvernee at xs4all.nl
Sat Sep 15 00:04:58 UTC 2018

Maurizio Cimadamore schreef op 2018-09-14 20:04:
> Hi,
> as mentioned in [1], this patch adds binder support for the so called
> 'direct' invocation scheme, which allows for greater native invocation
> downcall/upcall performances by means of specialized adapters. The
> core idea, also described in [1], is to define adapters of the kind:
> invokeNative_V_DDDDD
> invokeNative_V_JDDDD
> invokeNative_V_JJDDD
> invokeNative_V_JJJDD
> invokeNative_V_JJJJD
> invokeNative_V_JJJJJ
> Where long arguments come before double arguments (and do this for
> each arity e.g. <=5).
> If all arguments are passed in register, then this reordering doesn't
> affect behavior, and greatly limits the number of permutations to be
> supported/generated.

On windows the story seems to be more difficult then I initially 
thought. On SysV, if you have a C function like this:

void f(long l, double d);

`l` will be passed in the first integer register, and `d` will be passed 
in the first float/vector register. But on windows, `d` will be passed 
in the **second** float/vector register, and if there was a another 
integer argument it would be passed in the third integer register [1]. 
This becomes worse with varargs, which requires floats to be passed in 
both the integer and float/vector registers.

So I don't think reordering parameters will work on windows, since the 
parameter index dictates which register it uses. However, you should be 
able to still use the downcall-with-shuffling strategy (though I don't 
have that working yet for mixed argument classes).

> The downcall part (java to native) is relative straightforward: the
> directNativeInvoker.cpp file defines a bunch of native entry points,
> one per shape, which cast the input address to a function pointer of
> the desired shape, and then call it:
> jlong NI_invokeNative_J_JD(JNIEnv *env, jobject _unused, jlong addr,
> jlong arg0, jdouble arg1) {
>     return ((jlong (*)(jlong, jdouble))addr)(arg0, arg1);
> }

As an optimization here, I think you should make the function address 
the last argument, since that prevents having to shuffle the other 
arguments between registers before calling the function [2]

> * we need to setup a framework in which new invocation strategies can
> be plugged in - note that we now have essentially 4 cases:
> { NativeInvoker, UpcallHandler } x { Universal, Direct }
> When the code wants e.g. a NativeInvoker, it asks for one to the
> NativeInvoker::of factory (UpcallHandler work in a similar way); this
> factory will attempt to go down the fast path - if an error occurs
> when computing the fast path, the call will fallback to the universal
> (slow) path.

This sounds like a great idea!


[1] : 
[2] : https://godbolt.org/z/JjPJca

More information about the panama-dev mailing list