Using Array.newInstance still generates checkcast instructions

Vitaly Davidovich vitalyd at gmail.com
Tue Oct 27 18:19:39 UTC 2015


>
> Ah no, my bad. C2 actually intrinsifies j.l.r.Array::newArray.


That's right, it's intrinsified.  But irrespective of that, the issue isn't
speed of newArray but rather the dynamic type of the returned (and stored
in a field in my example) array -- it's exactly the "reified" T[] (String[]
in my example).

I would think storing that array instance into Object[] field trips any
> subsequent analysis. If I were you, I'd do more differential tests:
> pulling the "string" from the near-allocated newArray, the same with
> load/store through String[], the same with load/store through Object[],
> etc.


Again, the field is Object[] only statically.  I know C2 does receiver type
sharpening and other optimizations by looking at exact receiver type, so
it's surprising that this isn't triggering here, in a few straightforward
example (see the example I posted with assembly).

This whole thing is an attempt at manually reifying generics, and hoping
the JIT could see through it (at least in fully inlined callsites).


On Tue, Oct 27, 2015 at 2:12 PM, Aleksey Shipilev <
aleksey.shipilev at oracle.com> wrote:

> Ah no, my bad. C2 actually intrinsifies j.l.r.Array::newArray.
>
> I would think storing that array instance into Object[] field trips any
> subsequent analysis. If I were you, I'd do more differential tests:
> pulling the "string" from the near-allocated newArray, the same with
> load/store through String[], the same with load/store through Object[],
> etc.
>
> -Aleksey
>
> On 10/27/2015 09:00 PM, Aleksey Shipilev wrote:
> > The field is Object[] both in bytecode and "at JIT time".
> >
> > And you cannot do otherwise since pessimistically somebody can store,
> > say, Integer instead of String there, thus polluting the heap. As John
> > says, you can only propagate the type information if, among other
> > things, the instance is guaranteed to avoid heap pollution. Compiler
> > cannot change field types, it can only carry a limited set of
> > constraints about the types...
> >
> > AFAIR, once instance escapes, all bets are off. But even if
> > (hypothetically) dataflow analysis could have said the array has no
> > suspicious writes before your access right after the construction, I am
> > not very sure Array.newInstance is transparent for compiler at all.
> > Mostly because it delegates to a native method and apparently has no
> > vmSymbols entries that might indicate any special compiler treatment.
> > Thanks,
> > -Aleksey
> >
> > On 10/27/2015 08:46 PM, Vitaly Davidovich wrote:
> >> The whole use case is inlined here, which is the case that bothers me.
> >> If the underlying array access is inlined, couldn't its runtime type be
> >> checked? I don't understand the heap pollution issue in this case.  The
> >> field is not Object[] at JIT time.
> >>
> >> sent from my phone
> >>
> >> On Oct 27, 2015 1:40 PM, "John Rose" <john.r.rose at oracle.com
> >> <mailto:john.r.rose at oracle.com>> wrote:
> >>
> >>     It's an old problem we have talked about before:  There is only
> >>     limited type inference through field loads.  The JIT notes that the
> >>     type of the heap variable is the erased Object[].  It does not
> >>     attempt to attach special knowledge (T=String) to the type of
> >>     'strings' (ArrayList), because type parameter bindings are not
> >>     completely reliable at runtime, due to the possibility of heap
> >>     pollution (e.g., via reflective access).
> >>
> >>     In some cases if the whole use case is inlined (as perhaps may
> >>     happen here) then 'strings' can be scalarized and type propagation
> >>     will be more accurate, since 'strings._items' would be lifted into a
> >>     register.  (Type prop. through locals is not disturbed by the
> >>     possibility of reflective access, heap pollution, etc.)  If you are
> >>     seeing a cast then either (a) scalarization is incomplete (it can
> >>     fail for even tiny reasons which is why we need un-aliasable value
> >>     types), or (b) there is a bug somewhere.  The likely bet is (a).
> >>
> >>     — John
> >>
> >>     On Oct 27, 2015, at 10:23 AM, Vitaly Davidovich <vitalyd at gmail.com
> >>     <mailto:vitalyd at gmail.com>> wrote:
> >>     >
> >>     > Hi,
> >>     >
> >>     > I (intuitively) thought that using Array.newInstance() and
> >>     specifying a final class (e.g. String) would remove checkcasts in
> >>     the caller.  However, it appears that the check is still generated
> >>     (at least on 8u51).  Why would this be? It seems the JIT should know
> >>     the true runtime type of the array, and if accesses to it are
> >>     inlined, the checkcast could be removed.  Am I missing something?
> >>     >
> >>     > e.g.
> >>     >
> >>     > public final class ArrayList<T> {
> >>     >     private final T[] _items;
> >>     >
> >>     >     public ArrayList(Class<T> klass, int size) {
> >>     >          _items = (T[])Array.newInstance(klass, size);
> >>     >     }
> >>     >
> >>     >     // rest omitted for brevity
> >>     >
> >>     >     public T get(int index) { return _items[index]; }
> >>     >
> >>     > }
> >>     >
> >>     > ArrayList<String> strings = new ArrayList<>(String.class, 10);
> >>     > String s = strings.get(0); // why is this checkcast not
> eliminated?
> >>     >
> >>     >
> >>     > Thanks
> >>
> >
> >
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20151027/27abb72a/attachment.html>


More information about the hotspot-compiler-dev mailing list