// Copyright 2019 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-constructor-gen.h'

namespace typed_array {
extern builtin IterableToListMayPreserveHoles(
    Context, Object, Callable): JSArray;

extern macro TypedArrayBuiltinsAssembler::AllocateEmptyOnHeapBuffer(
    implicit context: Context)(uintptr): JSArrayBuffer;
extern macro CodeStubAssembler::AllocateByteArray(uintptr): ByteArray;
extern macro TypedArrayBuiltinsAssembler::GetDefaultConstructor(
    implicit context: Context)(JSTypedArray): JSFunction;
extern macro TypedArrayBuiltinsAssembler::SetupTypedArrayEmbedderFields(
    JSTypedArray): void;

extern runtime ThrowInvalidTypedArrayAlignment(implicit context: Context)(
    Map, String): never;

extern runtime GrowableSharedArrayBufferByteLength(implicit context: Context)(
    Object): JSAny;

transitioning macro AllocateTypedArray(implicit context: Context)(
    isOnHeap: constexpr bool, map: Map, buffer: JSArrayBuffer,
    byteOffset: uintptr, byteLength: uintptr, length: uintptr,
    isLengthTracking: bool): JSTypedArray {
  let elements: ByteArray;
  if constexpr (isOnHeap) {
    assert(!IsResizableArrayBuffer(buffer));
    assert(!isLengthTracking);
    elements = AllocateByteArray(byteLength);
  } else {
    elements = kEmptyByteArray;

    // The max byteOffset is 8 * MaxSmi on the particular platform. 32 bit
    // platforms are self-limiting, because we can't allocate an array bigger
    // than our 32-bit arithmetic range anyway. 64 bit platforms could
    // theoretically have an offset up to 2^35 - 1.
    const backingStore: uintptr = Convert<uintptr>(buffer.backing_store_ptr);

    // Assert no overflow has occurred. Only assert if the mock array buffer
    // allocator is NOT used. When the mock array buffer is used, impossibly
    // large allocations are allowed that would erroneously cause an overflow
    // and this assertion to fail.
    assert(
        IsMockArrayBufferAllocatorFlag() ||
        (backingStore + byteOffset) >= backingStore);
  }

  // We can't just build the new object with "new JSTypedArray" here because
  // Torque doesn't know its full size including embedder fields, so use CSA
  // for the allocation step.
  const typedArray =
      UnsafeCast<JSTypedArray>(AllocateFastOrSlowJSObjectFromMap(map));
  typedArray.elements = elements;
  typedArray.buffer = buffer;
  typedArray.byte_offset = byteOffset;
  typedArray.byte_length = byteLength;
  typedArray.length = length;
  typedArray.bit_field.is_length_tracking = isLengthTracking;
  typedArray.bit_field.is_backed_by_rab =
      IsResizableArrayBuffer(buffer) && !IsSharedArrayBuffer(buffer);
  typed_array::AllocateJSTypedArrayExternalPointerEntry(typedArray);
  if constexpr (isOnHeap) {
    typed_array::SetJSTypedArrayOnHeapDataPtr(typedArray, elements, byteOffset);
  } else {
    typed_array::SetJSTypedArrayOffHeapDataPtr(
        typedArray, buffer.backing_store_ptr, byteOffset);
    assert(
        typedArray.data_ptr ==
        (buffer.backing_store_ptr + Convert<intptr>(byteOffset)));
  }
  SetupTypedArrayEmbedderFields(typedArray);
  return typedArray;
}

transitioning macro TypedArrayInitialize(implicit context: Context)(
    initialize: constexpr bool, map: Map, length: uintptr,
    elementsInfo: typed_array::TypedArrayElementsInfo,
    bufferConstructor: JSReceiver): JSTypedArray labels IfRangeError {
  const byteLength = elementsInfo.CalculateByteLength(length)
      otherwise IfRangeError;
  const byteLengthNum = Convert<Number>(byteLength);
  const defaultConstructor = GetArrayBufferFunction();
  const byteOffset: uintptr = 0;

  try {
    if (bufferConstructor != defaultConstructor) {
      goto AttachOffHeapBuffer(ConstructWithTarget(
          defaultConstructor, bufferConstructor, byteLengthNum));
    }

    if (byteLength > kMaxTypedArrayInHeap) goto AllocateOffHeap;

    const buffer = AllocateEmptyOnHeapBuffer(byteLength);

    const isOnHeap: constexpr bool = true;
    const isLengthTracking: constexpr bool = false;
    const typedArray = AllocateTypedArray(
        isOnHeap, map, buffer, byteOffset, byteLength, length,
        isLengthTracking);

    if constexpr (initialize) {
      const backingStore = typedArray.data_ptr;
      typed_array::CallCMemset(backingStore, 0, byteLength);
    }

    return typedArray;
  } label AllocateOffHeap {
    if constexpr (initialize) {
      goto AttachOffHeapBuffer(Construct(defaultConstructor, byteLengthNum));
    } else {
      goto AttachOffHeapBuffer(Call(
          context, GetArrayBufferNoInitFunction(), Undefined, byteLengthNum));
    }
  } label AttachOffHeapBuffer(bufferObj: Object) {
    const buffer = Cast<JSArrayBuffer>(bufferObj) otherwise unreachable;
    const isOnHeap: constexpr bool = false;
    const isLengthTracking: constexpr bool = false;
    return AllocateTypedArray(
        isOnHeap, map, buffer, byteOffset, byteLength, length,
        isLengthTracking);
  }
}

// 22.2.4.2 TypedArray ( length )
// ES #sec-typedarray-length
transitioning macro ConstructByLength(implicit context: Context)(
    map: Map, lengthObj: JSAny,
    elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray {
  try {
    const length: uintptr = ToIndex(lengthObj) otherwise RangeError;
    const defaultConstructor: Constructor = GetArrayBufferFunction();
    const initialize: constexpr bool = true;
    return TypedArrayInitialize(
        initialize, map, length, elementsInfo, defaultConstructor)
        otherwise RangeError;
  } label RangeError deferred {
    ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, lengthObj);
  }
}

// 22.2.4.4 TypedArray ( object )
// ES #sec-typedarray-object
transitioning macro ConstructByArrayLike(implicit context: Context)(
    map: Map, arrayLike: HeapObject, length: uintptr,
    elementsInfo: typed_array::TypedArrayElementsInfo,
    bufferConstructor: JSReceiver): JSTypedArray {
  try {
    const initialize: constexpr bool = false;
    const typedArray = TypedArrayInitialize(
        initialize, map, length, elementsInfo, bufferConstructor)
        otherwise RangeError;

    try {
      const src: JSTypedArray = Cast<JSTypedArray>(arrayLike) otherwise IfSlow;

      if (IsDetachedBuffer(src.buffer)) {
        ThrowTypeError(MessageTemplate::kDetachedOperation, 'Construct');

      } else if (src.elements_kind != elementsInfo.kind) {
        goto IfSlow;

      } else if (length > 0) {
        const byteLength = typedArray.byte_length;
        assert(byteLength <= kArrayBufferMaxByteLength);
        if (IsSharedArrayBuffer(src.buffer)) {
          typed_array::CallCRelaxedMemcpy(
              typedArray.data_ptr, src.data_ptr, byteLength);
        } else {
          typed_array::CallCMemcpy(
              typedArray.data_ptr, src.data_ptr, byteLength);
        }
      }
    } label IfSlow deferred {
      if (length > 0) {
        TypedArrayCopyElements(
            context, typedArray, arrayLike, Convert<Number>(length));
      }
    }
    return typedArray;
  } label RangeError deferred {
    ThrowRangeError(
        MessageTemplate::kInvalidTypedArrayLength, Convert<Number>(length));
  }
}

// 22.2.4.4 TypedArray ( object )
// ES #sec-typedarray-object
transitioning macro ConstructByIterable(implicit context: Context)(
    iterable: JSReceiver, iteratorFn: Callable): never
    labels IfConstructByArrayLike(JSArray, uintptr, JSReceiver) {
  const array: JSArray =
      IterableToListMayPreserveHoles(context, iterable, iteratorFn);
  // Max JSArray length is a valid JSTypedArray length so we just use it.
  goto IfConstructByArrayLike(
      array, array.length_uintptr, GetArrayBufferFunction());
}

// 22.2.4.3 TypedArray ( typedArray )
// ES #sec-typedarray-typedarray
transitioning macro ConstructByTypedArray(implicit context: Context)(
    srcTypedArray: JSTypedArray): never
    labels IfConstructByArrayLike(JSTypedArray, uintptr, JSReceiver) {
  let bufferConstructor: JSReceiver = GetArrayBufferFunction();
  const srcBuffer: JSArrayBuffer = srcTypedArray.buffer;
  // TODO(petermarshall): Throw on detached typedArray.
  let length: uintptr = IsDetachedBuffer(srcBuffer) ? 0 : srcTypedArray.length;

  // The spec requires that constructing a typed array using a SAB-backed
  // typed array use the ArrayBuffer constructor, not the species constructor.
  // See https://tc39.github.io/ecma262/#sec-typedarray-typedarray.
  if (!IsSharedArrayBuffer(srcBuffer)) {
    bufferConstructor = SpeciesConstructor(srcBuffer, bufferConstructor);
    // TODO(petermarshall): Throw on detached typedArray.
    if (IsDetachedBuffer(srcBuffer)) length = 0;
  }
  goto IfConstructByArrayLike(srcTypedArray, length, bufferConstructor);
}

// 22.2.4.5 TypedArray ( buffer, byteOffset, length )
// ES #sec-typedarray-buffer-byteoffset-length
transitioning macro ConstructByArrayBuffer(implicit context: Context)(
    target: JSFunction, newTarget: JSReceiver, buffer: JSArrayBuffer,
    byteOffset: JSAny, length: JSAny): JSTypedArray {
  let map: Map;
  const isLengthTracking: bool =
      IsResizableArrayBuffer(buffer) && (length == Undefined);
  // Pick the RAB / GSAB map (containing the corresponding RAB / GSAB
  // ElementsKind). GSAB-backed non-length-tracking TypedArrays behave just like
  // normal TypedArrays, so exclude them.
  const rabGsab: bool = IsResizableArrayBuffer(buffer) &&
      (!IsSharedArrayBuffer(buffer) || isLengthTracking);
  if (rabGsab) {
    map = GetDerivedRabGsabMap(target, newTarget);
  } else {
    map = GetDerivedMap(target, newTarget);
  }

  // 5. Let elementSize be the Number value of the Element Size value in Table
  // 56 for constructorName.
  const elementsInfo = GetTypedArrayElementsInfo(map);

  try {
    // 6. Let offset be ? ToIndex(byteOffset).
    const offset: uintptr = ToIndex(byteOffset) otherwise IfInvalidOffset;

    // 7. If offset modulo elementSize ≠ 0, throw a RangeError exception.
    if (elementsInfo.IsUnaligned(offset)) {
      goto IfInvalidAlignment('start offset');
    }

    // 8. If length is present and length is not undefined, then
    // a. Let newLength be ? ToIndex(length).
    let newLength: uintptr = ToIndex(length) otherwise IfInvalidLength;
    let newByteLength: uintptr;

    // 9. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
    if (IsDetachedBuffer(buffer)) {
      ThrowTypeError(MessageTemplate::kDetachedOperation, 'Construct');
    }

    // 10. Let bufferByteLength be buffer.[[ArrayBufferByteLength]].
    let bufferByteLength: uintptr;
    if (IsResizableArrayBuffer(buffer) && IsSharedArrayBuffer(buffer)) {
      bufferByteLength = ToIndex(GrowableSharedArrayBufferByteLength(buffer))
          otherwise unreachable;
    } else {
      bufferByteLength = buffer.byte_length;
    }

    // 11. If length is either not present or undefined, then
    if (length == Undefined) {
      // a. If bufferByteLength modulo elementSize ≠ 0, throw a RangeError
      // exception.
      if (elementsInfo.IsUnaligned(bufferByteLength)) {
        goto IfInvalidAlignment('byte length');
      }

      // b. Let newByteLength be bufferByteLength - offset.
      // c. If newByteLength < 0, throw a RangeError exception.
      if (bufferByteLength < offset) goto IfInvalidOffset;

      // Spec step 16 length calculated here to avoid recalculating the length
      // in the step 12 branch.
      newByteLength = bufferByteLength - offset;
      newLength = elementsInfo.CalculateLength(newByteLength)
          otherwise IfInvalidOffset;

      // 12. Else,
    } else {
      // a. Let newByteLength be newLength × elementSize.
      newByteLength = elementsInfo.CalculateByteLength(newLength)
          otherwise IfInvalidLength;

      // b. If offset + newByteLength > bufferByteLength, throw a RangeError
      // exception.
      if ((bufferByteLength < newByteLength) ||
          (offset > bufferByteLength - newByteLength))
        goto IfInvalidLength;
    }

    const isOnHeap: constexpr bool = false;
    return AllocateTypedArray(
        isOnHeap, map, buffer, offset, newByteLength, newLength,
        isLengthTracking);
  } label IfInvalidAlignment(problemString: String) deferred {
    ThrowInvalidTypedArrayAlignment(map, problemString);
  } label IfInvalidLength deferred {
    ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, length);
  } label IfInvalidOffset deferred {
    ThrowRangeError(MessageTemplate::kInvalidOffset, byteOffset);
  }
}

