[change-array-by-copy] Refactor ConvertToRelativeIndex
This refactors ConvertToRelativeIndex into a clamping version and a version that takes OOB labels for the upcoming implementation of Array#with and TypedArray#with. Also gets rid of the the "to" in the name, because these macros are actually converting _from_ a relative index to an absolute one, not the other way around. Bug: v8:12764 Change-Id: I8bf1c16ce73008164acbd6b849f4259fb9315274 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3669655 Reviewed-by: Adam Klein <adamk@chromium.org> Commit-Queue: Shu-yu Guo <syg@chromium.org> Cr-Commit-Position: refs/heads/main@{#80786}
This commit is contained in:
parent
5299e11bda
commit
978506c3e2
@ -3,25 +3,39 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
namespace array {
|
||||
macro ConvertRelativeIndex(index: Number, length: Number):
|
||||
Number labels OutOfBoundsLow, OutOfBoundsHigh {
|
||||
const relativeIndex = index >= 0 ? index : length + index;
|
||||
if (relativeIndex < 0) goto OutOfBoundsLow;
|
||||
if (relativeIndex >= length) goto OutOfBoundsHigh;
|
||||
return relativeIndex;
|
||||
}
|
||||
|
||||
// https://tc39.es/proposal-item-method/#sec-array.prototype.at
|
||||
transitioning javascript builtin ArrayPrototypeAt(
|
||||
js-implicit context: NativeContext, receiver: JSAny)(index: JSAny): JSAny {
|
||||
// 1. Let O be ? ToObject(this value).
|
||||
const o = ToObject_Inline(context, receiver);
|
||||
|
||||
// 2. Let len be ? LengthOfArrayLike(O).
|
||||
const len = GetLengthProperty(o);
|
||||
// 3. Let relativeIndex be ? ToInteger(index).
|
||||
const relativeIndex = ToInteger_Inline(index);
|
||||
// 4. If relativeIndex ≥ 0, then
|
||||
// a. Let k be relativeIndex.
|
||||
// 5. Else,
|
||||
// a. Let k be len + relativeIndex.
|
||||
const k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;
|
||||
// 6. If k < 0 or k ≥ len, then return undefined.
|
||||
if (k < 0 || k >= len) {
|
||||
|
||||
try {
|
||||
// 3. Let relativeIndex be ? ToInteger(index).
|
||||
const relativeIndex = ToInteger_Inline(index);
|
||||
|
||||
// 4. If relativeIndex ≥ 0, then
|
||||
// a. Let k be relativeIndex.
|
||||
// 5. Else,
|
||||
// a. Let k be len + relativeIndex.
|
||||
const k = ConvertRelativeIndex(relativeIndex, len) otherwise OutOfBounds,
|
||||
OutOfBounds;
|
||||
|
||||
// 7. Return ? Get(O, ! ToString(k)).
|
||||
return GetProperty(o, k);
|
||||
} label OutOfBounds {
|
||||
// 6. If k < 0 or k ≥ len, then return undefined.
|
||||
return Undefined;
|
||||
}
|
||||
// 7. Return ? Get(O, ! ToString(k)).
|
||||
return GetProperty(o, k);
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,15 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
namespace array {
|
||||
macro ConvertToRelativeIndex(index: Number, length: Number): Number {
|
||||
return index < 0 ? Max(index + length, 0) : Min(index, length);
|
||||
macro ConvertAndClampRelativeIndex(index: Number, length: Number): Number {
|
||||
try {
|
||||
return ConvertRelativeIndex(index, length) otherwise OutOfBoundsLow,
|
||||
OutOfBoundsHigh;
|
||||
} label OutOfBoundsLow {
|
||||
return 0;
|
||||
} label OutOfBoundsHigh {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
// https://tc39.github.io/ecma262/#sec-array.prototype.copyWithin
|
||||
@ -21,14 +28,14 @@ transitioning javascript builtin ArrayPrototypeCopyWithin(
|
||||
|
||||
// 4. If relativeTarget < 0, let to be max((len + relativeTarget), 0);
|
||||
// else let to be min(relativeTarget, len).
|
||||
let to: Number = ConvertToRelativeIndex(relativeTarget, length);
|
||||
let to: Number = ConvertAndClampRelativeIndex(relativeTarget, length);
|
||||
|
||||
// 5. Let relativeStart be ? ToInteger(start).
|
||||
const relativeStart: Number = ToInteger_Inline(arguments[1]);
|
||||
|
||||
// 6. If relativeStart < 0, let from be max((len + relativeStart), 0);
|
||||
// else let from be min(relativeStart, len).
|
||||
let from: Number = ConvertToRelativeIndex(relativeStart, length);
|
||||
let from: Number = ConvertAndClampRelativeIndex(relativeStart, length);
|
||||
|
||||
// 7. If end is undefined, let relativeEnd be len;
|
||||
// else let relativeEnd be ? ToInteger(end).
|
||||
@ -39,7 +46,7 @@ transitioning javascript builtin ArrayPrototypeCopyWithin(
|
||||
|
||||
// 8. If relativeEnd < 0, let final be max((len + relativeEnd), 0);
|
||||
// else let final be min(relativeEnd, len).
|
||||
const final: Number = ConvertToRelativeIndex(relativeEnd, length);
|
||||
const final: Number = ConvertAndClampRelativeIndex(relativeEnd, length);
|
||||
|
||||
// 9. Let count be min(final-from, len-to).
|
||||
let count: Number = Min(final - from, length - to);
|
||||
|
@ -1643,44 +1643,65 @@ extern macro IsOneByteStringInstanceType(InstanceType): bool;
|
||||
// After converting an index to an integer, calculate a relative index:
|
||||
// return index < 0 ? max(length + index, 0) : min(index, length)
|
||||
@export
|
||||
transitioning macro ConvertToRelativeIndex(implicit context: Context)(
|
||||
transitioning macro ConvertAndClampRelativeIndex(implicit context: Context)(
|
||||
index: JSAny, length: uintptr): uintptr {
|
||||
const indexNumber: Number = ToInteger_Inline(index);
|
||||
return ConvertToRelativeIndex(indexNumber, length);
|
||||
return ConvertAndClampRelativeIndex(indexNumber, length);
|
||||
}
|
||||
|
||||
// Calculate a relative index:
|
||||
// return index < 0 ? max(length + index, 0) : min(index, length)
|
||||
@export
|
||||
macro ConvertToRelativeIndex(indexNumber: Number, length: uintptr): uintptr {
|
||||
macro ConvertAndClampRelativeIndex(indexNumber: Number, length: uintptr):
|
||||
uintptr {
|
||||
try {
|
||||
return ConvertRelativeIndex(indexNumber, length) otherwise OutOfBoundsLow,
|
||||
OutOfBoundsHigh;
|
||||
} label OutOfBoundsLow {
|
||||
return 0;
|
||||
} label OutOfBoundsHigh {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate a relative index with explicit out-of-bounds labels.
|
||||
macro ConvertRelativeIndex(indexNumber: Number, length: uintptr):
|
||||
uintptr labels OutOfBoundsLow, OutOfBoundsHigh {
|
||||
typeswitch (indexNumber) {
|
||||
case (indexSmi: Smi): {
|
||||
const indexIntPtr: intptr = Convert<intptr>(indexSmi);
|
||||
// The logic is implemented using unsigned types.
|
||||
if (indexIntPtr < 0) {
|
||||
const relativeIndex: uintptr = Unsigned(indexIntPtr) + length;
|
||||
return relativeIndex < length ? relativeIndex : 0;
|
||||
if (relativeIndex < length) return relativeIndex;
|
||||
goto OutOfBoundsLow;
|
||||
|
||||
} else {
|
||||
const relativeIndex: uintptr = Unsigned(indexIntPtr);
|
||||
return relativeIndex < length ? relativeIndex : length;
|
||||
if (relativeIndex < length) return relativeIndex;
|
||||
goto OutOfBoundsHigh;
|
||||
}
|
||||
}
|
||||
case (indexHeapNumber: HeapNumber): {
|
||||
dcheck(IsNumberNormalized(indexHeapNumber));
|
||||
const indexDouble: float64 = Convert<float64>(indexHeapNumber);
|
||||
// NaNs must already be handled by ConvertToRelativeIndex() version
|
||||
// NaNs must already be handled by ConvertAndClampRelativeIndex() version
|
||||
// above accepting JSAny indices.
|
||||
dcheck(!Float64IsNaN(indexDouble));
|
||||
const lengthDouble: float64 = Convert<float64>(length);
|
||||
dcheck(lengthDouble <= kMaxSafeInteger);
|
||||
if (indexDouble < 0) {
|
||||
const relativeIndex: float64 = lengthDouble + indexDouble;
|
||||
return relativeIndex > 0 ? ChangeFloat64ToUintPtr(relativeIndex) : 0;
|
||||
if (relativeIndex > 0) {
|
||||
return ChangeFloat64ToUintPtr(relativeIndex);
|
||||
}
|
||||
goto OutOfBoundsLow;
|
||||
|
||||
} else {
|
||||
return ChangeFloat64ToUintPtr(
|
||||
indexDouble < lengthDouble ? indexDouble : lengthDouble);
|
||||
if (indexDouble < lengthDouble) {
|
||||
return ChangeFloat64ToUintPtr(indexDouble);
|
||||
}
|
||||
goto OutOfBoundsHigh;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,13 +17,13 @@ transitioning javascript builtin StringPrototypeSlice(
|
||||
// Convert {start} to a relative index.
|
||||
const arg0 = arguments[0];
|
||||
const start: uintptr =
|
||||
arg0 != Undefined ? ConvertToRelativeIndex(arg0, length) : 0;
|
||||
arg0 != Undefined ? ConvertAndClampRelativeIndex(arg0, length) : 0;
|
||||
|
||||
// 5. If end is undefined, let intEnd be len;
|
||||
// else Convert {end} to a relative index.
|
||||
const arg1 = arguments[1];
|
||||
const end: uintptr =
|
||||
arg1 != Undefined ? ConvertToRelativeIndex(arg1, length) : length;
|
||||
arg1 != Undefined ? ConvertAndClampRelativeIndex(arg1, length) : length;
|
||||
|
||||
if (end <= start) {
|
||||
return kEmptyString;
|
||||
|
@ -20,7 +20,7 @@ transitioning javascript builtin StringPrototypeSubstr(
|
||||
// 6. If intStart < 0, set intStart to max(size + intStart, 0).
|
||||
const start = arguments[0];
|
||||
const initStart: uintptr =
|
||||
start != Undefined ? ConvertToRelativeIndex(start, size) : 0;
|
||||
start != Undefined ? ConvertAndClampRelativeIndex(start, size) : 0;
|
||||
|
||||
// 4. If length is undefined,
|
||||
// let end be +∞; otherwise let end be ? ToInteger(length).
|
||||
|
@ -76,7 +76,7 @@ transitioning javascript builtin TypedArrayPrototypeSlice(
|
||||
// else let k be min(relativeStart, len).
|
||||
const start = arguments[0];
|
||||
const k: uintptr =
|
||||
start != Undefined ? ConvertToRelativeIndex(start, len) : 0;
|
||||
start != Undefined ? ConvertAndClampRelativeIndex(start, len) : 0;
|
||||
|
||||
// 6. If end is undefined, let relativeEnd be len;
|
||||
// else let relativeEnd be ? ToInteger(end).
|
||||
@ -84,7 +84,7 @@ transitioning javascript builtin TypedArrayPrototypeSlice(
|
||||
// else let final be min(relativeEnd, len).
|
||||
const end = arguments[1];
|
||||
let final: uintptr =
|
||||
end != Undefined ? ConvertToRelativeIndex(end, len) : len;
|
||||
end != Undefined ? ConvertAndClampRelativeIndex(end, len) : len;
|
||||
|
||||
// 8. Let count be max(final - k, 0).
|
||||
let count: uintptr = Unsigned(IntPtrMax(Signed(final - k), 0));
|
||||
|
@ -35,15 +35,16 @@ transitioning javascript builtin TypedArrayPrototypeSubArray(
|
||||
// srcLength).
|
||||
const arg0 = arguments[0];
|
||||
const begin: uintptr =
|
||||
arg0 != Undefined ? ConvertToRelativeIndex(arg0, srcLength) : 0;
|
||||
arg0 != Undefined ? ConvertAndClampRelativeIndex(arg0, srcLength) : 0;
|
||||
|
||||
// 10. If end is undefined, let relativeEnd be srcLength;
|
||||
// else, let relativeEnd be ? ToInteger(end).
|
||||
// 11. If relativeEnd < 0, let endIndex be max((srcLength + relativeEnd),
|
||||
// 0); else let endIndex be min(relativeEnd, srcLength).
|
||||
const arg1 = arguments[1];
|
||||
const end: uintptr =
|
||||
arg1 != Undefined ? ConvertToRelativeIndex(arg1, srcLength) : srcLength;
|
||||
const end: uintptr = arg1 != Undefined ?
|
||||
ConvertAndClampRelativeIndex(arg1, srcLength) :
|
||||
srcLength;
|
||||
|
||||
// 12. Let newLength be max(endIndex - beginIndex, 0).
|
||||
const newLength: uintptr = Unsigned(IntPtrMax(Signed(end - begin), 0));
|
||||
|
@ -318,7 +318,7 @@ TEST(IsValidPositiveSmi) {
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST(ConvertToRelativeIndex) {
|
||||
TEST(ConvertAndClampRelativeIndex) {
|
||||
Isolate* isolate(CcTest::InitIsolateOnce());
|
||||
|
||||
const int kNumParams = 3;
|
||||
@ -335,7 +335,7 @@ TEST(ConvertToRelativeIndex) {
|
||||
TNode<UintPtrT> expected =
|
||||
m.ChangeUintPtrNumberToUintPtr(expected_relative_index);
|
||||
|
||||
TNode<UintPtrT> result = m.ConvertToRelativeIndex(index, length);
|
||||
TNode<UintPtrT> result = m.ConvertAndClampRelativeIndex(index, length);
|
||||
|
||||
m.Return(m.SelectBooleanConstant(m.WordEqual(result, expected)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user