Bug 1291463: Apply TypedArray sort optimisations to normal Array sort. r=jorendorff

Also change the temporary buffer to a normal Array to ensure the `Merge` helper
is called with the same object class.

Differential Revision: https://phabricator.services.mozilla.com/D24712

--HG--
extra : moz-landing-system : lando
This commit is contained in:
André Bargull 2019-07-08 16:33:12 +00:00
parent 091478789a
commit 42c851b033

View File

@ -221,45 +221,40 @@ function SwapArrayElements(array, i, j) {
}
// A helper function for MergeSort.
function Merge(list, start, mid, end, lBuffer, rBuffer, comparefn) {
var i, j, k;
//
// Merge comparefn-sorted slices list[start..<=mid] and list[mid+1..<=end],
// storing the merged sequence in out[start..<=end].
function Merge(list, out, start, mid, end, comparefn) {
// Skip lopsided runs to avoid doing useless work.
// Skip calling the comparator if the sub-list is already sorted.
if (mid >= end || comparefn(list[mid], list[mid + 1]) <= 0) {
for (var i = start; i <= end; i++) {
_DefineDataProperty(out, i, list[i]);
}
return;
}
var sizeLeft = mid - start + 1;
var sizeRight = end - mid;
// Copy our virtual lists into separate buffers.
for (i = 0; i < sizeLeft; i++)
lBuffer[i] = list[start + i];
for (j = 0; j < sizeRight; j++)
rBuffer[j] = list[mid + 1 + j];
i = 0;
j = 0;
k = start;
while (i < sizeLeft && j < sizeRight) {
if (comparefn(lBuffer[i], rBuffer[j]) <= 0) {
list[k] = lBuffer[i];
var i = start;
var j = mid + 1;
var k = start;
while (i <= mid && j <= end) {
var lvalue = list[i];
var rvalue = list[j];
if (comparefn(lvalue, rvalue) <= 0) {
_DefineDataProperty(out, k++, lvalue);
i++;
} else {
list[k] = rBuffer[j];
_DefineDataProperty(out, k++, rvalue);
j++;
}
k++;
}
// Empty out any remaining elements in the buffer.
while (i < sizeLeft) {
list[k] = lBuffer[i];
i++;
k++;
// Empty out any remaining elements.
while (i <= mid) {
_DefineDataProperty(out, k++, list[i++]);
}
while (j < sizeRight) {
list[k] = rBuffer[j];
j++;
k++;
while (j <= end) {
_DefineDataProperty(out, k++, list[j++]);
}
}
@ -296,25 +291,33 @@ function MergeSort(array, len, comparefn) {
}
// We do all of our allocating up front
var lBuffer = new List();
var rBuffer = new List();
var lBuffer = denseList;
var rBuffer = [];
var mid, end;
for (var windowSize = 1; windowSize < denseLen; windowSize = 2 * windowSize) {
for (var start = 0; start < denseLen - 1; start += 2 * windowSize) {
assert(windowSize < denseLen, "The window size is larger than the array denseLength!");
// Use insertion sort for initial ranges.
var windowSize = 4;
for (var start = 0; start < denseLen - 1; start += windowSize) {
var end = std_Math_min(start + windowSize - 1, denseLen - 1);
InsertionSort(lBuffer, start, end, comparefn);
}
for (; windowSize < denseLen; windowSize = 2 * windowSize) {
for (var start = 0; start < denseLen; start += 2 * windowSize) {
// The midpoint between the two subarrays.
mid = start + windowSize - 1;
var mid = start + windowSize - 1;
// To keep from going over the edge.
end = start + 2 * windowSize - 1;
end = end < denseLen - 1 ? end : denseLen - 1;
// Skip lopsided runs to avoid doing useless work
if (mid > end)
continue;
Merge(denseList, start, mid, end, lBuffer, rBuffer, comparefn);
var end = std_Math_min(start + 2 * windowSize - 1, denseLen - 1);
Merge(lBuffer, rBuffer, start, mid, end, comparefn);
}
// Swap both lists.
var swap = lBuffer;
lBuffer = rBuffer;
rBuffer = swap;
}
MoveHoles(array, len, denseList, denseLen);
MoveHoles(array, len, lBuffer, denseLen);
return array;
}