escape analysis issue with nested objects
Hontvári Attila
attila at hontvari.net
Fri May 26 13:15:45 UTC 2017
I've found a bug report that likely describes the same problem you
mentioned in your example: JDK-8171828
<https://bugs.openjdk.java.net/browse/JDK-8171828>
Another interesting thing is if we replace new Object() with a creation
of a primitive box object from a constant value, it will be eliminated,
even without a local variable.
private static void singleBoxedConstant() {
Object[] array = new Object[]{new Double(123.456)};
Object a = array[0];
}
It also works with multiple box objects:
private static void multiBoxedConstant() {
Object[] array = new Object[]{new Double(21), new Double(1.2)};
Object a = array[0];
Object b = array[1];
}
But if we replace the box constructor argument with a non-constant
value, it will again not work.
private static volatile double x = 43;
private static void multiBoxedNonconstant() {
Object[] array = new Object[]{new Double(x), new Double(1.2)};
Object a = array[0];
Object b = array[1];
}
2017-05-26 14:18 keltezéssel, Vitaly Davidovich írta:
> Indeed, you're right - I see the same (unsurprisingly) on 8u121. I
> wasn't looking at the loop compilation before, but just the
> single/multi methods standalone (analogous to them not being inlined).
>
> What's interesting also is that even single(), with just a slight
> re-arrangement, doesn't get eliminated. For instance:
>
> static void single() {
> final Object[] array = new Object[] {new Object()};
> final Object a = array[0];
> }
>
>
> On Fri, May 26, 2017 at 7:34 AM, Hontvári Attila <attila at hontvari.net
> <mailto:attila at hontvari.net>> wrote:
>
> They are eliminated only if multi() is not inlined into an
> enclosing loop. (8u101) If I disable inlining it with
> CompileCommand, C2 compiles it to an noop method. But when
> inlining is enabled, the wrapper loop compiles into a long code:
> http://pastebin.com/KAq5v2XE
>
> Maybe this issue is related to JDK-8155769
> <https://bugs.openjdk.java.net/browse/JDK-8155769>.
>
> 2017-05-25 21:50 keltezéssel, Vitaly Davidovich írta:
>> Looking at C2 generated assembly (8u121), both cases are
>> eliminated - the single() and multi() are dead code. To
>> alleviate the truly dead code scenario here, I had these methods
>> return something from the allocated object (I created a dummy
>> class that holds an int) and accessed those objects via array
>> indexing - no allocations are generated (not the array, and not
>> the objects).
>>
>> On Thu, May 25, 2017 at 3:12 PM, Kirk Pepperdine
>> <kirk.pepperdine at gmail.com <mailto:kirk.pepperdine at gmail.com>> wrote:
>>
>> I can see the arrays being DVE’ed.. in 8_121. EA seems to be
>> doing it’s job.
>>
>> Kind regards,
>> Kirk
>>
>> > On May 25, 2017, at 9:03 PM, Vladimir Kozlov
>> <vladimir.kozlov at oracle.com
>> <mailto:vladimir.kozlov at oracle.com>> wrote:
>> >
>> > Hi Attila,
>> >
>> > What Java version you are using?
>> >
>> > I tried jdk 7, 8, 9.
>> >
>> > What I see is that in both cases only arrays are eliminated
>> (-XX:+PrintEliminateAllocations with debug version of VM):
>> >
>> > BEGIN single
>> > Scalar 73 AllocateArray === 51 46 47 8 1 ( 71
>> 59 21 58 41 1 1 ) [[ 74 75 76 83 84 85 ]]
>> rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *, bool,
>> int ) NewMain::single @ bci:9 !jvms: NewMain::single @ bci:9
>> > ++++ Eliminated: 73 AllocateArray
>> > END single
>> > BEGIN multi
>> > Scalar 116 AllocateArray === 91 86 87 8 1 ( 114
>> 103 21 102 41 76 1 1 1 ) [[ 117 118 119 126 127 128
>> ]] rawptr:NotNull ( int:>=0, java/lang/Object:NotNull *,
>> bool, int ) NewMain::multi @ bci:17 !jvms: NewMain::multi @
>> bci:17
>> > ++++ Eliminated: 116 AllocateArray
>> > DONE
>> >
>> > But based on code non of objects should be allocated - both
>> methods should have only 'return' generated.
>> >
>> > Looks like EA missing such case when objects are stored
>> into small array.
>> >
>> > Thanks,
>> > Vladimir
>> >
>> > On 5/25/17 9:16 AM, Hontvári Attila wrote:
>> >> When creating a non-escaping array and putting a newly
>> created, non-escaping object in it, the EA works, there are
>> no heap allocations.
>> >> private static void single() {
>> >> Object x = new Object();
>> >> Object[] array = new Object[]{x};
>> >> Object a = array[0];
>> >> }
>> >> But if we do the same with two or more objects, the array
>> will be allocated on the heap, and not eliminated.
>> >> private static void multi() {
>> >> Object x = new Object();
>> >> Object y = new Object();
>> >> Object[] array = new Object[]{x, y};
>> >> Object a = array[0];
>> >> Object b = array[1];
>> >> }
>> >> Is there a reason why it is only working in the first case?
>> >> This would be useful for example,
>> MethodHandle::invokeWithArguments, when the primitive types
>> are boxed, and put into a varargs array, see my older email [1].
>> >> A complete test source code is in [2], if we run it with
>> -verbose:gc, we can see there are many GCs in the second
>> case, but there are no GCs in the first case.
>> >> [1]
>> http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-January/010933.html
>> <http://mail.openjdk.java.net/pipermail/jigsaw-dev/2017-January/010933.html>
>> >> [2]
>> https://gist.github.com/anonymous/bd46075ef1ebd858dae49fe6cfe39da8
>> <https://gist.github.com/anonymous/bd46075ef1ebd858dae49fe6cfe39da8>
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/hotspot-compiler-dev/attachments/20170526/109ba6d4/attachment.html>
More information about the hotspot-compiler-dev
mailing list