// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include 'src/builtins/builtins-typed-array-gen.h'

namespace typed_array {
  // Naming convention from elements.cc. We have a similar intent but implement
  // fastpaths using generics instead of using a class hierarchy for elements
  // kinds specific implementations.
  type Uint8Elements;
  type Int8Elements;
  type Uint16Elements;
  type Int16Elements;
  type Uint32Elements;
  type Int32Elements;
  type Float32Elements;
  type Float64Elements;
  type Uint8ClampedElements;
  type BigUint64Elements;
  type BigInt64Elements;

  struct TypedArrayElementsInfo {
    // Calculates the number of bytes required for specified number of elements.
    CalculateByteLength(lengthSmi: PositiveSmi): uintptr labels IfInvalid {
      const length = Convert<uintptr>(lengthSmi);
      const byteLength = length << this.sizeLog2;
      // If an overflow ocurred, the byte length exceeds
      // JSArrayBuffer::kMaxByteLength and is invalid.
      if (byteLength >>> this.sizeLog2 != length) goto IfInvalid;
      return byteLength;
    }

    // Calculates the maximum number of elements supported by a specified number
    // of bytes.
    CalculateLength(byteLength: uintptr): PositiveSmi labels IfInvalid {
      return Convert<PositiveSmi>(byteLength >>> this.sizeLog2)
          otherwise IfInvalid;
    }

    // Determines if `bytes` (byte offset or length) cannot be evenly divided by
    // element size.
    IsUnaligned(bytes: uintptr): bool {
      // Exploits the fact the element size is a power of 2. Determining whether
      // there is remainder (not aligned) can be achieved efficiently with bit
      // masking. Shift is safe as sizeLog2 can be 3 at most (see
      // ElementsKindToShiftSize).
      return (bytes & ((1 << this.sizeLog2) - 1)) != 0;
    }

    sizeLog2: uintptr;
    kind: ElementsKind;
  }
  extern runtime TypedArraySortFast(Context, Object): JSTypedArray;
  extern macro TypedArrayBuiltinsAssembler::ValidateTypedArray(
      Context, Object, constexpr string): JSTypedArray;

  extern macro TypedArrayBuiltinsAssembler::CallCMemcpy(
      RawPtr, RawPtr, uintptr): void;
  extern macro TypedArrayBuiltinsAssembler::CallCMemmove(
      RawPtr, RawPtr, uintptr): void;
  extern macro TypedArrayBuiltinsAssembler::CallCMemset(
      RawPtr, intptr, uintptr): void;
  extern macro TypedArrayBuiltinsAssembler::GetBuffer(
      implicit context: Context)(JSTypedArray): JSArrayBuffer;
  extern macro TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(
      JSTypedArray): TypedArrayElementsInfo;
  extern macro TypedArrayBuiltinsAssembler::GetTypedArrayElementsInfo(Map):
      TypedArrayElementsInfo;
  extern macro TypedArrayBuiltinsAssembler::IsBigInt64ElementsKind(
      ElementsKind): bool;
  extern macro LoadFixedTypedArrayElementAsTagged(
      RawPtr, Smi, constexpr ElementsKind): Numeric;
  extern macro StoreJSTypedArrayElementFromTagged(
      Context, JSTypedArray, Smi, Object, constexpr ElementsKind);

  type LoadFn = builtin(Context, JSTypedArray, Smi) => Object;
  type StoreFn = builtin(Context, JSTypedArray, Smi, Object) => Object;

  // AttachedJSTypedArray guards that the array's buffer is not detached.
  transient type AttachedJSTypedArray extends JSTypedArray;

  macro EnsureAttached(array: JSTypedArray): AttachedJSTypedArray
      labels Detached {
    if (IsDetachedBuffer(array.buffer)) goto Detached;
    return %RawDownCast<AttachedJSTypedArray>(array);
  }

  struct AttachedJSTypedArrayWitness {
    Get(): AttachedJSTypedArray {
      return this.unstable;
    }

    GetStable(): JSTypedArray {
      return this.stable;
    }

    Recheck() labels Detached {
      if (IsDetachedBuffer(this.stable.buffer)) goto Detached;
      this.unstable = %RawDownCast<AttachedJSTypedArray>(this.stable);
    }

    Load(implicit context: Context)(k: Smi): Object {
      const lf: LoadFn = this.loadfn;
      return lf(context, this.unstable, k);
    }

    stable: JSTypedArray;
    unstable: AttachedJSTypedArray;
    loadfn: LoadFn;
  }

  macro NewAttachedJSTypedArrayWitness(array: AttachedJSTypedArray):
      AttachedJSTypedArrayWitness {
    const kind = array.elements_kind;
    return AttachedJSTypedArrayWitness{
      stable: array,
      unstable: array,
      loadfn: GetLoadFnForElementsKind(kind)
    };
  }

