[foreign] RFR 8210223:Merge marshalling code paths in NativeInvoker and UpcallHandler

Sundararajan Athijegannathan sundararajan.athijegannathan at oracle.com
Thu Aug 30 15:38:15 UTC 2018


Hi,

I built/tested the patch on Mac - all 41 tests including the mac 
specific "python test" pass.

-Sundar

On 30/08/18, 8:03 PM, Maurizio Cimadamore wrote:
> Hi,
> as I'm working on a couple of biggie patches which touch the way in 
> which native invocation is performed, I thought it was better to start 
> with a cleanup which brings UpcallHandler and NativeInvoker much 
> closer together. The current code has a big issue: the native 
> invocation logic and the upcall logic use different pieces of code to 
> handle marshalling of Java values to and from register/stack.
>
> While it's true that, in principle, we need to specify the 
> marshalling/unmarshalling logic in a single place and then reuse the 
> same code from both places, doing so proved to be quite challenging:
>
> * first, there's a natural arity mismatch - for instance, 
> NativeInvoker needs to convert N Java values into M register/stack 
> words; but UpcallHandler needs to do so only to convert back the Java 
> return value. The reverse is true when we consider the opposite 
> translation - that is, UpcallHandler needs to read N Java values from 
> M registers, while NativeInvoker only needs to do that for the return 
> value.
>
> * then, there's the issue of return values passed in memory; this 
> introduce an asymmetry in the way we perform the 
> marshalling/unmarshalling logic, as for return in memory value, we 
> just need to copy/read the entire contents of the arg (typically a 
> struct) to/from a memory region pointed to by a pointer (this pointer 
> is stored in the first integer register)
>
> * finally, the fact that callbacks lead to stub generation at 
> invocation time, makes the logic even more convoluted (I will get rid 
> of this asymmetry in an upcoming patch)
>
> The idea is to use the following two functions
>
> void unboxValue(Object o, LayoutType<?> type, 
> java.util.function.Function<ArgumentBinding, Pointer<?>> dstPtrFunc, 
> List<ArgumentBinding> bindings)
>
> boxValue(LayoutType<?> type, 
> java.util.function.Function<ArgumentBinding, Pointer<?>> srcPtrFunc, 
> List<ArgumentBinding> bindings)
>
> Where the first converts a Java value into a bunch of register/stack 
> words, while the latter does the opposite, and turns a bunch of 
> register/stack words back into a Java value (in reality the signatures 
> are more complex than that, because of the callback issue mentioned 
> above).
>
> To specify the list of register/stack words to write/read to/from, we 
> use a list of ArgumentBinding instances - which are generated by the 
> CallingSequence. Doing the conversion one Java value at a time is a 
> lot more natural and simper to manage, and get rid of issues with the 
> previous code where we had to buffer intermediate results across 
> multiple reads.
>
> The function from binding to pointer allows the logic to remain 
> general: the code doesn't know how to read/write into the 
> register/stack words, so it just assumes there's some function mapping 
> a given binding back to a good old pointer (which can then be used to 
> read/write). This gives us the generality we need, and allows to share 
> the code between UpcallHandler and NativeInvoker.
>
> Finally, since this logic deals, as mentioned before, with one 
> argument at a time, we need a way to collect all ArgumentBinding 
> instances for a given argument. For this reason, I had to do some 
> surgery into CallingSequence (see new classifyBindings method), in 
> order to pre-compute the set of argument bindings associated to each 
> argument/return. This allow us to get the set of bindings for argument 
> at index I, which are then typically passed to the 'boxValue' routine. 
> There's also some offset pre-computation, so that, given a binding, we 
> know exactly where, in the long[] used by the NativeInvoker call 
> scheme, we have to store the resulting word.
>
>
> I've added a smoke test for structs passed/return by value, which 
> covers both the in-register and in-memory schemes. This use case was 
> not covered in our unit tests (but was covered by the clang-ffi test), 
> so I thought it would be better to have an explicit test for that.
>
> Please, test against anything you've got - the changes in here are 
> quite subtle - the more the merrier :-)
>
> Webrev:
>
> http://cr.openjdk.java.net/~mcimadamore/panama/8210223/
>
> Cheers
> Maurizio
>
>
>


More information about the panama-dev mailing list