[cleanup] Use implicit context and sortState for most Call* macros

This CL changes most Call* macros (and some others) in Array#sort to
pass the context and sortState implicitly. This improves
readability, especially for loads and stores.

R=jgruber@chromium.org, tebbi@chromium.org

Bug: v8:8567
Change-Id: I6528d080bb01ab676de3ba6a7bf8223b98b6db7f
Reviewed-on: https://chromium-review.googlesource.com/c/1450114
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#59320}
This commit is contained in:
Simon Zünd 2019-02-01 15:39:38 +01:00 committed by Commit Bot
parent 2e83e74992
commit dc4c8bdb05

View File

@ -344,8 +344,8 @@ namespace array {
return SelectBooleanConstant(obj.map == initialReceiverMap);
}
macro CallCompareFn(
context: Context, sortState: FixedArray, x: Object, y: Object): Number
macro CallCompareFn(implicit context: Context, sortState: FixedArray)(
x: Object, y: Object): Number
labels Bailout {
const userCmpFn: Object = sortState[kUserCmpFnIdx];
const sortCompare: CompareBuiltinFn =
@ -479,40 +479,38 @@ namespace array {
// readable since we can use labels and do not have to check kBailoutStatus
// or the return value.
macro CallLoad(
context: Context, sortState: FixedArray, load: LoadFn, index: Smi): Object
macro CallLoad(implicit context: Context, sortState: FixedArray)(
load: LoadFn, index: Smi): Object
labels Bailout {
const result: Object = load(context, sortState, index);
EnsureSuccess(sortState) otherwise Bailout;
return result;
}
macro CallStore(
context: Context, sortState: FixedArray, store: StoreFn, index: Smi,
value: Object) labels Bailout {
macro CallStore(implicit context: Context, sortState: FixedArray)(
store: StoreFn, index: Smi, value: Object) labels Bailout {
store(context, sortState, index, value);
EnsureSuccess(sortState) otherwise Bailout;
}
transitioning macro CallCopyFromTempArray(
context: Context, sortState: FixedArray, dstPos: Smi, srcPos: Smi,
length: Smi)
implicit context: Context,
sortState: FixedArray)(dstPos: Smi, srcPos: Smi, length: Smi)
labels Bailout {
CopyFromTempArray(context, sortState, dstPos, srcPos, length);
EnsureSuccess(sortState) otherwise Bailout;
}
transitioning macro CallCopyWithinSortArray(
context: Context, sortState: FixedArray, srcPos: Smi, dstPos: Smi,
length: Smi)
implicit context: Context,
sortState: FixedArray)(srcPos: Smi, dstPos: Smi, length: Smi)
labels Bailout {
CopyWithinSortArray(context, sortState, srcPos, dstPos, length);
EnsureSuccess(sortState) otherwise Bailout;
}
macro CallGallopRight(
context: Context, sortState: FixedArray, load: LoadFn, key: Object,
base: Smi, length: Smi, hint: Smi): Smi
macro CallGallopRight(implicit context: Context, sortState: FixedArray)(
load: LoadFn, key: Object, base: Smi, length: Smi, hint: Smi): Smi
labels Bailout {
const result: Smi =
GallopRight(context, sortState, load, key, base, length, hint);
@ -520,9 +518,8 @@ namespace array {
return result;
}
macro CallGallopLeft(
context: Context, sortState: FixedArray, load: LoadFn, key: Object,
base: Smi, length: Smi, hint: Smi): Smi
macro CallGallopLeft(implicit context: Context, sortState: FixedArray)(
load: LoadFn, key: Object, base: Smi, length: Smi, hint: Smi): Smi
labels Bailout {
const result: Smi =
GallopLeft(context, sortState, load, key, base, length, hint);
@ -531,15 +528,16 @@ namespace array {
}
transitioning macro
CallMergeAt(context: Context, sortState: FixedArray, i: Smi)
CallMergeAt(implicit context: Context, sortState: FixedArray)(i: Smi)
labels Bailout {
MergeAt(context, sortState, i);
EnsureSuccess(sortState) otherwise Bailout;
}
transitioning macro CopyToTempArray(
context: Context, sortState: FixedArray, load: LoadFn, srcPos: Smi,
tempArray: FixedArray, dstPos: Smi, length: Smi)
transitioning macro
CopyToTempArray(implicit context: Context, sortState: FixedArray)(
load: LoadFn, srcPos: Smi, tempArray: FixedArray, dstPos: Smi,
length: Smi)
labels Bailout {
assert(srcPos >= 0);
assert(dstPos >= 0);
@ -551,8 +549,7 @@ namespace array {
let to: Smi = srcPos + length;
while (srcIdx < to) {
let element: Object = CallLoad(context, sortState, load, srcIdx++)
otherwise Bailout;
const element = CallLoad(load, srcIdx++) otherwise Bailout;
tempArray[dstIdx++] = element;
}
}
@ -573,8 +570,7 @@ namespace array {
let to: Smi = srcPos + length;
try {
while (srcIdx < to) {
CallStore(context, sortState, store, dstIdx++, tempArray[srcIdx++])
otherwise Bailout;
CallStore(store, dstIdx++, tempArray[srcIdx++]) otherwise Bailout;
}
return kSuccess;
}
@ -599,16 +595,14 @@ namespace array {
let srcIdx: Smi = srcPos + length - 1;
let dstIdx: Smi = dstPos + length - 1;
while (srcIdx >= srcPos) {
CopyElement(context, sortState, load, store, srcIdx--, dstIdx--)
otherwise Bailout;
CopyElement(load, store, srcIdx--, dstIdx--) otherwise Bailout;
}
} else {
let srcIdx: Smi = srcPos;
let dstIdx: Smi = dstPos;
let to: Smi = srcPos + length;
while (srcIdx < to) {
CopyElement(context, sortState, load, store, srcIdx++, dstIdx++)
otherwise Bailout;
CopyElement(load, store, srcIdx++, dstIdx++) otherwise Bailout;
}
}
return kSuccess;
@ -618,16 +612,16 @@ namespace array {
}
}
// BinaryInsertionSort is the best method for sorting small arrays: it does
// few compares, but can do data movement quadratic in the number of elements.
// This is an advantage since comparisons are more expensive due to
// calling into JS.
// BinaryInsertionSort is the best method for sorting small arrays: it
// does few compares, but can do data movement quadratic in the number of
// elements. This is an advantage since comparisons are more expensive due
// to calling into JS.
//
// [low, high) is a contiguous range of a array, and is sorted via
// binary insertion. This sort is stable.
//
// On entry, must have low <= start <= high, and that [low, start) is already
// sorted. Pass start == low if you do not know!.
// On entry, must have low <= start <= high, and that [low, start) is
// already sorted. Pass start == low if you do not know!.
builtin BinaryInsertionSort(
context: Context, sortState: FixedArray, low: Smi, startArg: Smi,
high: Smi): Smi {
@ -644,8 +638,7 @@ namespace array {
let left: Smi = low;
let right: Smi = start;
const pivot: Object = CallLoad(context, sortState, load, right)
otherwise Bailout;
const pivot = CallLoad(load, right) otherwise Bailout;
// Invariants:
// pivot >= all in [low, left).
@ -655,11 +648,8 @@ namespace array {
// Find pivot insertion point.
while (left < right) {
const mid: Smi = left + ((right - left) >> 1);
const midElement: Object = CallLoad(context, sortState, load, mid)
otherwise Bailout;
const order: Number =
CallCompareFn(context, sortState, pivot, midElement)
otherwise Bailout;
const midElement = CallLoad(load, mid) otherwise Bailout;
const order = CallCompareFn(pivot, midElement) otherwise Bailout;
if (order < 0) {
right = mid;
@ -673,16 +663,13 @@ namespace array {
// pivot >= all in [low, left) and
// pivot < all in [left, start),
//
// so pivot belongs at left. Note that if there are elements equal to
// pivot, left points to the first slot after them -- that's why this
// sort is stable.
// Slide over to make room.
// so pivot belongs at left. Note that if there are elements equal
// to pivot, left points to the first slot after them -- that's why
// this sort is stable. Slide over to make room.
for (let p: Smi = start; p > left; --p) {
CopyElement(context, sortState, load, store, p - 1, p)
otherwise Bailout;
CopyElement(load, store, p - 1, p) otherwise Bailout;
}
CallStore(context, sortState, store, left, pivot)
otherwise Bailout;
CallStore(store, left, pivot) otherwise Bailout;
}
return kSuccess;
}
@ -691,9 +678,9 @@ namespace array {
}
}
// Return the length of the run beginning at low, in the range [low, high),
// low < high is required on entry.
// "A run" is the longest ascending sequence, with
// Return the length of the run beginning at low, in the range [low,
// high), low < high is required on entry. "A run" is the longest
// ascending sequence, with
//
// a[low] <= a[low + 1] <= a[low + 2] <= ...
//
@ -701,13 +688,13 @@ namespace array {
//
// a[low] > a[low + 1] > a[low + 2] > ...
//
// For its intended use in stable mergesort, the strictness of the definition
// of "descending" is needed so that the range can safely be reversed
// without violating stability (strict ">" ensures there are no equal
// elements to get out of order).
// For its intended use in stable mergesort, the strictness of the
// definition of "descending" is needed so that the range can safely be
// reversed without violating stability (strict ">" ensures there are no
// equal elements to get out of order).
//
// In addition, if the run is "descending", it is reversed, so the returned
// length is always an ascending sequence.
// In addition, if the run is "descending", it is reversed, so the
// returned length is always an ascending sequence.
macro CountAndMakeRun(
context: Context, sortState: FixedArray, lowArg: Smi, high: Smi): Smi
labels Bailout {
@ -721,13 +708,9 @@ namespace array {
let runLength: Smi = 2;
const elementLow: Object =
CallLoad(context, sortState, load, low) otherwise Bailout;
const elementLowPred: Object =
CallLoad(context, sortState, load, low - 1) otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, elementLow, elementLowPred)
otherwise Bailout;
const elementLow = CallLoad(load, low) otherwise Bailout;
const elementLowPred = CallLoad(load, low - 1) otherwise Bailout;
let order = CallCompareFn(elementLow, elementLowPred) otherwise Bailout;
// TODO(szuend): Replace with "order < 0" once Torque supports it.
// Currently the operator<(Number, Number) has return type
@ -736,10 +719,8 @@ namespace array {
let previousElement: Object = elementLow;
for (let idx: Smi = low + 1; idx < high; ++idx) {
const currentElement: Object =
CallLoad(context, sortState, load, idx) otherwise Bailout;
order = CallCompareFn(context, sortState, currentElement, previousElement)
otherwise Bailout;
const currentElement = CallLoad(load, idx) otherwise Bailout;
order = CallCompareFn(currentElement, previousElement) otherwise Bailout;
if (isDescending) {
if (order >= 0) break;
@ -767,14 +748,10 @@ namespace array {
let high: Smi = to - 1;
while (low < high) {
const elementLow: Object =
CallLoad(context, sortState, load, low) otherwise Bailout;
const elementHigh: Object =
CallLoad(context, sortState, load, high) otherwise Bailout;
CallStore(context, sortState, store, low++, elementHigh)
otherwise Bailout;
CallStore(context, sortState, store, high--, elementLow)
otherwise Bailout;
const elementLow = CallLoad(load, low) otherwise Bailout;
const elementHigh = CallLoad(load, high) otherwise Bailout;
CallStore(store, low++, elementHigh) otherwise Bailout;
CallStore(store, high--, elementLow) otherwise Bailout;
}
}
@ -816,10 +793,8 @@ namespace array {
try {
// Where does b start in a? Elements in a before that can be ignored,
// because they are already in place.
const keyRight: Object = CallLoad(context, sortState, load, baseB)
otherwise Bailout;
const k: Smi =
CallGallopRight(context, sortState, load, keyRight, baseA, lengthA, 0)
const keyRight = CallLoad(load, baseB) otherwise Bailout;
const k: Smi = CallGallopRight(load, keyRight, baseA, lengthA, 0)
otherwise Bailout;
assert(k >= 0);
@ -830,11 +805,8 @@ namespace array {
// Where does a end in b? Elements in b after that can be ignored,
// because they are already in place.
let keyLeft: Object =
CallLoad(context, sortState, load, baseA + lengthA - 1)
otherwise Bailout;
lengthB = CallGallopLeft(
context, sortState, load, keyLeft, baseB, lengthB, lengthB - 1)
let keyLeft = CallLoad(load, baseA + lengthA - 1) otherwise Bailout;
lengthB = CallGallopLeft(load, keyLeft, baseB, lengthB, lengthB - 1)
otherwise Bailout;
assert(lengthB >= 0);
if (lengthB == 0) return kSuccess;
@ -842,11 +814,9 @@ namespace array {
// Merge what remains of the runs, using a temp array with
// min(lengthA, lengthB) elements.
if (lengthA <= lengthB) {
MergeLow(context, sortState, baseA, lengthA, baseB, lengthB)
otherwise Bailout;
MergeLow(baseA, lengthA, baseB, lengthB) otherwise Bailout;
} else {
MergeHigh(context, sortState, baseA, lengthA, baseB, lengthB)
otherwise Bailout;
MergeHigh(baseA, lengthA, baseB, lengthB) otherwise Bailout;
}
return kSuccess;
}
@ -855,16 +825,17 @@ namespace array {
}
}
// Locates the proper position of key in a sorted array; if the array contains
// an element equal to key, return the position immediately to the left of
// the leftmost equal element. (GallopRight does the same except returns the
// position to the right of the rightmost equal element (if any)).
// Locates the proper position of key in a sorted array; if the array
// contains an element equal to key, return the position immediately to
// the left of the leftmost equal element. (GallopRight does the same
// except returns the position to the right of the rightmost equal element
// (if any)).
//
// The array is sorted with "length" elements, starting at "base".
// "length" must be > 0.
//
// "hint" is an index at which to begin the search, 0 <= hint < n. The closer
// hint is to the final result, the faster this runs.
// "hint" is an index at which to begin the search, 0 <= hint < n. The
// closer hint is to the final result, the faster this runs.
//
// The return value is the int offset in 0..length such that
//
@ -882,12 +853,8 @@ namespace array {
let offset: Smi = 1;
try {
const baseHintElement: Object =
CallLoad(context, sortState, load, base + hint)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, baseHintElement, key)
otherwise Bailout;
const baseHintElement = CallLoad(load, base + hint) otherwise Bailout;
let order = CallCompareFn(baseHintElement, key) otherwise Bailout;
if (order < 0) {
// a[base + hint] < key: gallop right, until
@ -896,11 +863,9 @@ namespace array {
// a[base + length - 1] is highest.
let maxOfs: Smi = length - hint;
while (offset < maxOfs) {
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint + offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, offsetElement, key)
otherwise Bailout;
const offsetElement =
CallLoad(load, base + hint + offset) otherwise Bailout;
order = CallCompareFn(offsetElement, key) otherwise Bailout;
// a[base + hint + offset] >= key? Break.
if (order >= 0) break;
@ -925,11 +890,9 @@ namespace array {
// a[base + hint] is lowest.
let maxOfs: Smi = hint + 1;
while (offset < maxOfs) {
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint - offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, offsetElement, key)
otherwise Bailout;
const offsetElement =
CallLoad(load, base + hint - offset) otherwise Bailout;
order = CallCompareFn(offsetElement, key) otherwise Bailout;
if (order < 0) break;
@ -950,19 +913,16 @@ namespace array {
assert(-1 <= lastOfs && lastOfs < offset && offset <= length);
// Now a[base+lastOfs] < key <= a[base+offset], so key belongs somewhere
// to the right of lastOfs but no farther right than offset. Do a binary
// search, with invariant:
// Now a[base+lastOfs] < key <= a[base+offset], so key belongs
// somewhere to the right of lastOfs but no farther right than offset.
// Do a binary search, with invariant:
// a[base + lastOfs - 1] < key <= a[base + offset].
lastOfs++;
while (lastOfs < offset) {
const m: Smi = lastOfs + ((offset - lastOfs) >> 1);
const baseMElement: Object =
CallLoad(context, sortState, load, base + m)
otherwise Bailout;
order = CallCompareFn(context, sortState, baseMElement, key)
otherwise Bailout;
const baseMElement = CallLoad(load, base + m) otherwise Bailout;
order = CallCompareFn(baseMElement, key) otherwise Bailout;
if (order < 0) {
lastOfs = m + 1; // a[base + m] < key.
@ -981,8 +941,8 @@ namespace array {
}
// Exactly like GallopLeft, except that if key already exists in
// [base, base + length), finds the position immediately to the right of the
// rightmost equal value.
// [base, base + length), finds the position immediately to the right of
// the rightmost equal value.
//
// The return value is the int offset in 0..length such that
//
@ -999,12 +959,8 @@ namespace array {
let offset: Smi = 1;
try {
const baseHintElement: Object =
CallLoad(context, sortState, load, base + hint)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, key, baseHintElement)
otherwise Bailout;
const baseHintElement = CallLoad(load, base + hint) otherwise Bailout;
let order = CallCompareFn(key, baseHintElement) otherwise Bailout;
if (order < 0) {
// key < a[base + hint]: gallop left, until
@ -1013,11 +969,9 @@ namespace array {
// a[base + hint] is lowest.
let maxOfs: Smi = hint + 1;
while (offset < maxOfs) {
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint - offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, key, offsetElement)
otherwise Bailout;
const offsetElement =
CallLoad(load, base + hint - offset) otherwise Bailout;
order = CallCompareFn(key, offsetElement) otherwise Bailout;
if (order >= 0) break;
@ -1041,11 +995,9 @@ namespace array {
// a[base + length - 1] is highest.
let maxOfs: Smi = length - hint;
while (offset < maxOfs) {
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint + offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, key, offsetElement)
otherwise Bailout;
const offsetElement =
CallLoad(load, base + hint + offset) otherwise Bailout;
order = CallCompareFn(key, offsetElement) otherwise Bailout;
// a[base + hint + ofs] <= key.
if (order < 0) break;
@ -1073,11 +1025,8 @@ namespace array {
while (lastOfs < offset) {
const m: Smi = lastOfs + ((offset - lastOfs) >> 1);
const baseMElement: Object =
CallLoad(context, sortState, load, base + m)
otherwise Bailout;
order = CallCompareFn(context, sortState, key, baseMElement)
otherwise Bailout;
const baseMElement = CallLoad(load, base + m) otherwise Bailout;
order = CallCompareFn(key, baseMElement) otherwise Bailout;
if (order < 0) {
offset = m; // key < a[base + m].
@ -1096,14 +1045,11 @@ namespace array {
}
// Copies a single element inside the array/object (NOT the tempArray).
macro CopyElement(
context: Context, sortState: FixedArray, load: LoadFn, store: StoreFn,
from: Smi, to: Smi)
macro CopyElement(implicit context: Context, sortState: FixedArray)(
load: LoadFn, store: StoreFn, from: Smi, to: Smi)
labels Bailout {
const element: Object = CallLoad(context, sortState, load, from)
otherwise Bailout;
CallStore(context, sortState, store, to, element)
otherwise Bailout;
const element = CallLoad(load, from) otherwise Bailout;
CallStore(store, to, element) otherwise Bailout;
}
// Merge the lengthA elements starting at baseA with the lengthB elements
@ -1113,8 +1059,9 @@ namespace array {
// that array[baseA + lengthA - 1] belongs at the end of the merge,
// and should have lengthA <= lengthB.
transitioning macro MergeLow(
context: Context, sortState: FixedArray, baseA: Smi, lengthAArg: Smi,
baseB: Smi, lengthBArg: Smi)
implicit context: Context,
sortState:
FixedArray)(baseA: Smi, lengthAArg: Smi, baseB: Smi, lengthBArg: Smi)
labels Bailout {
assert(0 < lengthAArg && 0 < lengthBArg);
assert(0 <= baseA && 0 < baseB);
@ -1127,15 +1074,13 @@ namespace array {
const store: StoreFn = GetStoreFn(sortState);
const tempArray: FixedArray = GetTempArray(sortState, lengthA);
CopyToTempArray(context, sortState, load, baseA, tempArray, 0, lengthA)
otherwise Bailout;
CopyToTempArray(load, baseA, tempArray, 0, lengthA) otherwise Bailout;
let dest: Smi = baseA;
let cursorTemp: Smi = 0;
let cursorB: Smi = baseB;
CopyElement(context, sortState, load, store, cursorB++, dest++)
otherwise Bailout;
CopyElement(load, store, cursorB++, dest++) otherwise Bailout;
try {
if (--lengthB == 0) goto Succeed;
@ -1155,15 +1100,12 @@ namespace array {
while (Int32TrueConstant()) {
assert(lengthA > 1 && lengthB > 0);
let elementB: Object = CallLoad(context, sortState, load, cursorB)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, elementB, tempArray[cursorTemp])
otherwise Bailout;
let elementB = CallLoad(load, cursorB) otherwise Bailout;
let order =
CallCompareFn(elementB, tempArray[cursorTemp]) otherwise Bailout;
if (order < 0) {
CopyElement(context, sortState, load, store, cursorB, dest)
otherwise Bailout;
CopyElement(load, store, cursorB, dest) otherwise Bailout;
++cursorB;
++dest;
@ -1174,8 +1116,7 @@ namespace array {
if (lengthB == 0) goto Succeed;
if (nofWinsB >= minGallop) break;
} else {
CallStore(context, sortState, store, dest, tempArray[cursorTemp])
otherwise Bailout;
CallStore(store, dest, tempArray[cursorTemp]) otherwise Bailout;
++cursorTemp;
++dest;
@ -1188,9 +1129,9 @@ namespace array {
}
}
// One run is winning so consistently that galloping may be a huge win.
// So try that, and continue galloping until (if ever) neither run
// appears to be winning consistently anymore.
// One run is winning so consistently that galloping may be a huge
// win. So try that, and continue galloping until (if ever) neither
// run appears to be winning consistently anymore.
++minGallop;
let firstIteration: bool = true;
while (nofWinsA >= kMinGallopWins || nofWinsB >= kMinGallopWins ||
@ -1201,17 +1142,14 @@ namespace array {
minGallop = SmiMax(1, minGallop - 1);
sortState[kMinGallopIdx] = minGallop;
let keyRight: Object = CallLoad(context, sortState, load, cursorB)
otherwise Bailout;
let keyRight = CallLoad(load, cursorB) otherwise Bailout;
nofWinsA = CallGallopRight(
context, sortState, Load<TempArrayElements>, keyRight, cursorTemp,
lengthA, 0) otherwise Bailout;
Load<TempArrayElements>, keyRight, cursorTemp, lengthA, 0)
otherwise Bailout;
assert(nofWinsA >= 0);
if (nofWinsA > 0) {
CallCopyFromTempArray(
context, sortState, dest, cursorTemp, nofWinsA)
otherwise Bailout;
CallCopyFromTempArray(dest, cursorTemp, nofWinsA) otherwise Bailout;
dest = dest + nofWinsA;
cursorTemp = cursorTemp + nofWinsA;
lengthA = lengthA - nofWinsA;
@ -1222,18 +1160,15 @@ namespace array {
// consistent, but we can't assume that it is.
if (lengthA == 0) goto Succeed;
}
CopyElement(context, sortState, load, store, cursorB++, dest++)
otherwise Bailout;
CopyElement(load, store, cursorB++, dest++) otherwise Bailout;
if (--lengthB == 0) goto Succeed;
nofWinsB = CallGallopLeft(
context, sortState, load, tempArray[cursorTemp], cursorB, lengthB,
0)
nofWinsB =
CallGallopLeft(load, tempArray[cursorTemp], cursorB, lengthB, 0)
otherwise Bailout;
assert(nofWinsB >= 0);
if (nofWinsB > 0) {
CallCopyWithinSortArray(context, sortState, cursorB, dest, nofWinsB)
otherwise Bailout;
CallCopyWithinSortArray(cursorB, dest, nofWinsB) otherwise Bailout;
dest = dest + nofWinsB;
cursorB = cursorB + nofWinsB;
@ -1241,8 +1176,7 @@ namespace array {
if (lengthB == 0) goto Succeed;
}
CallStore(context, sortState, store, dest++, tempArray[cursorTemp++])
otherwise Bailout;
CallStore(store, dest++, tempArray[cursorTemp++]) otherwise Bailout;
if (--lengthA == 1) goto CopyB;
}
++minGallop; // Penalize it for leaving galloping mode
@ -1251,18 +1185,14 @@ namespace array {
}
label Succeed {
if (lengthA > 0) {
CallCopyFromTempArray(context, sortState, dest, cursorTemp, lengthA)
otherwise Bailout;
CallCopyFromTempArray(dest, cursorTemp, lengthA) otherwise Bailout;
}
}
label CopyB {
assert(lengthA == 1 && lengthB > 0);
// The last element of run A belongs at the end of the merge.
CallCopyWithinSortArray(context, sortState, cursorB, dest, lengthB)
otherwise Bailout;
CallStore(
context, sortState, store, dest + lengthB, tempArray[cursorTemp])
otherwise Bailout;
CallCopyWithinSortArray(cursorB, dest, lengthB) otherwise Bailout;
CallStore(store, dest + lengthB, tempArray[cursorTemp]) otherwise Bailout;
}
}
@ -1271,8 +1201,9 @@ namespace array {
// be > 0. Must also have that array[baseA + lengthA - 1] belongs at the
// end of the merge and should have lengthA >= lengthB.
transitioning macro MergeHigh(
context: Context, sortState: FixedArray, baseA: Smi, lengthAArg: Smi,
baseB: Smi, lengthBArg: Smi)
implicit context: Context,
sortState:
FixedArray)(baseA: Smi, lengthAArg: Smi, baseB: Smi, lengthBArg: Smi)
labels Bailout {
assert(0 < lengthAArg && 0 < lengthBArg);
assert(0 <= baseA && 0 < baseB);
@ -1285,16 +1216,14 @@ namespace array {
const store: StoreFn = GetStoreFn(sortState);
const tempArray: FixedArray = GetTempArray(sortState, lengthB);
CopyToTempArray(context, sortState, load, baseB, tempArray, 0, lengthB)
otherwise Bailout;
CopyToTempArray(load, baseB, tempArray, 0, lengthB) otherwise Bailout;
// MergeHigh merges the two runs backwards.
let dest: Smi = baseB + lengthB - 1;
let cursorTemp: Smi = lengthB - 1;
let cursorA: Smi = baseA + lengthA - 1;
CopyElement(context, sortState, load, store, cursorA--, dest--)
otherwise Bailout;
CopyElement(load, store, cursorA--, dest--) otherwise Bailout;
try {
if (--lengthA == 0) goto Succeed;
@ -1314,15 +1243,12 @@ namespace array {
while (Int32TrueConstant()) {
assert(lengthA > 0 && lengthB > 1);
let elementA: Object = CallLoad(context, sortState, load, cursorA)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, tempArray[cursorTemp], elementA)
otherwise Bailout;
let elementA = CallLoad(load, cursorA) otherwise Bailout;
let order =
CallCompareFn(tempArray[cursorTemp], elementA) otherwise Bailout;
if (order < 0) {
CopyElement(context, sortState, load, store, cursorA, dest)
otherwise Bailout;
CopyElement(load, store, cursorA, dest) otherwise Bailout;
--cursorA;
--dest;
@ -1333,8 +1259,7 @@ namespace array {
if (lengthA == 0) goto Succeed;
if (nofWinsA >= minGallop) break;
} else {
CallStore(context, sortState, store, dest, tempArray[cursorTemp])
otherwise Bailout;
CallStore(store, dest, tempArray[cursorTemp]) otherwise Bailout;
--cursorTemp;
--dest;
@ -1347,9 +1272,9 @@ namespace array {
}
}
// One run is winning so consistently that galloping may be a huge win.
// So try that, and continue galloping until (if ever) neither run
// appears to be winning consistently anymore.
// One run is winning so consistently that galloping may be a huge
// win. So try that, and continue galloping until (if ever) neither
// run appears to be winning consistently anymore.
++minGallop;
let firstIteration: bool = true;
while (nofWinsA >= kMinGallopWins || nofWinsB >= kMinGallopWins ||
@ -1362,8 +1287,7 @@ namespace array {
sortState[kMinGallopIdx] = minGallop;
let k: Smi = CallGallopRight(
context, sortState, load, tempArray[cursorTemp], baseA, lengthA,
lengthA - 1)
load, tempArray[cursorTemp], baseA, lengthA, lengthA - 1)
otherwise Bailout;
assert(k >= 0);
nofWinsA = lengthA - k;
@ -1371,30 +1295,26 @@ namespace array {
if (nofWinsA > 0) {
dest = dest - nofWinsA;
cursorA = cursorA - nofWinsA;
CallCopyWithinSortArray(
context, sortState, cursorA + 1, dest + 1, nofWinsA)
CallCopyWithinSortArray(cursorA + 1, dest + 1, nofWinsA)
otherwise Bailout;
lengthA = lengthA - nofWinsA;
if (lengthA == 0) goto Succeed;
}
CallStore(context, sortState, store, dest--, tempArray[cursorTemp--])
otherwise Bailout;
CallStore(store, dest--, tempArray[cursorTemp--]) otherwise Bailout;
if (--lengthB == 1) goto CopyA;
let key: Object = CallLoad(context, sortState, load, cursorA)
otherwise Bailout;
let key = CallLoad(load, cursorA) otherwise Bailout;
k = CallGallopLeft(
context, sortState, Load<TempArrayElements>, key, 0, lengthB,
lengthB - 1) otherwise Bailout;
Load<TempArrayElements>, key, 0, lengthB, lengthB - 1)
otherwise Bailout;
assert(k >= 0);
nofWinsB = lengthB - k;
if (nofWinsB > 0) {
dest = dest - nofWinsB;
cursorTemp = cursorTemp - nofWinsB;
CallCopyFromTempArray(
context, sortState, dest + 1, cursorTemp + 1, nofWinsB)
CallCopyFromTempArray(dest + 1, cursorTemp + 1, nofWinsB)
otherwise Bailout;
lengthB = lengthB - nofWinsB;
@ -1404,8 +1324,7 @@ namespace array {
// consistent, but we can't assume that it is.
if (lengthB == 0) goto Succeed;
}
CopyElement(context, sortState, load, store, cursorA--, dest--)
otherwise Bailout;
CopyElement(load, store, cursorA--, dest--) otherwise Bailout;
if (--lengthA == 0) goto Succeed;
}
++minGallop;
@ -1415,8 +1334,7 @@ namespace array {
label Succeed {
if (lengthB > 0) {
assert(lengthA == 0);
CallCopyFromTempArray(
context, sortState, dest - (lengthB - 1), 0, lengthB)
CallCopyFromTempArray(dest - (lengthB - 1), 0, lengthB)
otherwise Bailout;
}
}
@ -1426,16 +1344,13 @@ namespace array {
// The first element of run B belongs at the front of the merge.
dest = dest - lengthA;
cursorA = cursorA - lengthA;
CallCopyWithinSortArray(
context, sortState, cursorA + 1, dest + 1, lengthA)
otherwise Bailout;
CallStore(context, sortState, store, dest, tempArray[cursorTemp])
otherwise Bailout;
CallCopyWithinSortArray(cursorA + 1, dest + 1, lengthA) otherwise Bailout;
CallStore(store, dest, tempArray[cursorTemp]) otherwise Bailout;
}
}
// Compute a good value for the minimum run length; natural runs shorter than
// this are boosted artificially via binary insertion sort.
// Compute a good value for the minimum run length; natural runs shorter
// than this are boosted artificially via binary insertion sort.
//
// If n < 64, return n (it's too small to bother with fancy stuff).
// Else if n is an exact power of 2, return 32.
@ -1495,11 +1410,11 @@ namespace array {
--n;
}
CallMergeAt(context, sortState, n) otherwise Bailout;
CallMergeAt(n) otherwise Bailout;
} else if (
GetPendingRunLength(pendingRuns, n) <=
GetPendingRunLength(pendingRuns, n + 1)) {
CallMergeAt(context, sortState, n) otherwise Bailout;
CallMergeAt(n) otherwise Bailout;
} else {
break;
}
@ -1523,7 +1438,7 @@ namespace array {
GetPendingRunLength(pendingRuns, n + 1)) {
--n;
}
CallMergeAt(context, sortState, n) otherwise Bailout;
CallMergeAt(n) otherwise Bailout;
}
}
@ -1599,8 +1514,7 @@ namespace array {
transitioning builtin
ArrayTimSort(context: Context, sortState: FixedArray, length: Smi): Object {
try {
ArrayTimSortImpl(context, sortState, length)
otherwise Slow;
ArrayTimSortImpl(context, sortState, length) otherwise Slow;
}
label Slow {
if (sortState[kAccessorIdx] == kGenericElementsAccessorId) {