  macro GetLoadFnForElementsKind(elementsKind: ElementsKind): LoadFn {
    if (IsElementsKindGreaterThan(elementsKind, UINT32_ELEMENTS)) {
      if (elementsKind == INT32_ELEMENTS) {
        return LoadFixedElement<Int32Elements>;
      } else if (elementsKind == FLOAT32_ELEMENTS) {
        return LoadFixedElement<Float32Elements>;
      } else if (elementsKind == FLOAT64_ELEMENTS) {
        return LoadFixedElement<Float64Elements>;
      } else if (elementsKind == UINT8_CLAMPED_ELEMENTS) {
        return LoadFixedElement<Uint8ClampedElements>;
      } else if (elementsKind == BIGUINT64_ELEMENTS) {
        return LoadFixedElement<BigUint64Elements>;
      } else if (elementsKind == BIGINT64_ELEMENTS) {
        return LoadFixedElement<BigInt64Elements>;
      } else {
        unreachable;
      }
    } else {
      if (elementsKind == UINT8_ELEMENTS) {
        return LoadFixedElement<Uint8Elements>;
      } else if (elementsKind == INT8_ELEMENTS) {
        return LoadFixedElement<Int8Elements>;
      } else if (elementsKind == UINT16_ELEMENTS) {
        return LoadFixedElement<Uint16Elements>;
      } else if (elementsKind == INT16_ELEMENTS) {
        return LoadFixedElement<Int16Elements>;
      } else if (elementsKind == UINT32_ELEMENTS) {
        return LoadFixedElement<Uint32Elements>;
      } else {
        unreachable;
      }
    }
  }

  macro KindForArrayType<T: type>(): constexpr ElementsKind;
  KindForArrayType<Uint8Elements>(): constexpr ElementsKind {
    return UINT8_ELEMENTS;
  }
  KindForArrayType<Int8Elements>(): constexpr ElementsKind {
    return INT8_ELEMENTS;
  }
  KindForArrayType<Uint16Elements>(): constexpr ElementsKind {
    return UINT16_ELEMENTS;
  }
  KindForArrayType<Int16Elements>(): constexpr ElementsKind {
    return INT16_ELEMENTS;
  }
  KindForArrayType<Uint32Elements>(): constexpr ElementsKind {
    return UINT32_ELEMENTS;
  }
  KindForArrayType<Int32Elements>(): constexpr ElementsKind {
    return INT32_ELEMENTS;
  }
  KindForArrayType<Float32Elements>(): constexpr ElementsKind {
    return FLOAT32_ELEMENTS;
  }
  KindForArrayType<Float64Elements>(): constexpr ElementsKind {
    return FLOAT64_ELEMENTS;
  }
  KindForArrayType<Uint8ClampedElements>(): constexpr ElementsKind {
    return UINT8_CLAMPED_ELEMENTS;
  }
  KindForArrayType<BigUint64Elements>(): constexpr ElementsKind {
    return BIGUINT64_ELEMENTS;
  }
  KindForArrayType<BigInt64Elements>(): constexpr ElementsKind {
    return BIGINT64_ELEMENTS;
  }

  builtin LoadFixedElement<T: type>(
      _context: Context, array: JSTypedArray, index: Smi): Object {
    return LoadFixedTypedArrayElementAsTagged(
        array.data_ptr, index, KindForArrayType<T>());
  }

  builtin StoreFixedElement<T: type>(
      context: Context, typedArray: JSTypedArray, index: Smi,
      value: Object): Object {
    StoreJSTypedArrayElementFromTagged(
        context, typedArray, index, value, KindForArrayType<T>());
    return Undefined;
  }

  transitioning macro CallCompare(
      implicit context: Context, array: JSTypedArray,
      comparefn: Callable)(a: Object, b: Object): Number {
    // a. Let v be ? ToNumber(? Call(comparefn, undefined, x, y)).
    const v: Number =
        ToNumber_Inline(context, Call(context, comparefn, Undefined, a, b));

    // b. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
    if (IsDetachedBuffer(array.buffer)) {
      ThrowTypeError(kDetachedOperation, '%TypedArray%.prototype.sort');
    }

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

    // d. return v.
    return v;
  }

  // Merges two sorted runs [from, middle) and [middle, to)
  // from "source" into "target".
  transitioning macro
  TypedArrayMerge(
      implicit context: Context, array: JSTypedArray, comparefn: Callable)(
      source: FixedArray, from: Smi, middle: Smi, to: Smi, target: FixedArray) {
    let left: Smi = from;
    let right: Smi = middle;

    for (let targetIndex: Smi = from; targetIndex < to; ++targetIndex) {
      if (left < middle && right >= to) {
        // If the left run has elements, but the right does not, we take
        // from the left.
        target.objects[targetIndex] = source.objects[left++];
      } else if (left < middle) {
        // If both have elements, we need to compare.
        const leftElement: Object = source.objects[left];
        const rightElement: Object = source.objects[right];
        if (CallCompare(leftElement, rightElement) <= 0) {
          target.objects[targetIndex] = leftElement;
          left++;
        } else {
          target.objects[targetIndex] = rightElement;
          right++;
        }
      } else {
        // No elements on the left, but the right does, so we take
        // from the right.
        assert(left == middle);
        target.objects[targetIndex] = source.objects[right++];
      }
    }
  }