// 22.2.4.6 TypedArrayCreate ( constructor, argumentList )
// ES #typedarray-create
@export
transitioning macro TypedArrayCreateByLength(implicit context: Context)(
    constructor: Constructor, length: Number, methodName: constexpr string):
    JSTypedArray {
  assert(IsSafeInteger(length));

  // 1. Let newTypedArray be ? Construct(constructor, argumentList).
  const newTypedArrayObj = Construct(constructor, length);

  // 2. Perform ? ValidateTypedArray(newTypedArray).
  //    ValidateTypedArray currently returns the array, not the ViewBuffer.
  const newTypedArray: JSTypedArray =
      ValidateTypedArray(context, newTypedArrayObj, methodName);
  newTypedArray.bit_field.is_length_tracking = false;
  newTypedArray.bit_field.is_backed_by_rab = false;

  if (IsDetachedBuffer(newTypedArray.buffer)) deferred {
      ThrowTypeError(MessageTemplate::kDetachedOperation, methodName);
    }

  // 3. If argumentList is a List of a single Number, then
  //   a. If newTypedArray.[[ArrayLength]] < argumentList[0], throw a
  //      TypeError exception.
  if (newTypedArray.length < Convert<uintptr>(length)) deferred {
      ThrowTypeError(MessageTemplate::kTypedArrayTooShort);
    }

  // 4. Return newTypedArray.
  return newTypedArray;
}

