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

[builtins] Make ToIndex() uintptr index friendly

The new ToIndex() must eventually replace ToSmiIndex().

The CL fixes the following abstract operations:
  GetViewValue(view, requestIndex, isLittleEndian, type)
  SetViewValue(view, requestIndex, isLittleEndian, type, value)

and the following builtins:
  DataView.prototype.getXXX
  DataView.prototype.setXXX

where XXX are all typed elements.

Bug: v8:4153
Change-Id: Ic2f33e91b59426deb0efa28bb4c15253e80a299c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1874345
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64506}
parent 1e256fc3
...@@ -1407,6 +1407,7 @@ const kArrayBufferMaxByteLength: ...@@ -1407,6 +1407,7 @@ const kArrayBufferMaxByteLength:
const kMaxTypedArrayInHeap: const kMaxTypedArrayInHeap:
constexpr int31 generates 'JSTypedArray::kMaxSizeInHeap'; constexpr int31 generates 'JSTypedArray::kMaxSizeInHeap';
const kMaxSafeInteger: constexpr float64 generates 'kMaxSafeInteger'; const kMaxSafeInteger: constexpr float64 generates 'kMaxSafeInteger';
const kMaxUInt32Double: constexpr float64 generates 'kMaxUInt32Double';
const kSmiMaxValue: constexpr uintptr generates 'kSmiMaxValue'; const kSmiMaxValue: constexpr uintptr generates 'kSmiMaxValue';
const kSmiMax: uintptr = kSmiMaxValue; const kSmiMax: uintptr = kSmiMaxValue;
// TODO(v8:8996): Use uintptr version instead and drop this one. // TODO(v8:8996): Use uintptr version instead and drop this one.
...@@ -1854,6 +1855,7 @@ extern transitioning macro ToInteger_Inline( ...@@ -1854,6 +1855,7 @@ 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;
// TODO(v8:4153): Use ToIndex() instead.
extern transitioning macro ToSmiIndex(implicit context: Context)(JSAny): extern transitioning macro ToSmiIndex(implicit context: Context)(JSAny):
PositiveSmi labels IfRangeError; PositiveSmi labels IfRangeError;
extern transitioning macro ToSmiLength(implicit context: Context)(JSAny): extern transitioning macro ToSmiLength(implicit context: Context)(JSAny):
...@@ -3615,18 +3617,46 @@ macro SameValue(a: JSAny, b: JSAny): bool { ...@@ -3615,18 +3617,46 @@ macro SameValue(a: JSAny, b: JSAny): bool {
BranchIfSameValue(a, b) otherwise return true, return false; BranchIfSameValue(a, b) otherwise return true, return false;
} }
transitioning macro ToIndex(input: JSAny, context: Context): Number // https://tc39.github.io/ecma262/#sec-toindex
labels RangeError { @export
if (input == Undefined) { transitioning macro ToIndex(implicit context: Context)(value: JSAny):
return 0; uintptr labels IfRangeError {
} if (value == Undefined) return 0;
const indexNumber = ToInteger_Inline(context, value, kTruncateMinusZero);
return ToIndex(indexNumber) otherwise IfRangeError;
}
const value: Number = ToInteger_Inline(context, input, kTruncateMinusZero); // https://tc39.github.io/ecma262/#sec-toindex
if (value < 0 || value > kMaxSafeInteger) { // Same as the version above but for Number arguments.
goto RangeError; macro ToIndex(indexNumber: Number): uintptr labels IfRangeError {
} typeswitch (indexNumber) {
case (indexSmi: Smi): {
if (indexSmi < 0) goto IfRangeError;
const index: uintptr = Unsigned(Convert<intptr>(indexSmi));
// Positive Smi values definitely fit into both [0, kMaxSafeInteger] and
// [0, kMaxUintPtr] ranges.
return index;
}
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;
return value; if constexpr (Is64()) {
if (indexDouble > kMaxSafeInteger) goto IfRangeError;
} else {
// On 32-bit architectures not all safe integers fit into uintptr but
// 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);
}
}
} }
transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny): transitioning macro GetLengthProperty(implicit context: Context)(o: JSAny):
...@@ -3694,7 +3724,7 @@ macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr { ...@@ -3694,7 +3724,7 @@ macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr {
const indexDouble: float64 = Convert<float64>(indexHeapNumber); const indexDouble: float64 = Convert<float64>(indexHeapNumber);
// NaNs must already be handled by ConvertToRelativeIndex() version // NaNs must already be handled by ConvertToRelativeIndex() version
// above accepting JSAny indices. // above accepting JSAny indices.
assert(indexDouble == indexDouble); assert(!Float64IsNaN(indexDouble));
const lengthDouble: float64 = Convert<float64>(length); const lengthDouble: float64 = Convert<float64>(length);
assert(lengthDouble <= kMaxSafeInteger); assert(lengthDouble <= kMaxSafeInteger);
if (indexDouble < 0) { if (indexDouble < 0) {
......
This diff is collapsed.
...@@ -212,17 +212,12 @@ namespace typed_array { ...@@ -212,17 +212,12 @@ namespace typed_array {
map: Map, buffer: JSArrayBuffer, byteOffset: JSAny, length: JSAny, map: Map, buffer: JSArrayBuffer, byteOffset: JSAny, length: JSAny,
elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray { elementsInfo: typed_array::TypedArrayElementsInfo): JSTypedArray {
try { try {
let offset: uintptr = 0; // 6. Let offset be ? ToIndex(byteOffset).
if (byteOffset != Undefined) { const offset: uintptr = ToIndex(byteOffset) otherwise IfInvalidOffset;
// 6. Let offset be ? ToIndex(byteOffset).
offset = TryNumberToUintPtr( // 7. If offset modulo elementSize ≠ 0, throw a RangeError exception.
ToInteger_Inline(context, byteOffset, kTruncateMinusZero)) if (elementsInfo.IsUnaligned(offset)) {
otherwise goto IfInvalidOffset; goto IfInvalidAlignment('start offset');
// 7. If offset modulo elementSize ≠ 0, throw a RangeError exception.
if (elementsInfo.IsUnaligned(offset)) {
goto IfInvalidAlignment('start offset');
}
} }
let newLength: PositiveSmi = 0; let newLength: PositiveSmi = 0;
......
...@@ -2664,6 +2664,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler ...@@ -2664,6 +2664,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler
}; };
// ES6 7.1.17 ToIndex, but jumps to range_error if the result is not a Smi. // ES6 7.1.17 ToIndex, but jumps to range_error if the result is not a Smi.
// TODO(v8:4153): Use ToIndex() instead.
TNode<Smi> ToSmiIndex(TNode<Context> context, TNode<Object> input, TNode<Smi> ToSmiIndex(TNode<Context> context, TNode<Object> input,
Label* range_error); Label* range_error);
......
...@@ -1043,6 +1043,8 @@ constexpr uint64_t kHoleNanInt64 = ...@@ -1043,6 +1043,8 @@ constexpr uint64_t kHoleNanInt64 =
// ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER // ES6 section 20.1.2.6 Number.MAX_SAFE_INTEGER
constexpr double kMaxSafeInteger = 9007199254740991.0; // 2^53-1 constexpr double kMaxSafeInteger = 9007199254740991.0; // 2^53-1
constexpr double kMaxUInt32Double = double{kMaxUInt32};
// The order of this enum has to be kept in sync with the predicates below. // The order of this enum has to be kept in sync with the predicates below.
enum class VariableMode : uint8_t { enum class VariableMode : uint8_t {
// User declared variables: // User declared variables:
......
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