RFR: Fix incorrect base offset handling in generated array field accessors
Maurizio Cimadamore
mcimadamore at openjdk.org
Wed Nov 12 10:51:43 UTC 2025
On Fri, 7 Nov 2025 01:15:32 GMT, devjeonghwan <duke at openjdk.org> wrote:
> #### 1. Status Quo
>
> Array field accessors generated by jextract (e.g., for `int arr[3]`) currently use a fixed base offset `0L` in `VarHandle.get/set` or `MethodHandle.invokeExact`.
> This causes all array accesses to start from the beginning of the struct, ignoring the field’s actual offset.
>
> #### 2. Problem
>
> Because of the missing base offset, writing to array elements in nested structs or unions can overwrite unrelated fields in the same structure.
> For example, updating `maxBlockDimension[1]` could corrupt `computeCapabilityMajor` or other preceding fields.
>
> typedef struct CudaDeviceInfo_st
> {
> int id;
>
> int computeCapabilityMajor;
> int computeCapabilityMinor;
> int multiprocessorCount;
>
> int warpSize;
> int maxThreadsPerBlock;
> int maxThreadsPerMultiprocessor;
> int maxBlockDimension[3];
> int maxGridDimension[3];
>
> bool unifiedAddressing;
> bool integratedMemory;
> } CudaDeviceInfo;
>
>
> #### 3. Fix
>
> This patch updates `emitFieldArrayGetter` and `emitFieldArraySetter` to pass the correct field offset (`offsetField`) to all generated array accessors.
> This ensures correct addressing for both primitive and struct/union element arrays.
>
> **Example:**
>
>
> // Before
> varHandle.get(struct, 0L, index);
>
> // After
> varHandle.get(struct, fieldOffset, index);
>
>
> #### 4. Additional Notes
>
> While the more idiomatic FFM approach of generating 'path-based' `VarHandle`s (e.g., `LAYOUT.varHandle(groupElement(...), ...)`) was considered, this patch takes a minimal-change approach. So It retains the existing handle and fixes the bug by passing the `fieldOffset` as the base offset (replacing `0L`).
>
> If the path-based `VarHandle` approach is preferred, I can rework this.
>
> #### 5. Testing
>
> New test cases were added to verify correct offset handling for:
>
> * Primitive arrays in structs
> * Struct arrays in structs
> * Struct arrays inside unions
>
> All tests pass locally.
Good fix, and well spotted! This bug probably sneaked in when we passed from path-based var handles to using offsets.
Marked as reviewed by mcimadamore (Reviewer).
test/jtreg/generator/testStructArrayFields/TestStructArrayFields.java line 125:
> 123: assertTrue(offTail < offFlag);
> 124:
> 125: assertEquals(3L * Integer.BYTES, Record_st.arr$layout().byteSize());
Maybe better to use C_INT * 3 here?
-------------
PR Review: https://git.openjdk.org/jextract/pull/294#pullrequestreview-3452824766
PR Review: https://git.openjdk.org/jextract/pull/294#pullrequestreview-3452829281
PR Review Comment: https://git.openjdk.org/jextract/pull/294#discussion_r2517820621
More information about the jextract-dev
mailing list