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

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Thu Aug 30 14:33:01 UTC 2018


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