Bug 1964692 - Part 1: Move ToIntegerIndex to jsnum. r=jandem

Add `ToIntegerIndex` in preparation for the next part.

`ToIntegerIndex` needs to be instantiated for `size_t` and `uint64_t`. It's not
valid add explicit instantiations for both `size_t` and `uint64_t`, because
`size_t` is `uint64_t` on 64-bit platforms and it's invalid to have duplicate
template instantiations. Instead instantiate `uint32_t` and `uint64_t` to handle
32- and 64-bit targets.

Differential Revision: https://phabricator.services.mozilla.com/D248007
This commit is contained in:
André Bargull
2025-05-09 05:22:48 +00:00
committed by andre.bargull@gmail.com
parent b35f392f6c
commit fd25a9d5fa
3 changed files with 67 additions and 34 deletions

View File

@@ -2205,6 +2205,39 @@ bool js::ToIndexSlow(JSContext* cx, JS::HandleValue v,
return true;
}
/**
* Convert |value| to an integer and clamp it to a valid integer index within
* the range `[0..length]`.
*/
template <typename ArrayLength>
bool js::ToIntegerIndexSlow(JSContext* cx, Handle<Value> value,
ArrayLength length, ArrayLength* result) {
MOZ_ASSERT(!value.isInt32());
double relative;
if (!ToInteger(cx, value, &relative)) {
return false;
}
if (relative >= 0) {
*result = ArrayLength(std::min(relative, double(length)));
} else {
*result = ArrayLength(std::max(relative + double(length), 0.0));
}
return true;
}
static_assert(std::is_same_v<size_t, uint32_t> ||
std::is_same_v<size_t, uint64_t>,
"If this assertion fails, add the corresponding unsigned int "
"type for size_t to the explicit instantiations below");
template bool js::ToIntegerIndexSlow<uint32_t>(JSContext*, Handle<Value>,
uint32_t, uint32_t*);
template bool js::ToIntegerIndexSlow<uint64_t>(JSContext*, Handle<Value>,
uint64_t, uint64_t*);
template <typename CharT>
double js_strtod(const CharT* begin, const CharT* end, const CharT** dEnd) {
const CharT* s = SkipSpace(begin, end);

View File

@@ -404,6 +404,40 @@ static MOZ_ALWAYS_INLINE bool IsDefinitelyIndex(const Value& v,
return ToIndex(cx, v, JSMSG_BAD_INDEX, index);
}
/**
* Convert |value| to an integer and clamp it to a valid integer index within
* the range `[0..length]`.
*/
template <typename ArrayLength>
[[nodiscard]] extern bool ToIntegerIndexSlow(JSContext* cx, Handle<Value> value,
ArrayLength length,
ArrayLength* result);
template <typename ArrayLength>
[[nodiscard]] static inline bool ToIntegerIndex(JSContext* cx,
Handle<Value> value,
ArrayLength length,
ArrayLength* result) {
static_assert(std::is_unsigned_v<ArrayLength>);
// Optimize for the common case when |value| is an int32 to avoid unnecessary
// floating point computations.
if (value.isInt32()) {
int32_t relative = value.toInt32();
if (relative >= 0) {
*result = std::min(ArrayLength(relative), length);
} else if (mozilla::Abs(relative) <= length) {
*result = length - mozilla::Abs(relative);
} else {
*result = 0;
}
return true;
}
return ToIntegerIndexSlow(cx, value, length, result);
}
} /* namespace js */
#endif /* jsnum_h */

View File

@@ -1844,40 +1844,6 @@ static bool TypedArray_set(JSContext* cx, unsigned argc, Value* vp) {
return CallNonGenericMethod<IsTypedArrayObject, TypedArray_set>(cx, args);
}
/**
* Convert |value| to an integer and clamp it to a valid integer index within
* the range `[0..length]`.
*/
static bool ToIntegerIndex(JSContext* cx, Handle<Value> value, size_t length,
size_t* result) {
// Optimize for the common case when |value| is an int32 to avoid unnecessary
// floating point computations.
if (value.isInt32()) {
int32_t relative = value.toInt32();
if (relative >= 0) {
*result = std::min(size_t(relative), length);
} else if (mozilla::Abs(relative) <= length) {
*result = length - mozilla::Abs(relative);
} else {
*result = 0;
}
return true;
}
double relative;
if (!ToInteger(cx, value, &relative)) {
return false;
}
if (relative >= 0) {
*result = size_t(std::min(relative, double(length)));
} else {
*result = size_t(std::max(relative + double(length), 0.0));
}
return true;
}
// ES2020 draft rev dc1e21c454bd316810be1c0e7af0131a2d7f38e9
// 22.2.3.5 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )
static bool TypedArray_copyWithin(JSContext* cx, const CallArgs& args) {