efficiency vs. immutability of inline classes

Brian Goetz brian.goetz at oracle.com
Fri Aug 21 15:33:24 UTC 2020



> First a general question: This has probably been discussed before (but I
> didn't find it in the list archive). What's the current thinking? Could
> someone point me to any discussions or results? Thanks!
>
> More specific questions: I recently read about "functional transformation
> of immutable objects".
> https://github.com/openjdk/amber-docs/blob/master/eg-drafts/reconstruction-records-and-classes.md
> This feature may initially be intended for records, but let's apply it to
> inline classes:

Yes, that's the plan.  The document says that straight out; this is a 
feature about transformations on objects, which is not restricted to 
records, or inline classes, or even immutable classes.  Records just 
happen to come out of the box with all the moving parts needed to hook 
this up trivially, but other classes will join the fun soon, and inlines 
are likely to be among the best customers.

> InlineType[] a = ...;  // InlineType has a field x
> for (int i = 0; i < a.length; i++)
>      a[i] = a[i] with { x = 3; };
>
> Semantically, this makes two copies (from array to local variable and back).
>
> Could the JIT be smart enough to transform this into an update of a single
> field, without any copies of the whole object?

Absolutely.  That's an essential aspect of the inline class design; the 
restrictions on inline classes are designed, in part, to support these 
sorts of optimizations as a casual mid-day snack.

The `with` syntax is a distraction in this analysis; imagine the above 
were merely

     a[i] = new InlineType(3, a.y())

The constructor is just a static factory method, which will routinely be 
inlined here because it's tiny.  Same for the y() accessor.  After 
inlining, SSA transformation, scalarization, value numbering, and 
register allocation, what will happen is that the x and y fields of your 
(hot) loop index will already be in registers, the store of a.y = a.y() 
will be trivially observed as dead, and what you'll get is "load #3 into 
register."

If the language automates this with `with`, same deal, because the 
language will generate ctor/dtor calls, which will get inlined, which 
are just scrutable data movement, which the JIT will similarly crush.

> Or maybe we should give the JIT a hint and allow compound assignment
> analogous to += et al.?
>
> a[i] = with { x = 3; };
>
> or
>
> a[i] with= { x = 3; };

A kind offer, but the JIT doesn't need this sort of help! Identifying 
these sorts of idioms is routine fare for compilers.

A better argument here would be that _humans_ would like this sort of 
help.  That's a valid discussion, but not needed at this point.

Cheers,
-Brian




More information about the valhalla-dev mailing list