transitioning macro ConstructByJSReceiver(implicit context: Context)(
    obj: JSReceiver): never
    labels IfConstructByArrayLike(JSReceiver, uintptr, JSReceiver) {
  try {
    // TODO(v8:8906): Use iterator::GetIteratorMethod() once it supports
    // labels.
    const iteratorMethod = GetMethod(obj, IteratorSymbolConstant())
        otherwise IfIteratorUndefined, IfIteratorNotCallable;
    ConstructByIterable(obj, iteratorMethod)
        otherwise IfConstructByArrayLike;
  } label IfIteratorUndefined {
    const lengthObj: JSAny = GetProperty(obj, kLengthString);
    const lengthNumber: Number = ToLength_Inline(lengthObj);
    // Throw RangeError here if the length does not fit in uintptr because
    // such a length will not pass bounds checks in ConstructByArrayLike()
    // anyway.
    const length: uintptr = ChangeSafeIntegerNumberToUintPtr(lengthNumber)
        otherwise goto IfInvalidLength(lengthNumber);
    goto IfConstructByArrayLike(obj, length, GetArrayBufferFunction());
  } label IfInvalidLength(length: Number) {
    ThrowRangeError(MessageTemplate::kInvalidTypedArrayLength, length);
  } label IfIteratorNotCallable(_value: JSAny) deferred {
    ThrowTypeError(MessageTemplate::kIteratorSymbolNonCallable);
  }
}

