// 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-typed-array-gen.h'

namespace typed_array {
const kBuiltinNameSet: constexpr string = '%TypedArray%.prototype.set';

extern runtime TypedArraySet(
    Context, JSTypedArray, Object, Number, Number): void;

extern macro
TypedArrayBuiltinsAssembler::CallCCopyFastNumberJSArrayElementsToTypedArray(
    Context,
    FastJSArray,           // source
    AttachedJSTypedArray,  // dest
    uintptr,               // sourceLength
    uintptr                // destOffset
    ): void;

extern macro
TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsToTypedArray(
    AttachedJSTypedArray,  // source
    AttachedJSTypedArray,  // dest
    uintptr,               // sourceLength
    uintptr                // destOffset
    ): void;

// %TypedArray%.prototype.set ( overloaded [ , offset ] )
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.set-overloaded-offset
transitioning javascript builtin
TypedArrayPrototypeSet(
    js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
  // Steps 2-8 are the same for
  // %TypedArray%.prototype.set ( array [ , offset ] ) and
  // %TypedArray%.prototype.set ( typedArray [ , offset ] ) overloads.

  let target: JSTypedArray;
  try {
    // 2. Let target be the this value.
    // 3. Perform ? RequireInternalSlot(target, [[TypedArrayName]]).
    // 4. Assert: target has a [[ViewedArrayBuffer]] internal slot.
    target = Cast<JSTypedArray>(receiver) otherwise NotTypedArray;
  } label NotTypedArray deferred {
    ThrowTypeError(MessageTemplate::kNotTypedArray, kBuiltinNameSet);
  }

  try {
    // 5. Let targetOffset be ? ToInteger(offset).
    // 6. If targetOffset < 0, throw a RangeError exception.
    let targetOffsetOverflowed: bool = false;
    let targetOffset: uintptr = 0;
    if (arguments.length > 1) {
      const offsetArg = arguments[1];
      try {
        targetOffset = ToUintPtr(offsetArg)
        // On values less than zero throw RangeError immediately.
            otherwise OffsetOutOfBounds,
            // On UintPtr or SafeInteger range overflow throw RangeError after
            // performing observable steps to follow the spec.
            OffsetOverflow, OffsetOverflow;
      } label OffsetOverflow {
        targetOffsetOverflowed = true;
      }
    } else {
      // If the offset argument is not provided then the targetOffset is 0.
    }

    // 7. Let targetBuffer be target.[[ViewedArrayBuffer]].
    // 8. If IsDetachedBuffer(targetBuffer) is true, throw a TypeError
    //   exception.
    const utarget = typed_array::EnsureAttached(target) otherwise IsDetached;

    const overloadedArg = arguments[0];
    try {
      // 1. Choose 22.2.3.23.2 or 22.2.3.23.1 depending on whether the
      //   overloadedArg has a [[TypedArrayName]] internal slot.
      //   If it does, the definition in 22.2.3.23.2 applies.
      //   If it does not, the definition in 22.2.3.23.1 applies.
      const typedArray =
          Cast<JSTypedArray>(overloadedArg) otherwise NotTypedArray;

      // Step 9 is not observable, do it later.

      // 10. Let srcBuffer be typedArray.[[ViewedArrayBuffer]].
      // 11. If IsDetachedBuffer(srcBuffer) is true, throw a TypeError
      //   exception.
      const utypedArray =
          typed_array::EnsureAttached(typedArray) otherwise IsDetached;

      TypedArrayPrototypeSetTypedArray(
          utarget, utypedArray, targetOffset, targetOffsetOverflowed)
          otherwise OffsetOutOfBounds;
      return Undefined;
    } label NotTypedArray deferred {
      TypedArrayPrototypeSetArray(
          utarget, overloadedArg, targetOffset, targetOffsetOverflowed)
          otherwise OffsetOutOfBounds, IsDetached;
      return Undefined;
    }
  } label OffsetOutOfBounds deferred {
    ThrowRangeError(MessageTemplate::kTypedArraySetOffsetOutOfBounds);
  } label IsDetached deferred {
    ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameSet);
  }
}

