// Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
// 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018 Python Software Foundation;
// All Rights Reserved

// This file implements a stable, adapative merge sort variant called TimSort.
//
// It was first implemented in python and this Torque implementation
// is based on the current version:
//
// https://github.com/python/cpython/blob/master/Objects/listobject.c
//
// Detailed analysis and a description of the algorithm can be found at:
//
// https://github.com/python/cpython/blob/master/Objects/listsort.txt

module array {
  // All accessors bail to the GenericElementsAccessor if assumptions checked
  // by "CanUseSameAccessor<>" are violated:
  //  Generic <- FastPackedSmi
  //          <- FastSmiOrObject
  //          <- FastDouble
  //          <- Dictionary
  //
  // The only exception is TempArrayElements, since it does not describe the
  // "elements" of the receiver, but instead is used as an "adaptor" so
  // GallopLeft/GallopRight can be reused with the temporary array.
  const kGenericElementsAccessorId: Smi = 0;
  const kFastElementsAccessorId: Smi = 1;

  // This is a special type, used to access the temporary array which is always
  // PACKED_ELEMENTS. As a result, we do not need a sanity check for it,
  // otherwise we might wrongly bail to the slow path.
  type TempArrayElements;

  // The following index constants describe the layout of the sortState.
  // The sortState is currently implemented as a FixedArray of
  // size kSortStateSize.

  // The receiver of the Array.p.sort call.
  const kReceiverIdx: constexpr int31 = 0;

  // The initial map and length of the receiver. After calling into JS, these
  // are reloaded and checked. If they changed we bail to the baseline
  // GenericElementsAccessor.
  const kInitialReceiverMapIdx: constexpr int31 = 1;
  const kInitialReceiverLengthIdx: constexpr int31 = 2;

  // If the user provided a comparison function, it is stored here.
  const kUserCmpFnIdx: constexpr int31 = 3;

  // Function pointer to the comparison function. This can either be a builtin
  // that calls the user-provided comparison function or "SortDefault", which
  // uses ToString and a lexicographical compare.
  const kSortComparePtrIdx: constexpr int31 = 4;

  // The following three function pointer represent a Accessor/Path.
  // These are used to Load/Store elements and to check whether to bail to the
  // baseline GenericElementsAccessor.
  const kLoadFnIdx: constexpr int31 = 5;
  const kStoreFnIdx: constexpr int31 = 6;
  const kCanUseSameAccessorFnIdx: constexpr int31 = 7;

  // If this field has the value kFailure, we need to bail to the baseline
  // GenericElementsAccessor.
  const kBailoutStatusIdx: constexpr int31 = 8;

  // This controls when we get *into* galloping mode. It's initialized to
  // kMinGallop. mergeLow and mergeHigh tend to nudge it higher for random data,
  // and lower for highly structured data.
  const kMinGallopIdx: constexpr int31 = 9;

  // A stack of sortState[kPendingRunsSizeIdx] pending runs yet to be merged.
  // Run #i starts at sortState[kPendingRunsIdx][2 * i] and extends for
  // sortState[kPendingRunsIdx][2 * i + 1] elements:
  //
  //   [..., base (i-1), length (i-1), base i, length i]
  //
  // It's always true (so long as the indices are in bounds) that
  //
  //   base of run #i + length of run #i == base of run #i + 1
  //
  const kPendingRunsSizeIdx: constexpr int31 = 10;
  const kPendingRunsIdx: constexpr int31 = 11;

  // The current size of the temporary array.
  const kTempArraySizeIdx: constexpr int31 = 12;

  // Pointer to the temporary array.
  const kTempArrayIdx: constexpr int31 = 13;

  // Contains a Smi constant describing which accessors to use. This is used
  // for reloading the right elements and for a sanity check.
  const kAccessorIdx: constexpr int31 = 14;

  const kSortStateSize: intptr = 15;

  const kFailure: Smi = -1;
  const kSuccess: Smi = 0;

  // The maximum number of entries in a SortState's pending-runs stack.
  // This is enough to sort arrays of size up to about
  //   32 * phi ** kMaxMergePending
  // where phi ~= 1.618. 85 is ridiculously large enough, good for an array with
  // 2 ** 64 elements.
  const kMaxMergePending: constexpr int31 = 85;

  // When we get into galloping mode, we stay there until both runs win less
  // often then kMinGallop consecutive times. See listsort.txt for more info.
  const kMinGallopWins: constexpr int31 = 7;

  // Default size of the temporary array. The temporary array is allocated when
  // 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 CanUseSameAccessorFn = builtin(Context, JSReceiver, Object, Number) =>
      Boolean;
  type CompareBuiltinFn = builtin(Context, Object, Object, Object) => Number;

  // The following builtins implement Load/Store for all the Accessors.
  // The most generic baseline version uses Get-/SetProperty. We do not need
  // to worry about the prototype chain, because the pre-processing step has
  // copied values from the prototype chain to the receiver if they were visible
  // through a hole.

  builtin Load<ElementsAccessor : type>(
      context: Context, sortState: FixedArray, elements: HeapObject,
      index: Smi): Object {
    return GetProperty(context, elements, index);
  }

  Load<FastPackedSmiElements>(
      context: Context, sortState: FixedArray, elements: HeapObject,
      index: Smi): Object {
    const elems: FixedArray = unsafe_cast<FixedArray>(elements);
    return elems[index];
  }

  Load<FastSmiOrObjectElements>(
      context: Context, sortState: FixedArray, elements: HeapObject,
      index: Smi): Object {
    const elems: FixedArray = unsafe_cast<FixedArray>(elements);
    const result: Object = elems[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
      // ToString changes the array.
      return Failure(sortState);
    }
    return result;
  }

  Load<FastDoubleElements>(
      context: Context, sortState: FixedArray, elements: HeapObject,
      index: Smi): Object {
    try {
      const elems: FixedDoubleArray = unsafe_cast<FixedDoubleArray>(elements);
      const value: float64 =
          LoadDoubleWithHoleCheck(elems, index) otherwise Bailout;
      return AllocateHeapNumberWithValue(value);
    }
    label Bailout {
      // 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
      // ToString changes the array.
      return Failure(sortState);
    }
  }

  Load<DictionaryElements>(
      context: Context, sortState: FixedArray, elements: HeapObject,
      index: Smi): Object {
    try {
      const dictionary: NumberDictionary =
          unsafe_cast<NumberDictionary>(elements);
      const intptr_index: intptr = convert<intptr>(index);
      const value: Object =
          BasicLoadNumberDictionaryElement(dictionary, intptr_index)
      otherwise Bailout, Bailout;
      return value;
    }
    label Bailout {
      return Failure(sortState);
    }
  }

  Load<TempArrayElements>(
      context: Context, sortState: FixedArray, elements: HeapObject,
      index: Smi): Object {
    assert(IsFixedArray(elements));
    const elems: FixedArray = unsafe_cast<FixedArray>(elements);
    return elems[index];
  }

  builtin Store<ElementsAccessor : type>(
      context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
      value: Object): Smi {
    SetProperty(context, elements, index, value);
    return kSuccess;
  }

  Store<FastPackedSmiElements>(
      context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
      value: Object): Smi {
    const elems: FixedArray = unsafe_cast<FixedArray>(elements);
    StoreFixedArrayElementSmi(elems, index, value, SKIP_WRITE_BARRIER);
    return kSuccess;
  }

  Store<FastSmiOrObjectElements>(
      context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
      value: Object): Smi {
    const elems: FixedArray = unsafe_cast<FixedArray>(elements);
    elems[index] = value;
    return kSuccess;
  }

