[cleanup] Remove usage of 'ReloadElements' from Array#sort

This CL is mostly a mechanical change. Loading either the receiver,
the backing store or the temp array from the sort state is pushed down
into each respective Load/Store builtin. This eliminates the need
for reloading the elements pointer after each compare function call.

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

Bug: v8:8562
Change-Id: I453e98635f9d891da58cf7b2a86c5c58f4a4069c
Reviewed-on: https://chromium-review.googlesource.com/c/1449613
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@{#59291}
This commit is contained in:
Simon Zünd 2019-02-01 12:24:36 +01:00 committed by Commit Bot
parent 30c1199f77
commit 0b2fa277fb

View File

@ -112,8 +112,8 @@ namespace array {
// it is first requested, but it has always at least this size.
const kSortStateTempSize: Smi = 32;
type LoadFn = builtin(Context, FixedArray, HeapObject, Smi) => Object;
type StoreFn = builtin(Context, FixedArray, HeapObject, Smi, Object) => Smi;
type LoadFn = builtin(Context, FixedArray, Smi) => Object;
type StoreFn = builtin(Context, FixedArray, Smi, Object) => Smi;
type CanUseSameAccessorFn = builtin(Context, JSReceiver, Object, Number) =>
Boolean;
type CompareBuiltinFn = builtin(Context, Object, Object, Object) => Number;
@ -125,23 +125,25 @@ namespace array {
// through a hole.
transitioning builtin Load<ElementsAccessor: type>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
return GetProperty(elements, index);
context: Context, sortState: FixedArray, index: Smi): Object {
const receiver = GetReceiver(sortState);
return GetProperty(receiver, index);
}
Load<FastPackedSmiElements>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
const elems: FixedArray = UnsafeCast<FixedArray>(elements);
return elems[index];
context: Context, sortState: FixedArray, index: Smi): Object {
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const elements = UnsafeCast<FixedArray>(object.elements);
return elements[index];
}
Load<FastSmiOrObjectElements>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
const elems: FixedArray = UnsafeCast<FixedArray>(elements);
const result: Object = elems[index];
context: Context, sortState: FixedArray, index: Smi): Object {
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const elements = UnsafeCast<FixedArray>(object.elements);
const result: Object = elements[index];
if (IsTheHole(result)) {
// The pre-processing step removed all holes by compacting all elements
// at the start of the array. Finding a hole means the cmp function or
@ -151,13 +153,13 @@ namespace array {
return result;
}
Load<FastDoubleElements>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
Load<FastDoubleElements>(context: Context, sortState: FixedArray, index: Smi):
Object {
try {
const elems: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
const value: float64 =
LoadDoubleWithHoleCheck(elems, index) otherwise Bailout;
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const elements = UnsafeCast<FixedDoubleArray>(object.elements);
const value = LoadDoubleWithHoleCheck(elements, index) otherwise Bailout;
return AllocateHeapNumberWithValue(value);
}
label Bailout {
@ -168,70 +170,71 @@ namespace array {
}
}
Load<DictionaryElements>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
Load<DictionaryElements>(context: Context, sortState: FixedArray, index: Smi):
Object {
try {
const dictionary: NumberDictionary =
UnsafeCast<NumberDictionary>(elements);
const intptrIndex: intptr = Convert<intptr>(index);
const value: Object =
BasicLoadNumberDictionaryElement(dictionary, intptrIndex)
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const dictionary = UnsafeCast<NumberDictionary>(object.elements);
const intptrIndex = Convert<intptr>(index);
return BasicLoadNumberDictionaryElement(dictionary, intptrIndex)
otherwise Bailout, Bailout;
return value;
}
label Bailout {
return Failure(sortState);
}
}
Load<TempArrayElements>(
context: Context, sortState: FixedArray, elements: HeapObject,
index: Smi): Object {
Load<TempArrayElements>(context: Context, sortState: FixedArray, index: Smi):
Object {
const elements = GetTempArray(sortState);
assert(IsFixedArray(elements));
const elems: FixedArray = UnsafeCast<FixedArray>(elements);
return elems[index];
return elements[index];
}
transitioning builtin Store<ElementsAccessor: type>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
SetProperty(elements, index, value);
context: Context, sortState: FixedArray, index: Smi, value: Object): Smi {
const receiver = GetReceiver(sortState);
SetProperty(receiver, index, value);
return kSuccess;
}
Store<FastPackedSmiElements>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
const elems: FixedArray = UnsafeCast<FixedArray>(elements);
StoreFixedArrayElementSmi(elems, index, value, SKIP_WRITE_BARRIER);
context: Context, sortState: FixedArray, index: Smi, value: Object): Smi {
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const elements = UnsafeCast<FixedArray>(object.elements);
StoreFixedArrayElementSmi(elements, index, value, SKIP_WRITE_BARRIER);
return kSuccess;
}
Store<FastSmiOrObjectElements>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
const elems: FixedArray = UnsafeCast<FixedArray>(elements);
elems[index] = value;
context: Context, sortState: FixedArray, index: Smi, value: Object): Smi {
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const elements = UnsafeCast<FixedArray>(object.elements);
elements[index] = value;
return kSuccess;
}
Store<FastDoubleElements>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
const elems: FixedDoubleArray = UnsafeCast<FixedDoubleArray>(elements);
const heapVal: HeapNumber = UnsafeCast<HeapNumber>(value);
context: Context, sortState: FixedArray, index: Smi, value: Object): Smi {
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const elements = UnsafeCast<FixedDoubleArray>(object.elements);
const heapVal = UnsafeCast<HeapNumber>(value);
// Make sure we do not store signalling NaNs into double arrays.
const val: float64 = Float64SilenceNaN(Convert<float64>(heapVal));
StoreFixedDoubleArrayElementWithSmiIndex(elems, index, val);
const val = Float64SilenceNaN(Convert<float64>(heapVal));
StoreFixedDoubleArrayElementWithSmiIndex(elements, index, val);
return kSuccess;
}
Store<DictionaryElements>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
const dictionary: NumberDictionary = UnsafeCast<NumberDictionary>(elements);
const intptrIndex: intptr = Convert<intptr>(index);
context: Context, sortState: FixedArray, index: Smi, value: Object): Smi {
const receiver = GetReceiver(sortState);
const object = UnsafeCast<JSObject>(receiver);
const dictionary = UnsafeCast<NumberDictionary>(object.elements);
const intptrIndex = Convert<intptr>(index);
try {
BasicStoreNumberDictionaryElement(dictionary, intptrIndex, value)
otherwise Fail, Fail, ReadOnly;
@ -240,7 +243,7 @@ namespace array {
label ReadOnly {
// We cannot write to read-only data properties. Throw the same TypeError
// as SetProperty would.
const receiver: JSReceiver = GetReceiver(sortState);
const receiver = GetReceiver(sortState);
ThrowTypeError(
context, kStrictReadOnlyProperty, index, Typeof(receiver), receiver);
}
@ -250,10 +253,9 @@ namespace array {
}
Store<TempArrayElements>(
context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
value: Object): Smi {
const elems: FixedArray = UnsafeCast<FixedArray>(elements);
elems[index] = value;
context: Context, sortState: FixedArray, index: Smi, value: Object): Smi {
const elements = GetTempArray(sortState);
elements[index] = value;
return kSuccess;
}
@ -281,10 +283,10 @@ namespace array {
}
// 5. Let xString be ? ToString(x).
const xString: String = ToString_Inline(context, x);
const xString = ToString_Inline(context, x);
// 6. Let yString be ? ToString(y).
const yString: String = ToString_Inline(context, y);
const yString = ToString_Inline(context, y);
// 7. Let xSmaller be the result of performing
// Abstract Relational Comparison xString < yString.
@ -303,11 +305,10 @@ namespace array {
transitioning builtin SortCompareUserFn(
context: Context, comparefn: Object, x: Object, y: Object): Number {
assert(comparefn != Undefined);
const cmpfn: Callable = UnsafeCast<Callable>(comparefn);
const cmpfn = UnsafeCast<Callable>(comparefn);
// a. Let v be ? ToNumber(? Call(comparefn, undefined, x, y)).
const v: Number =
ToNumber_Inline(context, Call(context, cmpfn, Undefined, x, y));
const v = ToNumber_Inline(context, Call(context, cmpfn, Undefined, x, y));
// b. If v is NaN, return +0.
if (NumberIsNaN(v)) return 0;
@ -365,19 +366,6 @@ namespace array {
return result;
}
// Reloading elements after returning from JS is needed since left-trimming
// might have occurred. This means we cannot leave any pointer to the elements
// backing store on the stack (since it would point to the filler object).
// TODO(v8:7995): Remove reloading once left-trimming is removed.
macro ReloadElements(implicit context: Context)(sortState: FixedArray):
HeapObject {
const receiver: JSReceiver = GetReceiver(sortState);
if (sortState[kAccessorIdx] == kGenericElementsAccessorId) return receiver;
const object: JSObject = UnsafeCast<JSObject>(receiver);
return object.elements;
}
macro GetInitialReceiverLength(implicit context:
Context)(sortState: FixedArray): Number {
return UnsafeCast<Number>(sortState[kInitialReceiverLengthIdx]);
@ -492,54 +480,52 @@ namespace array {
// or the return value.
macro CallLoad(
context: Context, sortState: FixedArray, load: LoadFn,
elements: HeapObject, index: Smi): Object
context: Context, sortState: FixedArray, load: LoadFn, index: Smi): Object
labels Bailout {
const result: Object = load(context, sortState, elements, index);
const result: Object = load(context, sortState, index);
EnsureSuccess(sortState) otherwise Bailout;
return result;
}
macro CallStore(
context: Context, sortState: FixedArray, store: StoreFn,
elements: HeapObject, index: Smi, value: Object) labels Bailout {
store(context, sortState, elements, index, value);
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, dstElements: HeapObject,
dstPos: Smi, tempArray: FixedArray, srcPos: Smi, length: Smi)
context: Context, sortState: FixedArray, dstPos: Smi, srcPos: Smi,
length: Smi)
labels Bailout {
CopyFromTempArray(
context, sortState, dstElements, dstPos, tempArray, srcPos, length);
CopyFromTempArray(context, sortState, dstPos, srcPos, length);
EnsureSuccess(sortState) otherwise Bailout;
}
transitioning macro CallCopyWithinSortArray(
context: Context, sortState: FixedArray, elements: HeapObject,
srcPos: Smi, dstPos: Smi, length: Smi)
context: Context, sortState: FixedArray, srcPos: Smi, dstPos: Smi,
length: Smi)
labels Bailout {
CopyWithinSortArray(context, sortState, elements, srcPos, dstPos, length);
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, useTempArray: Boolean): Smi
base: Smi, length: Smi, hint: Smi): Smi
labels Bailout {
const result: Smi = GallopRight(
context, sortState, load, key, base, length, hint, useTempArray);
const result: Smi =
GallopRight(context, sortState, load, key, base, length, hint);
EnsureSuccess(sortState) otherwise Bailout;
return result;
}
macro CallGallopLeft(
context: Context, sortState: FixedArray, load: LoadFn, key: Object,
base: Smi, length: Smi, hint: Smi, useTempArray: Boolean): Smi
base: Smi, length: Smi, hint: Smi): Smi
labels Bailout {
const result: Smi = GallopLeft(
context, sortState, load, key, base, length, hint, useTempArray);
const result: Smi =
GallopLeft(context, sortState, load, key, base, length, hint);
EnsureSuccess(sortState) otherwise Bailout;
return result;
}
@ -552,9 +538,8 @@ namespace array {
}
transitioning macro CopyToTempArray(
context: Context, sortState: FixedArray, load: LoadFn,
srcElements: HeapObject, srcPos: Smi, tempArray: FixedArray, dstPos: Smi,
length: Smi)
context: Context, sortState: FixedArray, load: LoadFn, srcPos: Smi,
tempArray: FixedArray, dstPos: Smi, length: Smi)
labels Bailout {
assert(srcPos >= 0);
assert(dstPos >= 0);
@ -566,16 +551,16 @@ namespace array {
let to: Smi = srcPos + length;
while (srcIdx < to) {
let element: Object =
CallLoad(context, sortState, load, srcElements, srcIdx++)
let element: Object = CallLoad(context, sortState, load, srcIdx++)
otherwise Bailout;
tempArray[dstIdx++] = element;
}
}
transitioning builtin CopyFromTempArray(
context: Context, sortState: FixedArray, dstElements: HeapObject,
dstPos: Smi, tempArray: FixedArray, srcPos: Smi, length: Smi): Smi {
context: Context, sortState: FixedArray, dstPos: Smi, srcPos: Smi,
length: Smi): Smi {
const tempArray = GetTempArray(sortState);
assert(srcPos >= 0);
assert(dstPos >= 0);
assert(srcPos <= tempArray.length - length);
@ -588,9 +573,7 @@ namespace array {
let to: Smi = srcPos + length;
try {
while (srcIdx < to) {
CallStore(
context, sortState, store, dstElements, dstIdx++,
tempArray[srcIdx++])
CallStore(context, sortState, store, dstIdx++, tempArray[srcIdx++])
otherwise Bailout;
}
return kSuccess;
@ -601,8 +584,8 @@ namespace array {
}
transitioning builtin CopyWithinSortArray(
context: Context, sortState: FixedArray, elements: HeapObject,
srcPos: Smi, dstPos: Smi, length: Smi): Smi {
context: Context, sortState: FixedArray, srcPos: Smi, dstPos: Smi,
length: Smi): Smi {
assert(srcPos >= 0);
assert(dstPos >= 0);
assert(srcPos <= GetInitialReceiverLength(sortState) - length);
@ -616,8 +599,7 @@ namespace array {
let srcIdx: Smi = srcPos + length - 1;
let dstIdx: Smi = dstPos + length - 1;
while (srcIdx >= srcPos) {
CopyElement(
context, sortState, load, store, elements, srcIdx--, dstIdx--)
CopyElement(context, sortState, load, store, srcIdx--, dstIdx--)
otherwise Bailout;
}
} else {
@ -625,8 +607,7 @@ namespace array {
let dstIdx: Smi = dstPos;
let to: Smi = srcPos + length;
while (srcIdx < to) {
CopyElement(
context, sortState, load, store, elements, srcIdx++, dstIdx++)
CopyElement(context, sortState, load, store, srcIdx++, dstIdx++)
otherwise Bailout;
}
}
@ -653,8 +634,6 @@ namespace array {
assert(low <= startArg && startArg <= high);
try {
let elements: HeapObject = ReloadElements(sortState);
const load: LoadFn = GetLoadFn(sortState);
const store: StoreFn = GetStoreFn(sortState);
@ -665,8 +644,7 @@ namespace array {
let left: Smi = low;
let right: Smi = start;
const pivot: Object =
CallLoad(context, sortState, load, elements, right)
const pivot: Object = CallLoad(context, sortState, load, right)
otherwise Bailout;
// Invariants:
@ -677,13 +655,11 @@ namespace array {
// Find pivot insertion point.
while (left < right) {
const mid: Smi = left + ((right - left) >> 1);
const midElement: Object =
CallLoad(context, sortState, load, elements, mid)
const midElement: Object = CallLoad(context, sortState, load, mid)
otherwise Bailout;
const order: Number =
CallCompareFn(context, sortState, pivot, midElement)
otherwise Bailout;
elements = ReloadElements(sortState);
if (order < 0) {
right = mid;
@ -702,10 +678,10 @@ namespace array {
// sort is stable.
// Slide over to make room.
for (let p: Smi = start; p > left; --p) {
CopyElement(context, sortState, load, store, elements, p - 1, p)
CopyElement(context, sortState, load, store, p - 1, p)
otherwise Bailout;
}
CallStore(context, sortState, store, elements, left, pivot)
CallStore(context, sortState, store, left, pivot)
otherwise Bailout;
}
return kSuccess;
@ -737,7 +713,6 @@ namespace array {
labels Bailout {
assert(lowArg < high);
let elements: HeapObject = ReloadElements(sortState);
const load: LoadFn = GetLoadFn(sortState);
const store: StoreFn = GetStoreFn(sortState);
@ -747,13 +722,12 @@ namespace array {
let runLength: Smi = 2;
const elementLow: Object =
CallLoad(context, sortState, load, elements, low) otherwise Bailout;
CallLoad(context, sortState, load, low) otherwise Bailout;
const elementLowPred: Object =
CallLoad(context, sortState, load, elements, low - 1) otherwise Bailout;
CallLoad(context, sortState, load, low - 1) otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, elementLow, elementLowPred)
otherwise Bailout;
elements = ReloadElements(sortState);
// TODO(szuend): Replace with "order < 0" once Torque supports it.
// Currently the operator<(Number, Number) has return type
@ -763,10 +737,9 @@ namespace array {
let previousElement: Object = elementLow;
for (let idx: Smi = low + 1; idx < high; ++idx) {
const currentElement: Object =
CallLoad(context, sortState, load, elements, idx) otherwise Bailout;
CallLoad(context, sortState, load, idx) otherwise Bailout;
order = CallCompareFn(context, sortState, currentElement, previousElement)
otherwise Bailout;
elements = ReloadElements(sortState);
if (isDescending) {
if (order >= 0) break;
@ -779,8 +752,7 @@ namespace array {
}
if (isDescending) {
ReverseRange(
context, sortState, load, store, elements, lowArg, lowArg + runLength)
ReverseRange(context, sortState, load, store, lowArg, lowArg + runLength)
otherwise Bailout;
}
@ -789,19 +761,19 @@ namespace array {
macro ReverseRange(
context: Context, sortState: FixedArray, load: LoadFn, store: StoreFn,
elements: HeapObject, from: Smi, to: Smi)
from: Smi, to: Smi)
labels Bailout {
let low: Smi = from;
let high: Smi = to - 1;
while (low < high) {
const elementLow: Object =
CallLoad(context, sortState, load, elements, low) otherwise Bailout;
CallLoad(context, sortState, load, low) otherwise Bailout;
const elementHigh: Object =
CallLoad(context, sortState, load, elements, high) otherwise Bailout;
CallStore(context, sortState, store, elements, low++, elementHigh)
CallLoad(context, sortState, load, high) otherwise Bailout;
CallStore(context, sortState, store, low++, elementHigh)
otherwise Bailout;
CallStore(context, sortState, store, elements, high--, elementLow)
CallStore(context, sortState, store, high--, elementLow)
otherwise Bailout;
}
}
@ -818,7 +790,6 @@ namespace array {
assert(i >= 0);
assert(i == stackSize - 2 || i == stackSize - 3);
let elements: HeapObject = ReloadElements(sortState);
const load: LoadFn = GetLoadFn(sortState);
const pendingRuns: FixedArray =
@ -845,13 +816,11 @@ 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, elements, baseB)
const keyRight: Object = CallLoad(context, sortState, load, baseB)
otherwise Bailout;
const k: Smi = CallGallopRight(
context, sortState, load, keyRight, baseA, lengthA, 0, False)
const k: Smi =
CallGallopRight(context, sortState, load, keyRight, baseA, lengthA, 0)
otherwise Bailout;
elements = ReloadElements(sortState);
assert(k >= 0);
baseA = baseA + k;
@ -862,12 +831,11 @@ 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, elements, baseA + lengthA - 1)
CallLoad(context, sortState, load, baseA + lengthA - 1)
otherwise Bailout;
lengthB = CallGallopLeft(
context, sortState, load, keyLeft, baseB, lengthB, lengthB - 1, False)
context, sortState, load, keyLeft, baseB, lengthB, lengthB - 1)
otherwise Bailout;
elements = ReloadElements(sortState);
assert(lengthB >= 0);
if (lengthB == 0) return kSuccess;
@ -887,12 +855,6 @@ namespace array {
}
}
macro LoadElementsOrTempArray(implicit context: Context)(
useTempArray: Boolean, sortState: FixedArray): HeapObject {
return useTempArray == True ? GetTempArray(sortState) :
ReloadElements(sortState);
}
// 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
@ -912,7 +874,7 @@ namespace array {
// is plus infinity. In other words, key belongs at index base + k.
builtin GallopLeft(
context: Context, sortState: FixedArray, load: LoadFn, key: Object,
base: Smi, length: Smi, hint: Smi, useTempArray: Boolean): Smi {
base: Smi, length: Smi, hint: Smi): Smi {
assert(length > 0 && base >= 0);
assert(0 <= hint && hint < length);
@ -920,9 +882,8 @@ namespace array {
let offset: Smi = 1;
try {
const baseHintElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState), base + hint)
const baseHintElement: Object =
CallLoad(context, sortState, load, base + hint)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, baseHintElement, key)
@ -935,10 +896,8 @@ namespace array {
// a[base + length - 1] is highest.
let maxOfs: Smi = length - hint;
while (offset < maxOfs) {
const offsetElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState),
base + hint + offset)
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint + offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, offsetElement, key)
otherwise Bailout;
@ -966,10 +925,8 @@ namespace array {
// a[base + hint] is lowest.
let maxOfs: Smi = hint + 1;
while (offset < maxOfs) {
const offsetElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState),
base + hint - offset)
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint - offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, offsetElement, key)
otherwise Bailout;
@ -1001,9 +958,8 @@ namespace array {
while (lastOfs < offset) {
const m: Smi = lastOfs + ((offset - lastOfs) >> 1);
const baseMElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState), base + m)
const baseMElement: Object =
CallLoad(context, sortState, load, base + m)
otherwise Bailout;
order = CallCompareFn(context, sortState, baseMElement, key)
otherwise Bailout;
@ -1035,7 +991,7 @@ namespace array {
// or kFailure on error.
builtin GallopRight(
context: Context, sortState: FixedArray, load: LoadFn, key: Object,
base: Smi, length: Smi, hint: Smi, useTempArray: Boolean): Smi {
base: Smi, length: Smi, hint: Smi): Smi {
assert(length > 0 && base >= 0);
assert(0 <= hint && hint < length);
@ -1043,9 +999,8 @@ namespace array {
let offset: Smi = 1;
try {
const baseHintElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState), base + hint)
const baseHintElement: Object =
CallLoad(context, sortState, load, base + hint)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, key, baseHintElement)
@ -1058,10 +1013,8 @@ namespace array {
// a[base + hint] is lowest.
let maxOfs: Smi = hint + 1;
while (offset < maxOfs) {
const offsetElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState),
base + hint - offset)
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint - offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, key, offsetElement)
otherwise Bailout;
@ -1088,10 +1041,8 @@ namespace array {
// a[base + length - 1] is highest.
let maxOfs: Smi = length - hint;
while (offset < maxOfs) {
const offsetElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState),
base + hint + offset)
const offsetElement: Object =
CallLoad(context, sortState, load, base + hint + offset)
otherwise Bailout;
order = CallCompareFn(context, sortState, key, offsetElement)
otherwise Bailout;
@ -1122,9 +1073,8 @@ namespace array {
while (lastOfs < offset) {
const m: Smi = lastOfs + ((offset - lastOfs) >> 1);
const baseMElement: Object = CallLoad(
context, sortState, load,
LoadElementsOrTempArray(useTempArray, sortState), base + m)
const baseMElement: Object =
CallLoad(context, sortState, load, base + m)
otherwise Bailout;
order = CallCompareFn(context, sortState, key, baseMElement)
otherwise Bailout;
@ -1148,11 +1098,11 @@ namespace array {
// Copies a single element inside the array/object (NOT the tempArray).
macro CopyElement(
context: Context, sortState: FixedArray, load: LoadFn, store: StoreFn,
elements: HeapObject, from: Smi, to: Smi)
from: Smi, to: Smi)
labels Bailout {
const element: Object = CallLoad(context, sortState, load, elements, from)
const element: Object = CallLoad(context, sortState, load, from)
otherwise Bailout;
CallStore(context, sortState, store, elements, to, element)
CallStore(context, sortState, store, to, element)
otherwise Bailout;
}
@ -1173,20 +1123,18 @@ namespace array {
let lengthA: Smi = lengthAArg;
let lengthB: Smi = lengthBArg;
let elements: HeapObject = ReloadElements(sortState);
const load: LoadFn = GetLoadFn(sortState);
const store: StoreFn = GetStoreFn(sortState);
const tempArray: FixedArray = GetTempArray(sortState, lengthA);
CopyToTempArray(
context, sortState, load, elements, baseA, tempArray, 0, lengthA)
CopyToTempArray(context, sortState, load, baseA, tempArray, 0, lengthA)
otherwise Bailout;
let dest: Smi = baseA;
let cursorTemp: Smi = 0;
let cursorB: Smi = baseB;
CopyElement(context, sortState, load, store, elements, cursorB++, dest++)
CopyElement(context, sortState, load, store, cursorB++, dest++)
otherwise Bailout;
try {
@ -1207,17 +1155,14 @@ namespace array {
while (Int32TrueConstant()) {
assert(lengthA > 1 && lengthB > 0);
let elementB: Object =
CallLoad(context, sortState, load, elements, cursorB)
let elementB: Object = CallLoad(context, sortState, load, cursorB)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, elementB, tempArray[cursorTemp])
otherwise Bailout;
elements = ReloadElements(sortState);
if (order < 0) {
CopyElement(
context, sortState, load, store, elements, cursorB, dest)
CopyElement(context, sortState, load, store, cursorB, dest)
otherwise Bailout;
++cursorB;
@ -1229,9 +1174,7 @@ namespace array {
if (lengthB == 0) goto Succeed;
if (nofWinsB >= minGallop) break;
} else {
CallStore(
context, sortState, store, elements, dest,
tempArray[cursorTemp])
CallStore(context, sortState, store, dest, tempArray[cursorTemp])
otherwise Bailout;
++cursorTemp;
@ -1258,19 +1201,17 @@ namespace array {
minGallop = SmiMax(1, minGallop - 1);
sortState[kMinGallopIdx] = minGallop;
let keyRight: Object =
CallLoad(context, sortState, load, elements, cursorB)
let keyRight: Object = CallLoad(context, sortState, load, cursorB)
otherwise Bailout;
nofWinsA = CallGallopRight(
context, sortState, Load<TempArrayElements>, keyRight, cursorTemp,
lengthA, 0, True) otherwise Bailout;
elements = ReloadElements(sortState);
lengthA, 0) otherwise Bailout;
assert(nofWinsA >= 0);
if (nofWinsA > 0) {
CallCopyFromTempArray(
context, sortState, elements, dest, tempArray, cursorTemp,
nofWinsA) otherwise Bailout;
context, sortState, dest, cursorTemp, nofWinsA)
otherwise Bailout;
dest = dest + nofWinsA;
cursorTemp = cursorTemp + nofWinsA;
lengthA = lengthA - nofWinsA;
@ -1281,20 +1222,17 @@ namespace array {
// consistent, but we can't assume that it is.
if (lengthA == 0) goto Succeed;
}
CopyElement(
context, sortState, load, store, elements, cursorB++, dest++)
CopyElement(context, sortState, load, store, cursorB++, dest++)
otherwise Bailout;
if (--lengthB == 0) goto Succeed;
nofWinsB = CallGallopLeft(
context, sortState, load, tempArray[cursorTemp], cursorB, lengthB,
0, False)
0)
otherwise Bailout;
elements = ReloadElements(sortState);
assert(nofWinsB >= 0);
if (nofWinsB > 0) {
CallCopyWithinSortArray(
context, sortState, elements, cursorB, dest, nofWinsB)
CallCopyWithinSortArray(context, sortState, cursorB, dest, nofWinsB)
otherwise Bailout;
dest = dest + nofWinsB;
@ -1303,9 +1241,7 @@ namespace array {
if (lengthB == 0) goto Succeed;
}
CallStore(
context, sortState, store, elements, dest++,
tempArray[cursorTemp++])
CallStore(context, sortState, store, dest++, tempArray[cursorTemp++])
otherwise Bailout;
if (--lengthA == 1) goto CopyB;
}
@ -1315,20 +1251,17 @@ namespace array {
}
label Succeed {
if (lengthA > 0) {
CallCopyFromTempArray(
context, sortState, elements, dest, tempArray, cursorTemp, lengthA)
CallCopyFromTempArray(context, sortState, 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, elements, cursorB, dest, lengthB)
CallCopyWithinSortArray(context, sortState, cursorB, dest, lengthB)
otherwise Bailout;
CallStore(
context, sortState, store, elements, dest + lengthB,
tempArray[cursorTemp])
context, sortState, store, dest + lengthB, tempArray[cursorTemp])
otherwise Bailout;
}
}
@ -1348,13 +1281,11 @@ namespace array {
let lengthA: Smi = lengthAArg;
let lengthB: Smi = lengthBArg;
let elements: HeapObject = ReloadElements(sortState);
const load: LoadFn = GetLoadFn(sortState);
const store: StoreFn = GetStoreFn(sortState);
const tempArray: FixedArray = GetTempArray(sortState, lengthB);
CopyToTempArray(
context, sortState, load, elements, baseB, tempArray, 0, lengthB)
CopyToTempArray(context, sortState, load, baseB, tempArray, 0, lengthB)
otherwise Bailout;
// MergeHigh merges the two runs backwards.
@ -1362,7 +1293,7 @@ namespace array {
let cursorTemp: Smi = lengthB - 1;
let cursorA: Smi = baseA + lengthA - 1;
CopyElement(context, sortState, load, store, elements, cursorA--, dest--)
CopyElement(context, sortState, load, store, cursorA--, dest--)
otherwise Bailout;
try {
@ -1383,17 +1314,14 @@ namespace array {
while (Int32TrueConstant()) {
assert(lengthA > 0 && lengthB > 1);
let elementA: Object =
CallLoad(context, sortState, load, elements, cursorA)
let elementA: Object = CallLoad(context, sortState, load, cursorA)
otherwise Bailout;
let order: Number =
CallCompareFn(context, sortState, tempArray[cursorTemp], elementA)
otherwise Bailout;
elements = ReloadElements(sortState);
if (order < 0) {
CopyElement(
context, sortState, load, store, elements, cursorA, dest)
CopyElement(context, sortState, load, store, cursorA, dest)
otherwise Bailout;
--cursorA;
@ -1405,9 +1333,7 @@ namespace array {
if (lengthA == 0) goto Succeed;
if (nofWinsA >= minGallop) break;
} else {
CallStore(
context, sortState, store, elements, dest,
tempArray[cursorTemp])
CallStore(context, sortState, store, dest, tempArray[cursorTemp])
otherwise Bailout;
--cursorTemp;
@ -1437,9 +1363,8 @@ namespace array {
let k: Smi = CallGallopRight(
context, sortState, load, tempArray[cursorTemp], baseA, lengthA,
lengthA - 1, False)
lengthA - 1)
otherwise Bailout;
elements = ReloadElements(sortState);
assert(k >= 0);
nofWinsA = lengthA - k;
@ -1447,25 +1372,21 @@ namespace array {
dest = dest - nofWinsA;
cursorA = cursorA - nofWinsA;
CallCopyWithinSortArray(
context, sortState, elements, cursorA + 1, dest + 1, nofWinsA)
context, sortState, cursorA + 1, dest + 1, nofWinsA)
otherwise Bailout;
lengthA = lengthA - nofWinsA;
if (lengthA == 0) goto Succeed;
}
CallStore(
context, sortState, store, elements, dest--,
tempArray[cursorTemp--])
CallStore(context, sortState, store, dest--, tempArray[cursorTemp--])
otherwise Bailout;
if (--lengthB == 1) goto CopyA;
let key: Object =
CallLoad(context, sortState, load, elements, cursorA)
let key: Object = CallLoad(context, sortState, load, cursorA)
otherwise Bailout;
k = CallGallopLeft(
context, sortState, Load<TempArrayElements>, key, 0, lengthB,
lengthB - 1, True) otherwise Bailout;
elements = ReloadElements(sortState);
lengthB - 1) otherwise Bailout;
assert(k >= 0);
nofWinsB = lengthB - k;
@ -1473,8 +1394,8 @@ namespace array {
dest = dest - nofWinsB;
cursorTemp = cursorTemp - nofWinsB;
CallCopyFromTempArray(
context, sortState, elements, dest + 1, tempArray,
cursorTemp + 1, nofWinsB) otherwise Bailout;
context, sortState, dest + 1, cursorTemp + 1, nofWinsB)
otherwise Bailout;
lengthB = lengthB - nofWinsB;
if (lengthB == 1) goto CopyA;
@ -1483,8 +1404,7 @@ namespace array {
// consistent, but we can't assume that it is.
if (lengthB == 0) goto Succeed;
}
CopyElement(
context, sortState, load, store, elements, cursorA--, dest--)
CopyElement(context, sortState, load, store, cursorA--, dest--)
otherwise Bailout;
if (--lengthA == 0) goto Succeed;
}
@ -1496,8 +1416,8 @@ namespace array {
if (lengthB > 0) {
assert(lengthA == 0);
CallCopyFromTempArray(
context, sortState, elements, dest - (lengthB - 1), tempArray, 0,
lengthB) otherwise Bailout;
context, sortState, dest - (lengthB - 1), 0, lengthB)
otherwise Bailout;
}
}
label CopyA {
@ -1507,10 +1427,9 @@ namespace array {
dest = dest - lengthA;
cursorA = cursorA - lengthA;
CallCopyWithinSortArray(
context, sortState, elements, cursorA + 1, dest + 1, lengthA)
context, sortState, cursorA + 1, dest + 1, lengthA)
otherwise Bailout;
CallStore(
context, sortState, store, elements, dest, tempArray[cursorTemp])
CallStore(context, sortState, store, dest, tempArray[cursorTemp])
otherwise Bailout;
}
}