[JAEGER] Fast-paths for STRICTEQ,NE when undefined or null are used.

This commit is contained in:
David Anderson 2010-06-17 00:29:28 -07:00
parent 335d797ee4
commit 8aba3afc06
4 changed files with 60 additions and 10 deletions

View File

@ -1008,6 +1008,13 @@ public:
m_assembler.movzbl_rr(dest, dest);
}
void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
{
m_assembler.cmpl_im(right.m_value, left.offset, left.base);
m_assembler.setCC_r(x86Condition(cond), dest);
m_assembler.movzbl_rr(dest, dest);
}
void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
{
if (((cond == Equal) || (cond == NotEqual)) && !right.m_value)

View File

@ -789,19 +789,11 @@ mjit::Compiler::generateMethod()
END_CASE(JSOP_LOOKUPSWITCH)
BEGIN_CASE(JSOP_STRICTEQ)
prepareStubCall();
stubCall(stubs::StrictEq, Uses(2), Defs(1));
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_MASK32_BOOLEAN, Registers::ReturnReg);
jsop_stricteq(op);
END_CASE(JSOP_STRICTEQ)
BEGIN_CASE(JSOP_STRICTNE)
prepareStubCall();
stubCall(stubs::StrictNe, Uses(2), Defs(1));
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_MASK32_BOOLEAN, Registers::ReturnReg);
jsop_stricteq(op);
END_CASE(JSOP_STRICTNE)
BEGIN_CASE(JSOP_ITER)

View File

@ -181,6 +181,7 @@ class Compiler
void jsop_localinc(JSOp op, uint32 slot, bool popped);
void jsop_setelem();
void jsop_getelem();
void jsop_stricteq(JSOp op);
#define STUB_CALL_TYPE(type) \
Call stubCall(type stub, Uses uses, Defs defs) { \

View File

@ -1191,3 +1191,53 @@ mjit::Compiler::jsop_getelem()
stubcc.rejoin(0);
}
static inline bool
ReallySimpleStrictTest(FrameEntry *fe, JSValueMask32 &mask)
{
if (!fe->isTypeKnown())
return false;
mask = fe->getTypeTag();
return mask == JSVAL_MASK32_NULL || mask == JSVAL_MASK32_UNDEFINED;
}
void
mjit::Compiler::jsop_stricteq(JSOp op)
{
FrameEntry *rhs = frame.peek(-1);
FrameEntry *lhs = frame.peek(-2);
Assembler::Condition cond = (op == JSOP_STRICTEQ) ? Assembler::Equal : Assembler::NotEqual;
/* Comparison against undefined or null is super easy. */
bool lhsTest;
JSValueMask32 mask;
if ((lhsTest = ReallySimpleStrictTest(lhs, mask)) || ReallySimpleStrictTest(rhs, mask)) {
FrameEntry *test = lhsTest ? rhs : lhs;
if (test->isTypeKnown()) {
frame.popn(2);
frame.push(BooleanTag((test->getTypeTag() == mask) == (op == JSOP_STRICTEQ)));
return;
}
/* This is only true if the other side is |null|. */
RegisterID result = frame.allocReg(Registers::SingleByteRegs);
if (frame.shouldAvoidTypeRemat(test))
masm.set32(cond, frame.addressOf(test), Imm32(mask), result);
else
masm.set32(cond, frame.tempRegForType(test), Imm32(mask), result);
frame.popn(2);
frame.pushTypedPayload(JSVAL_MASK32_BOOLEAN, result);
return;
}
prepareStubCall();
if (op == JSOP_STRICTEQ)
stubCall(stubs::StrictEq, Uses(2), Defs(1));
else
stubCall(stubs::StrictNe, Uses(2), Defs(1));
frame.popn(2);
frame.takeReg(Registers::ReturnReg);
frame.pushTypedPayload(JSVAL_MASK32_BOOLEAN, Registers::ReturnReg);
}