// %TypedArray%.prototype.set ( array [ , offset ] )
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.set-array-offset
transitioning macro
TypedArrayPrototypeSetArray(implicit context: Context, receiver: JSAny)(
    target: JSTypedArray, arrayArg: JSAny, targetOffset: uintptr,
    targetOffsetOverflowed: bool): void labels IfOffsetOutOfBounds,
    IfDetached {
  // Steps 9-13 are not observable, do them later.

  // TODO(v8:8906): This ported behaviour is an observable spec violation and
  // the comment below seems to be outdated. Consider removing this code.
  try {
    const _arrayArgNum = Cast<Number>(arrayArg) otherwise NotNumber;
    // For number as a first argument, throw TypeError instead of silently
    // ignoring the call, so that users know they did something wrong.
    // (Consistent with Firefox and Blink/WebKit)
    ThrowTypeError(MessageTemplate::kInvalidArgument);
  } label NotNumber {
    // Proceed to step 14.
  }

  // 14. Let src be ? ToObject(array).
  const src: JSReceiver = ToObject_Inline(context, arrayArg);

  // 15. Let srcLength be ? LengthOfArrayLike(src).
  const srcLengthNum: Number = GetLengthProperty(src);

  if (targetOffsetOverflowed) goto IfOffsetOutOfBounds;

  // 9. Let targetLength be target.[[ArrayLength]].
  const targetLength = target.length;

  // 16. If srcLength + targetOffset > targetLength, throw a RangeError
  //   exception.
  const srcLength = ChangeSafeIntegerNumberToUintPtr(srcLengthNum)
      otherwise IfOffsetOutOfBounds;
  CheckIntegerIndexAdditionOverflow(srcLength, targetOffset, targetLength)
      otherwise IfOffsetOutOfBounds;

  // All the obvervable side effects are executed, so there's nothing else
  // to do with the empty source array.
  if (srcLength == 0) return;

  // 10. Let targetName be the String value of target.[[TypedArrayName]].
  // 11. Let targetElementSize be the Element Size value specified in
  //   Table 62 for targetName.
  // 12. Let targetType be the Element Type value in Table 62 for
  //   targetName.

  try {
    // BigInt typed arrays are not handled by
    // CopyFastNumberJSArrayElementsToTypedArray.
    if (IsBigInt64ElementsKind(target.elements_kind)) goto IfSlow;

    const fastSrc: FastJSArray = Cast<FastJSArray>(src) otherwise goto IfSlow;
    const srcKind: ElementsKind = fastSrc.map.elements_kind;

    // CopyFastNumberJSArrayElementsToTypedArray() can be used only with the
    // following elements kinds:
    // PACKED_SMI_ELEMENTS, HOLEY_SMI_ELEMENTS, PACKED_DOUBLE_ELEMENTS,
    // HOLEY_DOUBLE_ELEMENTS.
    if (IsElementsKindInRange(
            srcKind, ElementsKind::PACKED_SMI_ELEMENTS,
            ElementsKind::HOLEY_SMI_ELEMENTS) ||
        IsElementsKindInRange(
            srcKind, ElementsKind::PACKED_DOUBLE_ELEMENTS,
            ElementsKind::HOLEY_DOUBLE_ELEMENTS)) {
      const utarget = typed_array::EnsureAttached(target) otherwise IfDetached;
      CallCCopyFastNumberJSArrayElementsToTypedArray(
          context, fastSrc, utarget, srcLength, targetOffset);

    } else {
      goto IfSlow;
    }
  } label IfSlow deferred {
    TypedArraySet(
        context, target, src, srcLengthNum, Convert<Number>(targetOffset));
  }
}

