-
Enhancement
-
Resolution: Duplicate
-
P3
-
None
-
repo-panama
The MemoryLayout class provides two factories for sequence layouts - one which take a size and one which doesn't. The one that does not take a size, infers the size as the result of the division between Long.MAX_VALUE and the size of the element layout.
The main reason to have unsized sequence layout factory is that, in some cases, a client might have a struct layout FOO, and might need to work with an array of FOOs, whose size is not known statically. In such case, it is not possible to create a layout of the right size (since the size of the outer sequence is unknown). So the API allows to wrap the FOO layout in a sequence, so that it can then be dereferenced using a var handle which accepts a dynamic index. E.g.
MemoryLayout FOO = ...
VarHandle handle = MemoryLayout.sequenceLayout(FOO, PathElement.sequenceElement(), ...);
Unfortunately, operating in this mode can lead to issues, especially with users that are unfamiliar with the peculiar behavior of the unsized sequence layout factory. E.g. it might be tempting to do this:
SequenceLayout FOO_ARRAY = MemoryLayout.sequenceLayout(FOO);
But then, how would the user allocate with such a sequence layout?
They might be tempted to use:
allocator.allocateArray(FOO_ARRAY, 100);
But this does not what the user might expects (e.g. dynamically bind the size of the sequence to 100). Instead, this simply takes the layout of FOO_ARRAY (whose size is already Long.MAX_VALUE), and multiplies that by 100 - which overflows. So a runtime exception is thrown.
To make the situation clearer, there are two possible options:
* a simpler option would be to simply rename the unsized sequence layout factory as "unboundedSequenceLayout".
* a more complex option would be to double down on the idiom promoted by API points such as `allocateArray`, `spliterator`, `arrayElementVarHandle` which allow the client to pass an _element_ layout, and consider it part of some sequence of which the size is unknown.
If we had the latter, users could just define a layout for FOO and work from there:
MemoryLayout FOO = ...
VarHandle handle = FOO.arrayElementVarHandle(...);
Not only is this more concise, but it also avoids the confusion of forcing the client to go through a sequence layout of maximal size, which can then be problematic when interacting with the allocation API.
If we went down this path, I think the following changes would be necessary:
* tweak `arrayElementVarHandle` so that it applies to all layouts. This method currently also takes extra sequence sizes - which seems not very useful (after all, if the sizes are known, one could create sequence layouts for it). This method should also take an array of PathElement. One issue with this approach is that it might need to be replicated for other PathElement-accepting methods. Which might be too much.
* Add an overload to AddressLayout::withTargetLayout that allows a target layout to be specified as an "element" layout (e.g. withTargetElementLayout).
The main reason to have unsized sequence layout factory is that, in some cases, a client might have a struct layout FOO, and might need to work with an array of FOOs, whose size is not known statically. In such case, it is not possible to create a layout of the right size (since the size of the outer sequence is unknown). So the API allows to wrap the FOO layout in a sequence, so that it can then be dereferenced using a var handle which accepts a dynamic index. E.g.
MemoryLayout FOO = ...
VarHandle handle = MemoryLayout.sequenceLayout(FOO, PathElement.sequenceElement(), ...);
Unfortunately, operating in this mode can lead to issues, especially with users that are unfamiliar with the peculiar behavior of the unsized sequence layout factory. E.g. it might be tempting to do this:
SequenceLayout FOO_ARRAY = MemoryLayout.sequenceLayout(FOO);
But then, how would the user allocate with such a sequence layout?
They might be tempted to use:
allocator.allocateArray(FOO_ARRAY, 100);
But this does not what the user might expects (e.g. dynamically bind the size of the sequence to 100). Instead, this simply takes the layout of FOO_ARRAY (whose size is already Long.MAX_VALUE), and multiplies that by 100 - which overflows. So a runtime exception is thrown.
To make the situation clearer, there are two possible options:
* a simpler option would be to simply rename the unsized sequence layout factory as "unboundedSequenceLayout".
* a more complex option would be to double down on the idiom promoted by API points such as `allocateArray`, `spliterator`, `arrayElementVarHandle` which allow the client to pass an _element_ layout, and consider it part of some sequence of which the size is unknown.
If we had the latter, users could just define a layout for FOO and work from there:
MemoryLayout FOO = ...
VarHandle handle = FOO.arrayElementVarHandle(...);
Not only is this more concise, but it also avoids the confusion of forcing the client to go through a sequence layout of maximal size, which can then be problematic when interacting with the allocation API.
If we went down this path, I think the following changes would be necessary:
* tweak `arrayElementVarHandle` so that it applies to all layouts. This method currently also takes extra sequence sizes - which seems not very useful (after all, if the sizes are known, one could create sequence layouts for it). This method should also take an array of PathElement. One issue with this approach is that it might need to be replicated for other PathElement-accepting methods. Which might be too much.
* Add an overload to AddressLayout::withTargetLayout that allows a target layout to be specified as an "element" layout (e.g. withTargetElementLayout).
- duplicates
-
JDK-8310048 Drop sequence layout factory with inferred count
-
- Resolved
-