  Store<FastDoubleElements>(
      context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
      value: Object): Smi {
    const elems: FixedDoubleArray = unsafe_cast<FixedDoubleArray>(elements);
    const heap_val: HeapNumber = unsafe_cast<HeapNumber>(value);
    // Make sure we do not store signalling NaNs into double arrays.
    const val: float64 = Float64SilenceNaN(convert<float64>(heap_val));
    StoreFixedDoubleArrayElementWithSmiIndex(elems, index, val);
    return kSuccess;
  }

  Store<DictionaryElements>(
      context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
      value: Object): Smi {
    const dictionary: NumberDictionary =
        unsafe_cast<NumberDictionary>(elements);
    const intptr_index: intptr = convert<intptr>(index);
    try {
      BasicStoreNumberDictionaryElement(dictionary, intptr_index, value)
      otherwise Fail, Fail, ReadOnly;
      return kSuccess;
    }
    label ReadOnly {
      // We cannot write to read-only data properties. Throw the same TypeError
      // as SetProperty would.
      const receiver: JSReceiver = GetReceiver(sortState);
      ThrowTypeError(
          context, kStrictReadOnlyProperty, index, Typeof(receiver), receiver);
    }
    label Fail {
      return Failure(sortState);
    }
  }

  Store<TempArrayElements>(
      context: Context, sortState: FixedArray, elements: HeapObject, index: Smi,
      value: Object): Smi {
    const elems: FixedArray = unsafe_cast<FixedArray>(elements);
    elems[index] = value;
    return kSuccess;
  }

  extern macro UnsafeCastObjectToCompareBuiltinFn(Object): CompareBuiltinFn;
  unsafe_cast<CompareBuiltinFn>(o: Object): CompareBuiltinFn {
    return UnsafeCastObjectToCompareBuiltinFn(o);
  }

  extern macro UnsafeCastObjectToLoadFn(Object): LoadFn;
  unsafe_cast<LoadFn>(o: Object): LoadFn {
    return UnsafeCastObjectToLoadFn(o);
  }

  extern macro UnsafeCastObjectToStoreFn(Object): StoreFn;
  unsafe_cast<StoreFn>(o: Object): StoreFn {
    return UnsafeCastObjectToStoreFn(o);
  }

  extern macro UnsafeCastObjectToCanUseSameAccessorFn(Object):
      CanUseSameAccessorFn;
  unsafe_cast<CanUseSameAccessorFn>(o: Object): CanUseSameAccessorFn {
    return UnsafeCastObjectToCanUseSameAccessorFn(o);
  }

  builtin SortCompareDefault(
      context: Context, comparefn: Object, x: Object, y: Object): Number {
    assert(comparefn == Undefined);

    if (TaggedIsSmi(x) && TaggedIsSmi(y)) {
      // TODO(szuend): Replace with a fast CallCFunction call.
      return SmiLexicographicCompare(context, x, y);
    }

    // 5. Let xString be ? ToString(x).
    const xString: String = ToString_Inline(context, x);

    // 6. Let yString be ? ToString(y).
    const yString: String = ToString_Inline(context, y);

    // 7. Let xSmaller be the result of performing
    //    Abstract Relational Comparison xString < yString.
    // 8. If xSmaller is true, return -1.
    if (StringLessThan(context, xString, yString) == True) return -1;

    // 9. Let ySmaller be the result of performing
    //    Abstract Relational Comparison yString < xString.
    // 10. If ySmaller is true, return 1.
    if (StringLessThan(context, yString, xString) == True) return 1;

    // 11. Return +0.
    return 0;
  }

  builtin SortCompareUserFn(
      context: Context, comparefn: Object, x: Object, y: Object): Number {
    assert(comparefn != Undefined);
    const cmpfn: Callable = unsafe_cast<Callable>(comparefn);

    // a. Let v be ? ToNumber(? Call(comparefn, undefined, x, y)).
    const v: Number =
        ToNumber_Inline(context, Call(context, cmpfn, Undefined, x, y));

    // b. If v is NaN, return +0.
    if (NumberIsNaN(v)) return 0;

    // c. return v.
    return v;
  }

  builtin CanUseSameAccessor<ElementsAccessor : type>(
      context: Context, receiver: JSReceiver, initialReceiverMap: Object,
      initialReceiverLength: Number): Boolean {
    assert(IsJSArray(receiver));

    let a: JSArray = unsafe_cast<JSArray>(receiver);
    if (a.map != initialReceiverMap) return False;

    assert(TaggedIsSmi(initialReceiverLength));
    let originalLength: Smi = unsafe_cast<Smi>(initialReceiverLength);
    if (a.length_fast != originalLength) return False;

    return True;
  }

  CanUseSameAccessor<GenericElementsAccessor>(
      context: Context, receiver: JSReceiver, initialReceiverMap: Object,
      initialReceiverLength: Number): Boolean {
    // Do nothing. We are already on the slow path.
    return True;
  }

  CanUseSameAccessor<DictionaryElements>(
      context: Context, receiver: JSReceiver, initialReceiverMap: Object,
      initialReceiverLength: Number): Boolean {
    let obj: JSReceiver = unsafe_cast<JSReceiver>(receiver);
    return SelectBooleanConstant(obj.map == initialReceiverMap);
  }

