Interaction between Panama and Valhalla

Maurizio Cimadamore maurizio.cimadamore at oracle.com
Wed Mar 2 11:08:34 UTC 2022


Hi,
as you point out, there is a deep connection between Valhalla and 
Panama, both for the Vector and the Foreign API.

In the Foreign API, which is what you refer to here, there are few 
possible candidates for the Valhalla treatment that we have considered:

1) MemoryAddress - as you say, this is a wrapper on a `long` so it's 
almost a slamdunk;

2) MemorySegment - since segments are also immutable, it would be 
possible, in principle to make these value classes too. This is harder 
though, as memory segments currently need to use a complex class 
hierarchy so that the optimizing compiler can see their on-heap vs. 
off-heap state. While it is possible that _some day_ the JVM might give 
us more power to flatten hierarchies like MemorySegment (by speculating 
on one or more memory segment fields, instead that on the memory segment 
concrete type), this is not something that will happen quickly. So 
opportunties to take advantage of Valhalla are, IMHO, somewhat limited, 
especially in the short term.

3) MemoryLayout - these are immutable too.  That said, layouts are 
almost always (if used correctly) stored in some static final constant. 
Removing allocations for layouts is not where the gains are.

4) ResourceScope/MemorySession. This is a stateful abstraction, Valhalla 
makes no sense here.

Now (1) is the most obvious candidate for a primitive class. In the 
current API, MemoryAddress is defined as an interface. This gives us 
freedom to tweak the implementation under the hood (e.g. and make it a 
primitive class) as we see fit. This also creates issues: to apply some 
of the more advanced optimizations, the JVM would need to "see through" 
the fact that MemoryAddress is a _sealed_ interface with only one known 
implementation. And maybe, even that won't be enough to fully achieve 
the primitive class Nirvana (e.g. flattening an array of MemoryAddress): 
the MemoryAddress interface type is nullable, and that might well 
perturb some of the analysis/optimizations.

That said, after having worked with the API for quite some time, I 
honestly think that doing (2), while harder, will produce much better 
returns in terms of performance. The MemoryAddress class is so simple 
that in 90% of cases Hotspot can already eliminate the allocation 
_today_, w/o any extra help from Valhalla. MemorySegments are a 
different story though, as they embed more state, and scalarization 
doesn't always happen (see [1]). As for (2), making MemorySegment a 
primitive class makes less sense, as memory segments have several 
fields, so it's not clear that having a flattened MemorySegment[] would 
be better, and tearing will probably be unacceptable here (as it can 
have the potential of breaking lifetime invariants). So I think for (2) 
value classes are just fine.

Decisions such as these have always to be taken in a context. Of course 
if, by the time Panama is about to exit preview, primitive classes are 
ready, I'm more than available to keep Panama previewing for a little 
longer, so that we can sprinke primitive class treatment where it 
belongs. But it's always a cost vs. benefit analysis. Value classes (JEP 
401) gives us better scalarization and better calling conventions, as 
well as limited flattening in some cases (esp. if value classes are 
nested inside other classes) and those improvements might, alone, 
provide a decent enough boost. While I agree that, in an ideal world, 
MemoryAddress would be a primitive class, I'm not so sure that holding 
back the entire Foreign API so that we can make MemoryAddress fully 
flattenable is the best option. The only real added bonus this option 
would provide is better flattening for MemoryAddress[] - which is 
something I have not encountered frequently when using the API; it is a 
lot more common, in my experience, to have an opaque MemorySegment 
filled with MemoryAddress, than having an heap array of MemoryAddress.

P.S.
Another area which will greatly benefit from Valhalla is jextract: value 
classes will give us a way to "box" a memory segment into an higher 
level abstraction (a struct view) without performance loss. Since 
Jextract bindings are not covered by compatibility guarantees (if you 
want old bindings, just run an old version of jextract), I think we do 
have more freedom in that space.

Maurizio

[1] - https://bugs.openjdk.java.net/browse/JDK-8281387


On 02/03/2022 03:55, Glavo wrote:
> Can someone answer my question?  Many thanks.
>
> On Thu, Jan 27, 2022 at 12:50 AM Glavo <zjx001202 at gmail.com> wrote:
>
>> I noticed that some Panama features seem to benefit from Valhalla's
>> features. A notable example is MemoryAddress, which has been marked as
>> value based and should be able to migrate to value classes in the future.
>>
>> However, this is not enough to satisfy me. MemoryAddress can be more than
>> just a value class (identity-free reference type), but also a perfect
>> candidate for the primitive class (JEP 401).
>> It would be perfect if it could become a primitive class: Eliminates the
>> possibility that Java's `null` being its value, we just need
>> `MemoryAddress.NULL`;
>> Such a small primitive class should almost always be flattened, storing it
>> in a field or array is as simple as a long
>> (According to the description of JEP draft 8280173, when value class is
>> stored in arrays and fields, it may not be flattened, and additional
>> objects still need to be created)...
>>
>> However, what worries me is that the current Valhalla prototype does not
>> seem to provide a way to migrate a class to a primitive class while
>> maintaining compatibility.
>> I'm worried that if Panama can't make it a primitive class before ending
>> the preview, it will become a permanent regret.
>> I don't know whether the two JDK preview functions can interact with each
>> other, so here I want to ask if it is possible for Panama to have closer
>> contact with Valhalla when Valhalla starts previewing at the same time?
>>


More information about the panama-dev mailing list