typed-array-slice.tq 3.76 KB
Newer Older
1 2 3 4 5 6
// 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'

7 8
namespace typed_array {
  const kBuiltinNameSlice: constexpr string = '%TypedArray%.prototype.slice';
9 10

  extern macro TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsSlice(
11
      JSTypedArray, JSTypedArray, uintptr, uintptr): void;
12 13

  macro FastCopy(
14
      src: typed_array::AttachedJSTypedArray, dest: JSTypedArray, k: uintptr,
15
      count: uintptr) labels IfSlow {
16
    if (IsForceSlowPath()) goto IfSlow;
17 18 19 20 21 22 23 24 25

    const srcKind: ElementsKind = src.elements_kind;
    const destInfo = typed_array::GetTypedArrayElementsInfo(dest);

    // dest could be a different type from src or share the same buffer
    // with the src because of custom species constructor. If the types
    // of src and result array are the same and they are not sharing the
    // same buffer, use memmove.
    if (srcKind != destInfo.kind) goto IfSlow;
26
    if (dest.buffer == src.buffer) {
27 28 29
      goto IfSlow;
    }

30 31 32
    const countBytes: uintptr = destInfo.CalculateByteLength(count)
        otherwise unreachable;
    const startOffset: uintptr = destInfo.CalculateByteLength(k)
33 34 35 36 37 38 39 40 41 42
        otherwise unreachable;
    const srcPtr: RawPtr = src.data_ptr + Convert<intptr>(startOffset);

    assert(countBytes <= dest.byte_length);
    assert(countBytes <= src.byte_length - startOffset);

    typed_array::CallCMemmove(dest.data_ptr, srcPtr, countBytes);
  }

  macro SlowCopy(implicit context: Context)(
43
      src: JSTypedArray, dest: JSTypedArray, k: uintptr, final: uintptr) {
44 45 46
    if (typed_array::IsBigInt64ElementsKind(src.elements_kind) !=
        typed_array::IsBigInt64ElementsKind(dest.elements_kind))
      deferred {
47
        ThrowTypeError(MessageTemplate::kBigIntMixedTypes);
48 49 50 51 52 53 54
      }

    CallCCopyTypedArrayElementsSlice(src, dest, k, final);
  }

  // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.slice
  transitioning javascript builtin TypedArrayPrototypeSlice(
55 56
      js-implicit context: NativeContext,
      receiver: JSAny)(...arguments): JSAny {
57 58 59 60 61 62
    // arguments[0] = start
    // arguments[1] = end

    // 1. Let O be the this value.
    // 2. Perform ? ValidateTypedArray(O).
    const src: JSTypedArray =
63
        ValidateTypedArray(context, receiver, kBuiltinNameSlice);
64 65

    // 3. Let len be O.[[ArrayLength]].
66
    const len: uintptr = src.length;
67 68 69 70 71

    // 4. Let relativeStart be ? ToInteger(start).
    // 5. If relativeStart < 0, let k be max((len + relativeStart), 0);
    //    else let k be min(relativeStart, len).
    const start = arguments[0];
72
    const k: uintptr =
73 74 75 76 77 78 79
        start != Undefined ? ConvertToRelativeIndex(start, len) : 0;

    // 6. If end is undefined, let relativeEnd be len;
    //    else let relativeEnd be ? ToInteger(end).
    // 7. If relativeEnd < 0, let final be max((len + relativeEnd), 0);
    //    else let final be min(relativeEnd, len).
    const end = arguments[1];
80
    const final: uintptr =
81 82 83
        end != Undefined ? ConvertToRelativeIndex(end, len) : len;

    // 8. Let count be max(final - k, 0).
84
    const count: uintptr = Unsigned(IntPtrMax(Signed(final - k), 0));
85 86

    // 9. Let A be ? TypedArraySpeciesCreate(O, « count »).
87 88
    const dest: JSTypedArray =
        TypedArraySpeciesCreateByLength(kBuiltinNameSlice, src, count);
89 90 91 92 93 94 95 96

    if (count > 0) {
      try {
        const srcAttached = typed_array::EnsureAttached(src)
            otherwise IfDetached;
        FastCopy(srcAttached, dest, k, count) otherwise IfSlow;
      }
      label IfDetached deferred {
97
        ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameSlice);
98 99 100 101 102 103 104 105 106
      }
      label IfSlow deferred {
        SlowCopy(src, dest, k, final);
      }
    }

    return dest;
  }
}