[builtins] Use uintptr for iteration in TypedArray builtins, pt.1
The CL fixes the following builtins: %TypedArray%.prototype.join %TypedArray%.prototype.every %TypedArray%.prototype.find %TypedArray%.prototype.findIndex %TypedArray%.prototype.forEach %TypedArray%.prototype.reduce %TypedArray%.prototype.reduceRight %TypedArray%.prototype.some Bug: v8:4153 Change-Id: I39cdb1801949b1df9d221988b8ed4ed5b2de9341 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1864941 Reviewed-by: Jakob Kummerow <jkummerow@chromium.org> Commit-Queue: Igor Sheludko <ishell@chromium.org> Cr-Commit-Position: refs/heads/master@{#64345}
This commit is contained in:
parent
dcc8b437c7
commit
581bf00eb2
@ -3,7 +3,7 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
namespace array_join {
|
||||
type LoadJoinElementFn = builtin(Context, JSReceiver, Number) => JSAny;
|
||||
type LoadJoinElementFn = builtin(Context, JSReceiver, uintptr) => JSAny;
|
||||
|
||||
// Fast C call to write a fixed array (see Buffer.fixedArray) to a single
|
||||
// string.
|
||||
@ -12,20 +12,20 @@ namespace array_join {
|
||||
FixedArray, intptr, String, String): String;
|
||||
|
||||
transitioning builtin LoadJoinElement<T: type>(
|
||||
context: Context, receiver: JSReceiver, k: Number): JSAny {
|
||||
return GetProperty(receiver, k);
|
||||
context: Context, receiver: JSReceiver, k: uintptr): JSAny {
|
||||
return GetProperty(receiver, Convert<Number>(k));
|
||||
}
|
||||
|
||||
transitioning LoadJoinElement<array::DictionaryElements>(
|
||||
context: Context, receiver: JSReceiver, k: Number): JSAny {
|
||||
context: Context, receiver: JSReceiver, k: uintptr): JSAny {
|
||||
const array: JSArray = UnsafeCast<JSArray>(receiver);
|
||||
const dict: NumberDictionary = UnsafeCast<NumberDictionary>(array.elements);
|
||||
try {
|
||||
return BasicLoadNumberDictionaryElement(dict, Signed(Convert<uintptr>(k)))
|
||||
return BasicLoadNumberDictionaryElement(dict, Signed(k))
|
||||
otherwise IfNoData, IfHole;
|
||||
}
|
||||
label IfNoData deferred {
|
||||
return GetProperty(receiver, k);
|
||||
return GetProperty(receiver, Convert<Number>(k));
|
||||
}
|
||||
label IfHole {
|
||||
return kEmptyString;
|
||||
@ -33,30 +33,29 @@ namespace array_join {
|
||||
}
|
||||
|
||||
LoadJoinElement<array::FastSmiOrObjectElements>(
|
||||
context: Context, receiver: JSReceiver, k: Number): JSAny {
|
||||
context: Context, receiver: JSReceiver, k: uintptr): JSAny {
|
||||
const array: JSArray = UnsafeCast<JSArray>(receiver);
|
||||
const fixedArray: FixedArray = UnsafeCast<FixedArray>(array.elements);
|
||||
const element: Object = fixedArray.objects[UnsafeCast<Smi>(k)];
|
||||
const element: Object = fixedArray.objects[k];
|
||||
return element == TheHole ? kEmptyString : UnsafeCast<JSAny>(element);
|
||||
}
|
||||
|
||||
LoadJoinElement<array::FastDoubleElements>(
|
||||
context: Context, receiver: JSReceiver, k: Number): JSAny {
|
||||
context: Context, receiver: JSReceiver, k: uintptr): JSAny {
|
||||
const array: JSArray = UnsafeCast<JSArray>(receiver);
|
||||
const fixedDoubleArray: FixedDoubleArray =
|
||||
UnsafeCast<FixedDoubleArray>(array.elements);
|
||||
const element: float64 = LoadDoubleWithHoleCheck(
|
||||
fixedDoubleArray, UnsafeCast<Smi>(k)) otherwise return kEmptyString;
|
||||
const element: float64 = LoadDoubleWithHoleCheck(fixedDoubleArray, k)
|
||||
otherwise return kEmptyString;
|
||||
return AllocateHeapNumberWithValue(element);
|
||||
}
|
||||
|
||||
builtin LoadJoinTypedElement<T: type>(
|
||||
context: Context, receiver: JSReceiver, k: Number): JSAny {
|
||||
context: Context, receiver: JSReceiver, k: uintptr): JSAny {
|
||||
const typedArray: JSTypedArray = UnsafeCast<JSTypedArray>(receiver);
|
||||
assert(!IsDetachedBuffer(typedArray.buffer));
|
||||
return typed_array::LoadFixedTypedArrayElementAsTagged(
|
||||
typedArray.data_ptr, UnsafeCast<Smi>(k),
|
||||
typed_array::KindForArrayType<T>());
|
||||
typedArray.data_ptr, k, typed_array::KindForArrayType<T>());
|
||||
}
|
||||
|
||||
transitioning builtin ConvertToLocaleString(
|
||||
@ -283,7 +282,7 @@ namespace array_join {
|
||||
}
|
||||
|
||||
// b. Let element be ? Get(O, ! ToString(k)).
|
||||
const element: JSAny = loadFn(context, receiver, Convert<Number>(k++));
|
||||
const element: JSAny = loadFn(context, receiver, k++);
|
||||
|
||||
// c. If element is undefined or null, let next be the empty String;
|
||||
// otherwise, let next be ? ToString(element).
|
||||
|
@ -3224,6 +3224,8 @@ extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, Smi): float64
|
||||
labels IfHole;
|
||||
extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, intptr): float64
|
||||
labels IfHole;
|
||||
extern macro LoadDoubleWithHoleCheck(FixedDoubleArray, uintptr): float64
|
||||
labels IfHole;
|
||||
extern macro StoreFixedDoubleArrayHoleSmi(FixedDoubleArray, Smi): void;
|
||||
|
||||
macro GetObjectFunction(implicit context: Context)(): JSFunction {
|
||||
|
@ -572,7 +572,7 @@ void TypedArrayBuiltinsAssembler::SetJSTypedArrayOffHeapDataPtr(
|
||||
|
||||
void TypedArrayBuiltinsAssembler::StoreJSTypedArrayElementFromTagged(
|
||||
TNode<Context> context, TNode<JSTypedArray> typed_array,
|
||||
TNode<Smi> index_node, TNode<Object> value, ElementsKind elements_kind) {
|
||||
TNode<UintPtrT> index, TNode<Object> value, ElementsKind elements_kind) {
|
||||
TNode<RawPtrT> data_ptr = LoadJSTypedArrayDataPtr(typed_array);
|
||||
switch (elements_kind) {
|
||||
case UINT8_ELEMENTS:
|
||||
@ -580,27 +580,25 @@ void TypedArrayBuiltinsAssembler::StoreJSTypedArrayElementFromTagged(
|
||||
case INT8_ELEMENTS:
|
||||
case UINT16_ELEMENTS:
|
||||
case INT16_ELEMENTS:
|
||||
StoreElement(data_ptr, elements_kind, index_node, SmiToInt32(CAST(value)),
|
||||
SMI_PARAMETERS);
|
||||
StoreElement(data_ptr, elements_kind, index, SmiToInt32(CAST(value)));
|
||||
break;
|
||||
case UINT32_ELEMENTS:
|
||||
case INT32_ELEMENTS:
|
||||
StoreElement(data_ptr, elements_kind, index_node,
|
||||
TruncateTaggedToWord32(context, value), SMI_PARAMETERS);
|
||||
StoreElement(data_ptr, elements_kind, index,
|
||||
TruncateTaggedToWord32(context, value));
|
||||
break;
|
||||
case FLOAT32_ELEMENTS:
|
||||
StoreElement(data_ptr, elements_kind, index_node,
|
||||
TruncateFloat64ToFloat32(LoadHeapNumberValue(CAST(value))),
|
||||
SMI_PARAMETERS);
|
||||
StoreElement(data_ptr, elements_kind, index,
|
||||
TruncateFloat64ToFloat32(LoadHeapNumberValue(CAST(value))));
|
||||
break;
|
||||
case FLOAT64_ELEMENTS:
|
||||
StoreElement(data_ptr, elements_kind, index_node,
|
||||
LoadHeapNumberValue(CAST(value)), SMI_PARAMETERS);
|
||||
StoreElement(data_ptr, elements_kind, index,
|
||||
LoadHeapNumberValue(CAST(value)));
|
||||
break;
|
||||
case BIGUINT64_ELEMENTS:
|
||||
case BIGINT64_ELEMENTS:
|
||||
StoreElement(data_ptr, elements_kind, index_node,
|
||||
UncheckedCast<BigInt>(value), SMI_PARAMETERS);
|
||||
StoreElement(data_ptr, elements_kind, index,
|
||||
UncheckedCast<BigInt>(value));
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
|
@ -16,12 +16,6 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
|
||||
explicit TypedArrayBuiltinsAssembler(compiler::CodeAssemblerState* state)
|
||||
: CodeStubAssembler(state) {}
|
||||
|
||||
template <class... TArgs>
|
||||
TNode<JSTypedArray> TypedArraySpeciesCreate(const char* method_name,
|
||||
TNode<Context> context,
|
||||
TNode<JSTypedArray> exemplar,
|
||||
TArgs... args);
|
||||
|
||||
void GenerateTypedArrayPrototypeIterationMethod(TNode<Context> context,
|
||||
TNode<Object> receiver,
|
||||
const char* method_name,
|
||||
@ -120,7 +114,7 @@ class TypedArrayBuiltinsAssembler : public CodeStubAssembler {
|
||||
TNode<UintPtrT> offset);
|
||||
void StoreJSTypedArrayElementFromTagged(TNode<Context> context,
|
||||
TNode<JSTypedArray> typed_array,
|
||||
TNode<Smi> index_node,
|
||||
TNode<UintPtrT> index_node,
|
||||
TNode<Object> value,
|
||||
ElementsKind elements_kind);
|
||||
};
|
||||
|
@ -46,6 +46,10 @@ namespace torque_internal {
|
||||
return this.TryAtIndex(index) otherwise unreachable;
|
||||
}
|
||||
|
||||
AtIndex(index: uintptr):&T {
|
||||
return this.TryAtIndex(Convert<intptr>(index)) otherwise unreachable;
|
||||
}
|
||||
|
||||
AtIndex(index: constexpr int31):&T {
|
||||
const i: intptr = Convert<intptr>(index);
|
||||
return this.TryAtIndex(i) otherwise unreachable;
|
||||
|
@ -11,15 +11,16 @@ namespace typed_array_every {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
thisArg: JSAny): Boolean {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
for (let k: Smi = 0; k < length; k++) {
|
||||
const length: uintptr = witness.Get().length;
|
||||
for (let k: uintptr = 0; k < length; k++) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
const result =
|
||||
Call(context, callbackfn, thisArg, value, k, witness.GetStable());
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
const result = Call(
|
||||
context, callbackfn, thisArg, value, Convert<Number>(k),
|
||||
witness.GetStable());
|
||||
if (!ToBoolean(result)) {
|
||||
return False;
|
||||
}
|
||||
|
@ -11,15 +11,16 @@ namespace typed_array_find {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
thisArg: JSAny): JSAny {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
for (let k: Smi = 0; k < length; k++) {
|
||||
const length: uintptr = witness.Get().length;
|
||||
for (let k: uintptr = 0; k < length; k++) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
const result =
|
||||
Call(context, callbackfn, thisArg, value, k, witness.GetStable());
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
const result = Call(
|
||||
context, callbackfn, thisArg, value, Convert<Number>(k),
|
||||
witness.GetStable());
|
||||
if (ToBoolean(result)) {
|
||||
return value;
|
||||
}
|
||||
|
@ -11,17 +11,19 @@ namespace typed_array_findindex {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
thisArg: JSAny): Number {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
for (let k: Smi = 0; k < length; k++) {
|
||||
const length: uintptr = witness.Get().length;
|
||||
for (let k: uintptr = 0; k < length; k++) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
const result =
|
||||
Call(context, callbackfn, thisArg, value, k, witness.GetStable());
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
const indexNumber: Number = Convert<Number>(k);
|
||||
const result = Call(
|
||||
context, callbackfn, thisArg, value, indexNumber,
|
||||
witness.GetStable());
|
||||
if (ToBoolean(result)) {
|
||||
return k;
|
||||
return indexNumber;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
|
@ -11,14 +11,16 @@ namespace typed_array_foreach {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
thisArg: JSAny): Undefined {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
for (let k: Smi = 0; k < length; k++) {
|
||||
const length: uintptr = witness.Get().length;
|
||||
for (let k: uintptr = 0; k < length; k++) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
Call(context, callbackfn, thisArg, value, k, witness.GetStable());
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
Call(
|
||||
context, callbackfn, thisArg, value, Convert<Number>(k),
|
||||
witness.GetStable());
|
||||
}
|
||||
return Undefined;
|
||||
}
|
||||
|
@ -11,11 +11,9 @@ namespace typed_array_reduce {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
initialValue: JSAny | TheHole): JSAny {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
const length: uintptr = witness.Get().length;
|
||||
let accumulator = initialValue;
|
||||
for (let k: Smi = 0; k < length; k++) {
|
||||
for (let k: uintptr = 0; k < length; k++) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
@ -24,9 +22,11 @@ namespace typed_array_reduce {
|
||||
accumulator = value;
|
||||
}
|
||||
case (accumulatorNotHole: JSAny): {
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
accumulator = Call(
|
||||
context, callbackfn, Undefined, accumulatorNotHole, value, k,
|
||||
witness.GetStable());
|
||||
context, callbackfn, Undefined, accumulatorNotHole, value,
|
||||
Convert<Number>(k), witness.GetStable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,11 +11,9 @@ namespace typed_array_reduceright {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
initialValue: JSAny | TheHole): JSAny {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
const length: uintptr = witness.Get().length;
|
||||
let accumulator = initialValue;
|
||||
for (let k: Smi = length - 1; k >= 0; k--) {
|
||||
for (let k: uintptr = length; k-- > 0;) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
@ -24,9 +22,11 @@ namespace typed_array_reduceright {
|
||||
accumulator = value;
|
||||
}
|
||||
case (accumulatorNotHole: JSAny): {
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
accumulator = Call(
|
||||
context, callbackfn, Undefined, accumulatorNotHole, value, k,
|
||||
witness.GetStable());
|
||||
context, callbackfn, Undefined, accumulatorNotHole, value,
|
||||
Convert<Number>(k), witness.GetStable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,15 +11,16 @@ namespace typed_array_some {
|
||||
array: typed_array::AttachedJSTypedArray, callbackfn: Callable,
|
||||
thisArg: JSAny): Boolean {
|
||||
let witness = typed_array::NewAttachedJSTypedArrayWitness(array);
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const length =
|
||||
Cast<Smi>(Convert<Number>(witness.Get().length)) otherwise unreachable;
|
||||
for (let k: Smi = 0; k < length; k++) {
|
||||
const length: uintptr = witness.Get().length;
|
||||
for (let k: uintptr = 0; k < length; k++) {
|
||||
// BUG(4895): We should throw on detached buffers rather than simply exit.
|
||||
witness.Recheck() otherwise break;
|
||||
const value: JSAny = witness.Load(k);
|
||||
const result =
|
||||
Call(context, callbackfn, thisArg, value, k, witness.GetStable());
|
||||
// TODO(v8:4153): Consider versioning this loop for Smi and non-Smi
|
||||
// indices to optimize Convert<Number>(k) for the most common case.
|
||||
const result = Call(
|
||||
context, callbackfn, thisArg, value, Convert<Number>(k),
|
||||
witness.GetStable());
|
||||
if (ToBoolean(result)) {
|
||||
return True;
|
||||
}
|
||||
|
@ -70,12 +70,12 @@ namespace typed_array {
|
||||
extern macro TypedArrayBuiltinsAssembler::IsBigInt64ElementsKind(
|
||||
ElementsKind): bool;
|
||||
extern macro LoadFixedTypedArrayElementAsTagged(
|
||||
RawPtr, Smi, constexpr ElementsKind): Numeric;
|
||||
RawPtr, uintptr, constexpr ElementsKind): Numeric;
|
||||
extern macro TypedArrayBuiltinsAssembler::StoreJSTypedArrayElementFromTagged(
|
||||
Context, JSTypedArray, Smi, JSAny, constexpr ElementsKind);
|
||||
Context, JSTypedArray, uintptr, JSAny, constexpr ElementsKind);
|
||||
|
||||
type LoadFn = builtin(Context, JSTypedArray, Smi) => JSAny;
|
||||
type StoreFn = builtin(Context, JSTypedArray, Smi, JSAny) => JSAny;
|
||||
type LoadFn = builtin(Context, JSTypedArray, uintptr) => JSAny;
|
||||
type StoreFn = builtin(Context, JSTypedArray, uintptr, JSAny) => JSAny;
|
||||
|
||||
extern macro TypedArrayBuiltinsAssembler::SetJSTypedArrayOnHeapDataPtr(
|
||||
JSTypedArray, ByteArray, uintptr): void;
|
||||
@ -105,11 +105,17 @@ namespace typed_array {
|
||||
this.unstable = %RawDownCast<AttachedJSTypedArray>(this.stable);
|
||||
}
|
||||
|
||||
Load(implicit context: Context)(k: Smi): JSAny {
|
||||
Load(implicit context: Context)(k: uintptr): JSAny {
|
||||
const lf: LoadFn = this.loadfn;
|
||||
return lf(context, this.unstable, k);
|
||||
}
|
||||
|
||||
// TODO(v8:4153): Remove this version once all builtins use uintptr indices
|
||||
// for iteration.
|
||||
Load(implicit context: Context)(k: Smi): JSAny {
|
||||
return this.Load(Unsigned(SmiUntag(k)));
|
||||
}
|
||||
|
||||
stable: JSTypedArray;
|
||||
unstable: AttachedJSTypedArray;
|
||||
loadfn: LoadFn;
|
||||
@ -195,13 +201,13 @@ namespace typed_array {
|
||||
}
|
||||
|
||||
builtin LoadFixedElement<T: type>(
|
||||
_context: Context, array: JSTypedArray, index: Smi): JSAny {
|
||||
_context: Context, array: JSTypedArray, index: uintptr): JSAny {
|
||||
return LoadFixedTypedArrayElementAsTagged(
|
||||
array.data_ptr, index, KindForArrayType<T>());
|
||||
}
|
||||
|
||||
builtin StoreFixedElement<T: type>(
|
||||
context: Context, typedArray: JSTypedArray, index: Smi,
|
||||
context: Context, typedArray: JSTypedArray, index: uintptr,
|
||||
value: JSAny): JSAny {
|
||||
typed_array::StoreJSTypedArrayElementFromTagged(
|
||||
context, typedArray, index, value, KindForArrayType<T>());
|
||||
@ -232,11 +238,12 @@ namespace typed_array {
|
||||
transitioning macro
|
||||
TypedArrayMerge(
|
||||
implicit context: Context, array: JSTypedArray, comparefn: Callable)(
|
||||
source: FixedArray, from: Smi, middle: Smi, to: Smi, target: FixedArray) {
|
||||
let left: Smi = from;
|
||||
let right: Smi = middle;
|
||||
source: FixedArray, from: uintptr, middle: uintptr, to: uintptr,
|
||||
target: FixedArray) {
|
||||
let left: uintptr = from;
|
||||
let right: uintptr = middle;
|
||||
|
||||
for (let targetIndex: Smi = from; targetIndex < to; ++targetIndex) {
|
||||
for (let targetIndex: uintptr = from; targetIndex < to; ++targetIndex) {
|
||||
if (left < middle && right >= to) {
|
||||
// If the left run has elements, but the right does not, we take
|
||||
// from the left.
|
||||
@ -262,17 +269,21 @@ namespace typed_array {
|
||||
}
|
||||
|
||||
transitioning builtin
|
||||
TypedArrayMergeSort(
|
||||
implicit context: Context, array: JSTypedArray, comparefn: Callable)(
|
||||
source: FixedArray, from: Smi, to: Smi, target: FixedArray): JSAny {
|
||||
TypedArrayMergeSort(implicit context: Context)(
|
||||
source: FixedArray, from: uintptr, to: uintptr, target: FixedArray,
|
||||
array: JSTypedArray, comparefn: Callable): JSAny {
|
||||
assert(to - from > 1);
|
||||
const middle: Smi = from + ((to - from) >> 1);
|
||||
const middle: uintptr = from + ((to - from) >>> 1);
|
||||
|
||||
// On the next recursion step source becomes target and vice versa.
|
||||
// This saves the copy of the relevant range from the original
|
||||
// array into a work array on each recursion step.
|
||||
if (middle - from > 1) TypedArrayMergeSort(target, from, middle, source);
|
||||
if (to - middle > 1) TypedArrayMergeSort(target, middle, to, source);
|
||||
if (middle - from > 1) {
|
||||
TypedArrayMergeSort(target, from, middle, source, array, comparefn);
|
||||
}
|
||||
if (to - middle > 1) {
|
||||
TypedArrayMergeSort(target, middle, to, source, array, comparefn);
|
||||
}
|
||||
|
||||
TypedArrayMerge(source, from, middle, to, target);
|
||||
|
||||
@ -304,8 +315,7 @@ namespace typed_array {
|
||||
}
|
||||
|
||||
// 4. Let len be obj.[[ArrayLength]].
|
||||
// TODO(v8:4153): Support huge TypedArrays here.
|
||||
const len = Cast<Smi>(Convert<Number>(array.length)) otherwise unreachable;
|
||||
const len: uintptr = array.length;
|
||||
|
||||
// Arrays of length 1 or less are considered sorted.
|
||||
if (len < 2) return array;
|
||||
@ -366,16 +376,16 @@ namespace typed_array {
|
||||
const work1: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));
|
||||
const work2: FixedArray = AllocateZeroedFixedArray(Convert<intptr>(len));
|
||||
|
||||
for (let i: Smi = 0; i < len; ++i) {
|
||||
for (let i: uintptr = 0; i < len; ++i) {
|
||||
const element: JSAny = loadfn(context, array, i);
|
||||
work1.objects[i] = element;
|
||||
work2.objects[i] = element;
|
||||
}
|
||||
|
||||
TypedArrayMergeSort(work2, 0, len, work1);
|
||||
TypedArrayMergeSort(work2, 0, len, work1, array, comparefn);
|
||||
|
||||
// work1 contains the sorted numbers. Write them back.
|
||||
for (let i: Smi = 0; i < len; ++i)
|
||||
for (let i: uintptr = 0; i < len; ++i)
|
||||
storefn(context, array, i, UnsafeCast<JSAny>(work1.objects[i]));
|
||||
|
||||
return array;
|
||||
|
@ -1413,6 +1413,11 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
TNode<Float64T> LoadDoubleWithHoleCheck(TNode<FixedDoubleArray> array,
|
||||
TNode<IntPtrT> index,
|
||||
Label* if_hole = nullptr);
|
||||
TNode<Float64T> LoadDoubleWithHoleCheck(TNode<FixedDoubleArray> array,
|
||||
TNode<UintPtrT> index,
|
||||
Label* if_hole = nullptr) {
|
||||
return LoadDoubleWithHoleCheck(array, Signed(index), if_hole);
|
||||
}
|
||||
|
||||
// Load Float64 value by |base| + |offset| address. If the value is a double
|
||||
// hole then jump to |if_hole|. If |machine_type| is None then only the hole
|
||||
@ -3251,6 +3256,10 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
|
||||
// teach TurboFan to handle int64_t on 32-bit platforms eventually.
|
||||
void StoreElement(Node* elements, ElementsKind kind, Node* index, Node* value,
|
||||
ParameterMode mode);
|
||||
void StoreElement(TNode<RawPtrT> elements, ElementsKind kind,
|
||||
TNode<UintPtrT> index, Node* value) {
|
||||
return StoreElement(elements, kind, index, value, INTPTR_PARAMETERS);
|
||||
}
|
||||
|
||||
// Implements the BigInt part of
|
||||
// https://tc39.github.io/proposal-bigint/#sec-numbertorawbytes,
|
||||
|
Loading…
Reference in New Issue
Block a user