[foreign-abi] On invokers
Jorn Vernee
jorn.vernee at oracle.com
Mon Sep 23 12:32:08 UTC 2019
Here is a webrev version of the changes as well:
http://cr.openjdk.java.net/~jvernee/prog-back/webrev.00/
Jorn
On 23/09/2019 13:43, Jorn Vernee wrote:
> Hi,
>
> I've been looking into the current set of invokers we have on the
> foreign-abi branch for the past few weeks. There is still work to be
> done in this area, both in terms of performance, and in terms of
> programmability. In this email I will focus on the latter.
>
> The UniversalNativeInvoker (UNI) API is currently the most programmble
> invoker that we have, so if we want to increase the programmability of
> our backend to cover more and more ABIs, this seems like a good place
> to start. UNI goes a ways in being programmable with the
> CallingSequence, ShuffleRecipe and ArgumentBinding APIs, being able to
> select in which registers to pass values, but there are still some
> aspects that could be polished:
>
> 1.) If you look into the VM code that processes the shuffle recipe,
> you'll notice that the eventual argument buffer that's being fed to
> the stub has a fixed set of registers it can work with on a given
> platform [1], namely the ones that are used by the C ABI. This works
> when we have only one ABI (C), but for different ABIs we'd probably
> want a different set of registers. We can change the stub generation
> code to take an 'ABIDescriptor' from which we derive the stub and
> argument buffer layout instead. This will also provide a place to put
> other ABI details that need to be customized, like stack alignment,
> and argument shadow space (Windows), as well as a set of volatile
> registers, which will be a super set of the argument registers. We
> would end up generating 1 generic downcall stub for each ABI. Also,
> note that we would need to create architecture definitions on the Java
> side to be able to specify the ABIDescriptors there (since ABIs are
> defined in terms of architecture).
>
> 2.) There is a need to pass meta arguments to a function sometimes.
> For instance, we need to pass in a pointer to a return buffer for
> in-memory-returns, and e.g. on SysV we need to pass in the number of
> float arguments in RAX (or rather AL) for variadic functions. The
> former is handled automatically by CallingSequenceBuilder, and the
> latter is hard-coded in the VM code. Since these are both ABI details,
> I believe they should be handled by the ABI implementations. Ideally
> we'd have an invoker API that let's us say: "add a Java argument with
> this carrier type, and this MemoryLayout, and then shuffle it into
> this register.", and then the ABI implementation can handle the
> further adaptation from the ABI-level signature (e.g. an additional
> MemoryAddress passed in as first argument), to the C-level signature
> (allocate a buffer as first argument and also return it). This is
> mostly a refactoring move in UNI::invoke and CallingSequenceBuilder
> that removes the handling for in memory returns, and replaces it with
> a more general way of passing those kinds of arguments.
>
> 3.) The unboxing/boxing is currently handled by calling into the
> various ABI implementations. We can make this code shared by extending
> the current ArgumentBinding 'recipe' to include other operations,
> besides moving from a pointer to a register, that cover the things
> that are currently handled by the ABI boxing/unboxing implementations.
> The various CallingSequenceBuilder implementations can then specify
> these additional binding operations when generating bindings. This
> means that we only need one shared piece of code that interprets this
> 'binding recipe'. The other advantage of doing this is that we would
> eventually be able to use these binding recipes + ABIDescriptor to
> generate a specialized stub for a particular call site.
>
> 4.) We are currently shuffling the arguments for a down call into a
> long[], and then in the VM we shuffle the arguments from the long[]
> into an argument buffer (ShuffleDowncallContext). We can merge these
> steps together, by directly shuffling the arguments into an argument
> buffer on the Java side (since we have an off-heap API). This
> decreases the overall complexity of the invoker implementation
> significantly, since we can drop all the code relating to shuffle
> recipes.
>
> I've been experimenting with these ideas, and have a prototype for
> downcalls on Windows [2]. For this I copied the relevant UNI classes
> to a separate `programmable` package and made the relevant changes
> there, since some of the code was shared with UniversalUpcallHandler.
> I've also preemptively removed the old UNI code (for x86) to show
> roughly how much code would be removed by switching to the new invoker
> API. I want to continue the experiment for upcalls as well, after
> which more old code could be removed; namely Argument,
> ArgumentBinding, CallingSequence (old), CallingSeqeunceBuilder (old),
> Storage, StorageClass, SharedUtils (mostly) and UniversalAdapter.
>
> How do these ideas sound? I'm mostly interested if this is flexible
> enough to support AArch64 and SysV. After the upcall support, I can
> look into porting the other 2 ABIs as well.
>
> Thanks,
> Jorn
>
> [1] :
> https://github.com/openjdk/panama/blob/foreign-abi/src/hotspot/cpu/x86/universalNativeInvoker_x86.cpp#L73
> [2] :
> https://github.com/openjdk/panama/compare/foreign-abi...JornVernee:prog-back-no-old
>
More information about the panama-dev
mailing list