  macro CallCompareFn(
      context: Context, sortState: FixedArray, x: Object, y: Object): Number
  labels Bailout {
    const userCmpFn: Object = sortState[kUserCmpFnIdx];
    const sortCompare: CompareBuiltinFn =
        unsafe_cast<CompareBuiltinFn>(sortState[kSortComparePtrIdx]);

    const result: Number = sortCompare(context, userCmpFn, x, y);

    const receiver: JSReceiver = GetReceiver(sortState);
    const initialReceiverMap: Object = sortState[kInitialReceiverMapIdx];
    const initialReceiverLength: Number =
        unsafe_cast<Number>(sortState[kInitialReceiverLengthIdx]);
    const CanUseSameAccessor: CanUseSameAccessorFn =
        GetCanUseSameAccessorFn(sortState);

    if (!CanUseSameAccessor(
            context, receiver, initialReceiverMap, initialReceiverLength)) {
      goto Bailout;
    }
    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(sortState: FixedArray): HeapObject {
    const receiver: JSReceiver = GetReceiver(sortState);
    if (sortState[kAccessorIdx] == kGenericElementsAccessorId) return receiver;

    const object: JSObject = unsafe_cast<JSObject>(receiver);
    return object.elements;
  }

  macro GetLoadFn(sortState: FixedArray): LoadFn {
    return unsafe_cast<LoadFn>(sortState[kLoadFnIdx]);
  }

  macro GetStoreFn(sortState: FixedArray): StoreFn {
    return unsafe_cast<StoreFn>(sortState[kStoreFnIdx]);
  }

  macro GetCanUseSameAccessorFn(sortState: FixedArray): CanUseSameAccessorFn {
    return unsafe_cast<CanUseSameAccessorFn>(
        sortState[kCanUseSameAccessorFnIdx]);
  }

  macro GetReceiver(sortState: FixedArray): JSReceiver {
    return unsafe_cast<JSReceiver>(sortState[kReceiverIdx]);
  }

  // Returns the temporary array without changing its size.
  macro GetTempArray(sortState: FixedArray): FixedArray {
    return unsafe_cast<FixedArray>(sortState[kTempArrayIdx]);
  }

  // Re-loading the stack-size is done in a few places. The small macro allows
  // for easier invariant checks at all use sites.
  macro GetPendingRunsSize(sortState: FixedArray): Smi {
    assert(TaggedIsSmi(sortState[kPendingRunsSizeIdx]));
    const stack_size: Smi = unsafe_cast<Smi>(sortState[kPendingRunsSizeIdx]);

    assert(stack_size >= 0);
    return stack_size;
  }

  macro SetPendingRunsSize(sortState: FixedArray, value: Smi) {
    sortState[kPendingRunsSizeIdx] = value;
  }

  macro GetPendingRunBase(pendingRuns: FixedArray, run: Smi): Smi {
    return unsafe_cast<Smi>(pendingRuns[run << 1]);
  }

  macro SetPendingRunBase(pendingRuns: FixedArray, run: Smi, value: Smi) {
    pendingRuns[run << 1] = value;
  }

  macro GetPendingRunLength(pendingRuns: FixedArray, run: Smi): Smi {
    return unsafe_cast<Smi>(pendingRuns[(run << 1) + 1]);
  }

  macro SetPendingRunLength(pendingRuns: FixedArray, run: Smi, value: Smi) {
    pendingRuns[(run << 1) + 1] = value;
  }

  macro PushRun(sortState: FixedArray, base: Smi, length: Smi) {
    assert(GetPendingRunsSize(sortState) < kMaxMergePending);

    const stack_size: Smi = GetPendingRunsSize(sortState);
    const pending_runs: FixedArray =
        unsafe_cast<FixedArray>(sortState[kPendingRunsIdx]);

    SetPendingRunBase(pending_runs, stack_size, base);
    SetPendingRunLength(pending_runs, stack_size, length);

    SetPendingRunsSize(sortState, stack_size + 1);
  }

  // Returns the temporary array and makes sure that it is big enough.
  // TODO(szuend): Implement a better re-size strategy.
  macro GetTempArray(sortState: FixedArray, requestedSize: Smi): FixedArray {
    const min_size: Smi = SmiMax(kSortStateTempSize, requestedSize);

    const current_size: Smi = unsafe_cast<Smi>(sortState[kTempArraySizeIdx]);
    if (current_size >= min_size) {
      return GetTempArray(sortState);
    }

    const temp_array: FixedArray =
        AllocateZeroedFixedArray(convert<intptr>(min_size));
    FillFixedArrayWithSmiZero(temp_array, min_size);

    sortState[kTempArraySizeIdx] = min_size;
    sortState[kTempArrayIdx] = temp_array;
    return temp_array;
  }

  // This macro jumps to the Bailout label iff kBailoutStatus is kFailure.
  macro EnsureSuccess(sortState: FixedArray) labels Bailout {
    const status: Smi = unsafe_cast<Smi>(sortState[kBailoutStatusIdx]);
    if (status == kFailure) goto Bailout;
  }

  // Sets kBailoutStatus to kFailure and returns kFailure.
  macro Failure(sortState: FixedArray): Smi {
    sortState[kBailoutStatusIdx] = kFailure;
    return kFailure;
  }

  // The following Call* macros wrap builtin calls, making call sites more
  // 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,
      elements: HeapObject, index: Smi): Object labels Bailout {
    const result: Object = Load(context, sortState, elements, 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);
    EnsureSuccess(sortState) otherwise Bailout;
  }

  macro CallCopyFromTempArray(
      context: Context, sortState: FixedArray, dstElements: HeapObject,
      dstPos: Smi, tempArray: FixedArray, srcPos: Smi, length: Smi)
  labels Bailout {
    CopyFromTempArray(
        context, sortState, dstElements, dstPos, tempArray, srcPos, length);
    EnsureSuccess(sortState) otherwise Bailout;
  }

