[foreign] RFR 8218153: Read/Write of Value layout should honor declared endianness
John Rose
john.r.rose at oracle.com
Sat Feb 2 22:02:09 UTC 2019
On Feb 2, 2019, at 7:24 AM, Maurizio Cimadamore <maurizio.cimadamore at oracle.com> wrote:
>
> I'm wondering what's the meaning of 'calling a function with different endianness' - I thought endianess had to do with mismatches between in-memory representation and in-register representation. When you extract a 'long' from memory, you need to know if the layout is LE or BE because, depending on your platform, you might need byte swap. But when you pass the same 'long' to a function, the long is already in a register (thanks to the VM) and you are probably copying it into another register, or on the stack - but as is. In other words, I guess I don't see how endianness would come to play in function calls. I know that, in our annotations, we allow endianness to be specified, but I'm not sure it makes sense talk about passing parameter to functions using a different endiannes?
That's my take also. Endian-ness is a parameter that applies when moving bytes
out of memory into registers larger than a byte, and vice versa. Once a value
is loaded into a register, there is little or no benefit to keeping the byte structure.
In a register there is a bit structure which is useful, and that can play a role in
addressing bitfields such as C defines. Basically, when you load into a register,
you leave the bytes behind and work with bits instead; any residual need to
talk about bytes is handled by talking about bit positions and bit-level layout,
with offsets and sizes that are multiples of 8.
The distinction between container and memory layout is an important one,
and we don't need to rederive it. Let's make use of it, as fully and carefully
documented in section 15 in this document:
http://cr.openjdk.java.net/~jrose/panama/minimal-ldl.html#c
This also is why memory layouts are not always an exact match for function
arguments and returns. When a function argument or return is passed in
a register, byte order is irrelevant. If we use memory layouts in a punning
way to also express containers, I see three options for dealing with the
byte order in them:
1. have a portable convention (LE)
2. have a local convention (PE = BE or LE according to context)
3. make byte order a partial query, return sentinel value NE (no endian polarity)
4. make byte order a partial query, throw an exception when queried
I prefer 3 or 4, when dealing with containers. Any dependency
on byte order in a register is a probable bug, especially in case
2 (sorry, Henry, I disagree with your solution) where the dependency
is on a value which can change depending on where the VM is run.
FTR, the "Minimal LDL" document uses solution 1, but it also holds
back, a little, from using memory layouts as function arguments and
returns. If we are going to overload memory layouts as register
descriptions, 3 or 4 is a better move than 1.
— John
More information about the panama-dev
mailing list