  transitioning builtin
  TypedArrayMergeSort(
      implicit context: Context, array: JSTypedArray, comparefn: Callable)(
      source: FixedArray, from: Smi, to: Smi, target: FixedArray): Object {
    assert(to - from > 1);
    const middle: Smi = from + ((to - from) >> 1);

    // On the next recursion step source becomes target and vice versa.
    // This saves the copy of the relevant range from the original
    // array into a work array on each recursion step.
    if (middle - from > 1) TypedArrayMergeSort(target, from, middle, source);
    if (to - middle > 1) TypedArrayMergeSort(target, middle, to, source);

    TypedArrayMerge(source, from, middle, to, target);

    return Undefined;
  }

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

    // 2. Let obj be the this value.
    const obj: Object = receiver;

    // 3. Let buffer be ? ValidateTypedArray(obj).
    //    ValidateTypedArray currently returns the array, not the ViewBuffer.
    const array: JSTypedArray =
        ValidateTypedArray(context, obj, '%TypedArray%.prototype.sort');

    // Default sorting is done in C++ using std::sort
    if (comparefnObj == Undefined) {
      return TypedArraySortFast(context, obj);
    }

    // 4. Let len be obj.[[ArrayLength]].
    // TODO(v8:4153): Support huge TypedArrays here.
    const len = Cast<Smi>(Convert<Number>(array.length)) otherwise unreachable;

    // Arrays of length 1 or less are considered sorted.
    if (len < 2) return array;

    const comparefn: Callable =
        Cast<Callable>(comparefnObj) otherwise unreachable;
    let loadfn: LoadFn;
    let storefn: StoreFn;

    const elementsKind: ElementsKind = array.elements_kind;

    if (IsElementsKindGreaterThan(elementsKind, UINT32_ELEMENTS)) {
      if (elementsKind == INT32_ELEMENTS) {
        loadfn = LoadFixedElement<Int32Elements>;
        storefn = StoreFixedElement<Int32Elements>;
      } else if (elementsKind == FLOAT32_ELEMENTS) {
        loadfn = LoadFixedElement<Float32Elements>;
        storefn = StoreFixedElement<Float32Elements>;
      } else if (elementsKind == FLOAT64_ELEMENTS) {
        loadfn = LoadFixedElement<Float64Elements>;
        storefn = StoreFixedElement<Float64Elements>;
      } else if (elementsKind == UINT8_CLAMPED_ELEMENTS) {
        loadfn = LoadFixedElement<Uint8ClampedElements>;
        storefn = StoreFixedElement<Uint8ClampedElements>;
      } else if (elementsKind == BIGUINT64_ELEMENTS) {
        loadfn = LoadFixedElement<BigUint64Elements>;
        storefn = StoreFixedElement<BigUint64Elements>;
      } else if (elementsKind == BIGINT64_ELEMENTS) {
        loadfn = LoadFixedElement<BigInt64Elements>;
        storefn = StoreFixedElement<BigInt64Elements>;
      } else {
        unreachable;
      }
    } else {
      if (elementsKind == UINT8_ELEMENTS) {
        loadfn = LoadFixedElement<Uint8Elements>;
        storefn = StoreFixedElement<Uint8Elements>;
      } else if (elementsKind == INT8_ELEMENTS) {
        loadfn = LoadFixedElement<Int8Elements>;
        storefn = StoreFixedElement<Int8Elements>;
      } else if (elementsKind == UINT16_ELEMENTS) {
        loadfn = LoadFixedElement<Uint16Elements>;
        storefn = StoreFixedElement<Uint16Elements>;
      } else if (elementsKind == INT16_ELEMENTS) {
        loadfn = LoadFixedElement<Int16Elements>;
        storefn = StoreFixedElement<Int16Elements>;
      } else if (elementsKind == UINT32_ELEMENTS) {
        loadfn = LoadFixedElement<Uint32Elements>;
        storefn = StoreFixedElement<Uint32Elements>;
      } else {
        unreachable;
      }
    }

    // Prepare the two work arrays. All numbers are converted to tagged
    // objects first, and merge sorted between the two FixedArrays.
    // The result is then written back into the JSTypedArray.
    const work1: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));
    const work2: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));

    for (let i: Smi = 0; i < len; ++i) {
      const element: Object = loadfn(context, array, i);
      work1.objects[i] = element;
      work2.objects[i] = element;
    }

    TypedArrayMergeSort(work2, 0, len, work1);

    // work1 contains the sorted numbers. Write them back.
    for (let i: Smi = 0; i < len; ++i)
      storefn(context, array, i, work1.objects[i]);

    return array;
  }
}
