Commit dc4c8bdb authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

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