RFR: 8333133: Simplify QuickSort::sort

Kim Barrett kbarrett at openjdk.org
Thu May 30 17:59:02 UTC 2024


On Thu, 30 May 2024 11:41:31 GMT, Aleksey Shipilev <shade at openjdk.org> wrote:

>> The "idempotent" argument is removed from that function, with associated
>> simplifications to the implementation. Callers are updated to remove that
>> argument. Callers that were providing a false value are unaffected in their
>> behavior.  The 3 callers that were providing a true value to request the
>> associated feature are also unaffected (other than by being made faster),
>> because the arrays involved don't contain any equivalent pairs.
>> 
>> There are also some miscellaneous cleanups, including using the swap utility
>> and fixing some comments.
>> 
>> Testing: mach5 tier1-3
>
> src/hotspot/share/utilities/quickSort.hpp line 75:
> 
>> 73:     for ( ; true; ++left_index, --right_index) {
>> 74:       for ( ; comparator(array[left_index], pivot_val) < 0; ++left_index) {
>> 75:         assert(left_index < (length - 1), "reached end of partition");
> 
> Let me see if I understand this change. It makes assert stronger: we do not accept `left_index == length - 1` anymore. I guess that would mean the pivot is at the last element? Which makes the partition is empty, which cannot happen?

The reason I looked at the assert carefully in the first place was that `left_index < length` could
pass and yet we could still do `array[length]`, which could be UB.  So the tightened condition must
be correct, else we have a bug.  Proving we don't have a bug is a little bit harder.

We know that the last element in the sequence can't be less than the pivot,
because of the way find_pivot works.  It arranges for the first, middle, and
last values in the sequence to be ordered A[0] <= A[pivot] <= A[length-1].

The tricky case is the sequence [Vi..., P, P], where P is the pivot and all
Vi < P. The from-left scan proceeds until it reaches the left occurrence of P.
The from-right scan immediately stops on the right occurrence of P. The two
P's are swapped. left_index is incremented and right_index is decremented.
The from-left scan is restarted with left_index == length - 1, stops
immediately because P < P is false, and does not execute the assert. Similarly,
the from-right scan is restarted with right_index == length - 2, and also stops
because P > P is false.  And now the outer loop terminates.

A similar argument applies for the from-right scan, where we already assert
right_index > 0.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/19464#discussion_r1621217067


More information about the shenandoah-dev mailing list