// 22.2.4 The TypedArray Constructors
// ES #sec-typedarray-constructors
transitioning builtin CreateTypedArray(
    context: Context, target: JSFunction, newTarget: JSReceiver, arg1: JSAny,
    arg2: JSAny, arg3: JSAny): JSTypedArray {
  assert(IsConstructor(target));
  // 4. Let O be ? AllocateTypedArray(constructorName, NewTarget,
  // "%TypedArrayPrototype%").
  try {
    typeswitch (arg1) {
      case (length: Smi): {
        goto IfConstructByLength(length);
      }
      case (buffer: JSArrayBuffer): {
        return ConstructByArrayBuffer(target, newTarget, buffer, arg2, arg3);
      }
      case (typedArray: JSTypedArray): {
        // TODO(v8:11111): Support RAB / GSAB.
        ConstructByTypedArray(typedArray) otherwise IfConstructByArrayLike;
      }
      case (obj: JSReceiver): {
        ConstructByJSReceiver(obj) otherwise IfConstructByArrayLike;
      }
      // The first argument was a number or fell through and is treated as
      // a number. https://tc39.github.io/ecma262/#sec-typedarray-length
      case (lengthObj: JSAny): {
        goto IfConstructByLength(lengthObj);
      }
    }
  } label IfConstructByLength(length: JSAny) {
    const map = GetDerivedMap(target, newTarget);
    // 5. Let elementSize be the Number value of the Element Size value in Table
    // 56 for constructorName.
    const elementsInfo = GetTypedArrayElementsInfo(map);

    return ConstructByLength(map, length, elementsInfo);
  } label IfConstructByArrayLike(
      arrayLike: JSReceiver, length: uintptr, bufferConstructor: JSReceiver) {
    const map = GetDerivedMap(target, newTarget);
    // 5. Let elementSize be the Number value of the Element Size value in Table
    // 56 for constructorName.
    const elementsInfo = GetTypedArrayElementsInfo(map);
    return ConstructByArrayLike(
        map, arrayLike, length, elementsInfo, bufferConstructor);
  }
}

