Bug 784765 - Add fastpath for string equality with different length. r=jandem

This commit is contained in:
Tom Schuster 2012-10-06 21:59:14 +02:00
parent 860a3dc1e2
commit b2ff782bd9
3 changed files with 25 additions and 13 deletions

View File

@ -1920,6 +1920,7 @@ CodeGenerator::visitCompareS(LCompareS *lir)
Register left = ToRegister(lir->left());
Register right = ToRegister(lir->right());
Register output = ToRegister(lir->output());
Register temp = ToRegister(lir->temp());
typedef bool (*pf)(JSContext *, HandleString, HandleString, JSBool *);
static const VMFunction stringsEqualInfo = FunctionInfo<pf>(ion::StringsEqual<true>);
@ -1943,20 +1944,26 @@ CodeGenerator::visitCompareS(LCompareS *lir)
masm.jump(ool->rejoin());
masm.bind(&notPointerEqual);
masm.loadPtr(Address(left, JSString::offsetOfLengthAndFlags()), output);
masm.loadPtr(Address(right, JSString::offsetOfLengthAndFlags()), temp);
// JSString::isAtom === !(lengthAndFlags & ATOM_MASK)
Imm32 atomMask(JSString::ATOM_BIT);
// This optimization is only correct for atomized strings,
// so we need to jump to the ool path.
masm.branchTest32(Assembler::Zero, Address(left, JSString::offsetOfLengthAndFlags()),
atomMask, ool->entry());
masm.branchTest32(Assembler::Zero, Address(right, JSString::offsetOfLengthAndFlags()),
atomMask, ool->entry());
Label notAtom;
// We can optimize the equality operation to a pointer compare for
// two atoms.
Imm32 atomBit(JSString::ATOM_BIT);
masm.branchTest32(Assembler::Zero, output, atomBit, &notAtom);
masm.branchTest32(Assembler::Zero, temp, atomBit, &notAtom);
masm.cmpPtr(left, right);
emitSet(JSOpToCondition(op), output);
masm.jump(ool->rejoin());
masm.bind(&notAtom);
// Strings of different length can never be equal.
masm.rshiftPtr(Imm32(JSString::LENGTH_SHIFT), output);
masm.rshiftPtr(Imm32(JSString::LENGTH_SHIFT), temp);
masm.branchPtr(Assembler::Equal, output, temp, ool->entry());
masm.move32(Imm32(op == JSOP_NE || op == JSOP_STRICTNE), output);
masm.bind(ool->rejoin());
return true;

View File

@ -930,13 +930,15 @@ class LCompareD : public LInstructionHelper<1, 2, 0>
}
};
class LCompareS : public LInstructionHelper<1, 2, 0>
class LCompareS : public LInstructionHelper<1, 2, 1>
{
public:
LIR_HEADER(CompareS);
LCompareS(const LAllocation &left, const LAllocation &right) {
LCompareS(const LAllocation &left, const LAllocation &right,
const LDefinition &temp) {
setOperand(0, left);
setOperand(1, right);
setTemp(0, temp);
}
const LAllocation *left() {
@ -945,6 +947,9 @@ class LCompareS : public LInstructionHelper<1, 2, 0>
const LAllocation *right() {
return getOperand(1);
}
const LDefinition *temp() {
return getTemp(0);
}
MCompare *mir() {
return mir_->toCompare();
}

View File

@ -454,7 +454,7 @@ LIRGenerator::visitCompare(MCompare *comp)
// LCompareSAndBranch. Doing this now wouldn't be wrong, but doesn't
// make sense and avoids confusion.
if (comp->specialization() == MIRType_String) {
LCompareS *lir = new LCompareS(useRegister(left), useRegister(right));
LCompareS *lir = new LCompareS(useRegister(left), useRegister(right), temp());
if (!define(lir, comp))
return false;
return assignSafepoint(lir, comp);