On Wed, 18 Oct 2023 20:08:26 GMT, Phil Race <p...@openjdk.org> wrote:
>> Requiring users to specify the size of the sequence layout was done in order >> to dispel the illusion that there was any kind of special handling for a >> sequence layout created without a size. e.g. if you try to allocate with it, >> what should happen? Should we detect that this as a special case? Or just >> crush with an OOME? This is something other users ran into in practice, and >> removing the size-less factory revealed some latent bugs in the tests as >> well. So, I feel that overall, dropping the size-less factory was the right >> move. This was more or less an orthogonal decision to the decision of adding >> the base offset parameter. >> >> The previous JDK 21 API asked users to construct layouts for memory of which >> they did not know the layout in advance. e.g. when creating a var handle >> from a sequence layout with the maximum number of elements, the in-memory >> array that is being accessed is likely not actually an array with the >> maximum number of elements? The special max element sequence layout is just >> a workaround used to be able to create an indexed var handle. >> >> Another example is a 2-dimensional matrix with a dynamic row and column >> size. How should this be represented using a memory layout? We can't use the >> max element sequence layout trick in that case, since the size of the inner >> sequence affects the scaling of the index for the outer sequence. >> >> The core issue is that, to get good performance, a user needs to construct >> the layout and derive var handles in advance, but at the same time it is not >> possible to represent a layout with a 'dynamic' size. We went back and forth >> on ideas in order to add better support for dynamic sizes in the layout API. >> But in the end, all the things we tried ended up being convoluted, and had >> their own set of corner cases that were ill-addressed. >> >> So, the conclusion we arrived at was that layouts are better left alone, and >> should only be used to represent memory layouts that are 'static'/fixed and >> known up front. In that case a user can declare the layout, and all the var >> handles they need, in advance, and stick them into `static final` fields, >> which is required to get good performance. >> >> But then the question becomes: what about structural access to memory whose >> layout can _not_ be represented statically? Even in those cases, often there >> is a part of the structure of the memory layout that is fixed, and part of >> the layout that is dynamic. The memory layout API can still be used for the >> fixed part, and then the extra bas... > > I feel like I'm starting to learn that once you've got your VarHandle from > FFM, you need to head over to java.lang.invoke and hunt around to see what > tricks you can do with it. > The less I have to do that the better. I wouldn't say it's necessarily required, but I would say that it is what ultimately leads to the most succinct code. I'm probably biased towards using the java.lang.invoke tricks though. The java.lang.invoke combinator API is a convenient way to generate wrapper functions around a VarHandle (or MethodHandle). But, you could also write out the wrapper functions manually. In this case that shouldn't be too much of a problem given that the code only uses `get`. You could declare basic field VarHandles created with `layout.varHandle(PathElement.groupElement(name));`, and then write the wrapper functions like so: public static int getYOffset(MemorySegment glyphPosArr, int index) { long posArrOffset = PositionLayout.scale(0, index); // or just: index * PositionLayout.byteSize() return (int) y_offsetHandle.get(glyphPosArr, posArrOffset); } You would need 6 of these in total. Or, just use the implementation 'inline', without the wrapper functions. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/15476#discussion_r1364697148