transitioning macro TypedArraySpeciesCreate(implicit context: Context)(
    methodName: constexpr string, numArgs: constexpr int31,
    exemplar: JSTypedArray, arg0: JSAny, arg1: JSAny,
    arg2: JSAny): JSTypedArray {
  const defaultConstructor = GetDefaultConstructor(exemplar);

  try {
    if (!IsPrototypeTypedArrayPrototype(exemplar.map)) goto IfSlow;
    if (IsTypedArraySpeciesProtectorCellInvalid()) goto IfSlow;

    const typedArray = CreateTypedArray(
        context, defaultConstructor, defaultConstructor, arg0, arg1, arg2);

    // It is assumed that the CreateTypedArray builtin does not produce a
    // typed array that fails ValidateTypedArray
    assert(!IsDetachedBuffer(typedArray.buffer));

    return typedArray;
  } label IfSlow deferred {
    const constructor =
        Cast<Constructor>(SpeciesConstructor(exemplar, defaultConstructor))
        otherwise unreachable;

    // TODO(pwong): Simplify and remove numArgs when varargs are supported in
    // macros.
    let newObj: JSAny = Undefined;
    if constexpr (numArgs == 1) {
      newObj = Construct(constructor, arg0);
    } else {
      assert(numArgs == 3);
      newObj = Construct(constructor, arg0, arg1, arg2);
    }

    return ValidateTypedArray(context, newObj, methodName);
  }
}

@export
transitioning macro TypedArraySpeciesCreateByLength(implicit context: Context)(
    methodName: constexpr string, exemplar: JSTypedArray, length: uintptr):
    JSTypedArray {
  const numArgs: constexpr int31 = 1;
  // TODO(v8:4153): pass length further as uintptr.
  const typedArray: JSTypedArray = TypedArraySpeciesCreate(
      methodName, numArgs, exemplar, Convert<Number>(length), Undefined,
      Undefined);
  if (typedArray.length < length) deferred {
      ThrowTypeError(MessageTemplate::kTypedArrayTooShort);
    }
  return typedArray;
}

transitioning macro TypedArraySpeciesCreateByBuffer(implicit context: Context)(
    methodName: constexpr string, exemplar: JSTypedArray, buffer: JSArrayBuffer,
    beginByteOffset: uintptr, newLength: uintptr): JSTypedArray {
  const numArgs: constexpr int31 = 3;
  // TODO(v8:4153): pass length further as uintptr.
  const typedArray: JSTypedArray = TypedArraySpeciesCreate(
      methodName, numArgs, exemplar, buffer, Convert<Number>(beginByteOffset),
      Convert<Number>(newLength));
  return typedArray;
}
}
