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

Reply via email to