I try to update java version from 22 to 23. We work with off-heap memory:
val intVh = MemoryLayout
.sequenceLayout(
Long.MaxValue / ValueLayout.JAVA_INT.byteSize(),
ValueLayout.JAVA_INT,
)
.varHandle(PathElement.sequenceElement())
@IntrinsicCandidate
@inline
def set[R <: Global](mem: Memory[L, R], value: Int, x1: Int)(
implicit
region: Region[R],
): Unit = {
intVh.set(mem.asJava, vh.offset0 + vh.step1 * x1 + vh.offset1, 0L, value)
}
That is main code.
When i change version from 22 to 23, i get this:
Assertion failed:
Exception in thread "zio-fiber-71,58,53" java.lang.IndexOutOfBoundsException: Out of bound access on segment MemorySegment{ address: 0x60000228f000, byteSize: 40 }; new offset = 0; new length = 9223372036854775804
at java.base/jdk.internal.foreign.AbstractMemorySegmentImpl.outOfBoundException(AbstractMemorySegmentImpl.java:439)
at java.base/jdk.internal.foreign.AbstractMemorySegmentImpl.apply(AbstractMemorySegmentImpl.java:420)
at java.base/jdk.internal.foreign.AbstractMemorySegmentImpl.apply(AbstractMemorySegmentImpl.java:70)
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:98)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:124)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:448)
at java.base/jdk.internal.foreign.AbstractMemorySegmentImpl.checkBounds(AbstractMemorySegmentImpl.java:409)
at java.base/jdk.internal.foreign.AbstractMemorySegmentImpl.checkAccess(AbstractMemorySegmentImpl.java:369)
at java.base/jdk.internal.foreign.LayoutPath.checkEnclosingLayout(LayoutPath.java:288)
at alien.memory.handle.MemoryHandle$Int1Ops$.set$extension(MemoryHandle.generated.scala:13808)
at scandex.db.segments.constructors.impl.v1.values.fixed.Int32ValueLookupSegmentBuilder.set(Int32ValueLookupSegmentBuilder.scala:23)
at scandex.db.segments.constructors.impl.v1.values.fixed.Int32ValueLookupSegmentBuilder$.$anonfun$assemble$1(Int32ValueLookupSegmentBuilder.scala:46)
at scandex.db.segments.constructors.impl.v1.values.fixed.Int32ValueLookupSegmentBuilder$.$anonfun$assemble$1$adapted(Int32ValueLookupSegmentBuilder.scala:46)
at scandex.db.segments.constructors.ValueLookupSegmentAssembler.$anonfun$impl$1(ValueLookupSegmentAssembler.scala:20)
at scandex.db.segments.constructors.ValueLookupSegmentAssembler.$anonfun$impl$1$adapted(ValueLookupSegmentAssembler.scala:19)
at scala.collection.IterableOnceOps.foldLeft(IterableOnce.scala:727)
at scala.collection.IterableOnceOps.foldLeft$(IterableOnce.scala:721)
at scala.collection.SortedMapOps$KeySortedSet.foldLeft(SortedMap.scala:134)
at scandex.db.segments.constructors.ValueLookupSegmentAssembler.impl(ValueLookupSegmentAssembler.scala:19)
at scandex.db.segments.constructors.ValueLookupSegmentAssembler.impl$(ValueLookupSegmentAssembler.scala:18)
at scandex.db.segments.constructors.impl.v1.values.fixed.Int32ValueLookupSegmentBuilder$.impl(Int32ValueLookupSegmentBuilder.scala:35)
at scandex.db.segments.constructors.impl.v1.values.fixed.Int32ValueLookupSegmentBuilder$.assemble(Int32ValueLookupSegmentBuilder.scala:46)
at scandex.db.segments.constructors.impl.v1.values.fixed.Int32ValueLookupSegmentBuilder$.assemble(Int32ValueLookupSegmentBuilder.scala:35)
at scandex.builder.segment.primary.PrimaryIdxBuilderImpl.build(PrimaryIdxBuilderImpl.scala:57)
at scandex.builder.index.BuildingPKImpl.build(BuildingPKImpl.scala:68)
at scandex.builder.db.State$$anon$1.$anonfun$apply$1(State.scala:47)
at zio.ZIOCompanionVersionSpecific.$anonfun$attempt$1(ZIOCompanionVersionSpecific.scala:100)
at zio.ZIO$.$anonfun$suspendSucceed$1(ZIO.scala:4850)
at scandex.builder.db.State.buildPkTask.$anon.apply(State.scala:46)
at scandex.builder.db.State.build(State.scala:130)
at vs.runtime.db.SampleDB.database(SampleDB.scala:52)
at vs.runtime.db.ScandexInterpreterSpec.live(ScandexInterpreterSpec.scala:29)
at vs.runtime.db.ScandexInterpreterSpec.live(ScandexInterpreterSpec.scala:27)
at vs.runtime.db.ScandexInterpreterSpec.spec(ScandexInterpreterSpec.scala:4
This exception is result of test. But this test works for java 22, but not for java 23.
Also, if i change this code to:
mem
.asJava
.set(
ValueLayout.JAVA_INT,
vh.offset0 + vh.step1 * x1 + vh.offset1,
value,
)
the test is successful with 22 and 23 java.
I assume that something has changed in java 23, but I can't figure out what I should fix.
P.S
mem.asJava - just memory segment
vh.offset0 + vh.step1 * x1 + vh.offset1 - just offset from 0 to 10
In Java 23, when accessing a memory segment using a var handle that was created from a memory layout (like is the case in your example), there is a check to see that the memory layout fits inside the memory segment being accessed. This is described in the javadoc of the varHandle
method:
The access operation must fall inside the spatial bounds of the accessed memory segment, or an IndexOutOfBoundsException is thrown. This is the case when B + A <= S, where B is the base offset (defined above), A is the size of this layout and S is the size of the accessed memory segment. Note that the size of this layout might be bigger than the size of the accessed layout (e.g. when accessing a struct member).
In your case 'this layout' is the sequence layout you've created, which evidently does not fit into the accessed memory segment.
Likely the simplest way to fix this is to do what you've done: use MemorySegment::set
. If you still need a VarHandle
that can be used to access an array of unknown size, you should switch to using arrayElementVarHandle
:
val intVh = ValueLayout.JAVA_INT.arrayElementVarHandle();
Although, in your particular example code, you are always accessing the first element (passing 0L
as the index). So, you should be able to also just use ValueLayout.JAVA_INT.varHandle()
, and then when accessing, just pass the base offset for the access:
intVh.set(mem.asJava, vh.offset0 + vh.step1 * x1 + vh.offset1, value)