[foreign-memaccess] RFR: Add unsigned adapter handles

Chris Hegarty chegar at openjdk.java.net
Sat May 16 08:33:18 UTC 2020


As part of feedback on the Foreign Memory API (when experimenting with its usage internally in the JDK), a small number
of potential usability enhancements could be made to the API. This is the third such.

This change proposes to add a new method:

When dealing with _unsigned_ native data types it is often convenient to model them as
wider _signed_ Java primitives (with appropriate magnitude checks). For example, it is convenient to model an _unsigned
short_ as a Java _int_ to avoid dealing with negative values, which would be the case if modeled as a Java short. We do
this all the time in the JDK implementation, and it even bleeds into the APIs sometimes.

To model this, I found myself reaching for `MemoryHandles::filterValue` to do the narrowing and widening, so that my
layout class could expose the set of memory handles with appropriate carrier types that the higher-level java code was
expecting. This worked fine, but Maurizio pointed out that this is something that the API should probably expose at a
slightly higher level. Writing these widening and narrowing adapters using _filterValue_ is not a lot of code, but easy
to make mistakes and a place for bugs to hide.

A single static adapter factory, `MemoryHandles::asUnsigned(VarHandle target, Class<?> adaptedType)`, (thanks Maurizio
for the suggestion) would be sufficient to provide such functionality. It adapts a target var handle by narrowing
incoming values and widening outgoing values, to and from the given type, respectively. When calling _set_ on the
resulting var handle, the incoming value (of type adaptedType) is converted by a narrowing primitive conversion and
then passed to the target var handle. Conversely, when calling _get_ on the resulting var handle, the returned value
obtained from the target var handle is converted by an unsigned widening conversion before being returned to the caller.

We don't necessarily need to, or can, support all combinations, but there seems to be a sweet spot where Java longs and
ints can be used to model _unsigned char_, _unsigned short_, and _unsigned int_, [1] which covers the majority of the
use-cases. This also seems to align nicely with the primitive wrapper unsigned widening methods, e.g.
`Byte::toUnsignedInt`, `Byte::toUnsignedLong`, etc.

I started this discussion as a PR so that hopefully the code changes can help convey the idea and inform readers.

Comments welcome.

[1] https://cr.openjdk.java.net/~chegar/foreign/asUnsigned.pdf


Commit messages:
 - Merge branch 'unsigned-adapters' of https://github.com/ChrisHegarty/panama-foreign into unsigned-adapters
 - test cleanup and spec fix
 - test cleanup
 - Merge branch 'foreign-memaccess' into unsigned-adapters
 - template the adapter classes
 - Merge branch 'foreign-memaccess' into unsigned-adapters
 - more asUnsigned changes
 - unsigned-adapters partial udpate
 - Initial MemoryHandles::asUnsigned prototype

Changes: https://git.openjdk.java.net/panama-foreign/pull/173/files
 Webrev: https://webrevs.openjdk.java.net/panama-foreign/173/webrev.00
  Stats: 490 lines in 7 files changed: 490 ins; 0 del; 0 mod
  Patch: https://git.openjdk.java.net/panama-foreign/pull/173.diff
  Fetch: git fetch https://git.openjdk.java.net/panama-foreign pull/173/head:pull/173

PR: https://git.openjdk.java.net/panama-foreign/pull/173

More information about the panama-dev mailing list