Commit d36eee56 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[builtins] Don't use ToSmiLength in TypedArray constructors

... and reimplement TryNumberToUintPtr.

Bug: v8:4153
Change-Id: I3b683b6a41ebf49229aee4ceea4910e94d35ccca
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1876817
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64566}
parent 4a614161
...@@ -1849,8 +1849,6 @@ extern transitioning macro ToInteger_Inline( ...@@ -1849,8 +1849,6 @@ extern transitioning macro ToInteger_Inline(
Context, JSAny, constexpr ToIntegerTruncationMode): Number; Context, JSAny, constexpr ToIntegerTruncationMode): Number;
extern transitioning macro ToLength_Inline(Context, JSAny): Number; extern transitioning macro ToLength_Inline(Context, JSAny): Number;
extern transitioning macro ToNumber_Inline(Context, JSAny): Number; extern transitioning macro ToNumber_Inline(Context, JSAny): Number;
extern transitioning macro ToSmiLength(implicit context: Context)(JSAny):
PositiveSmi labels IfRangeError;
extern transitioning macro ToString_Inline(Context, JSAny): String; extern transitioning macro ToString_Inline(Context, JSAny): String;
extern transitioning macro ToThisString(implicit context: Context)( extern transitioning macro ToThisString(implicit context: Context)(
JSAny, String): String; JSAny, String): String;
...@@ -2187,6 +2185,11 @@ extern operator '!' macro IsFalse(Boolean): bool; ...@@ -2187,6 +2185,11 @@ extern operator '!' macro IsFalse(Boolean): bool;
extern operator '.instanceType' macro LoadInstanceType(HeapObject): extern operator '.instanceType' macro LoadInstanceType(HeapObject):
InstanceType; InstanceType;
operator '.length_uintptr' macro LoadJSArrayLengthAsUintPtr(array: JSArray):
uintptr {
return Convert<uintptr>(array.length);
}
extern operator '.length_intptr' macro LoadStringLengthAsWord(String): intptr; extern operator '.length_intptr' macro LoadStringLengthAsWord(String): intptr;
operator '.length_uintptr' macro LoadStringLengthAsUintPtr(s: String): uintptr { operator '.length_uintptr' macro LoadStringLengthAsUintPtr(s: String): uintptr {
return Unsigned(s.length_intptr); return Unsigned(s.length_intptr);
...@@ -2797,8 +2800,6 @@ extern macro TruncateFloat64ToFloat32(float64): float32; ...@@ -2797,8 +2800,6 @@ extern macro TruncateFloat64ToFloat32(float64): float32;
extern macro TruncateHeapNumberValueToWord32(HeapNumber): int32; extern macro TruncateHeapNumberValueToWord32(HeapNumber): int32;
extern macro LoadJSArrayElementsMap(constexpr ElementsKind, NativeContext): Map; extern macro LoadJSArrayElementsMap(constexpr ElementsKind, NativeContext): Map;
extern macro LoadJSArrayElementsMap(ElementsKind, NativeContext): Map; extern macro LoadJSArrayElementsMap(ElementsKind, NativeContext): Map;
extern macro ChangeNonnegativeNumberToUintPtr(Number): uintptr;
extern macro TryNumberToUintPtr(Number): uintptr labels IfNegative;
extern macro NumberConstant(constexpr float64): Number; extern macro NumberConstant(constexpr float64): Number;
extern macro NumberConstant(constexpr int32): Number; extern macro NumberConstant(constexpr int32): Number;
extern macro NumberConstant(constexpr uint32): Number; extern macro NumberConstant(constexpr uint32): Number;
...@@ -3012,7 +3013,7 @@ Convert<float64, Number>(n: Number): float64 { ...@@ -3012,7 +3013,7 @@ Convert<float64, Number>(n: Number): float64 {
return ChangeNumberToFloat64(n); return ChangeNumberToFloat64(n);
} }
Convert<uintptr, Number>(n: Number): uintptr { Convert<uintptr, Number>(n: Number): uintptr {
return ChangeNonnegativeNumberToUintPtr(n); return ChangeUintPtrNumberToUintPtr(n);
} }
Convert<float64, float32>(f: float32): float64 { Convert<float64, float32>(f: float32): float64 {
return ChangeFloat32ToFloat64(f); return ChangeFloat32ToFloat64(f);
...@@ -3606,48 +3607,103 @@ macro SameValue(a: JSAny, b: JSAny): bool { ...@@ -3606,48 +3607,103 @@ macro SameValue(a: JSAny, b: JSAny): bool {
BranchIfSameValue(a, b) otherwise return true, return false; BranchIfSameValue(a, b) otherwise return true, return false;
} }
// https://tc39.github.io/ecma262/#sec-toindex // TODO(tebbi): Define enum here once they appear in Torque.
@export //
transitioning macro ToIndex(implicit context: Context)(value: JSAny): // The value is a SafeInteger that fits into uintptr range, so no bounds checks
uintptr labels IfRangeError { // are necessary.
if (value == Undefined) return 0; const kModeValueIsSafeIntegerUintPtr: constexpr int31 = 0;
const indexNumber = ToInteger_Inline(context, value, kTruncateMinusZero); // The value is a SafeInteger that may not fit into uintptr range, so only
return ToIndex(indexNumber) otherwise IfRangeError; // uintptr bounds check is necessary.
} const kModeValueIsSafeInteger: constexpr int31 = 1;
// The value is can be whatever non-NaN number, all checks are necessary.
// https://tc39.github.io/ecma262/#sec-toindex const kModeValueIsAnyNumber: constexpr int31 = 2;
// Same as the version above but for Number arguments.
macro ToIndex(indexNumber: Number): uintptr labels IfRangeError { macro TryNumberToUintPtr(valueNumber: Number, kMode: constexpr int31):
typeswitch (indexNumber) { uintptr labels IfLessThanZero, IfUIntPtrOverflow, IfSafeIntegerOverflow {
case (indexSmi: Smi): { typeswitch (valueNumber) {
if (indexSmi < 0) goto IfRangeError; case (valueSmi: Smi): {
const index: uintptr = Unsigned(Convert<intptr>(indexSmi)); if (kMode == kModeValueIsAnyNumber) {
if (valueSmi < 0) goto IfLessThanZero;
} else {
assert(valueSmi >= 0);
}
const value: uintptr = Unsigned(Convert<intptr>(valueSmi));
// Positive Smi values definitely fit into both [0, kMaxSafeInteger] and // Positive Smi values definitely fit into both [0, kMaxSafeInteger] and
// [0, kMaxUintPtr] ranges. // [0, kMaxUintPtr] ranges.
return index; return value;
}
case (valueHeapNumber: HeapNumber): {
assert(IsNumberNormalized(valueHeapNumber));
const valueDouble: float64 = Convert<float64>(valueHeapNumber);
// NaNs must be handled outside.
assert(!Float64IsNaN(valueDouble));
if (kMode == kModeValueIsAnyNumber) {
if (valueDouble < 0) goto IfLessThanZero;
} else {
assert(valueDouble >= 0);
} }
case (indexHeapNumber: HeapNumber): {
assert(IsNumberNormalized(indexHeapNumber));
const indexDouble: float64 = Convert<float64>(indexHeapNumber);
// NaNs must already be handled by ToIndex() version above accepting
// JSAny indices.
assert(!Float64IsNaN(indexDouble));
if (indexDouble < 0) goto IfRangeError;
if constexpr (Is64()) { if constexpr (Is64()) {
if (indexDouble > kMaxSafeInteger) goto IfRangeError; // On 64-bit architectures uintptr range is bigger than safe integer
// range.
if (kMode == kModeValueIsAnyNumber) {
if (valueDouble > kMaxSafeInteger) goto IfSafeIntegerOverflow;
} else { } else {
// On 32-bit architectures not all safe integers fit into uintptr but assert(valueDouble <= kMaxSafeInteger);
// callers handle this case the same way as the safe integer range
// overflow case so we don't need special handling for the values in
// (kMaxUInt32, kMaxSafeInteger] range.
if (indexDouble > kMaxUInt32Double) goto IfRangeError;
} }
return ChangeFloat64ToUintPtr(indexDouble); } else {
// On 32-bit architectures uintptr range is smaller than safe integer
// range.
if (kMode == kModeValueIsAnyNumber ||
kMode == kModeValueIsSafeInteger) {
if (valueDouble > kMaxUInt32Double) goto IfUIntPtrOverflow;
} else {
assert(valueDouble <= kMaxUInt32Double);
}
}
return ChangeFloat64ToUintPtr(valueDouble);
} }
} }
} }
@export
macro ChangeUintPtrNumberToUintPtr(value: Number): uintptr {
try {
return TryNumberToUintPtr(value, kModeValueIsSafeIntegerUintPtr)
otherwise InvalidValue, InvalidValue, InvalidValue;
}
label InvalidValue {
unreachable;
}
}
macro ChangeSafeIntegerNumberToUintPtr(value: Number):
uintptr labels IfUIntPtrOverflow {
try {
return TryNumberToUintPtr(value, kModeValueIsSafeInteger)
otherwise InvalidValue, IfUIntPtrOverflow, InvalidValue;
}
label InvalidValue {
unreachable;
}
}
// https://tc39.github.io/ecma262/#sec-toindex
// Unlike ToIndex from the spec this implementation triggers IfRangeError if
// the result is bigger than min(kMaxUIntPtr, kMaxSafeInteger).
// We can do this because all callers do a range checks against uintptr length
// anyway and throw a RangeError in case of out-of-bounds index.
@export
transitioning macro ToIndex(implicit context: Context)(value: JSAny):
uintptr labels IfRangeError {
if (value == Undefined) return 0;
const indexNumber = ToInteger_Inline(context, value, kTruncateMinusZero);
// Less than 0 case, uintptr range overflow and safe integer range overflow
// imply IfRangeError.
return TryNumberToUintPtr(indexNumber, kModeValueIsAnyNumber)
otherwise IfRangeError, IfRangeError, IfRangeError;
}
transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny): transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny):
Number { Number {
try { try {
......
...@@ -72,9 +72,9 @@ namespace typed_array { ...@@ -72,9 +72,9 @@ namespace typed_array {
transitioning macro TypedArrayInitialize(implicit context: Context)( transitioning macro TypedArrayInitialize(implicit context: Context)(
initialize: constexpr bool, map: Map, length: uintptr, initialize: constexpr bool, map: Map, length: uintptr,
elementsInfo: typed_array::TypedArrayElementsInfo, elementsInfo: typed_array::TypedArrayElementsInfo,
bufferConstructor: JSReceiver): JSTypedArray { bufferConstructor: JSReceiver): JSTypedArray labels IfRangeError {
const byteLength = elementsInfo.CalculateByteLength(length) const byteLength = elementsInfo.CalculateByteLength(length)
otherwise ThrowRangeError(kInvalidArrayBufferLength); otherwise IfRangeError;
const byteLengthNum = Convert<Number>(byteLength); const byteLengthNum = Convert<Number>(byteLength);
const defaultConstructor = GetArrayBufferFunction(); const defaultConstructor = GetArrayBufferFunction();
const byteOffset: uintptr = 0; const byteOffset: uintptr = 0;
...@@ -119,39 +119,36 @@ namespace typed_array { ...@@ -119,39 +119,36 @@ namespace typed_array {
// 22.2.4.2 TypedArray ( length ) // 22.2.4.2 TypedArray ( length )
// ES #sec-typedarray-length // ES #sec-typedarray-length
transitioning macro ConstructByLength(implicit context: Context)( transitioning macro ConstructByLength(implicit context: Context)(
map: Map, length: JSAny, map: Map, lengthObj: JSAny,
elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray { elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray {
const convertedLength: Number = try {
ToInteger_Inline(context, length, kTruncateMinusZero); const length: uintptr = ToIndex(lengthObj) otherwise RangeError;
// The maximum length of a TypedArray is MaxSmi().
// Note: this is not per spec, but rather a constraint of our current
// representation (which uses Smis).
// TODO(7881): support larger-than-smi typed array lengths
const positiveLength: PositiveSmi = Cast<PositiveSmi>(convertedLength)
otherwise ThrowRangeError(kInvalidTypedArrayLength, length);
const defaultConstructor: Constructor = GetArrayBufferFunction(); const defaultConstructor: Constructor = GetArrayBufferFunction();
const initialize: constexpr bool = true; const initialize: constexpr bool = true;
return TypedArrayInitialize( return TypedArrayInitialize(
initialize, map, Convert<uintptr>(positiveLength), elementsInfo, initialize, map, length, elementsInfo, defaultConstructor)
defaultConstructor); otherwise RangeError;
}
label RangeError deferred {
ThrowRangeError(kInvalidTypedArrayLength, lengthObj);
}
} }
// 22.2.4.4 TypedArray ( object ) // 22.2.4.4 TypedArray ( object )
// ES #sec-typedarray-object // ES #sec-typedarray-object
transitioning macro ConstructByArrayLike(implicit context: Context)( transitioning macro ConstructByArrayLike(implicit context: Context)(
map: Map, arrayLike: HeapObject, initialLength: JSAny, map: Map, arrayLike: HeapObject, length: uintptr,
elementsInfo: typed_array::TypedArrayElementsInfo, elementsInfo: typed_array::TypedArrayElementsInfo,
bufferConstructor: JSReceiver): JSTypedArray { bufferConstructor: JSReceiver): JSTypedArray {
// The caller has looked up length on arrayLike, which is observable. try {
const length: PositiveSmi = ToSmiLength(initialLength)
otherwise ThrowRangeError(kInvalidTypedArrayLength, initialLength);
const initialize: constexpr bool = false; const initialize: constexpr bool = false;
const typedArray = TypedArrayInitialize( const typedArray = TypedArrayInitialize(
initialize, map, Convert<uintptr>(length), elementsInfo, initialize, map, length, elementsInfo, bufferConstructor)
bufferConstructor); otherwise RangeError;
try { try {
const src: JSTypedArray = Cast<JSTypedArray>(arrayLike) otherwise IfSlow; const src: JSTypedArray =
Cast<JSTypedArray>(arrayLike) otherwise IfSlow;
if (IsDetachedBuffer(src.buffer)) { if (IsDetachedBuffer(src.buffer)) {
ThrowTypeError(kDetachedOperation, 'Construct'); ThrowTypeError(kDetachedOperation, 'Construct');
...@@ -162,38 +159,45 @@ namespace typed_array { ...@@ -162,38 +159,45 @@ namespace typed_array {
} else if (length > 0) { } else if (length > 0) {
const byteLength = typedArray.byte_length; const byteLength = typedArray.byte_length;
assert(byteLength <= kArrayBufferMaxByteLength); assert(byteLength <= kArrayBufferMaxByteLength);
typed_array::CallCMemcpy(typedArray.data_ptr, src.data_ptr, byteLength); typed_array::CallCMemcpy(
typedArray.data_ptr, src.data_ptr, byteLength);
} }
} }
label IfSlow deferred { label IfSlow deferred {
if (length > 0) { if (length > 0) {
TypedArrayCopyElements(context, typedArray, arrayLike, length); TypedArrayCopyElements(
context, typedArray, arrayLike, Convert<Number>(length));
} }
} }
return typedArray; return typedArray;
} }
label RangeError deferred {
ThrowRangeError(kInvalidTypedArrayLength, Convert<Number>(length));
}
}
// 22.2.4.4 TypedArray ( object ) // 22.2.4.4 TypedArray ( object )
// ES #sec-typedarray-object // ES #sec-typedarray-object
transitioning macro ConstructByIterable(implicit context: Context)( transitioning macro ConstructByIterable(implicit context: Context)(
iterable: JSReceiver, iteratorFn: Callable): never iterable: JSReceiver, iteratorFn: Callable): never
labels IfConstructByArrayLike(JSArray, Number, JSReceiver) { labels IfConstructByArrayLike(JSArray, uintptr, JSReceiver) {
const array: JSArray = const array: JSArray =
IterableToListMayPreserveHoles(context, iterable, iteratorFn); IterableToListMayPreserveHoles(context, iterable, iteratorFn);
goto IfConstructByArrayLike(array, array.length, GetArrayBufferFunction()); // Max JSArray length is a valid JSTypedArray length so we just use it.
goto IfConstructByArrayLike(
array, array.length_uintptr, GetArrayBufferFunction());
} }
// 22.2.4.3 TypedArray ( typedArray ) // 22.2.4.3 TypedArray ( typedArray )
// ES #sec-typedarray-typedarray // ES #sec-typedarray-typedarray
transitioning macro ConstructByTypedArray(implicit context: Context)( transitioning macro ConstructByTypedArray(implicit context: Context)(
srcTypedArray: JSTypedArray): never srcTypedArray: JSTypedArray): never
labels IfConstructByArrayLike(JSTypedArray, Number, JSReceiver) { labels IfConstructByArrayLike(JSTypedArray, uintptr, JSReceiver) {
let bufferConstructor: JSReceiver = GetArrayBufferFunction(); let bufferConstructor: JSReceiver = GetArrayBufferFunction();
const srcBuffer: JSArrayBuffer = srcTypedArray.buffer; const srcBuffer: JSArrayBuffer = srcTypedArray.buffer;
// TODO(petermarshall): Throw on detached typedArray. // TODO(petermarshall): Throw on detached typedArray.
// TODO(v8:4156): Update this to support huge TypedArrays. let length: uintptr =
let length = IsDetachedBuffer(srcBuffer) ? 0 : srcTypedArray.length;
IsDetachedBuffer(srcBuffer) ? 0 : Convert<Number>(srcTypedArray.length);
// The spec requires that constructing a typed array using a SAB-backed // The spec requires that constructing a typed array using a SAB-backed
// typed array use the ArrayBuffer constructor, not the species constructor. // typed array use the ArrayBuffer constructor, not the species constructor.
...@@ -255,7 +259,7 @@ namespace typed_array { ...@@ -255,7 +259,7 @@ namespace typed_array {
} else { } else {
// a. Let newByteLength be newLength × elementSize. // a. Let newByteLength be newLength × elementSize.
newByteLength = elementsInfo.CalculateByteLength(newLength) newByteLength = elementsInfo.CalculateByteLength(newLength)
otherwise IfInvalidByteLength; otherwise IfInvalidLength;
// b. If offset + newByteLength > bufferByteLength, throw a RangeError // b. If offset + newByteLength > bufferByteLength, throw a RangeError
// exception. // exception.
...@@ -271,9 +275,6 @@ namespace typed_array { ...@@ -271,9 +275,6 @@ namespace typed_array {
label IfInvalidAlignment(problemString: String) deferred { label IfInvalidAlignment(problemString: String) deferred {
ThrowInvalidTypedArrayAlignment(map, problemString); ThrowInvalidTypedArrayAlignment(map, problemString);
} }
label IfInvalidByteLength deferred {
ThrowRangeError(kInvalidArrayBufferLength);
}
label IfInvalidLength deferred { label IfInvalidLength deferred {
ThrowRangeError(kInvalidTypedArrayLength, length); ThrowRangeError(kInvalidTypedArrayLength, length);
} }
...@@ -284,7 +285,7 @@ namespace typed_array { ...@@ -284,7 +285,7 @@ namespace typed_array {
transitioning macro ConstructByJSReceiver(implicit context: transitioning macro ConstructByJSReceiver(implicit context:
Context)(obj: JSReceiver): never Context)(obj: JSReceiver): never
labels IfConstructByArrayLike(JSReceiver, Number, JSReceiver) { labels IfConstructByArrayLike(JSReceiver, uintptr, JSReceiver) {
try { try {
const iteratorMethod: Object = const iteratorMethod: Object =
GetIteratorMethod(obj) otherwise IfIteratorUndefined; GetIteratorMethod(obj) otherwise IfIteratorUndefined;
...@@ -295,11 +296,15 @@ namespace typed_array { ...@@ -295,11 +296,15 @@ namespace typed_array {
} }
label IfIteratorUndefined { label IfIteratorUndefined {
const lengthObj: JSAny = GetProperty(obj, kLengthString); const lengthObj: JSAny = GetProperty(obj, kLengthString);
const length: Smi = ToSmiLength(lengthObj) const lengthNumber: Number = ToLength_Inline(context, lengthObj);
otherwise goto IfInvalidLength(lengthObj); // Throw RangeError here if the length does not fit in uintptr because
// such a length will not pass bounds checks in ConstructByArrayLike()
// anyway.
const length: uintptr = ChangeSafeIntegerNumberToUintPtr(lengthNumber)
otherwise goto IfInvalidLength(lengthNumber);
goto IfConstructByArrayLike(obj, length, GetArrayBufferFunction()); goto IfConstructByArrayLike(obj, length, GetArrayBufferFunction());
} }
label IfInvalidLength(length: Object) { label IfInvalidLength(length: Number) {
ThrowRangeError(kInvalidTypedArrayLength, length); ThrowRangeError(kInvalidTypedArrayLength, length);
} }
} }
...@@ -344,7 +349,7 @@ namespace typed_array { ...@@ -344,7 +349,7 @@ namespace typed_array {
return ConstructByLength(map, length, elementsInfo); return ConstructByLength(map, length, elementsInfo);
} }
label IfConstructByArrayLike( label IfConstructByArrayLike(
arrayLike: JSReceiver, length: Number, bufferConstructor: JSReceiver) { arrayLike: JSReceiver, length: uintptr, bufferConstructor: JSReceiver) {
return ConstructByArrayLike( return ConstructByArrayLike(
map, arrayLike, length, elementsInfo, bufferConstructor); map, arrayLike, length, elementsInfo, bufferConstructor);
} }
......
...@@ -1647,11 +1647,6 @@ TNode<HeapObject> CodeStubAssembler::LoadSlowProperties( ...@@ -1647,11 +1647,6 @@ TNode<HeapObject> CodeStubAssembler::LoadSlowProperties(
[=] { return CAST(properties); }); [=] { return CAST(properties); });
} }
TNode<Number> CodeStubAssembler::LoadJSArrayLength(SloppyTNode<JSArray> array) {
CSA_ASSERT(this, IsJSArray(array));
return CAST(LoadObjectField(array, JSArray::kLengthOffset));
}
TNode<Object> CodeStubAssembler::LoadJSArgumentsObjectWithLength( TNode<Object> CodeStubAssembler::LoadJSArgumentsObjectWithLength(
SloppyTNode<JSArgumentsObjectWithLength> array) { SloppyTNode<JSArgumentsObjectWithLength> array) {
return LoadObjectField(array, JSArgumentsObjectWithLength::kLengthOffset); return LoadObjectField(array, JSArgumentsObjectWithLength::kLengthOffset);
...@@ -5723,37 +5718,6 @@ TNode<Float64T> CodeStubAssembler::ChangeNumberToFloat64(TNode<Number> value) { ...@@ -5723,37 +5718,6 @@ TNode<Float64T> CodeStubAssembler::ChangeNumberToFloat64(TNode<Number> value) {
return result.value(); return result.value();
} }
TNode<UintPtrT> CodeStubAssembler::TryNumberToUintPtr(TNode<Number> value,
Label* if_negative) {
TVARIABLE(UintPtrT, result);
Label done(this, &result);
Branch(
TaggedIsSmi(value),
[&] {
TNode<Smi> value_smi = CAST(value);
if (if_negative == nullptr) {
CSA_SLOW_ASSERT(this,
SmiGreaterThanOrEqual(value_smi, SmiConstant(0)));
} else {
GotoIfNot(TaggedIsPositiveSmi(value), if_negative);
}
result = UncheckedCast<UintPtrT>(SmiToIntPtr(value_smi));
Goto(&done);
},
[&] {
TNode<HeapNumber> value_hn = CAST(value);
TNode<Float64T> value = LoadHeapNumberValue(value_hn);
if (if_negative != nullptr) {
GotoIf(Float64LessThan(value, Float64Constant(0.0)), if_negative);
}
result = ChangeFloat64ToUintPtr(value);
Goto(&done);
});
BIND(&done);
return result.value();
}
TNode<WordT> CodeStubAssembler::TimesSystemPointerSize( TNode<WordT> CodeStubAssembler::TimesSystemPointerSize(
SloppyTNode<WordT> value) { SloppyTNode<WordT> value) {
return WordShl(value, kSystemPointerSizeLog2); return WordShl(value, kSystemPointerSizeLog2);
...@@ -9105,7 +9069,8 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor( ...@@ -9105,7 +9069,8 @@ TNode<Object> CodeStubAssembler::CallGetterIfAccessor(
GotoIfNot(IsLengthString( GotoIfNot(IsLengthString(
LoadObjectField(accessor_info, AccessorInfo::kNameOffset)), LoadObjectField(accessor_info, AccessorInfo::kNameOffset)),
if_bailout); if_bailout);
var_value.Bind(LoadJSArrayLength(receiver)); TNode<JSArray> array = CAST(receiver);
var_value.Bind(LoadJSArrayLength(array));
Goto(&done); Goto(&done);
} }
...@@ -10355,7 +10320,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value, ...@@ -10355,7 +10320,7 @@ void CodeStubAssembler::EmitElementStore(Node* object, Node* key, Node* value,
IsNonextensibleElementsKind(elements_kind)); IsNonextensibleElementsKind(elements_kind));
Node* length = SelectImpl( Node* length = SelectImpl(
IsJSArray(object), [=]() { return LoadJSArrayLength(object); }, IsJSArray(object), [=]() { return LoadJSArrayLength(CAST(object)); },
[=]() { return LoadFixedArrayBaseLength(elements); }, [=]() { return LoadFixedArrayBaseLength(elements); },
MachineRepresentation::kTagged); MachineRepresentation::kTagged);
length = TaggedToParameter(length, parameter_mode); length = TaggedToParameter(length, parameter_mode);
...@@ -13353,7 +13318,7 @@ void CodeStubAssembler::CheckPrototypeEnumCache(Node* receiver, ...@@ -13353,7 +13318,7 @@ void CodeStubAssembler::CheckPrototypeEnumCache(Node* receiver,
// It might still be an empty JSArray. // It might still be an empty JSArray.
GotoIfNot(IsJSArrayMap(object_map), if_slow); GotoIfNot(IsJSArrayMap(object_map), if_slow);
TNode<Number> object_length = LoadJSArrayLength(object); TNode<Number> object_length = LoadJSArrayLength(CAST(object));
Branch(TaggedEqual(object_length, SmiConstant(0)), &if_no_elements, Branch(TaggedEqual(object_length, SmiConstant(0)), &if_no_elements,
if_slow); if_slow);
......
...@@ -1127,8 +1127,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -1127,8 +1127,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
// Load the length of a JSArray instance. // Load the length of a JSArray instance.
TNode<Object> LoadJSArgumentsObjectWithLength( TNode<Object> LoadJSArgumentsObjectWithLength(
SloppyTNode<JSArgumentsObjectWithLength> array); SloppyTNode<JSArgumentsObjectWithLength> array);
// Load the length of a JSArray instance.
TNode<Number> LoadJSArrayLength(SloppyTNode<JSArray> array);
// Load the length of a fast JSArray instance. Returns a positive Smi. // Load the length of a fast JSArray instance. Returns a positive Smi.
TNode<Smi> LoadFastJSArrayLength(SloppyTNode<JSArray> array); TNode<Smi> LoadFastJSArrayLength(SloppyTNode<JSArray> array);
// Load the length of a fixed array base instance. // Load the length of a fixed array base instance.
...@@ -2320,10 +2318,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2320,10 +2318,6 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
TNode<Number> ChangeUintPtrToTagged(TNode<UintPtrT> value); TNode<Number> ChangeUintPtrToTagged(TNode<UintPtrT> value);
TNode<Uint32T> ChangeNumberToUint32(TNode<Number> value); TNode<Uint32T> ChangeNumberToUint32(TNode<Number> value);
TNode<Float64T> ChangeNumberToFloat64(TNode<Number> value); TNode<Float64T> ChangeNumberToFloat64(TNode<Number> value);
TNode<UintPtrT> TryNumberToUintPtr(TNode<Number> value, Label* if_negative);
TNode<UintPtrT> ChangeNonnegativeNumberToUintPtr(TNode<Number> value) {
return TryNumberToUintPtr(value, nullptr);
}
void TaggedToNumeric(Node* context, Node* value, Label* done, void TaggedToNumeric(Node* context, Node* value, Label* done,
Variable* var_numeric); Variable* var_numeric);
......
...@@ -338,9 +338,9 @@ TEST(ConvertToRelativeIndex) { ...@@ -338,9 +338,9 @@ TEST(ConvertToRelativeIndex) {
TNode<Number> length_number = m.CAST(m.Parameter(1)); TNode<Number> length_number = m.CAST(m.Parameter(1));
TNode<Number> expected_relative_index = m.CAST(m.Parameter(2)); TNode<Number> expected_relative_index = m.CAST(m.Parameter(2));
TNode<UintPtrT> length = m.ChangeNonnegativeNumberToUintPtr(length_number); TNode<UintPtrT> length = m.ChangeUintPtrNumberToUintPtr(length_number);
TNode<UintPtrT> expected = TNode<UintPtrT> expected =
m.ChangeNonnegativeNumberToUintPtr(expected_relative_index); m.ChangeUintPtrNumberToUintPtr(expected_relative_index);
TNode<UintPtrT> result = m.ConvertToRelativeIndex(index, length); TNode<UintPtrT> result = m.ConvertToRelativeIndex(index, length);
......
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