[foreign-abi] On invokers

Jorn Vernee jorn.vernee at oracle.com
Wed Oct 9 08:32:55 UTC 2019


Technically it seems possible, but I'd like the know the motivation for 
doing so? I guess you want to embed type classification information in 
MemoryLayout directly, Instead of storing a list of classes separately 
in ArgumentInfo?

Jorn

On 08/10/2019 16:08, Maurizio Cimadamore wrote:
> I was thinking... (unrelated from this)
>
> Can we make VMStorage a Constable? If we can, then we can attach them 
> directly to layouts as annotations? Currently we do that with 
> ArgumentClass; if VMStorage is too fine grained (it probably is), then 
> I suggest making the StorageClass under e.g. X86_64Architecture a 
> public enum, so that it becomes automatically constable, and can be 
> attached to layout annotations.
>
> Maurizio
>
>
> On 08/10/2019 12:40, Jorn Vernee wrote:
>> Here is an updated version that gets the build working on GCC: 
>> cr.openjdk.java.net/~jvernee/prog-back/webrev.03/
>>
>> This also fixes an encoding problem with some of the test files + 
>> adds missing copyright headers, and addresses some minor review 
>> comments given internally.
>>
>> Jorn
>>
>> On 03/10/2019 15:24, Maurizio Cimadamore wrote:
>>> Thanks Jorn,
>>> I plan to take a look at SysV in the next week or so.
>>>
>>> Maurizio
>>>
>>> On 03/10/2019 13:30, Jorn Vernee wrote:
>>>> Hi,
>>>>
>>>> I've finished the work for upcall support. Here is the patch: 
>>>> http://cr.openjdk.java.net/~jvernee/prog-back/webrev.02/
>>>>
>>>> This includes both the downcall support I did earlier and now also 
>>>> upcall support for Windows, and should give a good picture of the 
>>>> final state of things we want to get to. That is, have a single 
>>>> backend, so this removes the code for the other backends.
>>>>
>>>> I've also improved the testing for upcalls, by now saving each 
>>>> argument that is passed to the upcall into an array, and then 
>>>> checking that array against the input arguments at the end of the 
>>>> test (that is what the changes to TestUpcall.java are about). 
>>>> Sadly, the old CallingSequenceBuilderTests were not compatible with 
>>>> the new API, so I've removed them for now, but maybe we can bring 
>>>> these back again later on.
>>>>
>>>> The API is pretty much finalized. The only thing I foresee changing 
>>>> is the Binding IR, with things like different operators where they 
>>>> are needed to support new ABIs. So, now is a good time to start 
>>>> looking at porting to other ABIs.
>>>>
>>>> For x86 this is a little simpler since the support for that 
>>>> particular architecture is already there. The only thing that would 
>>>> have to be done is taking the old CallingSequenceBuilderImpl, and 
>>>> also have it generate the new type of Bindings, as well as handle 
>>>> in memory returns. A good example of the latter would be 
>>>> CallArranger::arrangeDowcall/arrangeUpcall in the new patch.
>>>>
>>>> For adding support for another architecture there are a few extra 
>>>> steps;
>>>> - Add an architecture descriptor, like X86_64Architecture.java 
>>>> does. This is basically a set of VMStorage constants that map the 
>>>> different registers defined in register_x86.hpp, as well as a set 
>>>> of integer constants defining the different storage types (see 
>>>> X86_64Architecture::StorageClasses).
>>>> - In foreign_globals_XXX.hpp/cpp add an architecture specific 
>>>> version of the Java ABIDescriptor/BufferLayout, and a way to 
>>>> translate from the Java version to the native version using JNI 
>>>> (see foreign_globals_x86.cpp/hpp).
>>>> - Change the stub generation code for upcalls and downcalls to use 
>>>> the registers and offsets defined by this 
>>>> ABIDescriptor/BufferLayout, instead of the ones defined globally 
>>>> for the C ABI (see 
>>>> universalNativeInvoker_x86.cpp/universalUpcallHandler_x86.cpp).
>>>>
>>>> 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