Bug 1644425 part 1 - Replace ToLength function in self-hosted code with an intrinsic. r=anba

This fixes a regression from bug 1643680 because the code relied on Math.min/max
with int32 and double arguments returning an int32 when possible. Porting this
to C++ should make this less brittle.

Differential Revision: https://phabricator.services.mozilla.com/D78917
This commit is contained in:
Jan de Mooij 2020-06-10 09:24:20 +00:00
parent 5f046f94b5
commit 96041ddffc
4 changed files with 24 additions and 15 deletions

View File

@ -154,7 +154,7 @@ bool js::GetLengthProperty(JSContext* cx, HandleObject obj, uint32_t* lengthp) {
}
// ES2017 7.1.15 ToLength.
static bool ToLength(JSContext* cx, HandleValue v, uint64_t* out) {
bool js::ToLength(JSContext* cx, HandleValue v, uint64_t* out) {
if (v.isInt32()) {
int32_t i = v.toInt32();
*out = i < 0 ? 0 : i;

View File

@ -118,6 +118,8 @@ extern ArrayObject* NewArrayWithGroup(JSContext* cx, uint32_t length,
HandleObjectGroup group,
bool convertDoubleElements);
extern bool ToLength(JSContext* cx, HandleValue v, uint64_t* out);
extern bool GetLengthProperty(JSContext* cx, HandleObject obj,
uint32_t* lengthp);

View File

@ -75,20 +75,6 @@ function RequireObjectCoercible(v) {
ThrowTypeError(JSMSG_CANT_CONVERT_TO, ToString(v), "object");
}
/* Spec: ECMAScript Draft, 6 edition May 22, 2014, 7.1.15 */
function ToLength(v) {
// Step 1.
v = ToInteger(v);
// Step 2.
// Use max(v, 0) here, because it's easier to optimize in Ion.
v = std_Math_max(v, 0);
// Step 3.
// Math.pow(2, 53) - 1 = 0x1fffffffffffff
return std_Math_min(v, 0x1fffffffffffff);
}
// ES2017 draft rev aebf014403a3e641fb1622aec47c40f051943527
// 7.2.10 SameValueZero ( x, y )
function SameValueZero(x, y) {

View File

@ -159,6 +159,26 @@ static bool intrinsic_IsCrossRealmArrayConstructor(JSContext* cx, unsigned argc,
return true;
}
static bool intrinsic_ToLength(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 1);
// Inline fast path for the common case.
if (args[0].isInt32()) {
int32_t i = args[0].toInt32();
args.rval().setInt32(i < 0 ? 0 : i);
return true;
}
uint64_t length = 0;
if (!ToLength(cx, args[0], &length)) {
return false;
}
args.rval().setNumber(double(length));
return true;
}
static bool intrinsic_ToInteger(JSContext* cx, unsigned argc, Value* vp) {
CallArgs args = CallArgsFromVp(argc, vp);
double result;
@ -2140,6 +2160,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
intrinsic_IsCrossRealmArrayConstructor, 1, 0,
IntrinsicIsCrossRealmArrayConstructor),
JS_INLINABLE_FN("ToInteger", intrinsic_ToInteger, 1, 0, IntrinsicToInteger),
JS_FN("ToLength", intrinsic_ToLength, 1, 0),
JS_INLINABLE_FN("ToString", intrinsic_ToString, 1, 0, IntrinsicToString),
JS_FN("ToSource", intrinsic_ToSource, 1, 0),
JS_FN("ToPropertyKey", intrinsic_ToPropertyKey, 1, 0),