Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8318539

Add a way to obtain a strided var handle from a layout

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • 22
    • core-libs
    • None
    • behavioral
    • minimal
    • This is a new method, as such it doesn't affect existing clients.
    • Java API
    • SE

      Summary

      Introduce a new var handle factory on MemoryLayout to obtain a strided var handle, useful to access segments modelling variable-length arrays.

      Problem

      Memory layouts work best when describing the layout of a region of memory whose size is known statically. There are cases, however, where the size of a region of memory is only known dynamically. This is the case, for instance, for segments modelling variable-length arrays.

      There are two cases where variable-length array come up: * a toplevel variable-length array, whose size is determined by an unrelated variable and/or parameter; * a variable-length array nested in a struct (in C, this is done using a feature called "Flexible Array Members").

      Let's say we have a struct described by the following layout:

      StructLayout POINT = MemoryLayout.ofStruct(
           JAVA_INT.withName("x"),
           JAVA_INT.withName("y"));

      And let's also assume we have a segment that contains some points, but that the size of the segment is not known statically:

      int size = ...
      MemorySegment points = Arena.ofAuto().allocate(POINT, size);

      How does a client obtain a var handle that can be used to access the "x" coordinate of all the points in the array?

      There are currently two approaches, neither of which is particularly straightforward. First, a client could wrap the POINT layout in a sequence layout of maximal size. This layout is then used to derive an indexed var handle:

      VarHandle POINT_X = MemoryLayout.sequenceLayout(Long.MAX_VALUE/POINT.byteSize(), POINT)
                                      .varHandle(PathElement.sequenceElement(), PathElement.groupElement("x"));

      This feels suboptimal: clients have to create a throwaway layout, just so that they can select a path from it. This layout is also dangerous: if used anywhere else (e.g. to allocate a new segment) it will likely cause exceptions to be thrown, due to its size.

      Alternatively, clients can use var handle combinators, to obtain a var handle which features an extra index coordinate. This is done by collecting the offset coordinate using the result of the scaleHandle method handle:

      VarHandle POINT_X = MethodHandles.collectCoordinates(POINT.varHandle(PathElement.groupElement("x")), 1, scaleHandle());

      While this is more elegant, it requires the use of var handle combinators, which is a rather advanced capability. As a result, there's no satisfying solution for accessing elements in a variable-length array using var handles and layouts.

      Solution

      The solution is to add a new method in MemoryLayout, namely MemoryLayout::arrayElementVarHandle. As the name implies, the var handle returned by this factory will accept an additional index parameter which can be used to stride over all the elements of a variable-length array. This method is implemented using var handle combinators (see above).

      Given this new methods, clients can now access the points memory segment as follows:

      VarHandle POINT_X = POINT.arrayElementVarHandle(PathElement.groupElement("x"));
      for (long i = 0 ; i < size ; i++) {
          ... POINT_X.get(points, 0L /* base offset */, /* index */ i);
      }

      Specification

            mcimadamore Maurizio Cimadamore
            mcimadamore Maurizio Cimadamore
            Jorn Vernee
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: