-
CSR
-
Resolution: Approved
-
P3
-
None
-
behavioral
-
minimal
-
This is a new method, as such it doesn't affect existing clients.
-
Java API
-
SE
Summary
Introduce a new var handle factory on MemoryLayout
to obtain a strided var handle, useful to access segments modelling variable-length arrays.
Problem
Memory layouts work best when describing the layout of a region of memory whose size is known statically. There are cases, however, where the size of a region of memory is only known dynamically. This is the case, for instance, for segments modelling variable-length arrays.
There are two cases where variable-length array come up: * a toplevel variable-length array, whose size is determined by an unrelated variable and/or parameter; * a variable-length array nested in a struct (in C, this is done using a feature called "Flexible Array Members").
Let's say we have a struct described by the following layout:
StructLayout POINT = MemoryLayout.ofStruct(
JAVA_INT.withName("x"),
JAVA_INT.withName("y"));
And let's also assume we have a segment that contains some points, but that the size of the segment is not known statically:
int size = ...
MemorySegment points = Arena.ofAuto().allocate(POINT, size);
How does a client obtain a var handle that can be used to access the "x" coordinate of all the points in the array?
There are currently two approaches, neither of which is particularly straightforward. First, a client could wrap the POINT
layout in a sequence layout of maximal size. This layout is then used to derive an indexed var handle:
VarHandle POINT_X = MemoryLayout.sequenceLayout(Long.MAX_VALUE/POINT.byteSize(), POINT)
.varHandle(PathElement.sequenceElement(), PathElement.groupElement("x"));
This feels suboptimal: clients have to create a throwaway layout, just so that they can select a path from it. This layout is also dangerous: if used anywhere else (e.g. to allocate a new segment) it will likely cause exceptions to be thrown, due to its size.
Alternatively, clients can use var handle combinators, to obtain a var handle which features an extra index coordinate. This is done by collecting the offset coordinate using the result of the scaleHandle
method handle:
VarHandle POINT_X = MethodHandles.collectCoordinates(POINT.varHandle(PathElement.groupElement("x")), 1, scaleHandle());
While this is more elegant, it requires the use of var handle combinators, which is a rather advanced capability. As a result, there's no satisfying solution for accessing elements in a variable-length array using var handles and layouts.
Solution
The solution is to add a new method in MemoryLayout
, namely MemoryLayout::arrayElementVarHandle
. As the name implies, the var handle returned by this factory will accept an additional index parameter which can be used to stride over all the elements of a variable-length array. This method is implemented using var handle combinators (see above).
Given this new methods, clients can now access the points
memory segment as follows:
VarHandle POINT_X = POINT.arrayElementVarHandle(PathElement.groupElement("x"));
for (long i = 0 ; i < size ; i++) {
... POINT_X.get(points, 0L /* base offset */, /* index */ i);
}
Specification
- csr of
-
JDK-8318538 Add a way to obtain a strided var handle from a layout
-
- Resolved
-