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