blob: 624e50bd483a36e0a2cc7188796e180285ee00da [file] [log] [blame]
// Copyright 2022 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.
namespace array {
transitioning macro CopyWorkArrayToNewFastJSArray(
implicit context: Context, sortState: SortState)(
elementsKind: constexpr ElementsKind, numberOfNonUndefined: Smi): JSArray {
dcheck(
elementsKind == ElementsKind::PACKED_SMI_ELEMENTS ||
elementsKind == ElementsKind::PACKED_ELEMENTS);
const len = sortState.sortLength;
dcheck(len == numberOfNonUndefined + sortState.numberOfUndefined);
dcheck(len <= kMaxFastArrayLength);
const copy: FixedArray = UnsafeCast<FixedArray>(
AllocateFixedArray(elementsKind, Convert<intptr>(len)));
const workArray = sortState.workArray;
CopyElements(
elementsKind, copy, 0, workArray, 0,
Convert<intptr>(numberOfNonUndefined));
dcheck(
sortState.numberOfUndefined == 0 ||
elementsKind == ElementsKind::PACKED_ELEMENTS);
for (let i = numberOfNonUndefined; i < len; ++i) {
copy.objects[i] = Undefined;
}
const map = LoadJSArrayElementsMap(elementsKind, LoadNativeContext(context));
return NewJSArray(map, copy);
}
transitioning macro CopyWorkArrayToNewJSArray(
implicit context: Context, sortState: SortState)(
numberOfNonUndefined: Smi): JSArray {
const len = sortState.sortLength;
dcheck(len == numberOfNonUndefined + sortState.numberOfUndefined);
const workArray = sortState.workArray;
const copy = ArrayCreate(len);
let i: Smi = 0;
for (; i < numberOfNonUndefined; ++i) {
SetProperty(copy, i, UnsafeCast<JSAny>(workArray.objects[i]));
}
for (; i < len; ++i) {
SetProperty(copy, i, Undefined);
}
return copy;
}
transitioning builtin ArrayTimSortIntoCopy(
context: Context, sortState: SortState): JSArray {
const isToSorted: constexpr bool = true;
const numberOfNonUndefined: Smi =
CompactReceiverElementsIntoWorkArray(isToSorted);
ArrayTimSortImpl(context, sortState, numberOfNonUndefined);
if (sortState.sortLength <= kMaxFastArrayLength) {
// The result copy of Array.prototype.toSorted is always packed.
try {
if (sortState.numberOfUndefined != 0) goto FastObject;
const workArray = sortState.workArray;
dcheck(numberOfNonUndefined <= workArray.length);
for (let i: Smi = 0; i < numberOfNonUndefined; ++i) {
const e = UnsafeCast<JSAny>(workArray.objects[i]);
// TODO(v8:12764): ArrayTimSortImpl already boxed doubles. Support
// PACKED_DOUBLE_ELEMENTS.
if (TaggedIsNotSmi(e)) {
goto FastObject;
}
}
return CopyWorkArrayToNewFastJSArray(
ElementsKind::PACKED_SMI_ELEMENTS, numberOfNonUndefined);
} label FastObject {
return CopyWorkArrayToNewFastJSArray(
ElementsKind::PACKED_ELEMENTS, numberOfNonUndefined);
}
}
return CopyWorkArrayToNewJSArray(numberOfNonUndefined);
}
// https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSorted
@incrementUseCounter('v8::Isolate::kArrayByCopy')
transitioning javascript builtin ArrayPrototypeToSorted(
js-implicit context: NativeContext, receiver: JSAny)(...arguments): JSAny {
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw
// a TypeError exception.
const comparefnObj: JSAny = arguments[0];
const comparefn = Cast<(Undefined | Callable)>(comparefnObj) otherwise
ThrowTypeError(MessageTemplate::kBadSortComparisonFunction, comparefnObj);
// 2. Let O be ? ToObject(this value).
const obj: JSReceiver = ToObject(context, receiver);
// 3. Let len be ? LengthOfArrayLike(O).
const len: Number = GetLengthProperty(obj);
if (len == 0) return ArrayCreate(0);
if (len == 1) {
const copy = ArrayCreate(1);
const zero: Smi = 0;
SetProperty(copy, zero, GetProperty(obj, zero));
return copy;
}
// 4. Let A be ? ArrayCreate(𝔽(len)).
//
// The actual array will be created later, but perform the range check.
if (len > kMaxArrayLength) {
ThrowRangeError(MessageTemplate::kInvalidArrayLength, len);
}
// 5. Let SortCompare be a new Abstract Closure with parameters (x, y) that
// captures comparefn and performs the following steps when called:
// a. Return ? CompareArrayElements(x, y, comparefn).
// 6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
// 7. Let j be 0.
// 8. Repeat, while j < len,
// a. Perform ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(j)),
// sortedList[j]). b. Set j to j + 1.
// 9. Return A.
//
// The implementation of the above steps is shared with Array.prototype.sort.
const isToSorted: constexpr bool = true;
const sortState: SortState = NewSortState(obj, comparefn, len, isToSorted);
return ArrayTimSortIntoCopy(context, sortState);
}
}