foreign API and Constable
Maurizio Cimadamore
maurizio.cimadamore at oracle.com
Wed Mar 23 14:46:55 UTC 2022
Hi,
the foreign API uses Constable in a few places, especially in
MemoryLayout and FunctionDescriptor. The idea behind making layouts and
descriptors constable is that, by doing so, they can more easily be
serialized into the constant pool of a class.
At some point, when jextract generated classfiles directly, we used to
take advantage of this:
https://github.com/openjdk/panama-foreign/blob/4d7180afb2ce0b4b555459ca4c65217876322c8e/src/jdk.incubator.jextract/share/classes/jdk/internal/jextract/impl/ClassConstantHelper.java
We also had an API to attach custom attributes to layouts, were
attributes were also expressed as constable (so that we could reify them
in the constant pool as well). But that API was removed when we started
associating value layouts with carriers.
In other words, today we are no longer relying on layouts and
descriptors being Constable - at least not in the JDK. For code
generators it might still be useful to have these types implement
Constable, but it seems to me that, the place we're in now is
inconsistent, for the following reasons:
* code generators would probably also need to model layout *paths* as
pool constants - so PathElement should come for the ride as well
* code generators might want to rely on some well-known bootstraps (e.g.
in ConstantBootstraps) to create e.g. dereference var handles (given a
layout path), or a downcall method handle (given a function descriptor),
etc.
* finally, the protocol by which layouts are encoded in the constant
pool today is far from being optimal - for instance, the following
struct layout:
```
MemoryLayout.groupLayout(
ValueLayout.JAVA_INT.withName("x"),
ValueLayout.JAVA_INT.withName("y")
).withName("point");
```
Would be represented as a very long and nested chain of dynamic
constants (one per method call in the above expression). It's not hard
to see that the above layout can be described, in a more succint form,
using its string representation:
```
[ i32(x) i32(y) ](point)
```
Which requires a single dynamic constant with a string static arg (a
similar trick can be pulled for function descriptors).
Using the string representation of a layout to create another layout is
something that can be useful even outside Constable; for instance we
could have a factory MemoryLayout::ofString which parses a layout string
and returns a new layout object. I can see such a functionality being
quite handy (of course, for that to work we would need to define a
blessed string representation format for layouts, so there's obviously
more to pull there).
My point is: the fact that MemoryLayout and FunctionDescriptor
implements Constable seems more a result of past decisions which, while
taken in good faith, do not necessarily reflect where the API has
landed. While at some point encoding layouts in the constant pool will
come in handy, I believe the current Constable support is not really
helpful and more akin to an half-hearted attempt at supporting constant
pool serialization.
For these reasons, I would prefer to leave "implements Constable" out of
the API for the time being, while we gather more use cases about how
such support might be used in the real world. Of course this assumes
that clients of the foreign API are not relying on this particular
corner of the API. While I'm relatively confident that this is the case,
I would like very much to know if somebody is relying on the Constable
nature of memory layouts.
Thanks
Maurizio
More information about the panama-dev
mailing list