annotate src/share/vm/utilities/quickSort.hpp @ 3779:04760e41b01e

7016112: CMS: crash during promotion testing Summary: Also reviewed by mikael.gerdin@oracle.com; stdlib:qsort() does byte-by-byte swapping on Windows. This leads to pointer shearing. Fix is to implement a quicksort that does full pointer updates. Reviewed-by: never, coleenp, ysr
author brutisso
date Tue, 28 Jun 2011 14:23:27 +0200
parents
children 3c648b9ad052
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
3779
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
1 /*
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
2 * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
4 *
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
7 * published by the Free Software Foundation.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
8 *
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
13 * accompanied this code).
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
14 *
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
18 *
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
21 * questions.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
22 *
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
23 */
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
24
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
25 #ifndef SHARE_VM_UTILITIES_QUICKSORT_HPP
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
26 #define SHARE_VM_UTILITIES_QUICKSORT_HPP
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
27
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
28 #include "memory/allocation.hpp"
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
29 #include "runtime/globals.hpp"
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
30 #include "utilities/debug.hpp"
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
31
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
32 class QuickSort : AllStatic {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
33
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
34 private:
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
35 template<class T>
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
36 static void swap(T* array, int x, int y) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
37 T tmp = array[x];
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
38 array[x] = array[y];
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
39 array[y] = tmp;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
40 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
41
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
42 // As pivot we use the median of the first, last and middle elements.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
43 // We swap in these three values at the right place in the array. This
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
44 // means that this method not only returns the index of the pivot
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
45 // element. It also alters the array so that:
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
46 // array[first] <= array[middle] <= array[last]
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
47 // A side effect of this is that arrays of length <= 3 are sorted.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
48 template<class T, class C>
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
49 static int find_pivot(T* array, int length, C comparator) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
50 assert(length > 1, "length of array must be > 0");
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
51
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
52 int middle_index = length / 2;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
53 int last_index = length - 1;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
54
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
55 if (comparator(array[0], array[middle_index]) == 1) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
56 swap(array, 0, middle_index);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
57 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
58 if (comparator(array[0], array[last_index]) == 1) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
59 swap(array, 0, last_index);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
60 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
61 if (comparator(array[middle_index], array[last_index]) == 1) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
62 swap(array, middle_index, last_index);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
63 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
64 // Now the value in the middle of the array is the median
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
65 // of the fist, last and middle values. Use this as pivot.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
66 return middle_index;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
67 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
68
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
69 template<class T, class C, bool idempotent>
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
70 static int partition(T* array, int pivot, int length, C comparator) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
71 int left_index = -1;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
72 int right_index = length;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
73 T pivot_val = array[pivot];
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
74
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
75 while (true) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
76 do {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
77 left_index++;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
78 } while (comparator(array[left_index], pivot_val) == -1);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
79 do {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
80 right_index--;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
81 } while (comparator(array[right_index], pivot_val) == 1);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
82
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
83 if (left_index < right_index) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
84 if (!idempotent || comparator(array[left_index], array[right_index]) != 0) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
85 swap(array, left_index, right_index);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
86 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
87 } else {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
88 return right_index;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
89 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
90 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
91
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
92 ShouldNotReachHere();
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
93 return 0;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
94 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
95
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
96 template<class T, class C, bool idempotent>
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
97 static void inner_sort(T* array, int length, C comparator) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
98 if (length < 2) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
99 return;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
100 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
101 int pivot = find_pivot(array, length, comparator);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
102 if (length < 4) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
103 // arrays up to length 3 will be sorted after finding the pivot
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
104 return;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
105 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
106 int split = partition<T, C, idempotent>(array, pivot, length, comparator);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
107 int first_part_length = split + 1;
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
108 inner_sort<T, C, idempotent>(array, first_part_length, comparator);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
109 inner_sort<T, C, idempotent>(&array[first_part_length], length - first_part_length, comparator);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
110 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
111
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
112 public:
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
113 // The idempotent parameter prevents the sort from
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
114 // reordering a previous valid sort by not swapping
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
115 // fields that compare as equal. This requires extra
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
116 // calls to the comparator, so the performance
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
117 // impact depends on the comparator.
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
118 template<class T, class C>
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
119 static void sort(T* array, int length, C comparator, bool idempotent) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
120 // Switch "idempotent" from function paramter to template parameter
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
121 if (idempotent) {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
122 inner_sort<T, C, true>(array, length, comparator);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
123 } else {
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
124 inner_sort<T, C, false>(array, length, comparator);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
125 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
126 }
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
127
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
128 // for unit testing
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
129 #ifndef PRODUCT
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
130 static void print_array(const char* prefix, int* array, int length);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
131 static bool compare_arrays(int* actual, int* expected, int length);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
132 template <class C> static bool sort_and_compare(int* arrayToSort, int* expectedResult, int length, C comparator, bool idempotent = false);
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
133 static bool test_quick_sort();
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
134 #endif
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
135 };
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
136
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
137
04760e41b01e 7016112: CMS: crash during promotion testing
brutisso
parents:
diff changeset
138 #endif //SHARE_VM_UTILITIES_QUICKSORT_HPP