[sanitizer] Generic sorting in sanitizer_common.

llvm-svn: 181698
This commit is contained in:
Sergey Matveev 2013-05-13 11:58:48 +00:00
parent 37432e815e
commit d9da20f56f
2 changed files with 46 additions and 38 deletions

View File

@ -132,45 +132,15 @@ uptr ReadFileToBuffer(const char *file_name, char **buff,
return read_len;
}
// We don't want to use std::sort to avoid including <algorithm>, as
// we may end up with two implementation of std::sort - one in instrumented
// code, and the other in runtime.
// qsort() from stdlib won't work as it calls malloc(), which results
// in deadlock in ASan allocator.
// We re-implement in-place sorting w/o recursion as straightforward heapsort.
typedef bool UptrComparisonFunction(const uptr &a, const uptr &b);
template<class T>
static inline bool CompareLess(const T &a, const T &b) {
return a < b;
}
void SortArray(uptr *array, uptr size) {
if (size < 2)
return;
// Stage 1: insert elements to the heap.
for (uptr i = 1; i < size; i++) {
uptr j, p;
for (j = i; j > 0; j = p) {
p = (j - 1) / 2;
if (array[j] > array[p])
Swap(array[j], array[p]);
else
break;
}
}
// Stage 2: swap largest element with the last one,
// and sink the new top.
for (uptr i = size - 1; i > 0; i--) {
Swap(array[0], array[i]);
uptr j, max_ind;
for (j = 0; j < i; j = max_ind) {
uptr left = 2 * j + 1;
uptr right = 2 * j + 2;
max_ind = j;
if (left < i && array[left] > array[max_ind])
max_ind = left;
if (right < i && array[right] > array[max_ind])
max_ind = right;
if (max_ind != j)
Swap(array[j], array[max_ind]);
else
break;
}
}
InternalSort<uptr*, UptrComparisonFunction>(&array, size, CompareLess);
}
// We want to map a chunk of address space aligned to 'alignment'.

View File

@ -340,6 +340,44 @@ class InternalVector {
uptr capacity_;
uptr size_;
};
// HeapSort for arrays and InternalVector.
template<class Container, class Compare>
void InternalSort(Container *v, uptr size, Compare comp) {
if (size < 2)
return;
// Stage 1: insert elements to the heap.
for (uptr i = 1; i < size; i++) {
uptr j, p;
for (j = i; j > 0; j = p) {
p = (j - 1) / 2;
if (comp((*v)[p], (*v)[j]))
Swap((*v)[j], (*v)[p]);
else
break;
}
}
// Stage 2: swap largest element with the last one,
// and sink the new top.
for (uptr i = size - 1; i > 0; i--) {
Swap((*v)[0], (*v)[i]);
uptr j, max_ind;
for (j = 0; j < i; j = max_ind) {
uptr left = 2 * j + 1;
uptr right = 2 * j + 2;
max_ind = j;
if (left < i && comp((*v)[max_ind], (*v)[left]))
max_ind = left;
if (right < i && comp((*v)[max_ind], (*v)[right]))
max_ind = right;
if (max_ind != j)
Swap((*v)[j], (*v)[max_ind]);
else
break;
}
}
}
} // namespace __sanitizer
#endif // SANITIZER_COMMON_H