[foreign] RFR - abi cleanup

Jorn Vernee jbvernee at xs4all.nl
Wed Apr 17 21:05:01 UTC 2019

Most of what SystemABI does currently, e.g. selecting which invoker to 
use, and choosing argument boxing/unboxing logic is geared towards a 
specific calling convention. So lumping together calling convention and 
SystemABI seems like a logical move. But, maybe the name 'SystemABI' 
isn't so great, since it's practically an implementation of a calling 
convention. We could also rename SystemABI to CallingConvention.


Maurizio Cimadamore schreef op 2019-04-17 22:08:
> On 17/04/2019 21:02, Henry Jen wrote:
>> Overall looks good, I think it’s a good improvement.
>> I am less keen for the rename of StandardCall to 
>> CallingSequenceBuilderImpl. Each implementation of 
>> CallingSequenceBuilder is a calling convention, thus I prefer to have 
>> named after specific calling convention rather than a generic name. 
>> Although we don’t support other calling conventions and not seeing 
>> much evidence of the needs yet.
> I take your point - I'd say less change names when we'll actually need
> to have multiple builders in the same ABI. As we discussed at some
> point, we could also expose different calling convention as separate
> ABIs and remove the calling convention business entirely; this is a
> bit of an unorthodox approach, but it's a lumping move that gives a
> lot of flexibility.
> Maurizio
>> Cheers,
>> Henry
>>> On Apr 17, 2019, at 10:11 AM, Maurizio Cimadamore 
>>> <maurizio.cimadamore at oracle.com> wrote:
>>> (Apologies for the lack of jbs issue, jbs seems to be down at the 
>>> moment)
>>> In the past few days I've been looking hard at ways to simplify the 
>>> ABI code. This was something we needed to look at, after the Windows 
>>> integration, which introduced a lot of duplicated code (and that was 
>>> a deliberate choice, in order to minimize complexity). I think time 
>>> has come to look at the impl again. I've consolidated the following 
>>> areas:
>>> * CallingSequence/CallingSequenceBuilder - now CallingSequenceBuilder 
>>> is a proper abstract class, which is ABI agnostic, and can be used by 
>>> a client to put together a calling sequence, given a 'Function'. This 
>>> is perhaps the part of the code that has changed the most. Note that 
>>> I've removed the split between Argument (ABI-independent) and 
>>> ArgumentInfo (ABI-dependent); now ArgumentInfo *is a* Argument, which 
>>> simplifies the builder flow significantly.
>>> * Another area that has changed a lot is the logic for putting 
>>> together ShuffleRecipe - there's now a new (and much simpler) 
>>> builder. Again, the code removes many indirection, and it also fixes 
>>> some of the issues in the old code, where, essentially, the recipe 
>>> builder depended on physical details such as vector register size. 
>>> One part that has changed a lot here is that I realized that many 
>>> aspects of building a recipe were being done in different places - 
>>> for instance, CallingSequenceBuilder added explicit 'skip' bindings 
>>> to support shuffle recipe (but same skips were not generated for 
>>> other argument classes). ShuffleRecipeCollector also added its own 
>>> steps (through the addPulls method), and so did the logic that 
>>> computed the final recipe array (which added a lot of 'STOP' steps). 
>>> Now the steps are all computed before hand in  ShuffleRecipe::make, 
>>> passed onto the builder which then puts together the array.
>>> * CalingSequence has been simplified and all the logic for computing 
>>> offsets have been moved to ShuffleRecipe, since this is where it 
>>> really belongs (after all, you need this offset info only if you want 
>>> to play with UniversalInvoker).
>>> * UniversalNativeInvokerImpl and UniversalUpcallHandlerImpl are gone. 
>>> Instead there's an helper interface called UniversalAdapter which 
>>> defines how arguments are boxed/unboxed. The specific ABI will 
>>> provide concrete implementation for these.
>>> * VarargsInvoker has also changed - we used to intercept a vararg 
>>> call, specialize everything then call ABI again to obtain another MH 
>>> and then use that. The new code gives up on all that; whenever 
>>> there's a variadic call, we infer layouts and carriers, create a new 
>>> calling sequence and then just dispatch the call through a fresh 
>>> UniversalInvoker instead. Some benchmarks I did with snprintf shows a 
>>> speedup up to 3x with the new approach (also thanks to the 
>>> streamlining of the logic surrounding the calling sequence creation). 
>>> This new technique allowed me to also ditch the various 'impl' 
>>> classes for VarargsInvoker.
>>> * I removed the unused ShuffleRecipeFieldHelper, too
>>> * I added a new test for 'unaligned' structs being passed as 
>>> arguments. That is, I realized we never stressed the code path which 
>>> took into account a mismatch between the alignment of an argument 
>>> passed on the stack; the shuffle recipe should add one or more SKIP 
>>> steps if extra padding is needed. Now, since layouts generated by 
>>> jextract are really derived from clang, clang already inserts all the 
>>> right amount of padding, so that, basically, the size of a layout is 
>>> always a multiple of the layout natural alignment. To exercise this 
>>> path I had to resort to manual layout annotations, use a `long 
>>> double` (which unfortunately makes the test SysV dependent) to have 
>>> an alignment of 16 and then omitted padding at the end, so that the 
>>> ABI would run into troubles.
>>> The end result of the cleanup is pleasing - to implement a new ABI, 
>>> only two classes need to be tinkered with:
>>> 1) you need to implement the SystemABI interface (of course!)
>>> 2) you need to provide an implementation for CallingSequenceBuilder
>>> Everything else should work (at least using the universal adapters).
>>> Webrev:
>>> http://cr.openjdk.java.net/~mcimadamore/panama/abi-cleanup/
>>> I tested on all platforms and results are all green.
>>> Cheers
>>> Maurizio

More information about the panama-dev mailing list