[foreign-memaccess] RFR 8223978: Add alignment support to layouts
Jorn Vernee
jbvernee at xs4all.nl
Thu May 16 12:02:08 UTC 2019
Looks good!
Jorn
Maurizio Cimadamore schreef op 2019-05-16 13:37:
> Here's new new webrev:
>
> http://cr.openjdk.java.net/~mcimadamore/panama/8223978_v2/
>
> I've changed implementation approach, and now added an OptionalLong to
> the AbstractLayout class. This way we can do almost everything in the
> superclass, and we can just rely on the already existing 'dup' feature
> (which we have to expand a bit) in order to produce a new layout with
> desired alignment.
>
> This is more regular, and automatcally handles thing such as covariant
> overrides.
>
> Maurizio
>
> On 16/05/2019 12:00, Maurizio Cimadamore wrote:
>>
>> On 16/05/2019 11:57, Jorn Vernee wrote:
>>>> I think you can still model that use case - essentially what you
>>>> want
>>>> is to just align everything to 8. (in fact that's what pragma
>>>> pack(1)
>>>> does).
>>>
>>> Ah, yes of course! My mistake.
>>>
>>> ---
>>>
>>> Btw, while testing this I also noticed that aligning e.g. a Group
>>> with alignTo() will return a Layout. I think we should use covariant
>>> return types here (and in the other Layout sub-types). Also, Address
>>> is missing on override for alignTo, so this will just return a Value.
>>
>> Whoops - good point.
>>
>> I also added a test with your 'pragma pack(1)' example. I'll spin a
>> new webrev shortly.
>>
>> Thanks
>> Maurizio
>>
>>>
>>> Thanks,
>>> Jorn
>>>
>>> [1] : https://docs.microsoft.com/en-us/cpp/cpp/align-cpp?view=vs-2019
>>>
>>> Maurizio Cimadamore schreef op 2019-05-16 12:25:
>>>> On 15/05/2019 21:07, Jorn Vernee wrote:
>>>>>> * you can align a layout using Layout::alignTo(long) - this sets
>>>>>> the
>>>>>> additional constraint (provided is power of two, non-negative, and
>>>>>> >=8)
>>>>>
>>>>> Why the power of two constraint? Shouldn't it just be a multiple of
>>>>> 8?
>>>>>
>>>>> This seems to preclude some packed structs, e.g. with elements with
>>>>> 3 byte alignment:
>>>>>
>>>>> #pragma pack(1)
>>>>>
>>>>> struct Foo {
>>>>> char x;
>>>>> short y; // 1 byte alignment
>>>>> int z; // 3 byte alignment
>>>>> }; // size = 7 bytes
>>>>>
>>>>> In the layout API this is:
>>>>>
>>>>> Value vChar = Value.ofSignedInt(8);
>>>>> Value vShort = Value.ofSignedInt(16);
>>>>> Value vInt = Value.ofSignedInt(32);
>>>>> Group g = Group.struct(vChar, vShort.alignTo(8),
>>>>> vInt.alignTo(24));
>>>>>
>>>>> But this throws an IAE because alignment of 24 is not allowed.
>>>>
>>>> I think you can still model that use case - essentially what you
>>>> want
>>>> is to just align everything to 8. (in fact that's what pragma
>>>> pack(1)
>>>> does).
>>>>
>>>> I don't think there's such a thing as 3-byte aligned memory access:
>>>> if
>>>> you want to read 4 bytes on a 3-byte aligned address, that's just
>>>> unaligned read.
>>>>
>>>> In other words, nothing new here - we're kind of following what the
>>>> pragma pack allows you to do: the argument to pragma pack must also
>>>> be
>>>> a power of 2 (1, 2, 4, 8 ...), see here [1, 2] - the only difference
>>>> in the Panama API is that everything has to be multiplied by 8,
>>>> because alignment (as sizes) are expressed in bits, to have more
>>>> room
>>>> to add sub-byte alignment (bit-fields, etc.) later on.
>>>>
>>>> So, back to your example:
>>>>
>>>> Value vChar = Value.ofSignedInt(8);
>>>> Value vShort = Value.ofSignedInt(16);
>>>> Value vInt = Value.ofSignedInt(32);
>>>> Group g = Group.struct(vChar.alignTo(8), vShort.alignTo(8),
>>>> vInt.alignTo(8));
>>>>
>>>> Maurizio
>>>>
>>>> [1] -
>>>> https://docs.microsoft.com/en-us/cpp/preprocessor/pack?view=vs-2019
>>>> [2] -
>>>> https://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Structure_002dPacking-Pragmas.html
>>>>>
>>>>> Jorn
>>>>>
>>>>> Maurizio Cimadamore schreef op 2019-05-15 19:57:
>>>>>> Hi,
>>>>>> this patch adds support to the API to express alignment
>>>>>> constraints on
>>>>>> layouts. Following the model John put forward in [1], I did the
>>>>>> following:
>>>>>>
>>>>>> * there's a way to compute the 'natural alignment' of a layout
>>>>>>
>>>>>> * if no alignment is specified, alignment is the natural alignment
>>>>>>
>>>>>> * you can align a layout using Layout::alignTo(long) - this sets
>>>>>> the
>>>>>> additional constraint (provided is power of two, non-negative, and
>>>>>> >=8)
>>>>>>
>>>>>> * When we obtain a VarHandle out of a Layout, at that point we are
>>>>>> in
>>>>>> the process of computing offsets; here we can catch e.g. if the
>>>>>> offset
>>>>>> of a given path doesn't match the specified alignment - in this
>>>>>> case
>>>>>> we fail fast, even before memory is accessed; this occurs e.g. if
>>>>>> the
>>>>>> layout path offset is not a multiple of its alignment, or if the
>>>>>> alignment of the nested element is stricter than the one of the
>>>>>> enclosing element.
>>>>>>
>>>>>> (in principle we could enforce these checks on layout creation,
>>>>>> but
>>>>>> given we have unresolved layouts in our radar, I think it's best
>>>>>> to do
>>>>>> minimal checks on layout creation and let the check fully kick in
>>>>>> on
>>>>>> path creation).
>>>>>>
>>>>>> * If VarHandle can be constructed, a dynamic check verifies that
>>>>>> alignment of address passed to VH matches the layout requirements
>>>>>>
>>>>>> * MemoryScope::allocate also honors the alignment requirements -
>>>>>> this
>>>>>> works by up-allocating memory (to make sure a pointer with desired
>>>>>> alignment exists in the allocated area) and then adjusting it
>>>>>> after
>>>>>> the fact. For alignments < 16bytes, nothing is done given that
>>>>>> malloc,
>>>>>> at least on x64 is guaranteed to respect that.
>>>>>>
>>>>>>
>>>>>> I think this is powerful and yet relatively simple to understand,
>>>>>> overall I quite like it.
>>>>>>
>>>>>> Webrev:
>>>>>> http://cr.openjdk.java.net/~mcimadamore/panama/8223978/
>>>>>>
>>>>>> Maurizio
More information about the panama-dev
mailing list