efficiency vs. immutability of inline classes

Jona Christopher Sahnwaldt jc at sahnwaldt.de
Fri Aug 21 16:06:45 UTC 2020

On Fri, Aug 21, 2020, 17:33 Brian Goetz <brian.goetz at oracle.com> wrote:

> > 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.

Thanks for the fast and thorough response! I totally underestimated how
much complexity the JIT is having for lunch every day. I'm beginning to
understand that efficiency and immutability aren't actually conflicting
goals in this case.

Quick follow-up question: If the InlineType ctor contains a check that y is
valid - will the JIT omit that check if it sees that y hasn't been
mentioned in the `with` block?

> > 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