Skip to content

Commit

Permalink
Bug 1811264 - Part 3: Handle remaining BigInt comparisons. r=jandem
Browse files Browse the repository at this point in the history
This adds support for BigInt x {Null, Undefined} relational comparisons.

Depends on D167265

Differential Revision: https://phabricator.services.mozilla.com/D167266
  • Loading branch information
anba committed Jan 20, 2023
1 parent 24efc8f commit b8bcbef
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 18 deletions.
82 changes: 82 additions & 0 deletions js/src/jit-test/tests/cacheir/bigint-compare-null-or-undef.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// Test relational comparison when one operand is null or undefined.

function test(xs) {
for (let i = 0; i < 200; ++i) {
let x = xs[i % xs.length];

// The result is equal when compared to the result with explicit ToNumber conversions.

// Test when null-or-undefined is on the right-hand side.
assertEq(x < nullOrUndef, x < (+nullOrUndef));
assertEq(x <= nullOrUndef, x <= (+nullOrUndef));
assertEq(x >= nullOrUndef, x >= (+nullOrUndef));
assertEq(x > nullOrUndef, x > (+nullOrUndef));

// Test when null-or-undefined is on the left-hand side.
assertEq(nullOrUndef < x, (+nullOrUndef) < x);
assertEq(nullOrUndef <= x, (+nullOrUndef) <= x);
assertEq(nullOrUndef >= x, (+nullOrUndef) >= x);
assertEq(nullOrUndef > x, (+nullOrUndef) > x);
}
}

function runTest(inputs) {
let fNull = Function(`return ${test}`.replaceAll("nullOrUndef", "null"))();
fNull(inputs);

let fUndefined = Function(`return ${test}`.replaceAll("nullOrUndef", "undefined"))();
fUndefined(inputs);
}

// BigInt inputs
runTest([
// Definitely heap digits.
-(2n ** 1000n),

// -(2n**64n)
-18446744073709551617n,
-18446744073709551616n,
-18446744073709551615n,

// -(2n**63n)
-9223372036854775809n,
-9223372036854775808n,
-9223372036854775807n,

// -(2**32)
-4294967297n,
-4294967296n,
-4294967295n,

// -(2**31)
-2147483649n,
-2147483648n,
-2147483647n,

-1n,
0n,
1n,

// 2**31
2147483647n,
2147483648n,
2147483649n,

// 2**32
4294967295n,
4294967296n,
4294967297n,

// 2n**63n
9223372036854775807n,
9223372036854775808n,
9223372036854775809n,

// 2n**64n
18446744073709551615n,
18446744073709551616n,
18446744073709551617n,

// Definitely heap digits.
2n ** 1000n,
]);
34 changes: 16 additions & 18 deletions js/src/jit/CacheIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11284,30 +11284,22 @@ AttachDecision CompareIRGenerator::tryAttachPrimitiveSymbol(

AttachDecision CompareIRGenerator::tryAttachBigIntInt32(ValOperandId lhsId,
ValOperandId rhsId) {
// Ensure BigInt x {Int32, Boolean}.
if (!(lhsVal_.isBigInt() && (rhsVal_.isInt32() || rhsVal_.isBoolean())) &&
!(rhsVal_.isBigInt() && (lhsVal_.isInt32() || lhsVal_.isBoolean()))) {
// Ensure BigInt x {Int32, Boolean, Null}.
if (!(lhsVal_.isBigInt() && CanConvertToInt32ForToNumber(rhsVal_)) &&
!(rhsVal_.isBigInt() && CanConvertToInt32ForToNumber(lhsVal_))) {
return AttachDecision::NoAction;
}

// Case should have been handled by tryAttachStrictDifferentTypes
MOZ_ASSERT(op_ != JSOp::StrictEq && op_ != JSOp::StrictNe);

auto createGuards = [&](const Value& v, ValOperandId vId) {
if (v.isBoolean()) {
return writer.guardBooleanToInt32(vId);
}
MOZ_ASSERT(v.isInt32());
return writer.guardToInt32(vId);
};

if (lhsVal_.isBigInt()) {
BigIntOperandId bigIntId = writer.guardToBigInt(lhsId);
Int32OperandId intId = createGuards(rhsVal_, rhsId);
Int32OperandId intId = EmitGuardToInt32ForToNumber(writer, rhsId, rhsVal_);

writer.compareBigIntInt32Result(op_, bigIntId, intId);
} else {
Int32OperandId intId = createGuards(lhsVal_, lhsId);
Int32OperandId intId = EmitGuardToInt32ForToNumber(writer, lhsId, lhsVal_);
BigIntOperandId bigIntId = writer.guardToBigInt(rhsId);

writer.compareBigIntInt32Result(ReverseCompareOp(op_), bigIntId, intId);
Expand All @@ -11320,22 +11312,28 @@ AttachDecision CompareIRGenerator::tryAttachBigIntInt32(ValOperandId lhsId,

AttachDecision CompareIRGenerator::tryAttachBigIntNumber(ValOperandId lhsId,
ValOperandId rhsId) {
// Ensure BigInt x Number.
if (!(lhsVal_.isBigInt() && rhsVal_.isNumber()) &&
!(rhsVal_.isBigInt() && lhsVal_.isNumber())) {
// Ensure BigInt x {Number, Undefined}.
if (!(lhsVal_.isBigInt() && CanConvertToDoubleForToNumber(rhsVal_)) &&
!(rhsVal_.isBigInt() && CanConvertToDoubleForToNumber(lhsVal_))) {
return AttachDecision::NoAction;
}

// Case should have been handled by tryAttachStrictDifferentTypes
MOZ_ASSERT(op_ != JSOp::StrictEq && op_ != JSOp::StrictNe);

// Case should have been handled by tryAttachBigIntInt32.
MOZ_ASSERT(!CanConvertToInt32ForToNumber(lhsVal_));
MOZ_ASSERT(!CanConvertToInt32ForToNumber(rhsVal_));

if (lhsVal_.isBigInt()) {
BigIntOperandId bigIntId = writer.guardToBigInt(lhsId);
NumberOperandId numId = writer.guardIsNumber(rhsId);
NumberOperandId numId =
EmitGuardToDoubleForToNumber(writer, rhsId, rhsVal_);

writer.compareBigIntNumberResult(op_, bigIntId, numId);
} else {
NumberOperandId numId = writer.guardIsNumber(lhsId);
NumberOperandId numId =
EmitGuardToDoubleForToNumber(writer, lhsId, lhsVal_);
BigIntOperandId bigIntId = writer.guardToBigInt(rhsId);

writer.compareBigIntNumberResult(ReverseCompareOp(op_), bigIntId, numId);
Expand Down

0 comments on commit b8bcbef

Please sign in to comment.