Bug 1689311: Don't box BigInt for MTest and MNot. r=jandem!

Differential Revision: https://phabricator.services.mozilla.com/D103298
This commit is contained in:
André Bargull 2021-01-29 17:12:43 +00:00
Родитель 0d128ebbfd
Коммит 43774473a1
4 изменённых файлов: 64 добавлений и 10 удалений

Просмотреть файл

@ -1474,6 +1474,21 @@ void CodeGenerator::testValueTruthy(const ValueOperand& value,
masm.jump(ifTruthy);
}
void CodeGenerator::visitTestBIAndBranch(LTestBIAndBranch* lir) {
Label* ifTrueLabel = getJumpLabelForBranch(lir->ifTrue());
Label* ifFalseLabel = getJumpLabelForBranch(lir->ifFalse());
Register input = ToRegister(lir->input());
if (isNextBlock(lir->ifFalse()->lir())) {
masm.branchIfBigIntIsNonZero(input, ifTrueLabel);
} else if (isNextBlock(lir->ifTrue()->lir())) {
masm.branchIfBigIntIsZero(input, ifFalseLabel);
} else {
masm.branchIfBigIntIsZero(input, ifFalseLabel);
jumpToBlock(lir->ifTrue());
}
}
void CodeGenerator::visitTestOAndBranch(LTestOAndBranch* lir) {
Label* truthy = getJumpLabelForBranch(lir->ifTruthy());
Label* falsy = getJumpLabelForBranch(lir->ifFalsy());
@ -10248,6 +10263,14 @@ void CodeGenerator::visitSetInitializedLength(LSetInitializedLength* lir) {
SetLengthFromIndex(masm, lir->index(), initLength);
}
void CodeGenerator::visitNotBI(LNotBI* lir) {
Register input = ToRegister(lir->input());
Register output = ToRegister(lir->output());
masm.cmp32Set(Assembler::Equal, Address(input, BigInt::offsetOfLength()),
Imm32(0), output);
}
void CodeGenerator::visitNotO(LNotO* lir) {
auto* ool = new (alloc()) OutOfLineTestObjectWithLabels();
addOutOfLineCode(ool, lir->mir());

Просмотреть файл

@ -571,10 +571,6 @@ void LIRGenerator::visitTest(MTest* test) {
// TestPolicy).
MOZ_ASSERT(opd->type() != MIRType::String);
// BigInt is boxed in type analysis.
MOZ_ASSERT(opd->type() != MIRType::BigInt,
"BigInt should be boxed by TestPolicy");
// Testing a constant.
if (MConstant* constant = opd->maybeConstantValue()) {
bool b;
@ -814,6 +810,9 @@ void LIRGenerator::visitTest(MTest* test) {
add(new (alloc())
LTestI64AndBranch(useInt64Register(opd), ifTrue, ifFalse));
break;
case MIRType::BigInt:
add(new (alloc()) LTestBIAndBranch(useRegister(opd), ifTrue, ifFalse));
break;
default:
MOZ_CRASH("Bad type");
}
@ -3008,13 +3007,13 @@ void LIRGenerator::visitNot(MNot* ins) {
// String is converted to length of string in the type analysis phase (see
// TestPolicy).
MOZ_ASSERT(op->type() != MIRType::String);
MOZ_ASSERT(op->type() != MIRType::BigInt,
"BigInt should be boxed by TestPolicy");
// - boolean: x xor 1
// - int32: LCompare(x, 0)
// - double: LCompare(x, 0)
// - null or undefined: true
// - symbol: false
// - bigint: LNotBI(x)
// - object: false if it never emulates undefined, else LNotO(x)
switch (op->type()) {
case MIRType::Boolean: {
@ -3042,6 +3041,9 @@ void LIRGenerator::visitNot(MNot* ins) {
case MIRType::Symbol:
define(new (alloc()) LInteger(0), ins);
break;
case MIRType::BigInt:
define(new (alloc()) LNotBI(useRegisterAtStart(op)), ins);
break;
case MIRType::Object:
define(new (alloc()) LNotO(useRegister(op)), ins);
break;

Просмотреть файл

@ -279,6 +279,7 @@ bool TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
case MIRType::Double:
case MIRType::Float32:
case MIRType::Symbol:
case MIRType::BigInt:
case MIRType::Object:
break;
@ -290,8 +291,7 @@ bool TestPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins) const {
}
default:
ins->replaceOperand(0, BoxAt(alloc, ins, op));
break;
MOZ_CRASH("Unexpected MIRType.");
}
return true;
}

Просмотреть файл

@ -1355,7 +1355,7 @@ class LTestI64AndBranch : public LControlInstructionHelper<2, INT64_PIECES, 0> {
MBasicBlock* ifFalse() const { return getSuccessor(1); }
};
// Takes in either an integer or boolean input and tests it for truthiness.
// Takes in a double input and tests it for truthiness.
class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {
public:
LIR_HEADER(TestDAndBranch)
@ -1372,7 +1372,7 @@ class LTestDAndBranch : public LControlInstructionHelper<2, 1, 0> {
MBasicBlock* ifFalse() const { return getSuccessor(1); }
};
// Takes in either an integer or boolean input and tests it for truthiness.
// Takes in a float32 input and tests it for truthiness.
class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {
public:
LIR_HEADER(TestFAndBranch)
@ -1389,6 +1389,23 @@ class LTestFAndBranch : public LControlInstructionHelper<2, 1, 0> {
MBasicBlock* ifFalse() const { return getSuccessor(1); }
};
// Takes in a bigint input and tests it for truthiness.
class LTestBIAndBranch : public LControlInstructionHelper<2, 1, 0> {
public:
LIR_HEADER(TestBIAndBranch)
LTestBIAndBranch(const LAllocation& in, MBasicBlock* ifTrue,
MBasicBlock* ifFalse)
: LControlInstructionHelper(classOpcode) {
setOperand(0, in);
setSuccessor(0, ifTrue);
setSuccessor(1, ifFalse);
}
MBasicBlock* ifTrue() { return getSuccessor(0); }
MBasicBlock* ifFalse() { return getSuccessor(1); }
};
// Takes an object and tests it for truthiness. An object is falsy iff it
// emulates |undefined|; see js::EmulatesUndefined.
class LTestOAndBranch : public LControlInstructionHelper<2, 1, 1> {
@ -1884,6 +1901,18 @@ class LNotF : public LInstructionHelper<1, 1, 0> {
MNot* mir() { return mir_->toNot(); }
};
// Not operation on a BigInt.
class LNotBI : public LInstructionHelper<1, 1, 0> {
public:
LIR_HEADER(NotBI)
explicit LNotBI(const LAllocation& input) : LInstructionHelper(classOpcode) {
setOperand(0, input);
}
MNot* mir() { return mir_->toNot(); }
};
// Boolean complement operation on an object.
class LNotO : public LInstructionHelper<1, 1, 0> {
public: