Bug 846531 - Add optimized stub for Compare(Boolean x Int32). r=bhackett

This commit is contained in:
Kannan Vijayan 2013-03-04 11:54:06 -05:00
parent cb5ae90745
commit 02c6091256
5 changed files with 125 additions and 0 deletions

View File

@ -1509,6 +1509,9 @@ DoCompareFallback(JSContext *cx, ICCompare_Fallback *stub, HandleValue lhs, Hand
if ((lhs.isNumber() && rhs.isUndefined()) ||
(lhs.isUndefined() && rhs.isNumber()))
{
IonSpew(IonSpew_BaselineIC, " Generating %s(%s, %s) stub", js_CodeName[op],
rhs.isUndefined() ? "Number" : "Undefined",
rhs.isUndefined() ? "Undefined" : "Number");
ICCompare_NumberWithUndefined::Compiler compiler(cx, op, lhs.isUndefined());
ICStub *doubleStub = compiler.getStub(compiler.getStubSpace(script));
if (!stub)
@ -1519,6 +1522,7 @@ DoCompareFallback(JSContext *cx, ICCompare_Fallback *stub, HandleValue lhs, Hand
}
if (lhs.isBoolean() && rhs.isBoolean()) {
IonSpew(IonSpew_BaselineIC, " Generating %s(Boolean, Boolean) stub", js_CodeName[op]);
ICCompare_Boolean::Compiler compiler(cx, op);
ICStub *booleanStub = compiler.getStub(compiler.getStubSpace(script));
if (!booleanStub)
@ -1528,6 +1532,19 @@ DoCompareFallback(JSContext *cx, ICCompare_Fallback *stub, HandleValue lhs, Hand
return true;
}
if ((lhs.isBoolean() && rhs.isInt32()) || (lhs.isInt32() && rhs.isBoolean())) {
IonSpew(IonSpew_BaselineIC, " Generating %s(%s, %s) stub", js_CodeName[op],
rhs.isInt32() ? "Boolean" : "Int32",
rhs.isInt32() ? "Int32" : "Boolean");
ICCompare_Int32WithBoolean::Compiler compiler(cx, op, lhs.isInt32());
ICStub *optStub = compiler.getStub(compiler.getStubSpace(script));
if (!optStub)
return false;
stub->addNewStub(optStub);
return true;
}
if (IsEqualityOp(op)) {
if (lhs.isString() && rhs.isString() && !stub->hasStub(ICStub::Compare_String)) {
IonSpew(IonSpew_BaselineIC, " Generating %s(String, String) stub", js_CodeName[op]);
@ -1542,6 +1559,7 @@ DoCompareFallback(JSContext *cx, ICCompare_Fallback *stub, HandleValue lhs, Hand
if (lhs.isObject() && rhs.isObject()) {
JS_ASSERT(!stub->hasStub(ICStub::Compare_Object));
IonSpew(IonSpew_BaselineIC, " Generating %s(Object, Object) stub", js_CodeName[op]);
ICCompare_Object::Compiler compiler(cx, op);
ICStub *objectStub = compiler.getStub(compiler.getStubSpace(script));
if (!objectStub)
@ -1555,6 +1573,8 @@ DoCompareFallback(JSContext *cx, ICCompare_Fallback *stub, HandleValue lhs, Hand
(rhs.isObject() || rhs.isNull() || rhs.isUndefined()) &&
!stub->hasStub(ICStub::Compare_ObjectWithUndefined))
{
IonSpew(IonSpew_BaselineIC, " Generating %s(Obj/Null/Undef, Obj/Null/Undef) stub",
js_CodeName[op]);
bool lhsIsUndefined = lhs.isNull() || lhs.isUndefined();
bool compareWithNull = lhs.isNull() || rhs.isNull();
ICCompare_ObjectWithUndefined::Compiler compiler(cx, op,
@ -1797,6 +1817,51 @@ ICCompare_ObjectWithUndefined::Compiler::generateStubCode(MacroAssembler &masm)
return true;
}
//
// Compare_Int32WithBoolean
//
bool
ICCompare_Int32WithBoolean::Compiler::generateStubCode(MacroAssembler &masm)
{
Label failure;
ValueOperand int32Val;
ValueOperand boolVal;
if (lhsIsInt32_) {
int32Val = R0;
boolVal = R1;
} else {
boolVal = R0;
int32Val = R1;
}
masm.branchTestBoolean(Assembler::NotEqual, boolVal, &failure);
masm.branchTestInt32(Assembler::NotEqual, int32Val, &failure);
if (op_ == JSOP_STRICTEQ || op_ == JSOP_STRICTNE) {
// Ints and booleans are never strictly equal, always strictly not equal.
masm.moveValue(BooleanValue(op_ == JSOP_STRICTNE), R0);
EmitReturnFromIC(masm);
} else {
Register boolReg = masm.extractBoolean(boolVal, ExtractTemp0);
Register int32Reg = masm.extractInt32(int32Val, ExtractTemp1);
// Compare payload regs of R0 and R1.
Assembler::Condition cond = JSOpToCondition(op_);
masm.cmp32(lhsIsInt32_ ? int32Reg : boolReg,
lhsIsInt32_ ? boolReg : int32Reg);
masm.emitSet(cond, R0.scratchReg());
// Box the result and return
masm.tagValue(JSVAL_TYPE_BOOLEAN, R0.scratchReg(), R0);
EmitReturnFromIC(masm);
}
// Failure case - jump to next stub
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// ToBool_Fallback
//

View File

@ -296,6 +296,7 @@ class ICEntry
_(Compare_Boolean) \
_(Compare_Object) \
_(Compare_ObjectWithUndefined) \
_(Compare_Int32WithBoolean) \
\
_(ToBool_Fallback) \
_(ToBool_Int32) \
@ -1881,6 +1882,54 @@ class ICCompare_ObjectWithUndefined : public ICStub
};
};
class ICCompare_Int32WithBoolean : public ICStub
{
friend class ICStubSpace;
ICCompare_Int32WithBoolean(IonCode *stubCode, bool lhsIsInt32)
: ICStub(ICStub::Compare_Int32WithBoolean, stubCode)
{
extra_ = lhsIsInt32;
}
public:
static inline ICCompare_Int32WithBoolean *New(ICStubSpace *space, IonCode *code,
bool lhsIsInt32)
{
if (!code)
return NULL;
return space->allocate<ICCompare_Int32WithBoolean>(code, lhsIsInt32);
}
bool lhsIsInt32() const {
return extra_;
}
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
JSOp op_;
bool lhsIsInt32_;
bool generateStubCode(MacroAssembler &masm);
virtual int32_t getKey() const {
return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
(static_cast<int32_t>(lhsIsInt32_) << 24));
}
public:
Compiler(JSContext *cx, JSOp op, bool lhsIsInt32)
: ICStubCompiler(cx, ICStub::Compare_Int32WithBoolean),
op_(op),
lhsIsInt32_(lhsIsInt32)
{}
ICStub *getStub(ICStubSpace *space) {
return ICCompare_Int32WithBoolean::New(space, getStubCode(), lhsIsInt32_);
}
};
};
// ToBool
// JSOP_IFNE

View File

@ -644,6 +644,9 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
Register extractInt32(const ValueOperand &value, Register scratch) {
return value.payloadReg();
}
Register extractBoolean(const ValueOperand &value, Register scratch) {
return value.payloadReg();
}
Register extractTag(const Address &address, Register scratch);
Register extractTag(const BaseIndex &address, Register scratch);
Register extractTag(const ValueOperand &value, Register scratch) {

View File

@ -803,6 +803,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
unboxInt32(value, scratch);
return scratch;
}
Register extractBoolean(const ValueOperand &value, Register scratch) {
JS_ASSERT(scratch != ScratchReg);
unboxBoolean(value, scratch);
return scratch;
}
Register extractTag(const Address &address, Register scratch) {
JS_ASSERT(scratch != ScratchReg);
loadPtr(address, scratch);

View File

@ -685,6 +685,9 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Register extractInt32(const ValueOperand &value, Register scratch) {
return value.payloadReg();
}
Register extractBoolean(const ValueOperand &value, Register scratch) {
return value.payloadReg();
}
Register extractTag(const Address &address, Register scratch) {
movl(tagOf(address), scratch);
return scratch;