Value objects and inheritance
Remi Forax
forax at univ-mlv.fr
Tue May 6 20:09:39 UTC 2025
> From: "Toby Reyelts" <rreyelts at gmail.com>
> To: "valhalla-dev" <valhalla-dev at openjdk.org>
> Sent: Monday, May 5, 2025 9:41:12 PM
> Subject: Value objects and inheritance
> [Apologies if this is the wrong list. I was hoping to find something more
> user-focused (e.g. a valhalla-users@), but this seems to be the recommended
> place to ask questions. Please LMK if there's somewhere more appropriate].
> I've been reading the JEPs and messing around with the early access build,
> trying to create a mental model for myself about how JVMs will typically be
> able to optimize value classes. It seems like a goal is effectively to be able
> to dump object headers:
> - no identity (no boxing/unboxing visibility, no gc)
> - no synchronization
> - restrictions on inheritance
> etc
> but this seems like it relies on the ability of the JIT to know the concrete
> value of the type at runtime. E.G. if I have the method:
> public void print(java.lang.Number! n) {
> System.out.println(n.toString());
> }
> It seems that the JVM must require some kind of object header to be able to
> determine the appropriate toString to dispatch to.
Not necessarily, if you call with print(Integer.valueOf(3)), if the JIT is able to inlining the call, the JIT will propagate the type (here Integer) so not boxing will occur.
> Similarly, if I have:
> class X {
> Number![] nums = someNums();
> }
> It seems like every Number in nums must still require an object header, because
> the JIT doesn't know the concrete type of said objects.
Here you have a field which store an array.
An array is never a value type, so you will always have a header for the array.
But at runtime, you can have an array of Integer!, in that case, all the elements of the array have no header.
> Reading JEP 401 more closely, I see now that scalarization can't be supported
> for supertypes:
>> One limitation of scalarization is that it is not typically applied to a
>> variable with a type that is a supertype of a value class type.
> Is heap flattening in the same category?
Heap flattening is usually harder to optimize than scalarization (see below).
> Are there any optimizations that end up working with supertypes, or is the
> general premise that you'll mostly need to be working with the concrete classes
> for optimizations to kick in?
Here is a simplified mental model :
The bytecode instructions are the same for an identity class or a value class. That allow us to retrofit Integer or Optional to be a value type without any recompilation (yai !).
Because of that, the value class optimizations have to be done at runtime, most of them are done by the JIT.
For parameters/local variable (scalarization), if you use a concrete class, it's easy for a JIT.
If you use a supertype, it depends on inlining.
For fields (flattening), if you use a concrete class, if sizeof(object) < 64 bits, it's easy for the JIT.
if you use a supertype, it depends on escape analysis.
In the future,
if sizeof(object) == 64 bits, the field has to be non-nullable.
if sizeof(object) >= 64 bits, the field has to be non-nullable and the class has to allow tearing (several reads/writes).
regards,
Rémi
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/valhalla-dev/attachments/20250506/0f2064ac/attachment-0001.htm>
More information about the valhalla-dev
mailing list