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:
committed by
andre.bargull@gmail.com
parent
b35f392f6c
commit
fd25a9d5fa
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user