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