Graal final field treatment with respect to optimizations
Vitaly Davidovich
vitalyd at gmail.com
Mon Apr 27 17:39:43 UTC 2015
Hi Tom,
I'm with you in terms of how this should be treated. However, Cliff Click
wrote a couple of blog posts a few years back on this topic:
http://www.azulsystems.com/blog/cliff/2011-10-17-writing-to-final-fields-via-reflection
http://www.azulsystems.com/blog/cliff/2011-10-27-final-fields-part-2
In short, some popular frameworks make use of this "feature". I suspect
the middle ground here would (or should) be to allow for that scenario, but
have user specify which class/package/<some_other_grouping> should be
excluded from JIT optimizations. Alternatively, have the compiler track
writes to final fields and then deopt without final field optimizations; I
think that's what the C2 guys are contemplating, if I understand correctly.
However, the thing I'm particularly curious about is what types of
additional optimizations, if any, Graal performs when it trusts final
fields. In C2, this doesn't appear to do much. In particular, final
fields are treated as constants only if enclosing instance is also
constant; the only practical difference that I found (in quick playing
around with this flag) this makes is that Enum.ordinal() is treated as a
constant in compiled code. There were certain "obvious" cases that weren't
optimized though, e.g.:
1) final array fields (even ones that were allocated inside the class ctor)
didn't have their length propagated as a constant to uses. In addition,
range checks were performed on accesses that should be "known" to be
legit. Basically, they didn't get the same codegen treatment as static
final arrays.
2) There didn't seem to be any "constraint" propagation of final fields.
For example, if the constructor throws a NPE if the field is null, the
field is still checked for null in uses. Likewise, say if an int field was
checked to be > 0, that info does not seem to make its way to uses.
John Rose indicated that these types of optimizations aren't done because
C2 doesn't do field profiling. I'm not sure #1 counts as profiling as it
seems like this type of thing could be detected at parse time. #2 also
isn't so much about profiling as about piggybacking on user checks that are
then predicated on final fields being unchanged thereafter.
Does Graal propagate this type of information to uses? Or more generally,
does it perform some set of additional optimizations (even if they're
peephole in nature) for final field uses?
Thanks
On Mon, Apr 27, 2015 at 1:07 PM, Tom Rodriguez <tom.rodriguez at oracle.com>
wrote:
>
> > On Apr 24, 2015, at 6:55 AM, Vitaly Davidovich <vitalyd at gmail.com>
> wrote:
> >
> > Hi guys,
> >
> > I recently had a thread on hotspot-compiler-dev where John Rose shed some
> > light on what the TrustNonStaticFinalFields experimental flag implies in
> > the C2 compiler:
> >
> http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/2015-April/017739.html
> >
> > Based on that exchange, I see that there are some scenarios where some
> > optimization opportunities are missed, specifically due to missing field
> > profiling. That got me thinking -- how does Graal handle this, and does
> it
> > do something better here? Clearly Graal has to also be mindful of final
> > fields being changed via reflection, but are there any speculative
> > optimizations around trusting that final fields are mostly unchanged (or
> > plans to do that)?
>
> We have a similar flag TrustFinalDefaultFields which defaults to true. I
> think anyone modifying final fields of published objects through reflection
> should just be laughed at and told to go away. The hole that allows
> modification of final fields through reflection was introduced to support
> deserialization. Any other use should just be considered undefined
> behaviour.
>
> tom
More information about the graal-dev
mailing list