> On 11 Dec 2019, at 16:43, Paul Sandoz <[email protected]> wrote:
>
> Looks very good,
+1 This looks very good to me too. Nice work.
-Chris.
> Paul.
>
>> On Dec 11, 2019, at 7:39 AM, Maurizio Cimadamore
>> <[email protected]> wrote:
>>
>> I went ahead and created a new revision:
>>
>> http://cr.openjdk.java.net/~mcimadamore/panama/8234049_v6/
>> <http://cr.openjdk.java.net/~mcimadamore/panama/8234049_v6/>
>> Delta from latest (v5) here:
>>
>> http://cr.openjdk.java.net/~mcimadamore/panama/8234049_v6_delta/
>> <http://cr.openjdk.java.net/~mcimadamore/panama/8234049_v6_delta/>
>> No javadoc chnages here.
>>
>> Summary of changes:
>>
>> * addressed Paul feedback on MemoryScope
>> * on further testing, I found two issues on var handle construction from
>> layouts:
>> - PathElement.sequenceElement(long) does not add the sequence element
>> offset to the new path element offset
>> - the layout path machiner does not check that strides are a multiple of
>> alignment - this allow creation of 'bad' var handles which are guaranteed
>> not to work in for all indices - consider this layout:
>>
>> var seq = MemoryLayout.ofSequence(JAVA_SHORT.withBitAlignment(32));
>>
>> The above layout has an issue: the element requests 32-bit alignent, but the
>> elements are only 16 bits apart. So, for odd access indices, there will be
>> an alignment exception.
>>
>> If you create a VarHandle with combinators, strides are checked against
>> alignment, so it is not possible to obtain a VarHandle for the above layout.
>> But with the Layout API is possible, because the layout path machinery does
>> not enforce same restriction.
>>
>> I've now fixed the code in LayoutPath (most of the changes are due to a
>> rename from 'scale' to 'stride') to take care of this.
>>
>> Bonus point: since offsets must satisfy alignment, and all strides must also
>> satisfy same alignment - it follows that whetever offset can come out of the
>> VH index machinery, it will be aligned. This means that, in the VarHandle
>> code we can just check the base address. In other words, the memory location
>> accessed by the VarHandle will be something like (below N denotes alignment,
>> s1..sn are strides, O1..Om are offsets):
>>
>>
>>
>> address = base + offset
>>
>> where:
>>
>> offset = N * s1 * i1 + N * s2 * i2 ... + N * sn * in + N * O1 + N * O2 + ...
>> N * Om
>> = N * (s1 * i1 + s2 * i2 ... + sn * in + O1 + O2 + ... Om)
>> = N * K
>>
>>
>>
>> So, in order to show that the "address" is aligned, we only have to show
>> that "base" is a multiple of N. This helps a lot, as e.g. when looping
>> through a native array, the base array stays the same, and only the offset
>> part changes, which means C2 will have no troubles hoisting out the
>> alignment check out of the loop.
>>
>>
>> As things appear stable, I do not plan to make any other changes to the
>> implementation/API ahead of integration, unless there's something critical
>> which reviewers think should be fixed.
>>
>> Thanks
>> Maurizio
>>
>>
>>
>>
>> On 11/12/2019 00:13, Maurizio Cimadamore wrote:
>>>
>>> On 10/12/2019 18:45, Paul Sandoz wrote:
>>>> MemoryScope changes look good.
>>>>
>>>> In j.u.concurrent we use ExceptionInInitializerError in the static blocks
>>>> when there is an error looking up the VH,
>>>>
>>>> FWIW close can also fail because it has already been closed but the
>>>> exception message does not distinguish between the two states (active or
>>>> already closed).
>>>> Paul.
>>>>
>>> Hi Paul,
>>>
>>> would something like this be satisfactory?
>>>
>>>
>>> diff -r 50ef46599c56
>>> src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryScope.java
>>> ---
>>> a/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryScope.java
>>> Tue Dec 10 16:28:03 2019 +0000
>>> +++
>>> b/src/jdk.incubator.foreign/share/classes/jdk/internal/foreign/MemoryScope.java
>>> Wed Dec 11 00:12:20 2019 +0000
>>> @@ -48,7 +48,7 @@
>>> try {
>>> COUNT_HANDLE =
>>> MethodHandles.lookup().findVarHandle(MemoryScope.class, "activeCount",
>>> int.class);
>>> } catch (Throwable ex) {
>>> - throw new IllegalStateException(ex);
>>> + throw new ExceptionInInitializerError(ex);
>>> }
>>> }
>>>
>>> @@ -107,6 +107,9 @@
>>>
>>> void close() {
>>> if (!COUNT_HANDLE.compareAndSet(this, UNACQUIRED, CLOSED)) {
>>> + //first check if already closed...
>>> + checkAliveConfined();
>>> + //...if not, then we have acquired views that are still active
>>> throw new IllegalStateException("Cannot close a segment that
>>> has active acquired views");
>>> }
>>> if (cleanupAction != null) {
>>>
>>>
>>>
>>> If you need a full webrev please let me know.
>>>
>>> Thanks
>>> Maurizio
>>>
>