  macro CallCopyWithinSortArray(
      context: Context, sortState: FixedArray, elements: HeapObject,
      srcPos: Smi, dstPos: Smi, length: Smi)
  labels Bailout {
    CopyWithinSortArray(context, sortState, elements, 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
  labels Bailout {
    const result: Smi = GallopRight(
        context, sortState, Load, key, base, length, hint, useTempArray);
    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
  labels Bailout {
    const result: Smi = GallopLeft(
        context, sortState, Load, key, base, length, hint, useTempArray);
    EnsureSuccess(sortState) otherwise Bailout;
    return result;
  }

  macro CallMergeAt(context: Context, sortState: FixedArray, i: Smi)
  labels Bailout {
    MergeAt(context, sortState, i);
    EnsureSuccess(sortState) otherwise Bailout;
  }

  // Used for OOB asserts in Copy* builtins.
  macro GetReceiverLengthProperty(
      context: Context, sortState: FixedArray): Smi {
    const receiver: JSReceiver = GetReceiver(sortState);

    if (IsJSArray(receiver)) return unsafe_cast<JSArray>(receiver).length_fast;

    const len: Number =
        ToLength_Inline(context, GetProperty(context, receiver, 'length'));
    return unsafe_cast<Smi>(len);
  }

  macro CopyToTempArray(
      context: Context, sortState: FixedArray, Load: LoadFn,
      srcElements: HeapObject, srcPos: Smi, tempArray: FixedArray, dstPos: Smi,
      length: Smi)
  labels Bailout {
    assert(srcPos >= 0);
    assert(dstPos >= 0);
    assert(srcPos <= GetReceiverLengthProperty(context, sortState) - length);
    assert(dstPos <= tempArray.length - length);

    let src_idx: Smi = srcPos;
    let dst_idx: Smi = dstPos;
    let to: Smi = srcPos + length;

    while (src_idx < to) {
      let element: Object =
          CallLoad(context, sortState, Load, srcElements, src_idx++)
      otherwise Bailout;
      tempArray[dst_idx++] = element;
    }
  }

  builtin CopyFromTempArray(
      context: Context, sortState: FixedArray, dstElements: HeapObject,
      dstPos: Smi, tempArray: FixedArray, srcPos: Smi, length: Smi): Smi {
    assert(srcPos >= 0);
    assert(dstPos >= 0);
    assert(srcPos <= tempArray.length - length);
    assert(dstPos <= GetReceiverLengthProperty(context, sortState) - length);

    let Store: StoreFn = GetStoreFn(sortState);

    let src_idx: Smi = srcPos;
    let dst_idx: Smi = dstPos;
    let to: Smi = srcPos + length;
    try {
      while (src_idx < to) {
        CallStore(
            context, sortState, Store, dstElements, dst_idx++,
            tempArray[src_idx++])
        otherwise Bailout;
      }
      return kSuccess;
    }
    label Bailout {
      return Failure(sortState);
    }
  }

  builtin CopyWithinSortArray(
      context: Context, sortState: FixedArray, elements: HeapObject,
      srcPos: Smi, dstPos: Smi, length: Smi): Smi {
    assert(srcPos >= 0);
    assert(dstPos >= 0);
    assert(srcPos <= GetReceiverLengthProperty(context, sortState) - length);
    assert(dstPos <= GetReceiverLengthProperty(context, sortState) - length);

    try {
      let Load: LoadFn = GetLoadFn(sortState);
      let Store: StoreFn = GetStoreFn(sortState);

      if (srcPos < dstPos) {
        let src_idx: Smi = srcPos + length - 1;
        let dst_idx: Smi = dstPos + length - 1;
        while (src_idx >= srcPos) {
          CopyElement(
              context, sortState, Load, Store, elements, src_idx--, dst_idx--)
          otherwise Bailout;
        }
      } else {
        let src_idx: Smi = srcPos;
        let dst_idx: Smi = dstPos;
        let to: Smi = srcPos + length;
        while (src_idx < to) {
          CopyElement(
              context, sortState, Load, Store, elements, src_idx++, dst_idx++)
          otherwise Bailout;
        }
      }
      return kSuccess;
    }
    label Bailout {
      return Failure(sortState);
    }
  }

  // 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!.
  builtin BinaryInsertionSort(
      context: Context, sortState: FixedArray, low: Smi, startArg: Smi,
      high: Smi): Smi {
    assert(low <= startArg && startArg <= high);

    try {
      let elements: HeapObject = ReloadElements(sortState);

      const Load: LoadFn = GetLoadFn(sortState);
      const Store: StoreFn = GetStoreFn(sortState);

      let start: Smi = low == startArg ? (startArg + 1) : startArg;

      for (; start < high; ++start) {
        // Set left to where a[start] belongs.
        let left: Smi = low;
        let right: Smi = start;

        const pivot: Object =
            CallLoad(context, sortState, Load, elements, right)
        otherwise Bailout;

        // Invariants:
        //   pivot >= all in [low, left).
        //   pivot  < all in [right, start).
        assert(left < right);

        // Find pivot insertion point.
        while (left < right) {
          const mid: Smi = left + ((right - left) >>> 1);
          const mid_element: Object =
              CallLoad(context, sortState, Load, elements, mid)
          otherwise Bailout;
          const order: Number =
              CallCompareFn(context, sortState, pivot, mid_element)
          otherwise Bailout;
          elements = ReloadElements(sortState);

          if (order < 0) {
            right = mid;
          } else {
            left = mid + 1;
          }
        }
        assert(left == right);

        // The invariants still hold, so:
        //   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.
        for (let p: Smi = start; p > left; --p) {
          CopyElement(context, sortState, Load, Store, elements, p - 1, p)
          otherwise Bailout;
        }
        CallStore(context, sortState, Store, elements, left, pivot)
        otherwise Bailout;
      }
      return kSuccess;
    }
    label Bailout {
      return Failure(sortState);
    }
  }

  // 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] <= ...
  //
  // or the longest descending sequence, with
  //
  //   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).
  //
  // 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 {
    assert(lowArg < high);

    let elements: HeapObject = ReloadElements(sortState);
    const Load: LoadFn = GetLoadFn(sortState);
    const Store: StoreFn = GetStoreFn(sortState);

    let low: Smi = lowArg + 1;
    if (low == high) return 1;

    let run_length: Smi = 2;

    const element_low: Object =
        CallLoad(context, sortState, Load, elements, low) otherwise Bailout;
    const element_low_pred: Object =
        CallLoad(context, sortState, Load, elements, low - 1) otherwise Bailout;
    let order: Number =
        CallCompareFn(context, sortState, element_low, element_low_pred)
    otherwise Bailout;
    elements = ReloadElements(sortState);

    // TODO(szuend): Replace with "order < 0" once Torque supports it.
    //               Currently the operator<(Number, Number) has return type
    //               'never' and uses two labels to branch.
    const is_descending: bool = order < 0 ? true : false;

    let previous_element: Object = element_low;
    for (let idx: Smi = low + 1; idx < high; ++idx) {
      const current_element: Object =
          CallLoad(context, sortState, Load, elements, idx) otherwise Bailout;
      order =
          CallCompareFn(context, sortState, current_element, previous_element)
      otherwise Bailout;
      elements = ReloadElements(sortState);

      if (is_descending) {
        if (order >= 0) break;
      } else {
        if (order < 0) break;
      }

      previous_element = current_element;
      ++run_length;
    }

    if (is_descending) {
      ReverseRange(
          context, sortState, Load, Store, elements, lowArg,
          lowArg + run_length)
      otherwise Bailout;
    }

    return run_length;
  }

  macro ReverseRange(
      context: Context, sortState: FixedArray, Load: LoadFn, Store: StoreFn,
      elements: HeapObject, from: Smi, to: Smi)
  labels Bailout {
    let low: Smi = from;
    let high: Smi = to - 1;

    while (low < high) {
      const element_low: Object =
          CallLoad(context, sortState, Load, elements, low) otherwise Bailout;
      const element_high: Object =
          CallLoad(context, sortState, Load, elements, high) otherwise Bailout;
      CallStore(context, sortState, Store, elements, low++, element_high)
      otherwise Bailout;
      CallStore(context, sortState, Store, elements, high--, element_low)
      otherwise Bailout;
    }
  }

  // Merges the two runs at stack indices i and i + 1.
  // Returns kFailure if we need to bailout, kSuccess otherwise.
  builtin MergeAt(context: Context, sortState: FixedArray, i: Smi): Smi {
    const stack_size: Smi = GetPendingRunsSize(sortState);

    // We are only allowed to either merge the two top-most runs, or leave
    // the top most run alone and merge the two next runs.
    assert(stack_size >= 2);
    assert(i >= 0);
    assert(i == stack_size - 2 || i == stack_size - 3);

    const elements: HeapObject = ReloadElements(sortState);
    const Load: LoadFn = GetLoadFn(sortState);

    const pending_runs: FixedArray =
        unsafe_cast<FixedArray>(sortState[kPendingRunsIdx]);
    let base_a: Smi = GetPendingRunBase(pending_runs, i);
    let length_a: Smi = GetPendingRunLength(pending_runs, i);
    let base_b: Smi = GetPendingRunBase(pending_runs, i + 1);
    let length_b: Smi = GetPendingRunLength(pending_runs, i + 1);
    assert(length_a > 0 && length_b > 0);
    assert(base_a + length_a == base_b);

    // Record the length of the combined runs; if i is the 3rd-last run now,
    // also slide over the last run (which isn't involved in this merge).
    // The current run i + 1 goes away in any case.
    SetPendingRunLength(pending_runs, i, length_a + length_b);
    if (i == stack_size - 3) {
      const base: Smi = GetPendingRunBase(pending_runs, i + 2);
      const length: Smi = GetPendingRunLength(pending_runs, i + 2);
      SetPendingRunBase(pending_runs, i + 1, base);
      SetPendingRunLength(pending_runs, i + 1, length);
    }
    SetPendingRunsSize(sortState, stack_size - 1);

    try {
      // Where does b start in a? Elements in a before that can be ignored,
      // because they are already in place.
      const key_right: Object =
          CallLoad(context, sortState, Load, elements, base_b)
      otherwise Bailout;
      const k: Smi = CallGallopRight(
          context, sortState, Load, key_right, base_a, length_a, 0, False)
      otherwise Bailout;
      assert(k >= 0);

      base_a = base_a + k;
      length_a = length_a - k;
      if (length_a == 0) return kSuccess;
      assert(length_a > 0);

      // Where does a end in b? Elements in b after that can be ignored,
      // because they are already in place.
      let key_left: Object =
          CallLoad(context, sortState, Load, elements, base_a + length_a - 1)
      otherwise Bailout;
      length_b = CallGallopLeft(
          context, sortState, Load, key_left, base_b, length_b, length_b - 1,
          False) otherwise Bailout;
      assert(length_b >= 0);
      if (length_b == 0) return kSuccess;

      // Merge what remains of the runs, using a temp array with
      // min(length_a, length_b) elements.
      if (length_a <= length_b) {
        MergeLow(context, sortState, base_a, length_a, base_b, length_b)
        otherwise Bailout;
      } else {
        MergeHigh(context, sortState, base_a, length_a, base_b, length_b)
        otherwise Bailout;
      }
      return kSuccess;
    }
    label Bailout {
      return Failure(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
  // 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.
  //
  // The return value is the int offset in 0..length such that
  //
  // array[base + offset] < key <= array[base + offset + 1]
  //
  // pretending that array[base - 1] is minus infinity and array[base + len]
  // 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 {
    assert(length > 0 && base >= 0);
    assert(0 <= hint && hint < length);

    // We cannot leave a pointer to elements on the stack (see comment at
    // ReloadElements). For this reason we pass a flag whether to reload
    // and which array to use.
    let elements: HeapObject = useTempArray == True ? GetTempArray(sortState) :
                                                      ReloadElements(sortState);

    let last_ofs: Smi = 0;
    let offset: Smi = 1;

    try {
      const base_hint_element: Object =
          CallLoad(context, sortState, Load, elements, base + hint)
      otherwise Bailout;
      let order: Number =
          CallCompareFn(context, sortState, base_hint_element, key)
      otherwise Bailout;
      if (useTempArray == False) {
        elements = ReloadElements(sortState);
      }

      if (order < 0) {
        // a[base + hint] < key: gallop right, until
        // a[base + hint + last_ofs] < key <= a[base + hint + offset].

        // a[base + length - 1] is highest.
        let max_ofs: Smi = length - hint;
        while (offset < max_ofs) {
          const offset_element: Object =
              CallLoad(context, sortState, Load, elements, base + hint + offset)
          otherwise Bailout;
          order = CallCompareFn(context, sortState, offset_element, key)
          otherwise Bailout;
          if (useTempArray == False) {
            elements = ReloadElements(sortState);
          }

          // a[base + hint + offset] >= key? Break.
          if (order >= 0) break;

          last_ofs = offset;
          offset = (offset << 1) + 1;

          // Integer overflow.
          if (offset <= 0) offset = max_ofs;
        }

        if (offset > max_ofs) offset = max_ofs;

        // Translate back to positive offsets relative to base.
        last_ofs = last_ofs + hint;
        offset = offset + hint;
      } else {
        // key <= a[base + hint]: gallop left, until
        // a[base + hint - offset] < key <= a[base + hint - last_ofs].
        assert(order >= 0);

        // a[base + hint] is lowest.
        let max_ofs: Smi = hint + 1;
        while (offset < max_ofs) {
          const offset_element: Object =
              CallLoad(context, sortState, Load, elements, base + hint - offset)
          otherwise Bailout;
          order = CallCompareFn(context, sortState, offset_element, key)
          otherwise Bailout;
          if (useTempArray == False) {
            elements = ReloadElements(sortState);
          }

          if (order < 0) break;

          last_ofs = offset;
          offset = (offset << 1) + 1;

          // Integer overflow.
          if (offset <= 0) offset = max_ofs;
        }

        if (offset > max_ofs) offset = max_ofs;

        // Translate back to positive offsets relative to base.
        const tmp: Smi = last_ofs;
        last_ofs = hint - offset;
        offset = hint - tmp;
      }

      assert(-1 <= last_ofs && last_ofs < offset && offset <= length);

      // Now a[base+last_ofs] < key <= a[base+offset], so key belongs somewhere
      // to the right of last_ofs but no farther right than offset. Do a binary
      // search, with invariant:
      //   a[base + last_ofs - 1] < key <= a[base + offset].
      last_ofs++;
      while (last_ofs < offset) {
        const m: Smi = last_ofs + ((offset - last_ofs) >>> 1);

        const base_m_element: Object =
            CallLoad(context, sortState, Load, elements, base + m)
        otherwise Bailout;
        order = CallCompareFn(context, sortState, base_m_element, key)
        otherwise Bailout;
        if (useTempArray == False) {
          elements = ReloadElements(sortState);
        }

        if (order < 0) {
          last_ofs = m + 1;  // a[base + m] < key.
        } else {
          offset = m;  // key <= a[base + m].
        }
      }
      // so a[base + offset - 1] < key <= a[base + offset].
      assert(last_ofs == offset);
      assert(0 <= offset && offset <= length);
      return offset;
    }
    label Bailout {
      return Failure(sortState);
    }
  }

  // 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.
  //
  // The return value is the int offset in 0..length such that
  //
  // array[base + offset - 1] <= key < array[base + offset]
  //
  // or kFailure on error.
  builtin GallopRight(
      context: Context, sortState: FixedArray, Load: LoadFn, key: Object,
      base: Smi, length: Smi, hint: Smi, useTempArray: Boolean): Smi {
    assert(length > 0 && base >= 0);
    assert(0 <= hint && hint < length);

    // We cannot leave a pointer to elements on the stack (see comment at
    // ReloadElements). For this reason we pass a flag whether to reload
    // and which array to use.
    let elements: HeapObject = useTempArray == True ? GetTempArray(sortState) :
                                                      ReloadElements(sortState);

    let last_ofs: Smi = 0;
    let offset: Smi = 1;

    try {
      const base_hint_element: Object =
          CallLoad(context, sortState, Load, elements, base + hint)
      otherwise Bailout;
      let order: Number =
          CallCompareFn(context, sortState, key, base_hint_element)
      otherwise Bailout;
      if (useTempArray == False) {
        elements = ReloadElements(sortState);
      }

      if (order < 0) {
        // key < a[base + hint]: gallop left, until
        // a[base + hint - offset] <= key < a[base + hint - last_ofs].

        // a[base + hint] is lowest.
        let max_ofs: Smi = hint + 1;
        while (offset < max_ofs) {
          const offset_element: Object =
              CallLoad(context, sortState, Load, elements, base + hint - offset)
          otherwise Bailout;
          order = CallCompareFn(context, sortState, key, offset_element)
          otherwise Bailout;
          if (useTempArray == False) {
            elements = ReloadElements(sortState);
          }

          if (order >= 0) break;

          last_ofs = offset;
          offset = (offset << 1) + 1;

          // Integer overflow.
          if (offset <= 0) offset = max_ofs;
        }

        if (offset > max_ofs) offset = max_ofs;

        // Translate back to positive offsets relative to base.
        const tmp: Smi = last_ofs;
        last_ofs = hint - offset;
        offset = hint - tmp;
      } else {
        // a[base + hint] <= key: gallop right, until
        // a[base + hint + last_ofs] <= key < a[base + hint + offset].

        // a[base + length - 1] is highest.
        let max_ofs: Smi = length - hint;
        while (offset < max_ofs) {
          const offset_element: Object =
              CallLoad(context, sortState, Load, elements, base + hint + offset)
          otherwise Bailout;
          order = CallCompareFn(context, sortState, key, offset_element)
          otherwise Bailout;
          if (useTempArray == False) {
            elements = ReloadElements(sortState);
          }

          // a[base + hint + ofs] <= key.
          if (order < 0) break;

          last_ofs = offset;
          offset = (offset << 1) + 1;

          // Integer overflow.
          if (offset <= 0) offset = max_ofs;
        }

        if (offset > max_ofs) offset = max_ofs;

        // Translate back to positive offests relative to base.
        last_ofs = last_ofs + hint;
        offset = offset + hint;
      }
      assert(-1 <= last_ofs && last_ofs < offset && offset <= length);

      // Now a[base + last_ofs] <= key < a[base + ofs], so key belongs
      // somewhere to the right of last_ofs but no farther right than ofs.
      // Do a binary search, with invariant
      // a[base + last_ofs - 1] < key <= a[base + ofs].
      last_ofs++;
      while (last_ofs < offset) {
        const m: Smi = last_ofs + ((offset - last_ofs) >>> 1);

        const base_m_element: Object =
            CallLoad(context, sortState, Load, elements, base + m)
        otherwise Bailout;
        order = CallCompareFn(context, sortState, key, base_m_element)
        otherwise Bailout;
        if (useTempArray == False) {
          elements = ReloadElements(sortState);
        }

        if (order < 0) {
          offset = m;  // key < a[base + m].
        } else {
          last_ofs = m + 1;  // a[base + m] <= key.
        }
      }
      // so a[base + offset - 1] <= key < a[base + offset].
      assert(last_ofs == offset);
      assert(0 <= offset && offset <= length);
      return offset;
    }
    label Bailout {
      return Failure(sortState);
    }
  }

  // Copies a single element inside the array/object (NOT the temp_array).
  macro CopyElement(
      context: Context, sortState: FixedArray, Load: LoadFn, Store: StoreFn,
      elements: HeapObject, from: Smi, to: Smi)
  labels Bailout {
    const element: Object = CallLoad(context, sortState, Load, elements, from)
    otherwise Bailout;
    CallStore(context, sortState, Store, elements, to, element)
    otherwise Bailout;
  }

  // Merge the length_a elements starting at base_a with the length_b elements
  // starting at base_b in a stable way, in-place. length_a and length_b must
  // be > 0, and base_a + length_a == base_b. Must also have that
  // array[base_b] < array[base_a],
  // that array[base_a + length_a - 1] belongs at the end of the merge,
  // and should have length_a <= length_b.
  macro MergeLow(
      context: Context, sortState: FixedArray, baseA: Smi, lengthA: Smi,
      baseB: Smi, lengthB: Smi)
  labels Bailout {
    assert(0 < lengthA && 0 < lengthB);
    assert(0 <= baseA && 0 < baseB);
    assert(baseA + lengthA == baseB);

    let length_a: Smi = lengthA;
    let length_b: Smi = lengthB;

    let elements: HeapObject = ReloadElements(sortState);
    const LoadF: LoadFn = GetLoadFn(sortState);
    const Store: StoreFn = GetStoreFn(sortState);

    const temp_array: FixedArray = GetTempArray(sortState, length_a);
    CopyToTempArray(
        context, sortState, LoadF, elements, baseA, temp_array, 0, length_a)
    otherwise Bailout;

    let dest: Smi = baseA;
    let cursor_temp: Smi = 0;
    let cursor_b: Smi = baseB;

    CopyElement(context, sortState, LoadF, Store, elements, cursor_b++, dest++)
    otherwise Bailout;

    try {
      if (--length_b == 0) goto Succeed;
      if (length_a == 1) goto CopyB;

      let min_gallop: Smi = unsafe_cast<Smi>(sortState[kMinGallopIdx]);
      // TODO(szuend): Replace with something that does not have a runtime
      //               overhead as soon as its available in Torque.
      while (Int32TrueConstant()) {
        let nof_wins_a: Smi = 0;  // # of times A won in a row.
        let nof_wins_b: Smi = 0;  // # of times B won in a row.

        // Do the straightforward thing until (if ever) one run appears to
        // win consistently.
        // TODO(szuend): Replace with something that does not have a runtime
        //               overhead as soon as its available in Torque.
        while (Int32TrueConstant()) {
          assert(length_a > 1 && length_b > 0);

          let element_b: Object =
              CallLoad(context, sortState, LoadF, elements, cursor_b)
          otherwise Bailout;
          let order: Number = CallCompareFn(
              context, sortState, element_b, temp_array[cursor_temp])
          otherwise Bailout;
          elements = ReloadElements(sortState);

          if (order < 0) {
            CopyElement(
                context, sortState, LoadF, Store, elements, cursor_b, dest)
            otherwise Bailout;

            ++cursor_b;
            ++dest;
            ++nof_wins_b;
            --length_b;
            nof_wins_a = 0;

            if (length_b == 0) goto Succeed;
            if (nof_wins_b >= min_gallop) break;
          } else {
            CallStore(
                context, sortState, Store, elements, dest,
                temp_array[cursor_temp])
            otherwise Bailout;

            ++cursor_temp;
            ++dest;
            ++nof_wins_a;
            --length_a;
            nof_wins_b = 0;

            if (length_a == 1) goto CopyB;
            if (nof_wins_a >= min_gallop) break;
          }
        }

        // 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.
        ++min_gallop;
        let first_iteration: bool = true;
        while (nof_wins_a >= kMinGallopWins || nof_wins_b >= kMinGallopWins ||
               first_iteration) {
          first_iteration = false;
          assert(length_a > 1 && length_b > 0);

          min_gallop = SmiMax(1, min_gallop - 1);
          sortState[kMinGallopIdx] = min_gallop;

          let key_right: Object =
              CallLoad(context, sortState, LoadF, elements, cursor_b)
          otherwise Bailout;
          nof_wins_a = CallGallopRight(
              context, sortState, Load<TempArrayElements>, key_right,
              cursor_temp, length_a, 0, True) otherwise Bailout;
          assert(nof_wins_a >= 0);

          if (nof_wins_a > 0) {
            CallCopyFromTempArray(
                context, sortState, elements, dest, temp_array, cursor_temp,
                nof_wins_a) otherwise Bailout;
            dest = dest + nof_wins_a;
            cursor_temp = cursor_temp + nof_wins_a;
            length_a = length_a - nof_wins_a;

            if (length_a == 1) goto CopyB;

            // length_a == 0 is impossible now if the comparison function is
            // consistent, but we can't assume that it is.
            if (length_a == 0) goto Succeed;
          }
          CopyElement(
              context, sortState, LoadF, Store, elements, cursor_b++, dest++)
          otherwise Bailout;
          if (--length_b == 0) goto Succeed;

          nof_wins_b = CallGallopLeft(
              context, sortState, LoadF, temp_array[cursor_temp], cursor_b,
              length_b, 0, False)
          otherwise Bailout;
          assert(nof_wins_b >= 0);
          if (nof_wins_b > 0) {
            CallCopyWithinSortArray(
                context, sortState, elements, cursor_b, dest, nof_wins_b)
            otherwise Bailout;

            dest = dest + nof_wins_b;
            cursor_b = cursor_b + nof_wins_b;
            length_b = length_b - nof_wins_b;

            if (length_b == 0) goto Succeed;
          }
          CallStore(
              context, sortState, Store, elements, dest++,
              temp_array[cursor_temp++])
          otherwise Bailout;
          if (--length_a == 1) goto CopyB;
        }
        ++min_gallop;  // Penalize it for leaving galloping mode
        sortState[kMinGallopIdx] = min_gallop;
      }
    }
    label Succeed {
      if (length_a > 0) {
        CallCopyFromTempArray(
            context, sortState, elements, dest, temp_array, cursor_temp,
            length_a) otherwise Bailout;
      }
    }
    label CopyB {
      assert(length_a == 1 && length_b > 0);
      // The last element of run A belongs at the end of the merge.
      CallCopyWithinSortArray(
          context, sortState, elements, cursor_b, dest, length_b)
      otherwise Bailout;
      CallStore(
          context, sortState, Store, elements, dest + length_b,
          temp_array[cursor_temp])
      otherwise Bailout;
    }
  }

  // Merge the length_a elements starting at base_a with the length_b elements
  // starting at base_b in a stable way, in-place. length_a and length_b must
  // be > 0. Must also have that array[base_a + length_a - 1] belongs at the
  // end of the merge and should have length_a >= length_b.
  macro MergeHigh(
      context: Context, sortState: FixedArray, baseA: Smi, lengthA: Smi,
      baseB: Smi, lengthB: Smi)
  labels Bailout {
    assert(0 < lengthA && 0 < lengthB);
    assert(0 <= baseA && 0 < baseB);
    assert(baseA + lengthA == baseB);

    let length_a: Smi = lengthA;
    let length_b: Smi = lengthB;

    let elements: HeapObject = ReloadElements(sortState);
    const LoadF: LoadFn = GetLoadFn(sortState);
    const Store: StoreFn = GetStoreFn(sortState);

    const temp_array: FixedArray = GetTempArray(sortState, length_b);
    CopyToTempArray(
        context, sortState, LoadF, elements, baseB, temp_array, 0, length_b)
    otherwise Bailout;

    // MergeHigh merges the two runs backwards.
    let dest: Smi = baseB + length_b - 1;
    let cursor_temp: Smi = length_b - 1;
    let cursor_a: Smi = baseA + length_a - 1;

    CopyElement(context, sortState, LoadF, Store, elements, cursor_a--, dest--)
    otherwise Bailout;

    try {
      if (--length_a == 0) goto Succeed;
      if (length_b == 1) goto CopyA;

      let min_gallop: Smi = unsafe_cast<Smi>(sortState[kMinGallopIdx]);
      // TODO(szuend): Replace with something that does not have a runtime
      //               overhead as soon as its available in Torque.
      while (Int32TrueConstant()) {
        let nof_wins_a: Smi = 0;  // # of times A won in a row.
        let nof_wins_b: Smi = 0;  // # of times B won in a row.

        // Do the straightforward thing until (if ever) one run appears to
        // win consistently.
        // TODO(szuend): Replace with something that does not have a runtime
        //               overhead as soon as its available in Torque.
        while (Int32TrueConstant()) {
          assert(length_a > 0 && length_b > 1);

          let element_a: Object =
              CallLoad(context, sortState, LoadF, elements, cursor_a)
          otherwise Bailout;
          let order: Number = CallCompareFn(
              context, sortState, temp_array[cursor_temp], element_a)
          otherwise Bailout;
          elements = ReloadElements(sortState);

          if (order < 0) {
            CopyElement(
                context, sortState, LoadF, Store, elements, cursor_a, dest)
            otherwise Bailout;

            --cursor_a;
            --dest;
            ++nof_wins_a;
            --length_a;
            nof_wins_b = 0;

            if (length_a == 0) goto Succeed;
            if (nof_wins_a >= min_gallop) break;
          } else {
            CallStore(
                context, sortState, Store, elements, dest,
                temp_array[cursor_temp])
            otherwise Bailout;

            --cursor_temp;
            --dest;
            ++nof_wins_b;
            --length_b;
            nof_wins_a = 0;

            if (length_b == 1) goto CopyA;
            if (nof_wins_b >= min_gallop) break;
          }
        }

        // 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.
        ++min_gallop;
        let first_iteration: bool = true;
        while (nof_wins_a >= kMinGallopWins || nof_wins_b >= kMinGallopWins ||
               first_iteration) {
          first_iteration = false;

          assert(length_a > 0 && length_b > 1);

          min_gallop = SmiMax(1, min_gallop - 1);
          sortState[kMinGallopIdx] = min_gallop;

          let k: Smi = CallGallopRight(
              context, sortState, LoadF, temp_array[cursor_temp], baseA,
              length_a, length_a - 1, False)
          otherwise Bailout;
          assert(k >= 0);
          nof_wins_a = length_a - k;

          if (nof_wins_a > 0) {
            dest = dest - nof_wins_a;
            cursor_a = cursor_a - nof_wins_a;
            CallCopyWithinSortArray(
                context, sortState, elements, cursor_a + 1, dest + 1,
                nof_wins_a)
            otherwise Bailout;

            length_a = length_a - nof_wins_a;
            if (length_a == 0) goto Succeed;
          }
          CallStore(
              context, sortState, Store, elements, dest--,
              temp_array[cursor_temp--])
          otherwise Bailout;
          if (--length_b == 1) goto CopyA;

          let key: Object =
              CallLoad(context, sortState, LoadF, elements, cursor_a)
          otherwise Bailout;
          k = CallGallopLeft(
              context, sortState, Load<TempArrayElements>, key, 0, length_b,
              length_b - 1, True) otherwise Bailout;
          assert(k >= 0);
          nof_wins_b = length_b - k;

          if (nof_wins_b > 0) {
            dest = dest - nof_wins_b;
            cursor_temp = cursor_temp - nof_wins_b;
            CallCopyFromTempArray(
                context, sortState, elements, dest + 1, temp_array,
                cursor_temp + 1, nof_wins_b) otherwise Bailout;

            length_b = length_b - nof_wins_b;
            if (length_b == 1) goto CopyA;

            // length_b == 0 is impossible now if the comparison function is
            // consistent, but we can't assume that it is.
            if (length_b == 0) goto Succeed;
          }
          CopyElement(
              context, sortState, LoadF, Store, elements, cursor_a--, dest--)
          otherwise Bailout;
          if (--length_a == 0) goto Succeed;
        }
        ++min_gallop;
        sortState[kMinGallopIdx] = min_gallop;
      }
    }
    label Succeed {
      if (length_b > 0) {
        assert(length_a == 0);
        CallCopyFromTempArray(
            context, sortState, elements, dest - (length_b - 1), temp_array, 0,
            length_b) otherwise Bailout;
      }
    }
    label CopyA {
      assert(length_b == 1 && length_a > 0);

      // The first element of run B belongs at the front of the merge.
      dest = dest - length_a;
      cursor_a = cursor_a - length_a;
      CallCopyWithinSortArray(
          context, sortState, elements, cursor_a + 1, dest + 1, length_a)
      otherwise Bailout;
      CallStore(
          context, sortState, Store, elements, dest, temp_array[cursor_temp])
      otherwise Bailout;
    }
  }

  // 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.
  // Else return an int k, 32 <= k <= 64, such that n/k is close to, but
  // strictly less than, an exact power of 2.
  //
  // See listsort.txt for more info.
  macro ComputeMinRunLength(nArg: Smi): Smi {
    let n: Smi = nArg;
    let r: Smi = 0;  // Becomes 1 if any 1 bits are shifted off.

    assert(n >= 0);
    while (n >= 64) {
      r = r | (n & 1);
      n = n >>> 1;
    }

    const min_run_length: Smi = n + r;
    assert(nArg < 64 || (32 <= min_run_length && min_run_length <= 64));
    return min_run_length;
  }

  // Returns true iff run_length(n - 2) > run_length(n - 1) + run_length(n).
  macro RunInvariantEstablished(pendingRuns: FixedArray, n: Smi): bool {
    if (n < 2) return true;

    const run_length_n: Smi = GetPendingRunLength(pendingRuns, n);
    const run_length_nm: Smi = GetPendingRunLength(pendingRuns, n - 1);
    const run_length_nmm: Smi = GetPendingRunLength(pendingRuns, n - 2);

    return run_length_nmm > run_length_nm + run_length_n;
  }

  // Examines the stack of runs waiting to be merged, merging adjacent runs
  // until the stack invariants are re-established:
  //
  //   1. run_length(i - 3) > run_length(i - 2) + run_length(i - 1)
  //   2. run_length(i - 2) > run_length(i - 1)
  //
  // TODO(szuend): Remove unnecessary loads. This macro was refactored to
  //               improve readability, introducing unnecessary loads in the
  //               process. Determine if all these extra loads are ok.
  macro MergeCollapse(context: Context, sortState: FixedArray)
  labels Bailout {
    const pending_runs: FixedArray =
        unsafe_cast<FixedArray>(sortState[kPendingRunsIdx]);

    // Reload the stack size because MergeAt might change it.
    while (GetPendingRunsSize(sortState) > 1) {
      let n: Smi = GetPendingRunsSize(sortState) - 2;

      if (!RunInvariantEstablished(pending_runs, n + 1) ||
          !RunInvariantEstablished(pending_runs, n)) {
        if (GetPendingRunLength(pending_runs, n - 1) <
            GetPendingRunLength(pending_runs, n + 1)) {
          --n;
        }

        CallMergeAt(context, sortState, n) otherwise Bailout;
      } else if (
          GetPendingRunLength(pending_runs, n) <=
          GetPendingRunLength(pending_runs, n + 1)) {
        CallMergeAt(context, sortState, n) otherwise Bailout;
      } else {
        break;
      }
    }
  }

  // Regardless of invariants, merge all runs on the stack until only one
  // remains. This is used at the end of the mergesort.
  macro MergeForceCollapse(context: Context, sortState: FixedArray)
  labels Bailout {
    let pending_runs: FixedArray =
        unsafe_cast<FixedArray>(sortState[kPendingRunsIdx]);

    // Reload the stack size becuase MergeAt might change it.
    while (GetPendingRunsSize(sortState) > 1) {
      let n: Smi = GetPendingRunsSize(sortState) - 2;

      if (n > 0 &&
          GetPendingRunLength(pending_runs, n - 1) <
              GetPendingRunLength(pending_runs, n + 1)) {
        --n;
      }
      CallMergeAt(context, sortState, n) otherwise Bailout;
    }
  }

  macro InitializeSortState(sortState: FixedArray) {
    sortState[kMinGallopIdx] = SmiConstant(kMinGallopWins);
    sortState[kTempArraySizeIdx] = SmiConstant(0);

    SetPendingRunsSize(sortState, 0);
    let pending_runs: FixedArray =
        AllocateZeroedFixedArray(convert<intptr>(kMaxMergePending));
    FillFixedArrayWithSmiZero(pending_runs, kMaxMergePending);
    sortState[kPendingRunsIdx] = pending_runs;
  }

  macro InitializeSortStateAccessor<Accessor : type>(sortState: FixedArray) {
    sortState[kAccessorIdx] = kFastElementsAccessorId;
    sortState[kLoadFnIdx] = Load<Accessor>;
    sortState[kStoreFnIdx] = Store<Accessor>;
    sortState[kCanUseSameAccessorFnIdx] = CanUseSameAccessor<Accessor>;
  }

  InitializeSortStateAccessor<GenericElementsAccessor>(sortState: FixedArray) {
    sortState[kAccessorIdx] = kGenericElementsAccessorId;
    sortState[kLoadFnIdx] = Load<GenericElementsAccessor>;
    sortState[kStoreFnIdx] = Store<GenericElementsAccessor>;
    sortState[kCanUseSameAccessorFnIdx] =
        CanUseSameAccessor<GenericElementsAccessor>;
  }

  macro ArrayTimSortImpl(context: Context, sortState: FixedArray, length: Smi)
  labels Bailout {
    InitializeSortState(sortState);

    if (length < 2) return;
    let remaining: Smi = length;

    // March over the array once, left to right, finding natural runs,
    // and extending short natural runs to minrun elements.
    let low: Smi = 0;
    const min_run_length: Smi = ComputeMinRunLength(remaining);
    while (remaining != 0) {
      let current_run_length: Smi =
          CountAndMakeRun(context, sortState, low, low + remaining)
      otherwise Bailout;

      // If the run is short, extend it to min(min_run_length, remaining).
      if (current_run_length < min_run_length) {
        const forced_run_length: Smi = SmiMin(min_run_length, remaining);
        BinaryInsertionSort(
            context, sortState, low, low + current_run_length,
            low + forced_run_length);
        EnsureSuccess(sortState) otherwise Bailout;
        current_run_length = forced_run_length;
      }

      // Push run onto pending-runs stack, and maybe merge.
      PushRun(sortState, low, current_run_length);

      MergeCollapse(context, sortState) otherwise Bailout;

      // Advance to find next run.
      low = low + current_run_length;
      remaining = remaining - current_run_length;
    }

    MergeForceCollapse(context, sortState) otherwise Bailout;
    assert(GetPendingRunsSize(sortState) == 1);
    assert(
        GetPendingRunLength(
            unsafe_cast<FixedArray>(sortState[kPendingRunsIdx]), 0) == length);
  }

  builtin ArrayTimSort(
      context: Context, sortState: FixedArray, length: Smi): Object {
    try {
      ArrayTimSortImpl(context, sortState, length)
      otherwise Slow;
    }
    label Slow {
      if (sortState[kAccessorIdx] == kGenericElementsAccessorId) {
        // We were already on the slow path. This must not happen.
        unreachable;
      }
      sortState[kBailoutStatusIdx] = kSuccess;

      InitializeSortStateAccessor<GenericElementsAccessor>(sortState);
      ArrayTimSort(context, sortState, length);
    }
    return kSuccess;
  }

  // For compatibility with JSC, we also sort elements inherited from
  // the prototype chain on non-Array objects.
  // We do this by copying them to this object and sorting only
  // own elements. This is not very efficient, but sorting with
  // inherited elements happens very, very rarely, if at all.
  // The specification allows "implementation dependent" behavior
  // if an element on the prototype chain has an element that
  // might interact with sorting.
  //
  // We also move all non-undefined elements to the front of the
  // array and move the undefineds after that. Holes are removed.
  // This happens for Array as well as non-Array objects.
  extern runtime PrepareElementsForSort(Context, Object, Number): Smi;
  extern macro FillFixedArrayWithSmiZero(FixedArray, Smi);

  // https://tc39.github.io/ecma262/#sec-array.prototype.sort
  javascript builtin ArrayPrototypeSort(
      context: Context, receiver: Object, ...arguments): Object {
    // 1. If comparefn is not undefined and IsCallable(comparefn) is false,
    //    throw a TypeError exception.
    const comparefnObj: Object = arguments[0];
    if (comparefnObj != Undefined && !TaggedIsCallable(comparefnObj)) {
      ThrowTypeError(context, kBadSortComparisonFunction, comparefnObj);
    }

    // 2. Let obj be ? ToObject(this value).
    const obj: JSReceiver = ToObject(context, receiver);
    let map: Map = obj.map;

    const sort_state: FixedArray =
        AllocateZeroedFixedArray(kSortStateSize);
    FillFixedArrayWithSmiZero(sort_state, SmiTag(kSortStateSize));

    sort_state[kReceiverIdx] = obj;
    sort_state[kUserCmpFnIdx] = comparefnObj;
    sort_state[kSortComparePtrIdx] =
        comparefnObj != Undefined ? SortCompareUserFn : SortCompareDefault;
    sort_state[kInitialReceiverMapIdx] = map;
    sort_state[kBailoutStatusIdx] = kSuccess;

    try {
      const a: JSArray = cast<JSArray>(obj) otherwise slow;
      const elementsKind: ElementsKind = map.elements_kind;
      if (!IsFastElementsKind(elementsKind)) goto slow;

      // 3. Let len be ? ToLength(? Get(obj, "length")).
      const len: Smi = a.length_fast;
      if (len < 2) return receiver;

      // TODO(szuend): Investigate performance tradeoff of skipping this step
      //               for PACKED_* and handling Undefineds during sorting.
      const nofNonUndefined: Smi = PrepareElementsForSort(context, obj, len);
      assert(a.map == map);

      sort_state[kInitialReceiverLengthIdx] = len;

      if (IsDoubleElementsKind(elementsKind)) {
        InitializeSortStateAccessor<FastDoubleElements>(sort_state);
      } else if (elementsKind == PACKED_SMI_ELEMENTS) {
        InitializeSortStateAccessor<FastPackedSmiElements>(sort_state);
      } else {
        InitializeSortStateAccessor<FastSmiOrObjectElements>(sort_state);
      }
      ArrayTimSort(context, sort_state, nofNonUndefined);
    }
    label slow {
      // 3. Let len be ? ToLength(? Get(obj, "length")).
      const len: Number =
          ToLength_Inline(context, GetProperty(context, obj, 'length'));

      if (len < 2) return receiver;
      const nofNonUndefined: Smi = PrepareElementsForSort(context, obj, len);

      sort_state[kInitialReceiverLengthIdx] = len;

      // Reload the map, PrepareElementsForSort might have changed the
      // elements kind.
      map = obj.map;

      if (map.elements_kind == DICTIONARY_ELEMENTS && IsExtensibleMap(map) &&
          !IsCustomElementsReceiverInstanceType(map.instance_type)) {
        InitializeSortStateAccessor<DictionaryElements>(sort_state);
      } else {
        InitializeSortStateAccessor<GenericElementsAccessor>(sort_state);
      }
      ArrayTimSort(context, sort_state, nofNonUndefined);
    }

    return receiver;
  }
}
