| // 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 kBuiltinNameSlice: constexpr string = '%TypedArray%.prototype.slice'; |
| |
| extern macro TypedArrayBuiltinsAssembler::CallCCopyTypedArrayElementsSlice( |
| JSTypedArray, JSTypedArray, uintptr, uintptr): void; |
| |
| macro FastCopy( |
| src: typed_array::AttachedJSTypedArray, dest: JSTypedArray, k: uintptr, |
| count: uintptr) labels IfSlow { |
| if (IsForceSlowPath()) goto IfSlow; |
| |
| 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; |
| if (dest.buffer == src.buffer) { |
| goto IfSlow; |
| } |
| |
| const countBytes: uintptr = destInfo.CalculateByteLength(count) |
| otherwise unreachable; |
| const startOffset: uintptr = destInfo.CalculateByteLength(k) |
| 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)( |
| src: JSTypedArray, dest: JSTypedArray, k: uintptr, final: uintptr) { |
| if (typed_array::IsBigInt64ElementsKind(src.elements_kind) != |
| typed_array::IsBigInt64ElementsKind(dest.elements_kind)) |
| deferred { |
| ThrowTypeError(MessageTemplate::kBigIntMixedTypes); |
| } |
| |
| CallCCopyTypedArrayElementsSlice(src, dest, k, final); |
| } |
| |
| // https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.slice |
| transitioning javascript builtin TypedArrayPrototypeSlice( |
| js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny { |
| // arguments[0] = start |
| // arguments[1] = end |
| |
| // 1. Let O be the this value. |
| // 2. Perform ? ValidateTypedArray(O). |
| const src: JSTypedArray = |
| ValidateTypedArray(context, receiver, kBuiltinNameSlice); |
| |
| // 3. Let len be O.[[ArrayLength]]. |
| const len: uintptr = src.length; |
| |
| // 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]; |
| const k: uintptr = |
| 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]; |
| const final: uintptr = |
| end != Undefined ? ConvertToRelativeIndex(end, len) : len; |
| |
| // 8. Let count be max(final - k, 0). |
| const count: uintptr = Unsigned(IntPtrMax(Signed(final - k), 0)); |
| |
| // 9. Let A be ? TypedArraySpeciesCreate(O, « count »). |
| const dest: JSTypedArray = |
| TypedArraySpeciesCreateByLength(kBuiltinNameSlice, src, count); |
| |
| if (count > 0) { |
| try { |
| const srcAttached = typed_array::EnsureAttached(src) |
| otherwise IfDetached; |
| FastCopy(srcAttached, dest, k, count) otherwise IfSlow; |
| } label IfDetached deferred { |
| ThrowTypeError(MessageTemplate::kDetachedOperation, kBuiltinNameSlice); |
| } label IfSlow deferred { |
| SlowCopy(src, dest, k, final); |
| } |
| } |
| |
| return dest; |
| } |
| } |