RFR(S): 8159611: C2: ArrayCopy elimination skips required parameter checks
Volker Simonis
volker.simonis at gmail.com
Tue Aug 16 14:57:20 UTC 2016
On Tue, Aug 16, 2016 at 7:24 AM, Tobias Hartmann
<tobias.hartmann at oracle.com> wrote:
> Hi Volker,
>
> thanks for taking care of this issue!
>
> Did you check what happens if the allocation is not eliminated and macro expansion phase emits another negative guard? Are the checks merged?
>
It depends. I just saw that in some cases the regression test worked
before, because the length check was done in
SharedRuntime::slow_arraycopy_C(). So in that case there's obviously
nothing that can be merged. But the test case is obviously a
degenerated example anyway, so I don't think that's a problem.
If I do a more real-world example like this where the arracopy can not
be eliminated because one of its arguments escapes:
public static boolean do_test2(int length, Object[] dest) {
try {
System.arraycopy(new Object[10], 1, dest, 1, length);
return false;
} catch (IndexOutOfBoundsException e) {
return true;
}
}
and call it with:
do_test2(8, new Object[10])
the generated code for do_test2() unfortunately contains one more
check now with my change (the 'length' field is in [rsp + #0]):
0a2 B4: # B18 B5 <- B3 Freq: 0,999999
0a2 movl R9, [rsp + #0] # spill
0a6 testl R9, R9
0a9 jl B18 P=0,000001 C=-1,000000
0a9
0af B5: # B18 B6 <- B4 Freq: 0,999998
0af movl RBX, R9 # spill
0b2 incl RBX # int
0b4 cmpl RBX, #10 # unsigned
0b7 jnbe,u B18 P=0,000001 C=-1,000000
The generated code before my change looked like this (againthe
'length' field is in [rsp + #0]):
0a1 B4: # B17 B5 <- B3 Freq: 0,999999
0a1 movl R11, [rsp + #8] # spill
0a6 incl R11 # int
0a9 cmpl R11, #10 # unsigned
0ad jnbe,u B17 P=0,000001 C=-1,000000
It seems that the 'length' check has been completely eliminated before.
So I need to do some more tests to understand why the new check isn't
eliminated.
Do you think the new check results in a performance regression? Have
you run some benchmarks?
> I would prefer brackets around the if body but you don't need to send another webrev:
> if (EliminateAllocations) {
> generate_negative_guard(length, slow_region);
> }
Yes, I agree.
>
> Best regards,
> Tobias
>
> On 12.08.2016 21:13, Volker Simonis wrote:
>> Hi,
>>
>> can I please have a review and sponsor for the following fix:
>>
>> http://cr.openjdk.java.net/~simonis/webrevs/2016/8159611
>> https://bugs.openjdk.java.net/browse/JDK-8159611
>>
>>
>> We are inserting several checks for the arguments of
>> System.arraycopy() in LibraryCallKit::inline_arraycopy() before
>> intensifying the call in LibraryCallKit::inline_arraycopy. However the
>> check for the 'length' argument of arracopy is postponed to the macro
>> expansion phase in PhaseMacroExpand::generate_arraycopy().
>>
>> But if we are running with EscapeAnalysis and EliminateAllocations,
>> the array allocations inside a call to System.arraycopy() may get
>> eliminated and thus the complete call to System.arraycopy() will be
>> removed (see PhaseMacroExpand::process_users_of_allocation). In this
>> case the extra 'length' check won't be added by
>> PhaseMacroExpand::generate_arraycopy() any more because macro
>> expansion happens after the elimination of macro nodes.
>>
>> In such a case it may happen that System.arraycopy() will silently
>> accept an invalid (i.e. negative) 'length' parameter, although it
>> should actually throw an ArrayOutOfBounds exception.
>>
>> The fix is simple: also insert a check for the length field in
>> LibraryCallKit::inline_arraycopy() if we are running with
>> EliminateAllocations.
>>
>> Regards,
>> Volker
>>
More information about the hotspot-compiler-dev
mailing list