Consider the following class:
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryHandles;
import jdk.incubator.foreign.MemoryLayout;
import jdk.incubator.foreign.MemoryLayouts;
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.SequenceLayout;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
public class PanamaPoint implements AutoCloseable {
private static final SequenceLayout LAYOUT = MemoryLayout.ofSequence(MemoryLayout.ofStruct(
MemoryLayouts.JAVA_INT.withOrder(ByteOrder.nativeOrder()).withName("x"),
MemoryLayouts.JAVA_INT.withOrder(ByteOrder.nativeOrder()).withName("y")));
private static final VarHandle VH_x = LAYOUT.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("x"));
private static final VarHandle VH_y = LAYOUT.varHandle(int.class, MemoryLayout.PathElement.sequenceElement(), MemoryLayout.PathElement.groupElement("y"));
private final MemorySegment segment;
private final MemoryAddress base;
public PanamaPoint(int size) {
this.segment = MemorySegment.allocateNative(LAYOUT.elementLayout().byteSize() * size);
this.base = segment.baseAddress();
}
public void setX(int x, int pos) {
VH_x.set(base, (long)pos, x);
}
public int getX(int pos) {
return (int) VH_x.get(base, (long)pos);
}
public void setY(int y, int pos) {
VH_y.set(base, (long)pos, y);
}
public int getY(int pos) {
return (int) VH_y.get(base, (long)pos);
}
@Override
public void close() {
segment.close();
}
}
And the following benchmark:
@Benchmark
public int panama_get() throws Throwable {
int res = 0;
for (int i = 0 ; i < SIZE ; i++) {
res+= panamaPoint.getX(i);
}
return res;
}
Despite the segment being accessed stays the same across the entire loop, a quick look at the generated code reveals that no hoisting is taking place - that is, upon every access we pay full cost for ownership checks, liveness check, bounds check, alignment check, read only check.