// %TypedArray%.prototype.set ( typedArray [ , offset ] )
// https://tc39.es/ecma262/#sec-%typedarray%.prototype.set-typedarray-offset
transitioning macro
TypedArrayPrototypeSetTypedArray(implicit context: Context, receiver: JSAny)(
    target: AttachedJSTypedArray, typedArray: AttachedJSTypedArray,
    targetOffset: uintptr,
    targetOffsetOverflowed: bool): void labels IfOffsetOutOfBounds {
  // Steps 12-20 are not observable, so we can handle offset overflow
  // at step 21 here.
  if (targetOffsetOverflowed) goto IfOffsetOutOfBounds;

  // 9. Let targetLength be target.[[ArrayLength]].
  const targetLength = target.length;

  // 19. Let srcLength be typedArray.[[ArrayLength]].
  const srcLength: uintptr = typedArray.length;

  // Steps 12-20 are not observable, so we can do step 21 here.

  // 21. If srcLength + targetOffset > targetLength, throw a RangeError
  //   exception.
  CheckIntegerIndexAdditionOverflow(srcLength, targetOffset, targetLength)
      otherwise IfOffsetOutOfBounds;

  // 12. Let targetName be the String value of target.[[TypedArrayName]].
  // 13. Let targetType be the Element Type value in Table 62 for
  //   targetName.
  // 14. Let targetElementSize be the Element Size value specified in
  //   Table 62 for targetName.
  const targetElementsInfo = GetTypedArrayElementsInfo(target);

  // 16. Let srcName be the String value of typedArray.[[TypedArrayName]].
  // 17. Let srcType be the Element Type value in Table 62 for srcName.
  // 18. Let srcElementSize be the Element Size value specified in
  //   Table 62 for srcName.
  const srcKind: ElementsKind = typedArray.elements_kind;
  // const srcElementsInfo = GetTypedArrayElementsInfo(typedArray);

  // We skip steps 23-25 because both memmove and
  // CopyTypedArrayElementsToTypedArray() properly handle overlapping
  // regions.

  // 23. If both IsSharedArrayBuffer(srcBuffer) and
  //   IsSharedArrayBuffer(targetBuffer) are true, then
  // 23a. If srcBuffer.[[ArrayBufferData]] and
  //   targetBuffer.[[ArrayBufferData]] are the same Shared Data Block
  //   values, let same be true; else let same be false.
  // 24. Else, let same be SameValue(srcBuffer, targetBuffer).
  // 25. If same is true, then
  //   a. Let srcByteLength be typedArray.[[ByteLength]].
  //   b. Set srcBuffer to ? CloneArrayBuffer(srcBuffer, srcByteOffset,
  //    srcByteLength, %ArrayBuffer%).
  //   c. NOTE: %ArrayBuffer% is used to clone srcBuffer because is it known
  //    to not have any observable side-effects.
  //   d. Let srcByteIndex be 0.

  try {
    // Use memmove if possible.
    if (srcKind != targetElementsInfo.kind) {
      // Uint8/Uint8Clamped elements could still be copied with memmove.
      if (!IsUint8ElementsKind(srcKind) ||
          !IsUint8ElementsKind(targetElementsInfo.kind)) {
        goto IfSlow;
      }
    }

    // All the obvervable side effects are executed, so there's nothing else
    // to do with the empty source array.
    if (srcLength == 0) return;

    // Source and destination typed arrays have same elements kinds (modulo
    // Uint8-Uint8Clamped difference) so we can use targetElementsInfo for
    // calculations.
    const countBytes: uintptr =
        targetElementsInfo.CalculateByteLength(srcLength)
        otherwise unreachable;
    const startOffset: uintptr =
        targetElementsInfo.CalculateByteLength(targetOffset)
        otherwise unreachable;
    const dstPtr: RawPtr = target.data_ptr + Convert<intptr>(startOffset);

    assert(countBytes <= target.byte_length - startOffset);
    assert(countBytes <= typedArray.byte_length);

    // 29. If srcType is the same as targetType, then
    //   a. NOTE: If srcType and targetType are the same, the transfer must
    //      be performed in a manner that preserves the bit-level encoding of
    //      the source data.
    //   b. Repeat, while targetByteIndex < limit
    //      i. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex, Uint8,
    //                                         true, Unordered).
    //     ii. Perform SetValueInBuffer(targetBuffer, targetByteIndex, Uint8,
    //                                  value, true, Unordered).
    //    iii. Set srcByteIndex to srcByteIndex + 1.
    //     iv. Set targetByteIndex to targetByteIndex + 1.
    CallCMemmove(dstPtr, typedArray.data_ptr, countBytes);
  } label IfSlow deferred {
    // 22. If target.[[ContentType]] is not equal to
    //   typedArray.[[ContentType]], throw a TypeError exception.
    if (IsBigInt64ElementsKind(srcKind) !=
        IsBigInt64ElementsKind(targetElementsInfo.kind))
      deferred {
        ThrowTypeError(MessageTemplate::kBigIntMixedTypes);
      }

    // All the obvervable side effects are executed, so there's nothing else
    // to do with the empty source array.
    if (srcLength == 0) return;

    // 30. Else,
    //   a. Repeat, while targetByteIndex < limit
    //      i. Let value be GetValueFromBuffer(srcBuffer, srcByteIndex,
    //                                         srcType, true, Unordered).
    //     ii. Perform SetValueInBuffer(targetBuffer, targetByteIndex,
    //                                  targetType, value, true, Unordered).
    //    iii. Set srcByteIndex to srcByteIndex + srcElementSize.
    //     iv. Set targetByteIndex to targetByteIndex + targetElementSize.
    CallCCopyTypedArrayElementsToTypedArray(
        typedArray, target, srcLength, targetOffset);
  }
}
}
