Ability to extend a MemorySegment
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Tue Jan 21 17:31:22 UTC 2020
I cooked up this test:
public class TestUnionAccess {
static final GroupLayout union = MemoryLayout.ofUnion(
MemoryLayouts.JAVA_BYTE.withName("one"),
MemoryLayouts.JAVA_LONG.withName("two"),
MemoryLayouts.JAVA_INT.withName("three"));
static final VarHandle unionHandle =
MemoryLayouts.JAVA_LONG.varHandle(long.class);
static final VarHandle fieldHandle = union.varHandle(long.class,
MemoryLayout.PathElement.groupElement("two"));
@Test
public void testUnionHandles() {
try (MemorySegment segment = MemorySegment.allocateNative(union)) {
fieldHandle.set(segment.baseAddress(), Long.MAX_VALUE);
assertEquals((long)unionHandle.get(segment.baseAddress()), Long.MAX_VALUE);
assertEquals((long)fieldHandle.get(segment.baseAddress()), Long.MAX_VALUE);
unionHandle.set(segment.baseAddress(), Long.MIN_VALUE);
assertEquals((long)unionHandle.get(segment.baseAddress()), Long.MIN_VALUE);
assertEquals((long)fieldHandle.get(segment.baseAddress()), Long.MIN_VALUE);
fieldHandle.set(segment.baseAddress(), Long.MAX_VALUE);
assertEquals((long)unionHandle.get(segment.baseAddress()), Long.MAX_VALUE);
assertEquals((long)fieldHandle.get(segment.baseAddress()), Long.MAX_VALUE);
}
}
@Test
public void testUnionSlices() {
try (MemorySegment segment = MemorySegment.allocateNative(union)) {
MemoryAddress unionAddress = segment.baseAddress();
MemoryAddress fieldAddress = segment.asSlice(0,
union.memberLayouts().get(1).byteSize()).baseAddress();
fieldHandle.set(fieldAddress, Long.MAX_VALUE);
assertEquals((long)fieldHandle.get(unionAddress),
Long.MAX_VALUE);
assertEquals((long)fieldHandle.get(fieldAddress),
Long.MAX_VALUE);
fieldHandle.set(unionAddress, Long.MIN_VALUE);
assertEquals((long)fieldHandle.get(unionAddress),
Long.MIN_VALUE);
assertEquals((long)fieldHandle.get(fieldAddress),
Long.MIN_VALUE);
fieldHandle.set(fieldAddress, Long.MAX_VALUE);
assertEquals((long)fieldHandle.get(unionAddress),
Long.MAX_VALUE);
assertEquals((long)fieldHandle.get(fieldAddress),
Long.MAX_VALUE);
}
}
}
This passes without issues.
I took a look at your code - and I noticed an endianness mismatch
between NumberField and Union:
https://github.com/BlueGoliath/Crosspoint/blob/master/src/main/java/org/goliath/crosspoint/fields/NumberField.java#L29
vs.
https://github.com/BlueGoliath/Crosspoint/blob/master/src/main/java/org/goliath/crosspoint/unions/BasicUnion.java#L39
Could this be the issue?
Maurizio
On 21/01/2020 17:03, Ty Young wrote:
> Yes.
>
>
> Union<Long> union = Union.ofLayouts(MemoryLayouts.JAVA_BYTE,
> MemoryLayouts.JAVA_LONG, MemoryLayouts.JAVA_INT);
>
> Field<Long> field = union.getField(1);
>
> field.setValue(Long.MAX_VALUE);
>
> System.out.println(field.getValue()); // GOOD
>
> union.setValue(Long.MIN_VALUE);
>
> System.out.println(field.getValue()); // BAD
>
> field.setValue(Long.MAX_VALUE);
>
> System.out.println(union.getValue()); // BAD
>
> System.out.println(field.getValue()); // GOOD
>
>
> Union class can be found here:
> https://github.com/BlueGoliath/Crosspoint/blob/master/src/main/java/org/goliath/crosspoint/unions/BasicUnion.java
>
>
>
> On 1/21/20 10:39 AM, Maurizio Cimadamore wrote:
>> Not aware of anything deliberate here - do you have an example?
>>
>> Maurizio
>>
>> On 21/01/2020 16:31, Ty Young wrote:
>>> I've noticed some weirdness with Unions in Memory Access as well -
>>> creating a slice that is the exact size of the Union's
>>> MemoryAddress(long for example) and applying a value results in the
>>> Union's base MemoryAddress being made invalid(despite being the same
>>> size). Maybe that's intentional.
More information about the panama-dev
mailing list