[foreign-memaccess] Simplifying memory access var handles

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Tue Jun 23 10:38:29 UTC 2020


As I was exploring the consequences of the latest API moves, I realized 
that, perhaps, our VarHandle story is too complex, and not in sync with 
the lower energy equilibrium of the new API configuration. I think this 
is pretty clear if you look at how the behavior of the static accessors 
is specified in my experimental branch - let’s take for instance the 
Java int accessor:

|This is equivalent to the following code: VarHandle handle = 
MemoryHandles.withStride(JAVA_INT.withBitAlignment(8).varHandle(int.class), 
1L); int value = (int)handle.get(addr, offset); |

It feels odd that, to get to such a low-level, primitive accessor, we 
have to jump through all these hops - e.g. crate a basic VH with given 
carrier and alignment, then using the stride combinator, setting the 
stride at 1, so that the offset taken as input is interpreted as a plain 
byte offset.

So, an idea occurred to me: what if the basic VH /was/ a VH that took a 
byte offset?

E.g.

|MemoryHandles.varHandle(int.class) -> VH(MemortSegment, long) -> int |

This feels like a good move, as a VH such as this one certainly does 
feel primitive - we can express all the other handles on top of it (with 
VH adaptations).

One of the questions posed by such an approach is: what do we do with 
the existing MemoryHandles.withStride/withOffset combinators? If we go 
for this approach I think the most sensible thing would be to just drop 
them: after all, accessing at an offset is simply binding a long into 
the basic VH; and adding a stride can also be easily achieved with 
coordinate filtering. Also, the layout API would do all this stuff for 
free, so it’s not like users will have to write complex combinator code: 
this actually plays to the strengths of the APIs we already have: use 
the layout info we captured in the API to construct complex, structured 
access.

The advantages are many:

  * there are less ways to do the same things - e.g. if you want
    structured access, you really need a layout now
  * we can drop all the VarHandle code generation support - the
    (MemorySegment, long) coordinate pair is general enough that we can
    derive anything from it, using just plain combination (this also
    means, likley, less startup cost)
  * since the offsets are expressed in longs, we no longer have the
    issue we had in the past where we had to adapt a MemoryAddress
    coordinate (e.g. by adding an offset to it) which was very expensive
    - in other words, adaptation can be made as fast as the current code
  * we no longer need to differentiate between “memory access var
    handle” and “regular var handles” and do different tricks depending
    on that

So I think, overall, the advantages of this approach are many - and 
there are no disadvantages I can see. It’s again one of those moves that 
goes towards regularizing the API and make it more tight, by moving 
around functionalities and simplifying the underlying impl, but w/o 
impacting usability much.

Maurizio

​


More information about the panama-dev mailing list