Commit 581bf00e authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

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