RFR: 7903649: Field and global variables of array type should have indexed accessors
Maurizio Cimadamore
mcimadamore at openjdk.org
Mon Jan 29 17:40:51 UTC 2024
This PR adds support for indexed accessors for struct fields and global variables whose type is an array type. These accessors feature a number of `long` access coordinates which has the same cardinality as that of the underlying array type.
For instance, consider the following global variable declaration:
int ints[2][3][4];
For this, jextract now emits:
private static SequenceLayout ints$LAYOUT() {
class Holder {
static final SequenceLayout LAYOUT = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(3, MemoryLayout.sequenceLayout(4, foo_h.C_INT)));
}
return Holder.LAYOUT;
}
private static MemorySegment ints$SEGMENT() {
class Holder {
static final MemorySegment SEGMENT = foo_h.findOrThrow("ints")
.reinterpret(ints$LAYOUT().byteSize());
}
return Holder.SEGMENT;
}
/**
* Getter for variable:
* {@snippet lang=c :
* int ints[2][3][4]
* }
*/
public static MemorySegment ints() {
return ints$SEGMENT();
}
/**
* Setter for variable:
* {@snippet lang=c :
* int ints[2][3][4]
* }
*/
public static void ints(MemorySegment varValue) {
MemorySegment.copy(varValue, 0L, ints$SEGMENT(), 0L, ints$LAYOUT().byteSize());
}
private static VarHandle ints$ELEM_HANDLE() {
class Holder {
static final VarHandle HANDLE = ints$LAYOUT().varHandle(sequenceElement(), sequenceElement(), sequenceElement());
}
return Holder.HANDLE;
}
/**
* Indexed getter for variable:
* {@snippet lang=c :
* int ints[2][3][4]
* }
*/
public static int ints(long index0, long index1, long index2) {
return (int)ints$ELEM_HANDLE().get(ints$SEGMENT(), 0L, index0, index1, index2);
}
/**
* Indexed setter for variable:
* {@snippet lang=c :
* int ints[2][3][4]
* }
*/
public static void ints(long index0, long index1, long index2, int varValue) {
ints$ELEM_HANDLE().set(ints$SEGMENT(), 0L, index0, index1, index2, varValue);
}
If the array element type is a struct, different code needs to be generated. Consider this global variable declaration:
struct Point { int x; int y; } points[2][3][4];
This generates the following:
private static SequenceLayout points$LAYOUT() {
class Holder {
static final SequenceLayout LAYOUT = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(3, MemoryLayout.sequenceLayout(4, Point.layout())));
}
return Holder.LAYOUT;
}
private static MemorySegment points$SEGMENT() {
class Holder {
static final MemorySegment SEGMENT = foo_h.findOrThrow("points")
.reinterpret(points$LAYOUT().byteSize());
}
return Holder.SEGMENT;
}
/**
* Getter for variable:
* {@snippet lang=c :
* struct Point points[2][3][4]
* }
*/
public static MemorySegment points() {
return points$SEGMENT();
}
/**
* Setter for variable:
* {@snippet lang=c :
* struct Point points[2][3][4]
* }
*/
public static void points(MemorySegment varValue) {
MemorySegment.copy(varValue, 0L, points$SEGMENT(), 0L, points$LAYOUT().byteSize());
}
private static MethodHandle points$ELEM_HANDLE() {
class Holder {
static final MethodHandle HANDLE = points$LAYOUT().sliceHandle(sequenceElement(), sequenceElement(), sequenceElement());
}
return Holder.HANDLE;
}
/**
* Indexed getter for variable:
* {@snippet lang=c :
* struct Point points[2][3][4]
* }
*/
public static MemorySegment points(long index0, long index1, long index2) {
try {
return (MemorySegment)points$ELEM_HANDLE().invokeExact(points$SEGMENT(), 0L, index0, index1, index2);
} catch (Throwable ex$) {
throw new AssertionError("should not reach here", ex$);
}
}
/**
* Indexed setter for variable:
* {@snippet lang=c :
* struct Point points[2][3][4]
* }
*/
public static void points(long index0, long index1, long index2, MemorySegment varValue) {
MemorySegment.copy(varValue, 0L, points(index0, index1, index2), 0L, Point.layout().byteSize());
}
(note that bulk copy is used for the setter).
For struct fields, we generate similar code - the only difference is that the var/method handle for accessing the array element is declared in a plain field (instead of using the holder idiom), similarly to what happens with other struct declarations. Note also that, for structs, the indexed accessors must receive an additional `MemorySegment` parameter (the segment struct being accessed).
-------------
Commit messages:
- Initial push
Changes: https://git.openjdk.org/jextract/pull/198/files
Webrev: https://webrevs.openjdk.org/?repo=jextract&pr=198&range=00
Issue: https://bugs.openjdk.org/browse/CODETOOLS-7903649
Stats: 522 lines in 8 files changed: 502 ins; 9 del; 11 mod
Patch: https://git.openjdk.org/jextract/pull/198.diff
Fetch: git fetch https://git.openjdk.org/jextract.git pull/198/head:pull/198
PR: https://git.openjdk.org/jextract/pull/198
More information about the jextract-dev
mailing list