Memory segment and unaligned access

Alexander Biryukov sanya.rnd at gmail.com
Mon Jun 13 13:06:24 UTC 2022


Hi, I'm testing MemorySegment and stumbled across some inconsistent
behavior in the API.

I have the following task:
* read binary file to RAM, file structure is fixed, but no
padding/alignment is present (lots of strings of variable length)
* read file content depending on the user input, e.g. sometimes I need to
read offset 13, sometimes offset 24 and so on
* Stored values are typically privitives (byte, long, double etc) or arrays
(byte[], short[], int[] and so on)
* Primitives are decoded on the fly to variables, same is true for arrays
(random access) or sometimes arrays are copied as a blob to another
MemorySegment

I'm trying to create a VarHandle for MemorySegment:

> @Test
> fun sample() {
>     val mem = MemorySegment.allocateNative(100,
> MemorySession.openImplicit())
>     val buf = ByteBuffer.allocateDirect(100).order(ByteOrder.LITTLE_ENDIAN)
>     buf.put(-20)        // 0
>     buf.putDouble(5.0)  // 1
>     buf.put(2)          // 9
>     buf.putInt(5)       // 10
>     buf.putInt(10)      // 14
>     buf.flip()
>     mem.copyFrom(MemorySegment.ofBuffer(buf))
>

>
    val mh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT)
>     val bh = MethodHandles.byteBufferViewVarHandle(IntArray::class.java,
> ByteOrder.LITTLE_ENDIAN)


>     println(mh.get(mem, 14L) as Int)               // <-- throws
> "Misaligned access at address"
>     println(bh.get(mem.asByteBuffer(), 14) as Int) // works, prints "10"
> }


The variant with memorySegmentViewVarHandle throws, while variant with
byteBufferViewVarHandle works.
I checked the source code and found that for some reason MemorySegment-variant
uses offsetNoVMAlignCheck, while ByteBuffer-variant doesn't.
Here's the code from the source:

ByteBuffer-variant

> return UNSAFE.getLongUnaligned(
>         ba,
>         ((long) index(ba, index)) + Unsafe.ARRAY_BYTE_BASE_OFFSET,
>         handle.be);
>

MemorySegment-variant

> return SCOPED_MEMORY_ACCESS.getIntUnaligned(bb.sessionImpl(),
>         bb.unsafeGetBase(),
>         offsetNoVMAlignCheck(bb, base, handle.alignmentMask),
>         handle.be);
>


I'm not sure, but it seems like  offsetNoVMAlignCheck shouldn't be present
or there must be an alternative API for querying unaligned data?
If nothing is wrong, is there a way to query data in MemorySegment without
alignment?
ByteBuffer is technically fine for the time being, but I'm expecting a high
load on the service, and since I'm not using ByteBuffers I'd rather not pay
for them (GC).


Best regards,
Alexander Biryukov


More information about the panama-dev mailing list