зеркало из https://github.com/mozilla/gecko-dev.git
Bug 836373 - IonMonkey changes to compareString for the baseline jit. r=jandem
This commit is contained in:
Родитель
0aac10ccdb
Коммит
d0e36df95e
|
@ -2866,33 +2866,7 @@ CodeGenerator::emitCompareS(LInstruction *lir, JSOp op, Register left, Register
|
||||||
if (!ool)
|
if (!ool)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
Label notPointerEqual;
|
masm.compareStrings(op, left, right, output, temp, ool->entry());
|
||||||
// Fast path for identical strings
|
|
||||||
masm.branchPtr(Assembler::NotEqual, left, right, ¬PointerEqual);
|
|
||||||
masm.move32(Imm32(op == JSOP_EQ || op == JSOP_STRICTEQ), output);
|
|
||||||
masm.jump(ool->rejoin());
|
|
||||||
|
|
||||||
masm.bind(¬PointerEqual);
|
|
||||||
masm.loadPtr(Address(left, JSString::offsetOfLengthAndFlags()), output);
|
|
||||||
masm.loadPtr(Address(right, JSString::offsetOfLengthAndFlags()), temp);
|
|
||||||
|
|
||||||
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, ¬Atom);
|
|
||||||
masm.branchTest32(Assembler::Zero, temp, atomBit, ¬Atom);
|
|
||||||
|
|
||||||
masm.cmpPtr(left, right);
|
|
||||||
emitSet(JSOpToCondition(op), output);
|
|
||||||
masm.jump(ool->rejoin());
|
|
||||||
|
|
||||||
masm.bind(¬Atom);
|
|
||||||
// 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());
|
masm.bind(ool->rejoin());
|
||||||
return true;
|
return true;
|
||||||
|
@ -3056,7 +3030,7 @@ CodeGenerator::visitIsNullOrLikeUndefined(LIsNullOrLikeUndefined *lir)
|
||||||
else
|
else
|
||||||
cond = masm.testUndefined(cond, value);
|
cond = masm.testUndefined(cond, value);
|
||||||
|
|
||||||
emitSet(cond, output);
|
masm.emitSet(cond, output);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4096,7 +4070,7 @@ CodeGenerator::visitIteratorMore(LIteratorMore *lir)
|
||||||
// Set output to true if props_cursor < props_end.
|
// Set output to true if props_cursor < props_end.
|
||||||
masm.loadPtr(Address(output, offsetof(NativeIterator, props_end)), temp);
|
masm.loadPtr(Address(output, offsetof(NativeIterator, props_end)), temp);
|
||||||
masm.cmpPtr(Address(output, offsetof(NativeIterator, props_cursor)), temp);
|
masm.cmpPtr(Address(output, offsetof(NativeIterator, props_cursor)), temp);
|
||||||
emitSet(Assembler::LessThan, output);
|
masm.emitSet(Assembler::LessThan, output);
|
||||||
|
|
||||||
masm.bind(ool->rejoin());
|
masm.bind(ool->rejoin());
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -432,6 +432,43 @@ MacroAssembler::initGCThing(const Register &obj, JSObject *templateObject)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
MacroAssembler::compareStrings(JSOp op, Register left, Register right, Register result,
|
||||||
|
Register temp, Label *fail)
|
||||||
|
{
|
||||||
|
JS_ASSERT(IsEqualityOp(op));
|
||||||
|
|
||||||
|
Label done;
|
||||||
|
Label notPointerEqual;
|
||||||
|
// Fast path for identical strings.
|
||||||
|
branchPtr(Assembler::NotEqual, left, right, ¬PointerEqual);
|
||||||
|
move32(Imm32(op == JSOP_EQ || op == JSOP_STRICTEQ), result);
|
||||||
|
jump(&done);
|
||||||
|
|
||||||
|
bind(¬PointerEqual);
|
||||||
|
loadPtr(Address(left, JSString::offsetOfLengthAndFlags()), result);
|
||||||
|
loadPtr(Address(right, JSString::offsetOfLengthAndFlags()), temp);
|
||||||
|
|
||||||
|
Label notAtom;
|
||||||
|
// Optimize the equality operation to a pointer compare for two atoms.
|
||||||
|
Imm32 atomBit(JSString::ATOM_BIT);
|
||||||
|
branchTest32(Assembler::Zero, result, atomBit, ¬Atom);
|
||||||
|
branchTest32(Assembler::Zero, temp, atomBit, ¬Atom);
|
||||||
|
|
||||||
|
cmpPtr(left, right);
|
||||||
|
emitSet(JSOpToCondition(op), result);
|
||||||
|
jump(&done);
|
||||||
|
|
||||||
|
bind(¬Atom);
|
||||||
|
// Strings of different length can never be equal.
|
||||||
|
rshiftPtr(Imm32(JSString::LENGTH_SHIFT), result);
|
||||||
|
rshiftPtr(Imm32(JSString::LENGTH_SHIFT), temp);
|
||||||
|
branchPtr(Assembler::Equal, result, temp, fail);
|
||||||
|
move32(Imm32(op == JSOP_NE || op == JSOP_STRICTNE), result);
|
||||||
|
|
||||||
|
bind(&done);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MacroAssembler::parCheckInterruptFlags(const Register &tempReg,
|
MacroAssembler::parCheckInterruptFlags(const Register &tempReg,
|
||||||
Label *fail)
|
Label *fail)
|
||||||
|
|
|
@ -500,6 +500,11 @@ class MacroAssembler : public MacroAssemblerSpecific
|
||||||
Label *fail);
|
Label *fail);
|
||||||
void initGCThing(const Register &obj, JSObject *templateObject);
|
void initGCThing(const Register &obj, JSObject *templateObject);
|
||||||
|
|
||||||
|
// Compares two strings for equality based on the JSOP.
|
||||||
|
// This checks for identical pointers, atoms and length and fails for everything else.
|
||||||
|
void compareStrings(JSOp op, Register left, Register right, Register result,
|
||||||
|
Register temp, Label *fail);
|
||||||
|
|
||||||
// Checks the flags that signal that parallel code may need to interrupt or
|
// Checks the flags that signal that parallel code may need to interrupt or
|
||||||
// abort. Branches to fail in that case.
|
// abort. Branches to fail in that case.
|
||||||
void parCheckInterruptFlags(const Register &tempReg,
|
void parCheckInterruptFlags(const Register &tempReg,
|
||||||
|
|
|
@ -103,13 +103,6 @@ CodeGeneratorARM::visitTestIAndBranch(LTestIAndBranch *test)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CodeGeneratorARM::emitSet(Assembler::Condition cond, const Register &dest)
|
|
||||||
{
|
|
||||||
masm.ma_mov(Imm32(0), dest);
|
|
||||||
masm.ma_mov(Imm32(1), dest, NoSetCond, cond);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CodeGeneratorARM::visitCompare(LCompare *comp)
|
CodeGeneratorARM::visitCompare(LCompare *comp)
|
||||||
{
|
{
|
||||||
|
@ -1236,7 +1229,7 @@ CodeGeneratorARM::visitCompareD(LCompareD *comp)
|
||||||
|
|
||||||
Assembler::DoubleCondition cond = JSOpToDoubleCondition(comp->mir()->jsop());
|
Assembler::DoubleCondition cond = JSOpToDoubleCondition(comp->mir()->jsop());
|
||||||
masm.compareDouble(lhs, rhs);
|
masm.compareDouble(lhs, rhs);
|
||||||
emitSet(Assembler::ConditionFromDoubleCondition(cond), ToRegister(comp->output()));
|
masm.emitSet(Assembler::ConditionFromDoubleCondition(cond), ToRegister(comp->output()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1270,7 +1263,7 @@ CodeGeneratorARM::visitCompareB(LCompareB *lir)
|
||||||
masm.cmp32(lhs.payloadReg(), Imm32(rhs->toConstant()->toBoolean()));
|
masm.cmp32(lhs.payloadReg(), Imm32(rhs->toConstant()->toBoolean()));
|
||||||
else
|
else
|
||||||
masm.cmp32(lhs.payloadReg(), ToRegister(rhs));
|
masm.cmp32(lhs.payloadReg(), ToRegister(rhs));
|
||||||
emitSet(JSOpToCondition(mir->jsop()), output);
|
masm.emitSet(JSOpToCondition(mir->jsop()), output);
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1322,7 +1315,7 @@ CodeGeneratorARM::visitCompareV(LCompareV *lir)
|
||||||
masm.j(Assembler::NotEqual, ¬Equal);
|
masm.j(Assembler::NotEqual, ¬Equal);
|
||||||
{
|
{
|
||||||
masm.cmp32(lhs.payloadReg(), rhs.payloadReg());
|
masm.cmp32(lhs.payloadReg(), rhs.payloadReg());
|
||||||
emitSet(cond, output);
|
masm.emitSet(cond, output);
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
}
|
}
|
||||||
masm.bind(¬Equal);
|
masm.bind(¬Equal);
|
||||||
|
@ -1363,7 +1356,7 @@ CodeGeneratorARM::visitNotI(LNotI *ins)
|
||||||
{
|
{
|
||||||
// It is hard to optimize !x, so just do it the basic way for now.
|
// It is hard to optimize !x, so just do it the basic way for now.
|
||||||
masm.ma_cmp(ToRegister(ins->input()), Imm32(0));
|
masm.ma_cmp(ToRegister(ins->input()), Imm32(0));
|
||||||
emitSet(Assembler::Equal, ToRegister(ins->output()));
|
masm.emitSet(Assembler::Equal, ToRegister(ins->output()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,9 +57,6 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
||||||
|
|
||||||
void emitRoundDouble(const FloatRegister &src, const Register &dest, Label *fail);
|
void emitRoundDouble(const FloatRegister &src, const Register &dest, Label *fail);
|
||||||
|
|
||||||
// Emits a conditional set.
|
|
||||||
void emitSet(Assembler::Condition cond, const Register &dest);
|
|
||||||
|
|
||||||
// Emits a branch that directs control flow to the true block if |cond| is
|
// Emits a branch that directs control flow to the true block if |cond| is
|
||||||
// true, and the false block if |cond| is false.
|
// true, and the false block if |cond| is false.
|
||||||
void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse);
|
void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse);
|
||||||
|
|
|
@ -1065,6 +1065,13 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
||||||
ma_lsl(imm, dest, dest);
|
ma_lsl(imm, dest, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
emitSet(Assembler::Condition cond, const Register &dest)
|
||||||
|
{
|
||||||
|
ma_mov(Imm32(0), dest);
|
||||||
|
ma_mov(Imm32(1), dest, NoSetCond, cond);
|
||||||
|
}
|
||||||
|
|
||||||
// Setup a call to C/C++ code, given the number of general arguments it
|
// Setup a call to C/C++ code, given the number of general arguments it
|
||||||
// takes. Note that this only supports cdecl.
|
// takes. Note that this only supports cdecl.
|
||||||
//
|
//
|
||||||
|
|
|
@ -120,42 +120,6 @@ CodeGeneratorX86Shared::visitTestDAndBranch(LTestDAndBranch *test)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
CodeGeneratorX86Shared::emitSet(Assembler::Condition cond, const Register &dest,
|
|
||||||
Assembler::NaNCond ifNaN)
|
|
||||||
{
|
|
||||||
if (GeneralRegisterSet(Registers::SingleByteRegs).has(dest)) {
|
|
||||||
// If the register we're defining is a single byte register,
|
|
||||||
// take advantage of the setCC instruction
|
|
||||||
masm.setCC(cond, dest);
|
|
||||||
masm.movzxbl(dest, dest);
|
|
||||||
|
|
||||||
if (ifNaN != Assembler::NaN_Unexpected) {
|
|
||||||
Label noNaN;
|
|
||||||
masm.j(Assembler::NoParity, &noNaN);
|
|
||||||
if (ifNaN == Assembler::NaN_IsTrue)
|
|
||||||
masm.movl(Imm32(1), dest);
|
|
||||||
else
|
|
||||||
masm.xorl(dest, dest);
|
|
||||||
masm.bind(&noNaN);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Label end;
|
|
||||||
Label ifFalse;
|
|
||||||
|
|
||||||
if (ifNaN == Assembler::NaN_IsFalse)
|
|
||||||
masm.j(Assembler::Parity, &ifFalse);
|
|
||||||
masm.movl(Imm32(1), dest);
|
|
||||||
masm.j(cond, &end);
|
|
||||||
if (ifNaN == Assembler::NaN_IsTrue)
|
|
||||||
masm.j(Assembler::Parity, &end);
|
|
||||||
masm.bind(&ifFalse);
|
|
||||||
masm.xorl(dest, dest);
|
|
||||||
|
|
||||||
masm.bind(&end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CodeGeneratorX86Shared::emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right)
|
CodeGeneratorX86Shared::emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right)
|
||||||
{
|
{
|
||||||
|
@ -176,7 +140,7 @@ bool
|
||||||
CodeGeneratorX86Shared::visitCompare(LCompare *comp)
|
CodeGeneratorX86Shared::visitCompare(LCompare *comp)
|
||||||
{
|
{
|
||||||
emitCompare(comp->mir()->compareType(), comp->left(), comp->right());
|
emitCompare(comp->mir()->compareType(), comp->left(), comp->right());
|
||||||
emitSet(JSOpToCondition(comp->jsop()), ToRegister(comp->output()));
|
masm.emitSet(JSOpToCondition(comp->jsop()), ToRegister(comp->output()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,7 +161,7 @@ CodeGeneratorX86Shared::visitCompareD(LCompareD *comp)
|
||||||
|
|
||||||
Assembler::DoubleCondition cond = JSOpToDoubleCondition(comp->mir()->jsop());
|
Assembler::DoubleCondition cond = JSOpToDoubleCondition(comp->mir()->jsop());
|
||||||
masm.compareDouble(cond, lhs, rhs);
|
masm.compareDouble(cond, lhs, rhs);
|
||||||
emitSet(Assembler::ConditionFromDoubleCondition(cond), ToRegister(comp->output()),
|
masm.emitSet(Assembler::ConditionFromDoubleCondition(cond), ToRegister(comp->output()),
|
||||||
Assembler::NaNCondFromDoubleCondition(cond));
|
Assembler::NaNCondFromDoubleCondition(cond));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -206,7 +170,7 @@ bool
|
||||||
CodeGeneratorX86Shared::visitNotI(LNotI *ins)
|
CodeGeneratorX86Shared::visitNotI(LNotI *ins)
|
||||||
{
|
{
|
||||||
masm.cmpl(ToRegister(ins->input()), Imm32(0));
|
masm.cmpl(ToRegister(ins->input()), Imm32(0));
|
||||||
emitSet(Assembler::Equal, ToRegister(ins->output()));
|
masm.emitSet(Assembler::Equal, ToRegister(ins->output()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +181,7 @@ CodeGeneratorX86Shared::visitNotD(LNotD *ins)
|
||||||
|
|
||||||
masm.xorpd(ScratchFloatReg, ScratchFloatReg);
|
masm.xorpd(ScratchFloatReg, ScratchFloatReg);
|
||||||
masm.compareDouble(Assembler::DoubleEqualOrUnordered, opd, ScratchFloatReg);
|
masm.compareDouble(Assembler::DoubleEqualOrUnordered, opd, ScratchFloatReg);
|
||||||
emitSet(Assembler::Equal, ToRegister(ins->output()), Assembler::NaN_IsTrue);
|
masm.emitSet(Assembler::Equal, ToRegister(ins->output()), Assembler::NaN_IsTrue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,11 +64,6 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||||
|
|
||||||
void emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right);
|
void emitCompare(MCompare::CompareType type, const LAllocation *left, const LAllocation *right);
|
||||||
|
|
||||||
// Emits a conditional set.
|
|
||||||
void emitSet(Assembler::Condition cond, const Register &dest,
|
|
||||||
Assembler::NaNCond ifNaN = Assembler::NaN_Unexpected);
|
|
||||||
void emitSet(Assembler::DoubleCondition cond, const Register &dest);
|
|
||||||
|
|
||||||
// Emits a branch that directs control flow to the true block if |cond| is
|
// Emits a branch that directs control flow to the true block if |cond| is
|
||||||
// true, and the false block if |cond| is false.
|
// true, and the false block if |cond| is false.
|
||||||
void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse,
|
void emitBranch(Assembler::Condition cond, MBasicBlock *ifTrue, MBasicBlock *ifFalse,
|
||||||
|
|
|
@ -391,6 +391,40 @@ class MacroAssemblerX86Shared : public Assembler
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void emitSet(Assembler::Condition cond, const Register &dest,
|
||||||
|
Assembler::NaNCond ifNaN = Assembler::NaN_Unexpected) {
|
||||||
|
if (GeneralRegisterSet(Registers::SingleByteRegs).has(dest)) {
|
||||||
|
// If the register we're defining is a single byte register,
|
||||||
|
// take advantage of the setCC instruction
|
||||||
|
setCC(cond, dest);
|
||||||
|
movzxbl(dest, dest);
|
||||||
|
|
||||||
|
if (ifNaN != Assembler::NaN_Unexpected) {
|
||||||
|
Label noNaN;
|
||||||
|
j(Assembler::NoParity, &noNaN);
|
||||||
|
if (ifNaN == Assembler::NaN_IsTrue)
|
||||||
|
movl(Imm32(1), dest);
|
||||||
|
else
|
||||||
|
xorl(dest, dest);
|
||||||
|
bind(&noNaN);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Label end;
|
||||||
|
Label ifFalse;
|
||||||
|
|
||||||
|
if (ifNaN == Assembler::NaN_IsFalse)
|
||||||
|
j(Assembler::Parity, &ifFalse);
|
||||||
|
movl(Imm32(1), dest);
|
||||||
|
j(cond, &end);
|
||||||
|
if (ifNaN == Assembler::NaN_IsTrue)
|
||||||
|
j(Assembler::Parity, &end);
|
||||||
|
bind(&ifFalse);
|
||||||
|
xorl(dest, dest);
|
||||||
|
|
||||||
|
bind(&end);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Emit a JMP that can be toggled to a CMP. See ToggleToJmp(), ToggleToCmp().
|
// Emit a JMP that can be toggled to a CMP. See ToggleToJmp(), ToggleToCmp().
|
||||||
CodeOffsetLabel toggledJump(Label *label) {
|
CodeOffsetLabel toggledJump(Label *label) {
|
||||||
CodeOffsetLabel offset(size());
|
CodeOffsetLabel offset(size());
|
||||||
|
|
|
@ -347,7 +347,7 @@ CodeGeneratorX64::visitCompareB(LCompareB *lir)
|
||||||
|
|
||||||
// Perform the comparison.
|
// Perform the comparison.
|
||||||
masm.cmpq(lhs.valueReg(), ScratchReg);
|
masm.cmpq(lhs.valueReg(), ScratchReg);
|
||||||
emitSet(JSOpToCondition(mir->jsop()), output);
|
masm.emitSet(JSOpToCondition(mir->jsop()), output);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,11 +380,10 @@ CodeGeneratorX64::visitCompareV(LCompareV *lir)
|
||||||
const ValueOperand rhs = ToValue(lir, LCompareV::RhsInput);
|
const ValueOperand rhs = ToValue(lir, LCompareV::RhsInput);
|
||||||
const Register output = ToRegister(lir->output());
|
const Register output = ToRegister(lir->output());
|
||||||
|
|
||||||
JS_ASSERT(mir->jsop() == JSOP_EQ || mir->jsop() == JSOP_STRICTEQ ||
|
JS_ASSERT(IsEqualityOp(mir->jsop()));
|
||||||
mir->jsop() == JSOP_NE || mir->jsop() == JSOP_STRICTNE);
|
|
||||||
|
|
||||||
masm.cmpq(lhs.valueReg(), rhs.valueReg());
|
masm.cmpq(lhs.valueReg(), rhs.valueReg());
|
||||||
emitSet(JSOpToCondition(mir->jsop()), output);
|
masm.emitSet(JSOpToCondition(mir->jsop()), output);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -351,7 +351,7 @@ CodeGeneratorX86::visitCompareB(LCompareB *lir)
|
||||||
masm.cmp32(lhs.payloadReg(), Imm32(rhs->toConstant()->toBoolean()));
|
masm.cmp32(lhs.payloadReg(), Imm32(rhs->toConstant()->toBoolean()));
|
||||||
else
|
else
|
||||||
masm.cmp32(lhs.payloadReg(), ToRegister(rhs));
|
masm.cmp32(lhs.payloadReg(), ToRegister(rhs));
|
||||||
emitSet(JSOpToCondition(mir->jsop()), output);
|
masm.emitSet(JSOpToCondition(mir->jsop()), output);
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
}
|
}
|
||||||
masm.bind(¬Boolean);
|
masm.bind(¬Boolean);
|
||||||
|
@ -394,15 +394,14 @@ CodeGeneratorX86::visitCompareV(LCompareV *lir)
|
||||||
const ValueOperand rhs = ToValue(lir, LCompareV::RhsInput);
|
const ValueOperand rhs = ToValue(lir, LCompareV::RhsInput);
|
||||||
const Register output = ToRegister(lir->output());
|
const Register output = ToRegister(lir->output());
|
||||||
|
|
||||||
JS_ASSERT(mir->jsop() == JSOP_EQ || mir->jsop() == JSOP_STRICTEQ ||
|
JS_ASSERT(IsEqualityOp(mir->jsop()));
|
||||||
mir->jsop() == JSOP_NE || mir->jsop() == JSOP_STRICTNE);
|
|
||||||
|
|
||||||
Label notEqual, done;
|
Label notEqual, done;
|
||||||
masm.cmp32(lhs.typeReg(), rhs.typeReg());
|
masm.cmp32(lhs.typeReg(), rhs.typeReg());
|
||||||
masm.j(Assembler::NotEqual, ¬Equal);
|
masm.j(Assembler::NotEqual, ¬Equal);
|
||||||
{
|
{
|
||||||
masm.cmp32(lhs.payloadReg(), rhs.payloadReg());
|
masm.cmp32(lhs.payloadReg(), rhs.payloadReg());
|
||||||
emitSet(cond, output);
|
masm.emitSet(cond, output);
|
||||||
masm.jump(&done);
|
masm.jump(&done);
|
||||||
}
|
}
|
||||||
masm.bind(¬Equal);
|
masm.bind(¬Equal);
|
||||||
|
|
|
@ -459,6 +459,12 @@ IsGlobalOp(JSOp op)
|
||||||
return js_CodeSpec[op].format & JOF_GNAME;
|
return js_CodeSpec[op].format & JOF_GNAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
IsEqualityOp(JSOp op)
|
||||||
|
{
|
||||||
|
return op == JSOP_EQ || op == JSOP_NE || op == JSOP_STRICTEQ || op == JSOP_STRICTNE;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
IsGetterPC(jsbytecode *pc)
|
IsGetterPC(jsbytecode *pc)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче