[foreign-memaccess] RFR 8228447: Remove kinds from value layouts

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Mon Jul 22 09:30:57 UTC 2019


On 19/07/2019 23:55, John Rose wrote:
> Good simplification.
>
> FTR, kinds were in some early versions of the layout design as explained here:
>    http://cr.openjdk.java.net/~jrose/panama/minimal-ldl.html#kann
>
> More background, FTR:
>
> The idea is that memory layouts, for small items, are loosely coupled to the machine registers into
> which they are loaded.  (After all, memory layouts are relatively useless unless their elements can
> be loaded *out* of memory *into* something else.)  So the float vs. int distinction is useful because
> many CPUs make a distinction between those kinds of registers.  The distinction becomes important
> when you spin code to load or store such elements.  In today’s APIs, that distinction is driven by
> (Java) carrier type, so it doesn’t need to be present in the layout.

One note - while I agree with most of what you say - and it's true that 
this design was already captured in your (great) LDL document, I think 
relying too much on carriers is a siren song. Yes, we could disambiguate 
float vs. int passed to a function looking at the carrier being used:

* long, int, short, byte -> integer register
* float, double -> SSE register

But we can't sadly, do much else. At least that's the conclusion I've 
reached when it comes to aggregates. Yes, we could have, in principle, 
different systems to communicate ABI info on different types - e.g. use 
carriers for scalar values, and use layouts for aggregates. But, if you 
go down that path, it still means that your layout must be able to 
capture the float vs. int distinction on its own (otherwise how do you 
classify struct { int x; } vs. struct { float f; } ?).

To solve this problem, there are two options: enhance the layouts with 
something like annotations - which is what I've described. Or we could 
enhance the carrier system to cover aggregates - e.g. 
StructWithOneInt.class - but if you look at the ABI (esp. SysV) there 
are so many combinations to pass small structs into registers that 
having one single carrier for each combination is just overkill. And, 
needless to say, such carrier would end up replicating some of the 
structural info already available in the layout.

So, to me, sprinkling kinds on top of layouts seems a more robust move 
going forward than having a (big) set of ABI-specific carriers to 
support recursive aggregate classification.

That's not to say we don't need new carriers - we need them, but I think 
we need them not for classification - but rather to be able to construct 
the values we wanna pass down to native functions. E.g. we need a vector 
carrier, or an x87, or a quad float carrier (or even an unsigned long 
one), unless we want to lower everything down to the carriers to know 
and love.

In terms of design of the invoker, this probably means that, when it 
comes to extend linkToNative to support more invocation modes, using a 
MemberName like parameter (like method handles do) is a preferrable 
approach than just using carriers. This extra parameter could embed 
relevant layout information about nested fields that could be useful to 
the ABI to (1) locate these fields into the MemorySegment and (2) pass 
them to the function accordingly.

Maurizio

>
> More distinctions can be made relative to the registers into which memory data are loaded, once
> you realize that “registers” don’t have to be actual physical hardware resources; a “virtual register”
> is really an optimizable container or named/numbered value outside of alias-able memory, something
> a VM or JIT can get a handle on without worrying about alias conditions, races, and mutability.
>
> A virtual register can have a size which differs from (is larger than) the memory element it contains.
> E.g. a memory byte can be loaded into a 64-bit register.  This immediately motivates a distinction
> between signed and unsigned ints, which are padded using distinct conventions (and loaded using
> distinct instructions on most platforms).  Vector registers are a different kind of container.  And bitwise
> images of structs are yet another kind of (virtual!) container.  Varargs conventions seem (to me) to
> introduce more container types as well, since their values are manipulated (by VMs and JITs)
> according to peculiar conditions discussed elsewhere.  Even machine pointers seem to be
> distinct enough from floats and ints to merit a kind, in some accounts, because they have their
> own conversion rules which may or may not be the same as sign or zero extension.
>
> I think all of these distinctions can be driven (and are now driven) from carrier types and other
> bits of API context.  But it’s useful, sometimes, to think of the as their own set of concepts,
> distinct from and decoupled (in principle) from API binding details.
>
> — John
>
>> On Jul 19, 2019, at 10:17 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>>
>> Hi,
>> this patch removes the Kind enum from ValueLayout - and consolidates the various ValueLayout factories even further:
>>
>> cr.openjdk.java.net/~mcimadamore/panama/8228447/
>>
>> (this is based on top of the patch for 8228444).
>>
>> I like how it simplifies the API, and removes the float/int/signed/unsigned from the equation which, as Jorn pointed out, wasn't  really used anywhere.
>>
>> Maurizio
>>


More information about the panama-dev mailing list